// TODO: Candidate util method private static long skipToEOF(final ImageInputStream stream) throws IOException { long length = stream.length(); if (length > 0) { // Known length, skip there and we're done. stream.seek(length); } else { // Otherwise, seek to EOF the hard way. // First, store stream position... long pos = stream.getStreamPosition(); // ...skip 1k blocks until we're passed EOF... while (stream.skipBytes(1024l) > 0) { if (stream.read() == -1) { break; } pos = stream.getStreamPosition(); } // ...go back to last known pos... stream.seek(pos); // ...finally seek until EOF one byte at a time. Done. while (stream.read() != -1) {} } return stream.getStreamPosition(); }
public boolean canDecodeInput(Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } ImageInputStream stream = (ImageInputStream) source; stream.mark(); int type = stream.readByte(); // TypeField byte fixHeaderField = stream.readByte(); int width = ImageUtil.readMultiByteInteger(stream); int height = ImageUtil.readMultiByteInteger(stream); long remainingBytes = stream.length() - stream.getStreamPosition(); stream.reset(); // check WBMP "header" if (type != 0 || fixHeaderField != 0) { // while WBMP reader does not support ext WBMP headers return false; } // check image dimension if (width <= 0 || height <= 0) { return false; } long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1); return (remainingBytes == scanSize * height); }
private void readFile() { // Do not allow this header to be read more than once. if (readFile) return; // Make sure that the application has set the input source. if (stream == null) throw new IllegalStateException("No input stream!"); // Read the header. decoder = new JBIG2Decoder(); try { byte[] data; int size = (int) stream.length(); if (size == -1) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] temp = new byte[8192]; for (int len = 0; (len = stream.read(temp)) > 0; ) { bos.write(temp, 0, len); } bos.close(); data = bos.toByteArray(); } else { data = new byte[size]; stream.readFully(data); } decoder.decodeJBIG2(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JBIG2Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } readFile = true; }
private long getTileOrStripByteCount(int tileIndex) throws IOException { TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS); if (f == null) { f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS); } if (f == null) { f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); } long tileOrStripByteCount; if (f != null) { tileOrStripByteCount = f.getAsLong(tileIndex); } else { processWarningOccurred( "TIFF directory contains neither StripByteCounts nor TileByteCounts field: attempting to calculate from strip or tile width and height."); // Initialize to number of bytes per strip or tile assuming // no compression. int bitsPerPixel = bitsPerSample[0]; for (int i = 1; i < samplesPerPixel; i++) { bitsPerPixel += bitsPerSample[i]; } int bytesPerRow = (getTileOrStripWidth() * bitsPerPixel + 7) / 8; tileOrStripByteCount = bytesPerRow * getTileOrStripHeight(); // Clamp to end of stream if possible. long streamLength = stream.length(); if (streamLength != -1) { tileOrStripByteCount = Math.min(tileOrStripByteCount, streamLength - getTileOrStripOffset(tileIndex)); } else { processWarningOccurred( "Stream length is unknown: cannot clamp estimated strip or tile byte count to EOF."); } } return tileOrStripByteCount; }
@Override public long length() throws IOException { return iis.length(); }
private void readHeader() throws IOException { if (gotHeader) { iis.seek(128); return; } metadata = new PCXMetadata(); manufacturer = iis.readByte(); // manufacturer if (manufacturer != MANUFACTURER) throw new IllegalStateException("image is not a PCX file"); metadata.version = iis.readByte(); // version encoding = iis.readByte(); // encoding if (encoding != ENCODING) throw new IllegalStateException("image is not a PCX file, invalid encoding " + encoding); metadata.bitsPerPixel = iis.readByte(); metadata.xmin = iis.readShort(); metadata.ymin = iis.readShort(); xmax = iis.readShort(); ymax = iis.readShort(); metadata.hdpi = iis.readShort(); metadata.vdpi = iis.readShort(); iis.readFully(smallPalette); iis.readByte(); // reserved colorPlanes = iis.readByte(); bytesPerLine = iis.readShort(); paletteType = iis.readShort(); metadata.hsize = iis.readShort(); metadata.vsize = iis.readShort(); iis.skipBytes(54); // skip filler width = xmax - metadata.xmin + 1; height = ymax - metadata.ymin + 1; if (colorPlanes == 1) { if (paletteType == PALETTE_GRAYSCALE) { ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY); int[] nBits = {8}; colorModel = new ComponentColorModel( cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, new int[] {0}); } else { if (metadata.bitsPerPixel == 8) { // read palette from end of file, then reset back to image data iis.mark(); if (iis.length() == -1) { // read until eof, and work backwards while (iis.read() != -1) ; iis.seek(iis.getStreamPosition() - 256 * 3 - 1); } else { iis.seek(iis.length() - 256 * 3 - 1); } int palletteMagic = iis.read(); if (palletteMagic != 12) processWarningOccurred( "Expected palette magic number 12; instead read " + palletteMagic + " from this image."); iis.readFully(largePalette); iis.reset(); colorModel = new IndexColorModel(metadata.bitsPerPixel, 256, largePalette, 0, false); sampleModel = colorModel.createCompatibleSampleModel(width, height); } else { int msize = metadata.bitsPerPixel == 1 ? 2 : 16; colorModel = new IndexColorModel(metadata.bitsPerPixel, msize, smallPalette, 0, false); sampleModel = colorModel.createCompatibleSampleModel(width, height); } } } else { ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); int[] nBits = {8, 8, 8}; colorModel = new ComponentColorModel( cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); sampleModel = new ComponentSampleModel( DataBuffer.TYPE_BYTE, width, height, 1, width * colorPlanes, new int[] {0, width, width * 2}); } originalSampleModel = sampleModel; originalColorModel = colorModel; gotHeader = true; }
private void decodeTile(int ti, int tj, int band) throws IOException { if (DEBUG) { System.out.println("decodeTile(" + ti + "," + tj + "," + band + ")"); } // Compute the region covered by the strip or tile Rectangle tileRect = new Rectangle( ti * tileOrStripWidth, tj * tileOrStripHeight, tileOrStripWidth, tileOrStripHeight); // Clip against the image bounds if the image is not tiled. If it // is tiled, the tile may legally extend beyond the image bounds. if (!isImageTiled(currIndex)) { tileRect = tileRect.intersection(new Rectangle(0, 0, width, height)); } // Return if the intersection is empty. if (tileRect.width <= 0 || tileRect.height <= 0) { return; } int srcMinX = tileRect.x; int srcMinY = tileRect.y; int srcWidth = tileRect.width; int srcHeight = tileRect.height; // Determine dest region that can be derived from the // source region dstMinX = iceil(srcMinX - sourceXOffset, srcXSubsampling); int dstMaxX = ifloor(srcMinX + srcWidth - 1 - sourceXOffset, srcXSubsampling); dstMinY = iceil(srcMinY - sourceYOffset, srcYSubsampling); int dstMaxY = ifloor(srcMinY + srcHeight - 1 - sourceYOffset, srcYSubsampling); dstWidth = dstMaxX - dstMinX + 1; dstHeight = dstMaxY - dstMinY + 1; dstMinX += dstXOffset; dstMinY += dstYOffset; // Clip against image bounds Rectangle dstRect = new Rectangle( dstMinX, dstMinY, dstWidth, dstHeight); dstRect = dstRect.intersection(theImage.getRaster().getBounds()); dstMinX = dstRect.x; dstMinY = dstRect.y; dstWidth = dstRect.width; dstHeight = dstRect.height; if (dstWidth <= 0 || dstHeight <= 0) { return; } // Backwards map dest region to source to determine // active source region int activeSrcMinX = (dstMinX - dstXOffset) * srcXSubsampling + sourceXOffset; int sxmax = (dstMinX + dstWidth - 1 - dstXOffset) * srcXSubsampling + sourceXOffset; int activeSrcWidth = sxmax - activeSrcMinX + 1; int activeSrcMinY = (dstMinY - dstYOffset) * srcYSubsampling + sourceYOffset; int symax = (dstMinY + dstHeight - 1 - dstYOffset) * srcYSubsampling + sourceYOffset; int activeSrcHeight = symax - activeSrcMinY + 1; decompressor.setSrcMinX(srcMinX); decompressor.setSrcMinY(srcMinY); decompressor.setSrcWidth(srcWidth); decompressor.setSrcHeight(srcHeight); decompressor.setDstMinX(dstMinX); decompressor.setDstMinY(dstMinY); decompressor.setDstWidth(dstWidth); decompressor.setDstHeight(dstHeight); decompressor.setActiveSrcMinX(activeSrcMinX); decompressor.setActiveSrcMinY(activeSrcMinY); decompressor.setActiveSrcWidth(activeSrcWidth); decompressor.setActiveSrcHeight(activeSrcHeight); int tileIndex = tj * tilesAcross + ti; if (planarConfiguration == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { tileIndex += band * tilesAcross * tilesDown; } long offset = getTileOrStripOffset(tileIndex); long byteCount = getTileOrStripByteCount(tileIndex); // // Attempt to handle truncated streams, i.e., where reading the // compressed strip or tile would result in an EOFException. The // number of bytes to read is clamped to the number available // from the stream starting at the indicated position in the hope // that the decompressor will handle it. // long streamLength = stream.length(); if (streamLength > 0 && offset + byteCount > streamLength) { processWarningOccurred("Attempting to process truncated stream."); if (Math.max(byteCount = streamLength - offset, 0) == 0) { processWarningOccurred("No bytes in strip/tile: skipping."); return; } } decompressor.setStream(stream); decompressor.setOffset(offset); decompressor.setByteCount((int) byteCount); decompressor.beginDecoding(); stream.mark(); decompressor.decode(); stream.reset(); }
/** Reads the header. Does nothing if the header has already been loaded. */ private void readHeader() throws IOException { if (numImages == -1) { ImageInputStream in = (ImageInputStream) getInput(); in.seek(0); er = new EXIFReader(in); er.setFirstImageOnly(false); er.read(); // Get some information that is easy to obtain through a map { HashMap<TIFFTag, TIFFField> m = er.getMetaDataMap(); TIFFField mde; if ((mde = m.get(MPFTagSet.get(MPFTagSet.TAG_NumberOfImages))) != null) { numImages = ((Number) mde.getData()).intValue(); } else { numImages = 1; } if ((mde = m.get(EXIFTagSet.PixelXDimension)) != null) { width = ((Number) mde.getData()).intValue(); } if ((mde = m.get(EXIFTagSet.PixelYDimension)) != null) { height = ((Number) mde.getData()).intValue(); } } imageOffsets = new long[numImages]; imageLengths = new long[numImages]; if (numImages == 1) { imageOffsets[0] = 0; imageLengths[0] = in.length(); } // Get now at the tough part int index = 0; for (Iterator<TIFFNode> e = er.getMetaDataTree().preorderIterator(); e.hasNext(); ) { TIFFNode n = e.next(); if (n instanceof TIFFDirectory) { TIFFDirectory dir = (TIFFDirectory) n; // System.out.println("dir:" + dir.getName()); if (dir.getName() != null && dir.getName().equals("MPEntry")) { long dirOffset = dir.getFileSegments().get(0).getOffset(); TIFFField offsetField = dir.getField(MPEntryTagSet.IndividualImageDataOffset); TIFFField lengthField = dir.getField(MPEntryTagSet.IndividualImageSize); if (offsetField != null && lengthField != null) { long dataOffset = (Long) offsetField.getData(); imageOffsets[index] = dataOffset == 0 ? 0 : dirOffset + dataOffset; imageLengths[index] = (Long) lengthField.getData(); index++; } } } } // Store metadata for later access String formatName = "com_sun_media_imageio_plugins_tiff_image_1.0"; imageMetadata = new IIOMetadata[numImages]; for (int i = 0; i < numImages; i++) { imageMetadata[i] = new DefaultIIOMetadata(formatName, er.getIIOMetadataTree(formatName, i)); } in.seek(0); } }