📄 pngimagereader.java
字号:
/* * @(#)PNGImageReader.java 1.60 06/03/01 * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.imageio.plugins.png;import java.awt.Point;import java.awt.Rectangle;import java.awt.color.ColorSpace;import java.awt.image.BufferedImage;import java.awt.image.DataBuffer;import java.awt.image.DataBufferByte;import java.awt.image.DataBufferUShort;import java.awt.image.Raster;import java.awt.image.WritableRaster;import java.io.BufferedInputStream;import java.io.ByteArrayInputStream;import java.io.DataInputStream;import java.io.InputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Arrays;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.zip.Inflater;import java.util.zip.InflaterInputStream;import javax.imageio.IIOException;import javax.imageio.ImageReader;import javax.imageio.ImageReadParam;import javax.imageio.ImageTypeSpecifier;import javax.imageio.metadata.IIOMetadata;import javax.imageio.spi.ImageReaderSpi;import javax.imageio.stream.ImageInputStream;import com.sun.imageio.plugins.common.InputStreamAdapter;import com.sun.imageio.plugins.common.ReaderUtil;import com.sun.imageio.plugins.common.SubImageInputStream;class PNGImageDataEnumeration implements Enumeration { boolean firstTime = true; ImageInputStream stream; int length; public PNGImageDataEnumeration(ImageInputStream stream) throws IOException { this.stream = stream; this.length = stream.readInt(); int type = stream.readInt(); // skip chunk type } public Object nextElement() { try { firstTime = false; ImageInputStream iis = new SubImageInputStream(stream, length); return new InputStreamAdapter(iis); } catch (IOException e) { return null; } } public boolean hasMoreElements() { if (firstTime) { return true; } try { int crc = stream.readInt(); this.length = stream.readInt(); int type = stream.readInt(); if (type == PNGImageReader.IDAT_TYPE) { return true; } else { return false; } } catch (IOException e) { return false; } }}/** * @version 0.5 */public class PNGImageReader extends ImageReader { /* * Note: The following chunk type constants are autogenerated. Each * one is derived from the ASCII values of its 4-character name. For * example, IHDR_TYPE is calculated as follows: * ('I' << 24) | ('H' << 16) | ('D' << 8) | 'R' */ // Critical chunks static final int IHDR_TYPE = 0x49484452; static final int PLTE_TYPE = 0x504c5445; static final int IDAT_TYPE = 0x49444154; static final int IEND_TYPE = 0x49454e44; // Ancillary chunks static final int bKGD_TYPE = 0x624b4744; static final int cHRM_TYPE = 0x6348524d; static final int gAMA_TYPE = 0x67414d41; static final int hIST_TYPE = 0x68495354; static final int iCCP_TYPE = 0x69434350; static final int iTXt_TYPE = 0x69545874; static final int pHYs_TYPE = 0x70485973; static final int sBIT_TYPE = 0x73424954; static final int sPLT_TYPE = 0x73504c54; static final int sRGB_TYPE = 0x73524742; static final int tEXt_TYPE = 0x74455874; static final int tIME_TYPE = 0x74494d45; static final int tRNS_TYPE = 0x74524e53; static final int zTXt_TYPE = 0x7a545874; static final int PNG_COLOR_GRAY = 0; static final int PNG_COLOR_RGB = 2; static final int PNG_COLOR_PALETTE = 3; static final int PNG_COLOR_GRAY_ALPHA = 4; static final int PNG_COLOR_RGB_ALPHA = 6; // The number of bands by PNG color type static final int[] inputBandsForColorType = { 1, // gray -1, // unused 3, // rgb 1, // palette 2, // gray + alpha -1, // unused 4 // rgb + alpha }; static final int PNG_FILTER_NONE = 0; static final int PNG_FILTER_SUB = 1; static final int PNG_FILTER_UP = 2; static final int PNG_FILTER_AVERAGE = 3; static final int PNG_FILTER_PAETH = 4; static final int[] adam7XOffset = { 0, 4, 0, 2, 0, 1, 0 }; static final int[] adam7YOffset = { 0, 0, 4, 0, 2, 0, 1 }; static final int[] adam7XSubsampling = { 8, 8, 4, 4, 2, 2, 1, 1 }; static final int[] adam7YSubsampling = { 8, 8, 8, 4, 4, 2, 2, 1 }; private static final boolean debug = true; ImageInputStream stream = null; boolean gotHeader = false; boolean gotMetadata = false; ImageReadParam lastParam = null; long imageStartPosition = -1L; Rectangle sourceRegion = null; int sourceXSubsampling = -1; int sourceYSubsampling = -1; int sourceMinProgressivePass = 0; int sourceMaxProgressivePass = 6; int[] sourceBands = null; int[] destinationBands = null; Point destinationOffset = new Point(0, 0); PNGMetadata metadata = new PNGMetadata(); DataInputStream pixelStream = null; BufferedImage theImage = null; // The number of source pixels processed int pixelsDone = 0; // The total number of pixels in the source image int totalPixels; public PNGImageReader(ImageReaderSpi originatingProvider) { super(originatingProvider); } public void setInput(Object input, boolean seekForwardOnly, boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); this.stream = (ImageInputStream)input; // Always works // Clear all values based on the previous stream contents resetStreamSettings(); } private String readNullTerminatedString() throws IOException { StringBuilder b = new StringBuilder(); int c; while ((c = stream.read()) != 0) { b.append((char)c); } return b.toString(); } private void readHeader() throws IIOException { if (gotHeader) { return; } if (stream == null) { throw new IllegalStateException("Input source not set!"); } try { byte[] signature = new byte[8]; stream.readFully(signature); if (signature[0] != (byte)137 || signature[1] != (byte)80 || signature[2] != (byte)78 || signature[3] != (byte)71 || signature[4] != (byte)13 || signature[5] != (byte)10 || signature[6] != (byte)26 || signature[7] != (byte)10) { throw new IIOException("Bad PNG signature!"); } int IHDR_length = stream.readInt(); if (IHDR_length != 13) { throw new IIOException("Bad length for IHDR chunk!"); } int IHDR_type = stream.readInt(); if (IHDR_type != IHDR_TYPE) { throw new IIOException("Bad type for IHDR chunk!"); } this.metadata = new PNGMetadata(); int width = stream.readInt(); int height = stream.readInt(); // Re-use signature array to bulk-read these unsigned byte values stream.readFully(signature, 0, 5); int bitDepth = signature[0] & 0xff; int colorType = signature[1] & 0xff; int compressionMethod = signature[2] & 0xff; int filterMethod = signature[3] & 0xff; int interlaceMethod = signature[4] & 0xff; // Skip IHDR CRC stream.skipBytes(4); stream.flushBefore(stream.getStreamPosition()); if (width == 0) { throw new IIOException("Image width == 0!"); } if (height == 0) { throw new IIOException("Image height == 0!"); } if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 && bitDepth != 8 && bitDepth != 16) { throw new IIOException("Bit depth must be 1, 2, 4, 8, or 16!"); } if (colorType != 0 && colorType != 2 && colorType != 3 && colorType != 4 && colorType != 6) { throw new IIOException("Color type must be 0, 2, 3, 4, or 6!"); } if (colorType == PNG_COLOR_PALETTE && bitDepth == 16) { throw new IIOException("Bad color type/bit depth combination!"); } if ((colorType == PNG_COLOR_RGB || colorType == PNG_COLOR_RGB_ALPHA || colorType == PNG_COLOR_GRAY_ALPHA) && (bitDepth != 8 && bitDepth != 16)) { throw new IIOException("Bad color type/bit depth combination!"); } if (compressionMethod != 0) { throw new IIOException("Unknown compression method (not 0)!"); } if (filterMethod != 0) { throw new IIOException("Unknown filter method (not 0)!"); } if (interlaceMethod != 0 && interlaceMethod != 1) { throw new IIOException("Unknown interlace method (not 0 or 1)!"); } metadata.IHDR_present = true; metadata.IHDR_width = width; metadata.IHDR_height = height; metadata.IHDR_bitDepth = bitDepth; metadata.IHDR_colorType = colorType; metadata.IHDR_compressionMethod = compressionMethod; metadata.IHDR_filterMethod = filterMethod; metadata.IHDR_interlaceMethod = interlaceMethod; gotHeader = true; } catch (IOException e) { throw new IIOException("I/O error reading PNG header!", e); } } private void parse_PLTE_chunk(int chunkLength) throws IOException { if (metadata.PLTE_present) { processWarningOccurred("A PNG image may not contain more than one PLTE chunk.\n" +"The chunk wil be ignored."); return; } else if (metadata.IHDR_colorType == PNG_COLOR_GRAY || metadata.IHDR_colorType == PNG_COLOR_GRAY_ALPHA) { processWarningOccurred("A PNG gray or gray alpha image cannot have a PLTE chunk.\n" +"The chunk wil be ignored."); return; } byte[] palette = new byte[chunkLength]; stream.readFully(palette); int numEntries = chunkLength/3; if (metadata.IHDR_colorType == PNG_COLOR_PALETTE) { int maxEntries = 1 << metadata.IHDR_bitDepth; if (numEntries > maxEntries) { processWarningOccurred("PLTE chunk contains too many entries for bit depth, ignoring extras."); numEntries = maxEntries; } numEntries = Math.min(numEntries, maxEntries); } // Round array sizes up to 2^2^n int paletteEntries; if (numEntries > 16) { paletteEntries = 256; } else if (numEntries > 4) { paletteEntries = 16; } else if (numEntries > 2) { paletteEntries = 4; } else { paletteEntries = 2; } metadata.PLTE_present = true; metadata.PLTE_red = new byte[paletteEntries]; metadata.PLTE_green = new byte[paletteEntries]; metadata.PLTE_blue = new byte[paletteEntries]; int index = 0; for (int i = 0; i < numEntries; i++) { metadata.PLTE_red[i] = palette[index++]; metadata.PLTE_green[i] = palette[index++]; metadata.PLTE_blue[i] = palette[index++]; } } private void parse_bKGD_chunk() throws IOException { if (metadata.IHDR_colorType == PNG_COLOR_PALETTE) { metadata.bKGD_colorType = PNG_COLOR_PALETTE; metadata.bKGD_index = stream.readUnsignedByte(); } else if (metadata.IHDR_colorType == PNG_COLOR_GRAY || metadata.IHDR_colorType == PNG_COLOR_GRAY_ALPHA) { metadata.bKGD_colorType = PNG_COLOR_GRAY; metadata.bKGD_gray = stream.readUnsignedShort(); } else { // RGB or RGB_ALPHA metadata.bKGD_colorType = PNG_COLOR_RGB; metadata.bKGD_red = stream.readUnsignedShort(); metadata.bKGD_green = stream.readUnsignedShort(); metadata.bKGD_blue = stream.readUnsignedShort(); } metadata.bKGD_present = true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -