📄 gifimagereader.java
字号:
} // Fill in the entire table for robustness against // out-of-sequence codes. for (int i = numEntries; i < 4096; i++) { prefix[i] = -1; length[i] = 1; } // tableIndex = numEntries + 2; // codeSize = initCodeSize + 1; // codeMask = (1 << codeSize) - 1; } Rectangle sourceRegion; int sourceXSubsampling; int sourceYSubsampling; int sourceMinProgressivePass; int sourceMaxProgressivePass; Point destinationOffset; Rectangle destinationRegion; // Used only if IIOReadUpdateListeners are present int updateMinY; int updateYStep; boolean decodeThisRow = true; int destY = 0; byte[] rowBuf; private void outputRow() { // Clip against ImageReadParam int width = Math.min(sourceRegion.width, destinationRegion.width*sourceXSubsampling); int destX = destinationRegion.x; if (sourceXSubsampling == 1) { theTile.setDataElements(destX, destY, width, 1, rowBuf); } else { for (int x = 0; x < width; x += sourceXSubsampling, destX++) { theTile.setSample(destX, destY, 0, rowBuf[x] & 0xff); } } // Update IIOReadUpdateListeners, if any if (updateListeners != null) { int[] bands = { 0 }; // updateYStep will have been initialized if // updateListeners is non-null processImageUpdate(theImage, destX, destY, width, 1, 1, updateYStep, bands); } } private void computeDecodeThisRow() { this.decodeThisRow = (destY < destinationRegion.y + destinationRegion.height) && (streamY >= sourceRegion.y) && (streamY < sourceRegion.y + sourceRegion.height) && (((streamY - sourceRegion.y) % sourceYSubsampling) == 0); } private void outputPixels(byte[] string, int len) { if (interlacePass < sourceMinProgressivePass || interlacePass > sourceMaxProgressivePass) { return; } for (int i = 0; i < len; i++) { if (streamX >= sourceRegion.x) { rowBuf[streamX - sourceRegion.x] = string[i]; } // Process end-of-row ++streamX; if (streamX == width) { // Update IIOReadProgressListeners ++rowsDone; processImageProgress(100.0F*rowsDone/height); if (decodeThisRow) { outputRow(); } streamX = 0; if (imageMetadata.interlaceFlag) { streamY += interlaceIncrement[interlacePass]; if (streamY >= height) { // Inform IIOReadUpdateListeners of end of pass if (updateListeners != null) { processPassComplete(theImage); } ++interlacePass; if (interlacePass > sourceMaxProgressivePass) { return; } streamY = interlaceOffset[interlacePass]; startPass(interlacePass); } } else { ++streamY; } // Determine whether pixels from this row will // be written to the destination this.destY = destinationRegion.y + (streamY - sourceRegion.y)/sourceYSubsampling; computeDecodeThisRow(); } } } // END LZW STUFF private void readHeader() throws IIOException { if (gotHeader) { return; } if (stream == null) { throw new IllegalStateException("Input not set!"); } // Create an object to store the stream metadata this.streamMetadata = new GIFStreamMetadata(); try { stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); byte[] signature = new byte[6]; stream.readFully(signature); StringBuffer version = new StringBuffer(3); version.append((char)signature[3]); version.append((char)signature[4]); version.append((char)signature[5]); streamMetadata.version = version.toString(); streamMetadata.logicalScreenWidth = stream.readUnsignedShort(); streamMetadata.logicalScreenHeight = stream.readUnsignedShort(); int packedFields = stream.readUnsignedByte(); boolean globalColorTableFlag = (packedFields & 0x80) != 0; streamMetadata.colorResolution = ((packedFields >> 4) & 0x7) + 1; streamMetadata.sortFlag = (packedFields & 0x8) != 0; int numGCTEntries = 1 << ((packedFields & 0x7) + 1); streamMetadata.backgroundColorIndex = stream.readUnsignedByte(); streamMetadata.pixelAspectRatio = stream.readUnsignedByte(); if (globalColorTableFlag) { streamMetadata.globalColorTable = new byte[3*numGCTEntries]; stream.readFully(streamMetadata.globalColorTable); } else { streamMetadata.globalColorTable = null; } // Found position of metadata for image 0 imageStartPosition.add(new Long(stream.getStreamPosition())); } catch (IOException e) { throw new IIOException("I/O error reading header!", e); } gotHeader = true; } private boolean skipImage() throws IIOException { // Stream must be at the beginning of an image descriptor // upon exit try { while (true) { int blockType = stream.readUnsignedByte(); if (blockType == 0x2c) { stream.skipBytes(8); int packedFields = stream.readUnsignedByte(); if ((packedFields & 0x80) != 0) { // Skip color table if any int bits = (packedFields & 0x7) + 1; stream.skipBytes(3*(1 << bits)); } stream.skipBytes(1); int length = 0; do { length = stream.readUnsignedByte(); stream.skipBytes(length); } while (length > 0); return true; } else if (blockType == 0x3b) { return false; } else if (blockType == 0x21) { int label = stream.readUnsignedByte(); int length = 0; do { length = stream.readUnsignedByte(); stream.skipBytes(length); } while (length > 0); } else if (blockType == 0x0) { // EOF return false; } else { int length = 0; do { length = stream.readUnsignedByte(); stream.skipBytes(length); } while (length > 0); } } } catch (EOFException e) { return false; } catch (IOException e) { throw new IIOException("I/O error locating image!", e); } } private int locateImage(int imageIndex) throws IIOException { readHeader(); try { // Find closest known index int index = Math.min(imageIndex, imageStartPosition.size() - 1); // Seek to that position Long l = (Long)imageStartPosition.get(index); stream.seek(l.longValue()); // Skip images until at desired index or last image found while (index < imageIndex) { if (!skipImage()) { --index; return index; } Long l1 = new Long(stream.getStreamPosition()); imageStartPosition.add(l1); ++index; } } catch (IOException e) { throw new IIOException("Couldn't seek!", e); } if (currIndex != imageIndex) { imageMetadata = null; } currIndex = imageIndex; return imageIndex; } // Read blocks of 1-255 bytes, stop at a 0-length block private byte[] concatenateBlocks() throws IOException { byte[] data = new byte[0]; while (true) { int length = stream.readUnsignedByte(); if (length == 0) { break; } byte[] newData = new byte[data.length + length]; System.arraycopy(data, 0, newData, 0, data.length); stream.readFully(newData, data.length, length); data = newData; } return data; } // Stream must be positioned at start of metadata for 'currIndex' private void readMetadata() throws IIOException { if (stream == null) { throw new IllegalStateException("Input not set!"); } try { // Create an object to store the image metadata this.imageMetadata = new GIFImageMetadata(); long startPosition = stream.getStreamPosition(); while (true) { int blockType = stream.readUnsignedByte(); if (blockType == 0x2c) { // Image Descriptor imageMetadata.imageLeftPosition = stream.readUnsignedShort(); imageMetadata.imageTopPosition = stream.readUnsignedShort(); imageMetadata.imageWidth = stream.readUnsignedShort(); imageMetadata.imageHeight = stream.readUnsignedShort(); int idPackedFields = stream.readUnsignedByte(); boolean localColorTableFlag = (idPackedFields & 0x80) != 0; imageMetadata.interlaceFlag = (idPackedFields & 0x40) != 0; imageMetadata.sortFlag = (idPackedFields & 0x20) != 0; int numLCTEntries = 1 << ((idPackedFields & 0x7) + 1); if (localColorTableFlag) { // Read color table if any imageMetadata.localColorTable = new byte[3*numLCTEntries]; stream.readFully(imageMetadata.localColorTable); } else { imageMetadata.localColorTable = null; } // Record length of this metadata block this.imageMetadataLength = (int)(stream.getStreamPosition() - startPosition); // Now positioned at start of LZW-compressed pixels return; } else if (blockType == 0x21) { // Extension block int label = stream.readUnsignedByte(); if (label == 0xf9) { // Graphics Control Extension int gceLength = stream.readUnsignedByte(); // 4 int gcePackedFields = stream.readUnsignedByte(); imageMetadata.disposalMethod = (gcePackedFields >> 2) & 0x3; imageMetadata.userInputFlag = (gcePackedFields & 0x2) != 0; imageMetadata.transparentColorFlag =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -