📄 pngimagereader.java
字号:
imRas.setRect(updateMinX, dstY, passRow); } else { int newSrcX = srcX; for (int dstX = updateMinX; dstX < updateMinX + updateWidth; dstX += updateXStep) { passRow.getPixel(newSrcX, 0, ps); if (adjustBitDepths) { for (int b = 0; b < numBands; b++) { ps[b] = scale[b][ps[b]]; } } imRas.setPixel(dstX, dstY, ps); newSrcX += srcXStep; } } processImageUpdate(theImage, updateMinX, dstY, updateWidth, 1, updateXStep, updateYStep, destinationBands); // If read has been aborted, just return // processReadAborted will be called later if (abortRequested()) { return; } } } processPassComplete(theImage); } private void decodeImage() throws IOException, IIOException { int width = metadata.IHDR_width; int height = metadata.IHDR_height; this.pixelsDone = 0; this.totalPixels = width*height; clearAbortRequest(); if (metadata.IHDR_interlaceMethod == 0) { decodePass(0, 0, 0, 1, 1, width, height); } else { for (int i = 0; i <= sourceMaxProgressivePass; i++) { int XOffset = adam7XOffset[i]; int YOffset = adam7YOffset[i]; int XSubsampling = adam7XSubsampling[i]; int YSubsampling = adam7YSubsampling[i]; int xbump = adam7XSubsampling[i + 1] - 1; int ybump = adam7YSubsampling[i + 1] - 1; if (i >= sourceMinProgressivePass) { decodePass(i, XOffset, YOffset, XSubsampling, YSubsampling, (width + xbump)/XSubsampling, (height + ybump)/YSubsampling); } else { skipPass((width + xbump)/XSubsampling, (height + ybump)/YSubsampling); } // If read has been aborted, just return // processReadAborted will be called later if (abortRequested()) { return; } } } } private void readImage(ImageReadParam param) throws IIOException { readMetadata(); int width = metadata.IHDR_width; int height = metadata.IHDR_height; // Init default values sourceXSubsampling = 1; sourceYSubsampling = 1; sourceMinProgressivePass = 0; sourceMaxProgressivePass = 6; sourceBands = null; destinationBands = null; destinationOffset = new Point(0, 0); // If an ImageReadParam is available, get values from it if (param != null) { sourceXSubsampling = param.getSourceXSubsampling(); sourceYSubsampling = param.getSourceYSubsampling(); sourceMinProgressivePass = Math.max(param.getSourceMinProgressivePass(), 0); sourceMaxProgressivePass = Math.min(param.getSourceMaxProgressivePass(), 6); sourceBands = param.getSourceBands(); destinationBands = param.getDestinationBands(); destinationOffset = param.getDestinationOffset(); } try { stream.seek(imageStartPosition); Enumeration e = new PNGImageDataEnumeration(stream); InputStream is = new SequenceInputStream(e); is = new InflaterInputStream(is, new Inflater()); is = new BufferedInputStream(is); this.pixelStream = new DataInputStream(is); theImage = getDestination(param, getImageTypes(0), width, height); Rectangle destRegion = new Rectangle(0, 0, 0, 0); sourceRegion = new Rectangle(0, 0, 0, 0); computeRegions(param, width, height, theImage, sourceRegion, destRegion); destinationOffset.setLocation(destRegion.getLocation()); // At this point the header has been read and we know // how many bands are in the image, so perform checking // of the read param. int colorType = metadata.IHDR_colorType; checkReadParamBandSettings(param, inputBandsForColorType[colorType], theImage.getSampleModel().getNumBands()); processImageStarted(0); decodeImage(); if (abortRequested()) { processReadAborted(); } else { processImageComplete(); } } catch (IOException e) { throw new IIOException("Error reading PNG image data", e); } } public int getNumImages(boolean allowSearch) throws IIOException { if (stream == null) { throw new IllegalStateException("No input source set!"); } if (seekForwardOnly && allowSearch) { throw new IllegalStateException ("seekForwardOnly and allowSearch can't both be true!"); } return 1; } public int getWidth(int imageIndex) throws IIOException { if (imageIndex != 0) { throw new IndexOutOfBoundsException("imageIndex != 0!"); } readHeader(); return metadata.IHDR_width; } public int getHeight(int imageIndex) throws IIOException { if (imageIndex != 0) { throw new IndexOutOfBoundsException("imageIndex != 0!"); } readHeader(); return metadata.IHDR_height; } public Iterator getImageTypes(int imageIndex) throws IIOException { if (imageIndex != 0) { throw new IndexOutOfBoundsException("imageIndex != 0!"); } readHeader(); ArrayList l = new ArrayList(1); // List of ImageTypeSpecifiers ColorSpace rgb; ColorSpace gray; int[] bandOffsets; int bitDepth = metadata.IHDR_bitDepth; int colorType = metadata.IHDR_colorType; int dataType; if (bitDepth <= 8) { dataType = DataBuffer.TYPE_BYTE; } else { dataType = DataBuffer.TYPE_USHORT; } switch (colorType) { case PNG_COLOR_GRAY: // Packed grayscale l.add(ImageTypeSpecifier.createGrayscale(bitDepth, dataType, false)); break; case PNG_COLOR_RGB: // Component R, G, B rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB); bandOffsets = new int[3]; bandOffsets[0] = 0; bandOffsets[1] = 1; bandOffsets[2] = 2; l.add(ImageTypeSpecifier.createInterleaved(rgb, bandOffsets, dataType, false, false)); break; case PNG_COLOR_PALETTE: readMetadata(); // Need tRNS chunk /* * The PLTE chunk spec says: * * The number of palette entries must not exceed the range that * can be represented in the image bit depth (for example, 2^4 = 16 * for a bit depth of 4). It is permissible to have fewer entries * than the bit depth would allow. In that case, any out-of-range * pixel value found in the image data is an error. * * http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.PLTE * * Consequently, the case when the palette length is smaller than * 2^bitDepth is legal in the view of PNG spec. * * However the spec of createIndexed() method demands the exact * equality of the palette lengh and number of possible palette * entries (2^bitDepth). * * {@link javax.imageio.ImageTypeSpecifier.html#createIndexed} * * In order to avoid this contradiction we need to extend the * palette arrays to the limit defined by the bitDepth. */ int plength = 1 << bitDepth; byte[] red = metadata.PLTE_red; byte[] green = metadata.PLTE_green; byte[] blue = metadata.PLTE_blue; if (metadata.PLTE_red.length < plength) { red = Arrays.copyOf(metadata.PLTE_red, plength); Arrays.fill(red, metadata.PLTE_red.length, plength, metadata.PLTE_red[metadata.PLTE_red.length - 1]); green = Arrays.copyOf(metadata.PLTE_green, plength); Arrays.fill(green, metadata.PLTE_green.length, plength, metadata.PLTE_green[metadata.PLTE_green.length - 1]); blue = Arrays.copyOf(metadata.PLTE_blue, plength); Arrays.fill(blue, metadata.PLTE_blue.length, plength, metadata.PLTE_blue[metadata.PLTE_blue.length - 1]); } // Alpha from tRNS chunk may have fewer entries than // the RGB LUTs from the PLTE chunk; if so, pad with // 255. byte[] alpha = null; if (metadata.tRNS_present && (metadata.tRNS_alpha != null)) { if (metadata.tRNS_alpha.length == red.length) { alpha = metadata.tRNS_alpha; } else { alpha = Arrays.copyOf(metadata.tRNS_alpha, red.length); Arrays.fill(alpha, metadata.tRNS_alpha.length, red.length, (byte)255); } } l.add(ImageTypeSpecifier.createIndexed(red, green, blue, alpha, bitDepth, DataBuffer.TYPE_BYTE)); break; case PNG_COLOR_GRAY_ALPHA: // Component G, A gray = ColorSpace.getInstance(ColorSpace.CS_GRAY); bandOffsets = new int[2]; bandOffsets[0] = 0; bandOffsets[1] = 1; l.add(ImageTypeSpecifier.createInterleaved(gray, bandOffsets, dataType, true, false)); break; case PNG_COLOR_RGB_ALPHA: // Component R, G, B, A (non-premultiplied) rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB); bandOffsets = new int[4]; bandOffsets[0] = 0; bandOffsets[1] = 1; bandOffsets[2] = 2; bandOffsets[3] = 3; l.add(ImageTypeSpecifier.createInterleaved(rgb, bandOffsets, dataType, true, false)); break; default: break; } return l.iterator(); } public ImageReadParam getDefaultReadParam() { return new ImageReadParam(); } public IIOMetadata getStreamMetadata() throws IIOException { return null; } public IIOMetadata getImageMetadata(int imageIndex) throws IIOException { if (imageIndex != 0) { throw new IndexOutOfBoundsException("imageIndex != 0!"); } readMetadata(); return metadata; } public BufferedImage read(int imageIndex, ImageReadParam param) throws IIOException { if (imageIndex != 0) { throw new IndexOutOfBoundsException("imageIndex != 0!"); } readImage(param); return theImage; } public void reset() { super.reset(); resetStreamSettings(); } private void resetStreamSettings() { gotHeader = false; gotMetadata = false; metadata = null; pixelStream = null; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -