📄 gifimagereader.java
字号:
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 = (gcePackedFields & 0x1) != 0; imageMetadata.delayTime = stream.readUnsignedShort(); imageMetadata.transparentColorIndex = stream.readUnsignedByte(); int terminator = stream.readUnsignedByte(); } else if (label == 0x1) { // Plain text extension int length = stream.readUnsignedByte(); imageMetadata.hasPlainTextExtension = true; imageMetadata.textGridLeft = stream.readUnsignedShort(); imageMetadata.textGridTop = stream.readUnsignedShort(); imageMetadata.textGridWidth = stream.readUnsignedShort(); imageMetadata.textGridHeight = stream.readUnsignedShort(); imageMetadata.characterCellWidth = stream.readUnsignedByte(); imageMetadata.characterCellHeight = stream.readUnsignedByte(); imageMetadata.textForegroundColor = stream.readUnsignedByte(); imageMetadata.textBackgroundColor = stream.readUnsignedByte(); imageMetadata.text = concatenateBlocks(); } else if (label == 0xfe) { // Comment extension byte[] comment = concatenateBlocks(); if (imageMetadata.comments == null) { imageMetadata.comments = new ArrayList(); } imageMetadata.comments.add(comment); } else if (label == 0xff) { // Application extension int blockSize = stream.readUnsignedByte(); byte[] applicationID = new byte[8]; stream.readFully(applicationID); byte[] authCode = new byte[3]; stream.readFully(authCode); byte[] applicationData = concatenateBlocks(); // Init lists if necessary if (imageMetadata.applicationIDs == null) { imageMetadata.applicationIDs = new ArrayList(); imageMetadata.authenticationCodes = new ArrayList(); imageMetadata.applicationData = new ArrayList(); } imageMetadata.applicationIDs.add(applicationID); imageMetadata.authenticationCodes.add(authCode); imageMetadata.applicationData.add(applicationData); } else { // Skip over unknown extension blocks int length = 0; do { length = stream.readUnsignedByte(); stream.skipBytes(length); } while (length > 0); } } else if (blockType == 0x3b) { // Trailer throw new IndexOutOfBoundsException ("Attempt to read past end of image sequence!"); } else { throw new IIOException("Unexpected block type " + blockType + "!"); } } } catch (IIOException iioe) { throw iioe; } catch (IOException ioe) { throw new IIOException("I/O error reading image metadata!", ioe); } } // Helper for protected computeUpdatedPixels method private static void computeUpdatedPixels(int sourceOffset, int sourceExtent, int destinationOffset, int dstMin, int dstMax, int sourceSubsampling, int passStart, int passExtent, int passPeriod, int[] vals, int offset) { // We need to satisfy the congruences: // dst = destinationOffset + (src - sourceOffset)/sourceSubsampling // // src - passStart == 0 (mod passPeriod) // src - sourceOffset == 0 (mod sourceSubsampling) // // subject to the inequalities: // // src >= passStart // src < passStart + passExtent // src >= sourceOffset // src < sourceOffset + sourceExtent // dst >= dstMin // dst <= dstmax // // where // // dst = destinationOffset + (src - sourceOffset)/sourceSubsampling // // For now we use a brute-force approach although we could
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -