public void write(final ImageOutputStream ios, final long ifdOffset, final long nextIfdOffset) throws IOException { Guardian.assertGreaterThan("ifdOffset", ifdOffset, -1); computeOffsets(ifdOffset); ios.seek(ifdOffset); final TiffDirectoryEntry[] entries = entrySet.getEntries(); new TiffShort(entries.length).write(ios); long entryPosition = ios.getStreamPosition(); for (TiffDirectoryEntry entry : entries) { ios.seek(entryPosition); entry.write(ios); entryPosition += TiffDirectoryEntry.BYTES_PER_ENTRY; } writeNextIfdOffset(ios, ifdOffset, nextIfdOffset); }
/** * Gets pixel data of an <code>IIOImage</code> object. * * @param image an <code>IIOImage</code> object * @return a byte buffer of pixel data * @throws Exception */ public static ByteBuffer getImageByteBuffer(IIOImage image) throws IOException { // Set up the writeParam TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US); tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED); // Get tif writer and set output to file Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(TIFF_FORMAT); ImageWriter writer = writers.next(); if (writer == null) { throw new RuntimeException( "Need to install JAI Image I/O package.\nhttps://jai-imageio.dev.java.net"); } // Get the stream metadata IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(tiffWriteParam); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream); writer.setOutput(ios); writer.write( streamMetadata, new IIOImage(image.getRenderedImage(), null, null), tiffWriteParam); // writer.write(image.getRenderedImage()); writer.dispose(); // ImageIO.write(image.getRenderedImage(), "tiff", ios); // this can be used in lieu of // writer ios.seek(0); BufferedImage bi = ImageIO.read(ios); return convertImageData(bi); }
/** * Gets pixel data of an <code>IIOImage</code> object. * * @param oimage an <code>IIOImage</code> object * @return a byte buffer of pixel data * @throws Exception */ public static ByteBuffer getImageByteBuffer(BufferedImage oimage) throws IOException { // Get tif writer and set output to file ImageWriter writer = new TIFFImageWriterSpi().createWriterInstance(); // Set up the writeParam // We are using the old JAI ImageIO plugin, because for some reason, OCR don't work with // TwelveMonkeys' plugin ImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.US); tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED); // Get the stream metadata IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(tiffWriteParam); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream); writer.setOutput(ios); writer.write(streamMetadata, new IIOImage(oimage, null, null), tiffWriteParam); writer.dispose(); // Read the writed image ios.seek(0); ImageReader reader = new TIFFImageReaderSpi().createReaderInstance(); ImageReadParam param = reader.getDefaultReadParam(); reader.setInput(ios, true, true); BufferedImage bi; try { bi = reader.read(0, param); } finally { reader.dispose(); ios.close(); } return convertImageData(bi); }
private long available() throws IOException { checkClosed(); long pos = out.getStreamPosition(); if (pos < offset) { out.seek(offset); pos = offset; } return offset + out.length() - pos; }
public SubImageOutputStream( ImageOutputStream out, long offset, ByteOrder bo, boolean forwardFlushAndClose) throws IOException { this.out = out; this.offset = offset; this.forwardFlushAndClose = forwardFlushAndClose; setByteOrder(bo); out.seek(offset); }
/** * Writes raster data from the given in-memory source buffer into the data sink specified by the * given source band and region. * * <p> * * <h3>Source band</h3> * * The source band is used to identify the data sink in which this method transfers the sample * values given in the source buffer. The method does not modify the pixel data of the given * source band at all. * * <p> * * <h3>Source buffer</h3> * * The first element of the source buffer corresponds to the given <code>sourceOffsetX</code> and * <code>sourceOffsetY</code> of the source region. These parameters are an offset within the * band's raster data and <b>not</b> an offset within the source buffer.<br> * The number of elements in the buffer must be exactly be <code>sourceWidth * sourceHeight</code> * . The pixel values to be writte are considered to be stored in line-by-line order, so the * raster X co-ordinate varies faster than the Y. * * <p> * * <h3>Source region</h3> * * The given destination region specified by the <code>sourceOffsetX</code>, <code>sourceOffsetY * </code>, <code>sourceWidth</code> and <code>sourceHeight</code> parameters is given in the * source band's raster co-ordinates. These co-ordinates are identical with the destination raster * co-ordinates since product writers do not support spectral or spatial subsets. * * @param sourceBand the source band which identifies the data sink to which to write the sample * values * @param regionData the data buffer which provides the sample values to be written * @param regionX the X-offset in the band's raster co-ordinates * @param regionY the Y-offset in the band's raster co-ordinates * @param regionWidth the width of region to be written given in the band's raster co-ordinates * @param regionHeight the height of region to be written given in the band's raster co-ordinates * @throws java.io.IOException if an I/O error occurs * @throws IllegalArgumentException if the number of elements source buffer not equals <code> * sourceWidth * * sourceHeight</code> or the source region is out of the band's * raster * @see Band#getRasterWidth() * @see Band#getRasterHeight() */ public void writeBandRasterData( final Band sourceBand, final int regionX, final int regionY, final int regionWidth, final int regionHeight, final ProductData regionData, ProgressMonitor pm) throws IOException { if (!tempProduct.containsBand(sourceBand.getName())) { throw new IllegalArgumentException( "'" + sourceBand.getName() + "' is not a band of the product"); } final int bandDataType = ifd.getBandDataType(); final int stripIndex = getStripIndex(sourceBand); final TiffValue[] offsetValues = ifd.getEntry(TiffTag.STRIP_OFFSETS).getValues(); final long stripOffset = ((TiffLong) offsetValues[stripIndex]).getValue(); final TiffValue[] bitsPerSampleValues = ifd.getEntry(TiffTag.BITS_PER_SAMPLE).getValues(); final long elemSize = ((TiffShort) bitsPerSampleValues[stripIndex]).getValue() / 8; final long sourceWidthBytes = sourceBand.getSceneRasterWidth() * elemSize; final long regionOffsetXInBytes = regionX * elemSize; final long pixelOffset = sourceWidthBytes * regionY + regionOffsetXInBytes; final long startOffset = stripOffset + pixelOffset; pm.beginTask("Writing band '" + sourceBand.getName() + "'...", regionHeight); try { for (int y = 0; y < regionHeight; y++) { ios.seek(startOffset + y * sourceWidthBytes); final int stride = y * regionWidth; if (bandDataType == ProductData.TYPE_UINT8) { final byte[] data = new byte[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (byte) regionData.getElemUIntAt(stride + x); } ios.write(data); } else if (bandDataType == ProductData.TYPE_INT8) { final byte[] data = new byte[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (byte) regionData.getElemIntAt(stride + x); } ios.write(data); } else if (bandDataType == ProductData.TYPE_UINT16) { final short[] data = new short[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (short) regionData.getElemUIntAt(stride + x); } ios.writeShorts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_INT16) { final short[] data = new short[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (short) regionData.getElemIntAt(stride + x); } ios.writeShorts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_UINT32) { final int[] data = new int[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (int) regionData.getElemUIntAt(stride + x); } ios.writeInts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_INT32) { final int[] data = new int[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = regionData.getElemIntAt(stride + x); } ios.writeInts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_FLOAT32) { final float[] data = new float[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = regionData.getElemFloatAt(stride + x); } ios.writeFloats(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_FLOAT64) { final double[] data = new double[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = regionData.getElemDoubleAt(stride + x); } ios.writeDoubles(data, 0, regionWidth); } pm.worked(1); } } finally { pm.done(); } }
private void writeNextIfdOffset( final ImageOutputStream ios, final long ifdOffset, final long nextIfdOffset) throws IOException { ios.seek(getPosForNextIfdOffset(ifdOffset)); new TiffLong(nextIfdOffset).write(ios); }
@Override public void seek(long pos) throws IOException { out.seek(pos + offset); length = Math.max(pos - offset + 1, length); }
public void writeToStream(ImageOutputStream stream, final boolean isBTIFF) throws IOException { long nextSpace; if (!isBTIFF) { int numFields = getNumTIFFFields(); stream.writeShort(numFields); nextSpace = stream.getStreamPosition() + 12 * numFields + 4; } else { long numFields = getNumTIFFFields(); stream.writeLong(numFields); nextSpace = stream.getStreamPosition() + 20 * numFields + 8; } Iterator iter = iterator(); while (iter.hasNext()) { TIFFField f = (TIFFField) iter.next(); TIFFTag tag = f.getTag(); int type = f.getType(); int count = f.getCount(); // Hack to deal with unknown tags if (type == 0) { type = TIFFTag.TIFF_UNDEFINED; } int size = count * TIFFTag.getSizeOfType(type); if (type == TIFFTag.TIFF_ASCII) { int chars = 0; for (int i = 0; i < count; i++) { chars += f.getAsString(i).length() + 1; } count = chars; size = count; } int tagNumber = f.getTagNumber(); stream.writeShort(tagNumber); stream.writeShort(type); if (isBTIFF) { stream.writeLong(count); stream.writeLong(0); stream.mark(); // Mark beginning of next field stream.skipBytes(-8); } else { stream.writeInt(count); stream.writeInt(0); stream.mark(); // Mark beginning of next field stream.skipBytes(-4); } long pos; if (!isBTIFF) { if (size > 4 || tag.isIFDPointer()) { // Ensure IFD or value is written on a word boundary nextSpace = (nextSpace + 3) & ~0x3; stream.writeInt((int) nextSpace); stream.seek(nextSpace); pos = nextSpace; if (tag.isIFDPointer()) { TIFFIFD subIFD = (TIFFIFD) f.getData(); subIFD.writeToStream(stream, isBTIFF); nextSpace = subIFD.lastPosition; } else { writeTIFFFieldToStream(f, stream); nextSpace = stream.getStreamPosition(); } } else { pos = stream.getStreamPosition(); writeTIFFFieldToStream(f, stream); } } else { if (size > 8 || tag.isIFDPointer()) { // Ensure IFD or value is written on a Long boundary nextSpace = (nextSpace + 7) & ~0x7; stream.writeLong(nextSpace); stream.seek(nextSpace); pos = nextSpace; if (tag.isIFDPointer()) { TIFFIFD subIFD = (TIFFIFD) f.getData(); subIFD.writeToStream(stream, isBTIFF); nextSpace = subIFD.lastPosition; } else { writeTIFFFieldToStream(f, stream); nextSpace = stream.getStreamPosition(); } } else { pos = stream.getStreamPosition(); writeTIFFFieldToStream(f, stream); } } // If we are writing the data for the // StripByteCounts, TileByteCounts, StripOffsets, // TileOffsets, JPEGInterchangeFormat, or // JPEGInterchangeFormatLength fields, record the current stream // position for backpatching if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = pos; } else if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = pos; } stream.reset(); // Go to marked position of next field } this.lastPosition = nextSpace; }