📄 pngimage.java
字号:
* @see #getTextChunks * @see #getEverything * @see #getProperty * @param key the key of the desired chunk * @return the text chunk, or null if not present. */ public TextChunk getTextChunk(String key) throws IOException { readToData(); return (TextChunk)data.textChunks.get(key); } /** * Returns the keys of all known text chunks. * <p> * <b>Note:</b> Text chunks may appear anywhere in the file. This * method will only read up to the beginning of the image data * unless the image data has already been read, either through the * consumer/producer interface or by calling * <code>getEverything</code>. * @see #getTextChunk * @see #getEverything * @return an <code>Enumeration</code> of the keys of text chunks read so far. */ public Enumeration getTextChunks() throws IOException { readToData(); return data.textChunks.elements(); } /** * Returns all known GIF Application Extensions. * <p> * <b>Note:</b> GIF Application Extensions may appear anywhere in * the file. This method will only read up to the beginning of the * image data unless the image data has already been read, either * through the consumer/producer interface or by calling * <code>getEverything</code>. * @see #getEverything * @return an <code>Enumeration</code> of all GifExtension objects read so far. * @see GifExtension */ public Enumeration getGifExtensions() throws IOException { readToData(); return data.gifExtensions.elements(); } /** * Readies this PngImage to be flushed after the next image * production, to free memory (default false). * <p> * After flushing, you may only call the <code>getErrors</code> * and <code>hasErrors</code> methods on this object. The pixel * data will no longer be available through the consumer/producer * interface. * <p> * <b>Note:</b> Using a PixelGrabber object on an Image produced * by this PngImage object will ask for a second production of the * pixel data, which will fail if the object has been flushed. * @see #getErrors * @see #hasErrors */ public void setFlushAfterNextProduction(boolean useFlush) { data.useFlush = useFlush; } private void flush() { if (data != null) { try { data.in_idat.close(); } catch (IOException e) { // TODO: ignore? } data = null; } } /////////////////// end public //////////////////////// static { registerChunk(new Chunk_IHDR()); registerChunk(new Chunk_PLTE()); registerChunk(new Chunk_IDAT()); registerChunk(new Chunk_IEND()); registerChunk(new Chunk_tRNS()); } private void init(InputStream in_raw) { data.properties.put("gamma", new Long(DEFAULT_GAMMA)); data.in_idat = new IDATInputStream(this, in_raw); } private synchronized void readToData() throws IOException { try { if (data == null) { throw new EOFException("Object has been flushed."); } data.in_idat.readToData(); } catch (PngException e) { addError(e); throw e; } } private static void registerChunk(Chunk proto) { prototypes.put(new Integer(proto.type), proto); } /* package */ static Chunk getRegisteredChunk(int type) { Integer type_obj = new Integer(type); if (prototypes.containsKey(type_obj)) { return ((Chunk)prototypes.get(type_obj)).copy(); } else { try { String clsName = "com.sixlegs.image.png.Chunk_" + Chunk.typeToString(type); registerChunk((Chunk)Class.forName(clsName).newInstance()); return getRegisteredChunk(type); } catch (Exception e) { return new Chunk(type); } } } /* package */ Chunk getChunk(int type) { return (Chunk)data.chunks.get(new Integer(type)); } /* package */ void putChunk(int type, Chunk c) { data.chunks.put(new Integer(type), c); } /* package */ void addError(Exception e) { if (errorList == null) { errorList = new Vector(); } errorList.addElement(e); } /* package */ void fillGammaTable() { try { long file_gamma = ((Long)getProperty("gamma")).longValue(); int max = (data.header.paletteUsed ? 0xFF : (1 << data.header.outputDepth) - 1); double decoding_exponent = (USER_EXPONENT * 100000d / (file_gamma * DISPLAY_EXPONENT)); for (int i = 0; i <= max; i++) { int v = (int)(Math.pow((double)i / max, decoding_exponent) * 0xFF); if (!data.header.colorUsed) { data.gammaTable[i] = v | v << 8 | v << 16; } else { data.gammaTable[i] = v; } } if (data.palette != null) data.palette.calculate(); } catch (IOException e) { } } private synchronized void produceHelper(ImageConsumer[] ics) { try { readToData(); for (int i = 0; i < ics.length; i++) { ics[i].setDimensions(data.header.width, data.header.height); ics[i].setProperties(data.properties); ics[i].setColorModel(data.header.model); if (data.produceFailed) ics[i].imageComplete(ImageConsumer.IMAGEERROR); } if (data.produceFailed) return; if (data.pixels == null) { firstProduction(ics); } else { setHints(ics); for (int i = 0; i < ics.length; i++) { ics[i].setPixels(0, 0, data.header.width, data.header.height, data.header.model, data.pixels, 0, data.header.width); ics[i].imageComplete(ImageConsumer.STATICIMAGEDONE); } } } catch (IOException e) { data.produceFailed = true; addError(e); for (int i = 0; i < ics.length; i++) { ics[i].imageComplete(ImageConsumer.IMAGEERROR); } } if (data.useFlush) flush(); } private void firstProduction(ImageConsumer[] ics) throws IOException { UnfilterInputStream in_filter = new UnfilterInputStream(this, data.in_idat); InputStream is = new BufferedInputStream(in_filter, BUFFER_SIZE); PixelInputStream pis = new PixelInputStream(this, is); setHints(ics); if (data.header.interlace == INTERLACE_TYPE_NONE) { // this is just for optimization // omitting it will cause NullInterlacer to be used produceNonInterlaced(ics, pis); } else { produceInterlaced(ics, pis); } for (int i = 0; i < ics.length; i++) { ics[i].imageComplete(ImageConsumer.STATICIMAGEDONE); } } private void setHints(ImageConsumer[] ics) { for (int i = 0; i < ics.length; i++) { if (progressive && data.pixels == null && (data.header.interlace != INTERLACE_TYPE_NONE)) { ics[i].setHints(ImageConsumer.RANDOMPIXELORDER); } else { ics[i].setHints(ImageConsumer.TOPDOWNLEFTRIGHT | ImageConsumer.SINGLEPASS | ImageConsumer.SINGLEFRAME | ImageConsumer.COMPLETESCANLINES); } } } private void produceNonInterlaced(ImageConsumer[] ics, PixelInputStream pis) throws IOException { int w = data.header.width, h = data.header.height; // if we're going to flush, don't bother saving pixel data if (!data.useFlush) { data.pixels = new int[w * h]; } int[] rowbuf = new int[w + 8]; int pixelsWidth = w; int extra = w % pis.fillSize; if (extra > 0) pixelsWidth += (pis.fillSize - extra); int off = 0; for (int y = 0; y < h; y++) { pis.read(rowbuf, 0, pixelsWidth); for (int i = 0; i < ics.length; i++) { ics[i].setPixels(0, y, w, 1, data.header.model, rowbuf, 0, pixelsWidth); } if (!data.useFlush) { System.arraycopy(rowbuf, 0, data.pixels, w * y, w); } } } private void produceInterlaced(ImageConsumer[] ics, PixelInputStream pis) throws IOException { int w = data.header.width, h = data.header.height; data.pixels = new int[w * h]; int[] rowbuf = new int[w + 8]; int numPasses = data.header.interlacer.numPasses(); Interlacer lace = data.header.interlacer; for (int pass = 0; pass < numPasses; pass++) { int passWidth = lace.getPassWidth(pass); int extra = passWidth % pis.fillSize; if (extra > 0) passWidth += (pis.fillSize - extra); int blockWidth = (progressive ? lace.getBlockWidth(pass) : 1); int blockHeight = (progressive ? lace.getBlockHeight(pass) : 1); int rowIncrement = lace.getSpacingY(pass); int colIncrement = lace.getSpacingX(pass); int offIncrement = rowIncrement * w; int colStart = lace.getOffsetX(pass); int row = lace.getOffsetY(pass); int off = row * w; while (row < h) { pis.read(rowbuf, 0, passWidth); int col = colStart; int x = 0; while (col < w) { int bw = Math.min(blockWidth, w - col); int bh = Math.min(blockHeight, h - row); int poff = off + col; int pix = rowbuf[x++]; while (bh-- > 0) { int poffend = poff + bw; while (poff < poffend) { data.pixels[poff++] = pix; } poff += w - bw; } col += colIncrement; } off += offIncrement; row += rowIncrement; } if (progressive) { for (int i = 0; i < ics.length; i++) { ics[i].setPixels(0, 0, w, h, data.header.model, data.pixels, 0, w); ics[i].imageComplete(ImageConsumer.SINGLEFRAMEDONE); } } } if (!progressive) { for (int i = 0; i < ics.length; i++) { ics[i].setPixels(0, 0, w, h, data.header.model, data.pixels, 0, w); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -