/** * Writes the data for this segment to the stream in valid JPEG format. The length written takes * the thumbnail width and height into account. If necessary, the thumbnail is clipped to 255 x * 255 and a warning is sent to the writer argument. Progress updates are sent to the writer * argument. */ void write(ImageOutputStream ios, BufferedImage thumb, JPEGImageWriter writer) throws IOException { int thumbWidth = 0; int thumbHeight = 0; int thumbLength = 0; int[] thumbData = null; if (thumb != null) { // Clip if necessary and get the data in thumbData thumbWidth = thumb.getWidth(); thumbHeight = thumb.getHeight(); if ((thumbWidth > MAX_THUMB_WIDTH) || (thumbHeight > MAX_THUMB_HEIGHT)) { writer.warningOccurred(JPEGImageWriter.WARNING_THUMB_CLIPPED); } thumbWidth = Math.min(thumbWidth, MAX_THUMB_WIDTH); thumbHeight = Math.min(thumbHeight, MAX_THUMB_HEIGHT); thumbData = thumb.getRaster().getPixels(0, 0, thumbWidth, thumbHeight, (int[]) null); thumbLength = thumbData.length; } length = DATA_SIZE + LENGTH_SIZE + thumbLength; writeTag(ios); byte[] id = {0x4A, 0x46, 0x49, 0x46, 0x00}; ios.write(id); ios.write(majorVersion); ios.write(minorVersion); ios.write(resUnits); write2bytes(ios, Xdensity); write2bytes(ios, Ydensity); ios.write(thumbWidth); ios.write(thumbHeight); if (thumbData != null) { writer.thumbnailStarted(0); writeThumbnailData(ios, thumbData, writer); writer.thumbnailComplete(); } }
private void writeGraphicControlExtension( int disposalMethod, boolean userInputFlag, boolean transparentColorFlag, int delayTime, int transparentColorIndex) throws IOException { try { stream.write(0x21); stream.write(0xf9); stream.write(4); int packedFields = (disposalMethod & 0x3) << 2; if (userInputFlag) { packedFields |= 0x2; } if (transparentColorFlag) { packedFields |= 0x1; } stream.write(packedFields); stream.writeShort((short) delayTime); stream.write(transparentColorIndex); stream.write(0x00); } catch (IOException e) { throw new IIOException("I/O error writing Graphic Control Extension!", e); } }
void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { length = LENGTH_SIZE + DATA_SIZE + thumb.getLength(); writeTag(ios); byte[] id = {0x4A, 0x46, 0x58, 0x58, 0x00}; ios.write(id); ios.write(code); thumb.write(ios, writer); }
void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { if ((thumbWidth > MAX_THUMB_WIDTH) || (thumbHeight > MAX_THUMB_HEIGHT)) { writer.warningOccurred(JPEGImageWriter.WARNING_THUMB_CLIPPED); } thumbWidth = Math.min(thumbWidth, MAX_THUMB_WIDTH); thumbHeight = Math.min(thumbHeight, MAX_THUMB_HEIGHT); ios.write(thumbWidth); ios.write(thumbHeight); }
public void writeBits(int bits, int numbits) throws IOException { int bitsWritten = 0; int numBytes = 255; // gif block count do { // This handles the GIF block count stuff if ((index_ == 254 && bitsLeft_ == 0) || index_ > 254) { if (blocks_) output_.write(numBytes); output_.write(buffer_, 0, numBytes); buffer_[0] = 0; index_ = 0; bitsLeft_ = 8; } if (numbits <= bitsLeft_) // bits contents fit in current index byte { if (blocks_) // GIF { buffer_[index_] |= (bits & ((1 << numbits) - 1)) << (8 - bitsLeft_); bitsWritten += numbits; bitsLeft_ -= numbits; numbits = 0; } else { buffer_[index_] |= (bits & ((1 << numbits) - 1)) << (bitsLeft_ - numbits); bitsWritten += numbits; bitsLeft_ -= numbits; numbits = 0; } } else // bits overflow from current byte to next. { if (blocks_) // GIF { // if bits > space left in current byte then the lowest order bits // of code are taken and put in current byte and rest put in next. buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) << (8 - bitsLeft_); bitsWritten += bitsLeft_; bits >>= bitsLeft_; numbits -= bitsLeft_; buffer_[++index_] = 0; bitsLeft_ = 8; } else { // if bits > space left in current byte then the highest order bits // of code are taken and put in current byte and rest put in next. // at highest order bit location !! int topbits = (bits >>> (numbits - bitsLeft_)) & ((1 << bitsLeft_) - 1); buffer_[index_] |= topbits; numbits -= bitsLeft_; // ok this many bits gone off the top bitsWritten += bitsLeft_; buffer_[++index_] = 0; // next index bitsLeft_ = 8; } } } while (numbits != 0); }
public void flush() throws IOException { int numBytes = index_ + (bitsLeft_ == 8 ? 0 : 1); if (numBytes > 0) { if (blocks_) output_.write(numBytes); output_.write(buffer_, 0, numBytes); buffer_[0] = 0; index_ = 0; bitsLeft_ = 8; } }
private void writeBlocks(byte[] data) throws IOException { if (data != null && data.length > 0) { int offset = 0; while (offset < data.length) { int len = Math.min(data.length - offset, 255); stream.write(len); stream.write(data, offset, len); offset += len; } } }
private void writeCommentExtension(GIFWritableImageMetadata im) throws IOException { if (im.comments != null) { try { Iterator iter = im.comments.iterator(); while (iter.hasNext()) { stream.write(0x21); stream.write(0xfe); writeBlocks((byte[]) iter.next()); stream.write(0x00); } } catch (IOException e) { throw new IIOException("I/O error writing Comment Extension!", e); } } }
/** * This method writes the Contiguous codestream box * * @param cs The contiguous codestream * @exception java.io.IOException If an I/O error ocurred. */ public void writeContiguousCodeStreamBox() throws IOException { // when write a jp2 file if (metadata != null) { // Write box length (LBox) // This value is set to 0 since in this implementation, this box is // always last stream.writeInt(clength + 8); // Write contiguous codestream box name (TBox) stream.writeInt(CONTIGUOUS_CODESTREAM_BOX); } // Read and buffer the codestream BEBufferedRandomAccessFile fi = new BEBufferedRandomAccessFile(file, "rw+"); int remainder = clength; byte[] codestream = new byte[1024]; while (remainder > 0) { int len = remainder > 1024 ? 1024 : remainder; fi.readFully(codestream, 0, len); // Write codestream stream.write(codestream, 0, len); remainder -= len; } // Close the file. fi.close(); }
private void writeHeader( String version, int logicalScreenWidth, int logicalScreenHeight, int colorResolution, int pixelAspectRatio, int backgroundColorIndex, boolean sortFlag, int bitsPerPixel, byte[] globalColorTable) throws IOException { try { // Signature stream.writeBytes("GIF" + version); // Screen Descriptor // Width stream.writeShort((short) logicalScreenWidth); // Height stream.writeShort((short) logicalScreenHeight); // Global Color Table // Packed fields int packedFields = globalColorTable != null ? 0x80 : 0x00; packedFields |= ((colorResolution - 1) & 0x7) << 4; if (sortFlag) { packedFields |= 0x8; } packedFields |= (bitsPerPixel - 1); stream.write(packedFields); // Background color index stream.write(backgroundColorIndex); // Pixel aspect ratio stream.write(pixelAspectRatio); // Global Color Table if (globalColorTable != null) { stream.write(globalColorTable); } } catch (IOException e) { throw new IIOException("I/O error writing header!", e); } }
/** * Write out the given profile to the stream, embedded in the necessary number of APP2 segments, * per the ICC spec. This is the only mechanism for writing an ICC profile to a stream. */ static void writeICC(ICC_Profile profile, ImageOutputStream ios) throws IOException { int LENGTH_LENGTH = 2; final String ID = "ICC_PROFILE"; int ID_LENGTH = ID.length() + 1; // spec says it's null-terminated int COUNTS_LENGTH = 2; int MAX_ICC_CHUNK_SIZE = 65535 - LENGTH_LENGTH - ID_LENGTH - COUNTS_LENGTH; byte[] data = profile.getData(); int numChunks = data.length / MAX_ICC_CHUNK_SIZE; if ((data.length % MAX_ICC_CHUNK_SIZE) != 0) { numChunks++; } int chunkNum = 1; int offset = 0; for (int i = 0; i < numChunks; i++) { int dataLength = Math.min(data.length - offset, MAX_ICC_CHUNK_SIZE); int segLength = dataLength + COUNTS_LENGTH + ID_LENGTH + LENGTH_LENGTH; ios.write(0xff); ios.write(JPEG.APP2); MarkerSegment.write2bytes(ios, segLength); byte[] id = ID.getBytes("US-ASCII"); ios.write(id); ios.write(0); // Null-terminate the string ios.write(chunkNum++); ios.write(numChunks); ios.write(data, offset, dataLength); offset += dataLength; } }
private void writePlainTextExtension(GIFWritableImageMetadata im) throws IOException { if (im.hasPlainTextExtension) { try { stream.write(0x21); stream.write(0x1); stream.write(12); stream.writeShort(im.textGridLeft); stream.writeShort(im.textGridTop); stream.writeShort(im.textGridWidth); stream.writeShort(im.textGridHeight); stream.write(im.characterCellWidth); stream.write(im.characterCellHeight); stream.write(im.textForegroundColor); stream.write(im.textBackgroundColor); writeBlocks(im.text); stream.write(0x00); } catch (IOException e) { throw new IIOException("I/O error writing Plain Text Extension!", e); } } }
private void writeBox(IIOMetadataNode node) throws IOException { int type = Box.getTypeInt((String) Box.getAttribute(node, "Type")); int length = new Integer((String) Box.getAttribute(node, "Length")).intValue(); Box box = Box.createBox(type, node); otherLength += length; stream.writeInt(length); stream.writeInt(type); byte[] data = box.getContent(); stream.write(data, 0, data.length); }
/* * Write out the values in the integer array as a sequence of bytes, * reporting progress to the writer argument. */ void writeThumbnailData(ImageOutputStream ios, int[] thumbData, JPEGImageWriter writer) throws IOException { int progInterval = thumbData.length / 20; // approx. every 5% if (progInterval == 0) { progInterval = 1; } for (int i = 0; i < thumbData.length; i++) { ios.write(thumbData[i]); if ((i > progInterval) && (i % progInterval == 0)) { writer.thumbnailProgress(((float) i * 100) / ((float) thumbData.length)); } } }
public void write(IIOMetadata streamMetadata, IIOImage img, ImageWriteParam param) throws IOException { ImageOutputStream out = (ImageOutputStream) getOutput(); if (!(img.getRenderedImage() instanceof BufferedImage)) { throw new IOException(getClass().getName() + "write:\nCan only write BufferedImage objects"); } BufferedImage image = (BufferedImage) img.getRenderedImage(); int width = image.getWidth(); int height = image.getHeight(); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); JFIFOutputStream os; if (image.getType() == BufferedImage.TYPE_BYTE_GRAY) { // one component; grey scale os = new JFIFOutputStream(baos, false, height, width); // SOF:start of frame WritableRaster raster = image.getRaster(); DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer(); byte[] imgdata = (byte[]) buffer.getData(); os.write(imgdata); os.close(); // EOF: end of frame } else if (image.getType() == BufferedImage.TYPE_INT_RGB) { // three components; YCbCr os = new JFIFOutputStream(baos, true, height, width); // SOF:start of frame WritableRaster raster = image.getRaster(); DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); int[] imgdata = (int[]) buffer.getData(); os.write(imgdata); os.close(); // EOF: end of frame } else { // three components; YCbCr os = new JFIFOutputStream(baos, true, height, width); // SOF:start of frame for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { os.write(image.getRGB(x, y)); } } os.close(); // EOF: end of frame } out.write(baos.toByteArray()); // write to image stream } catch (Exception e) { e.printStackTrace(); throw new IOException( getClass().getName() + ".write:\n\tCould not write image due to :\n\t" + e.getMessage()); } }
private void writeApplicationExtension(GIFWritableImageMetadata im) throws IOException { if (im.applicationIDs != null) { Iterator iterIDs = im.applicationIDs.iterator(); Iterator iterCodes = im.authenticationCodes.iterator(); Iterator iterData = im.applicationData.iterator(); while (iterIDs.hasNext()) { try { stream.write(0x21); stream.write(0xff); stream.write(11); stream.write((byte[]) iterIDs.next(), 0, 8); stream.write((byte[]) iterCodes.next(), 0, 3); writeBlocks((byte[]) iterData.next()); stream.write(0x00); } catch (IOException e) { throw new IIOException("I/O error writing Application Extension!", e); } } } }
private void writeImageDescriptor( int imageLeftPosition, int imageTopPosition, int imageWidth, int imageHeight, boolean interlaceFlag, boolean sortFlag, int bitsPerPixel, byte[] localColorTable) throws IOException { try { stream.write(0x2c); stream.writeShort((short) imageLeftPosition); stream.writeShort((short) imageTopPosition); stream.writeShort((short) imageWidth); stream.writeShort((short) imageHeight); int packedFields = localColorTable != null ? 0x80 : 0x00; if (interlaceFlag) { packedFields |= 0x40; } if (sortFlag) { packedFields |= 0x8; } packedFields |= (bitsPerPixel - 1); stream.write(packedFields); if (localColorTable != null) { stream.write(localColorTable); } } catch (IOException e) { throw new IIOException("I/O error writing Image Descriptor!", e); } }
void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { int progInterval = data.length / 20; // approx. every 5% if (progInterval == 0) { progInterval = 1; } for (int offset = 0; offset < data.length; ) { int len = Math.min(progInterval, data.length - offset); ios.write(data, offset, len); offset += progInterval; float percentDone = ((float) offset * 100) / data.length; if (percentDone > 100.0F) { percentDone = 100.0F; } writer.thumbnailProgress(percentDone); } }
/** * The image encoder. * * @param o - the image output stream * @param streamMetadata - metadata associated with this stream, or null * @param image - an IIOImage containing image data. * @param param - image writing parameters, or null * @exception IOException if a write error occurs */ public void encode( ImageOutputStream o, IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { int size; int value; int j; int rowCount; int rowIndex; int lastRowIndex; int[] bitmap; byte rgb[] = new byte[3]; size = (infoHeader.biWidth * infoHeader.biHeight) - 1; rowCount = 1; rowIndex = size - infoHeader.biWidth; lastRowIndex = rowIndex; try { bitmap = new int[infoHeader.biWidth * infoHeader.biHeight]; PixelGrabber pg = new PixelGrabber( (BufferedImage) image.getRenderedImage(), 0, 0, infoHeader.biWidth, infoHeader.biHeight, bitmap, 0, infoHeader.biWidth); pg.grabPixels(); for (j = 0; j < size; j++) { value = bitmap[rowIndex]; rgb[0] = (byte) (value & 0xFF); rgb[1] = (byte) ((value >> 8) & 0xFF); rgb[2] = (byte) ((value >> 16) & 0xFF); o.write(rgb); if (rowCount == infoHeader.biWidth) { rowCount = 1; rowIndex = lastRowIndex - infoHeader.biWidth; lastRowIndex = rowIndex; } else rowCount++; rowIndex++; } } catch (Exception wb) { wb.printStackTrace(); } }
void write(ImageOutputStream ios, JPEGImageWriter writer) throws IOException { super.write(ios, writer); // width and height // Write the palette (must be 768 bytes) byte[] palette = new byte[768]; IndexColorModel icm = (IndexColorModel) thumbnail.getColorModel(); byte[] reds = new byte[256]; byte[] greens = new byte[256]; byte[] blues = new byte[256]; icm.getReds(reds); icm.getGreens(greens); icm.getBlues(blues); for (int i = 0; i < 256; i++) { palette[i * 3] = reds[i]; palette[i * 3 + 1] = greens[i]; palette[i * 3 + 2] = blues[i]; } ios.write(palette); writePixels(ios, writer); }
private IFD writeRGBImage( ImageOutputStream out, BufferedImage image, int comp, TIFFImageWriteParam param) throws IOException { image = convert(image, BufferedImage.TYPE_INT_RGB); try { int width = image.getWidth(); int height = image.getHeight(); IFD ifd = new IFD(); // entries need to be in tag order ! ifd.add(new DEFactory.NewSubfileTypeDE(2)); // 254 single page of multipage file ifd.add(new DEFactory.ImageWidthDE(width)); // 256 ifd.add(new DEFactory.ImageLengthDE(height)); // 257 DEFactory.BitsPerSampleDE bpss = new DEFactory.BitsPerSampleDE(3); bpss.setBitsPerSample(0, 8); // red bpss.setBitsPerSample(1, 8); // green bpss.setBitsPerSample(2, 8); // blue ifd.add(bpss); // 258 ifd.add(new DEFactory.CompressionDE(comp)); // 259 ifd.add(new DEFactory.PhotometricInterpretationDE(RGB)); // 262 int maxrps, maxstripes; // max RowsPerStrip if ((1 << 13) <= width) { maxrps = 1; maxstripes = height; // one row per strip } else { maxrps = (1 << 13) / width; maxstripes = (height + maxrps - 1) / maxrps; } if (comp == JPEG) { maxrps = ((maxrps + 8 - 1) / 8) * 8; maxstripes = (height + maxrps - 1) / maxrps; } DEFactory.StripOffsetsDE offsets = new DEFactory.StripOffsetsDE(maxstripes); ifd.add(offsets); // 273 ifd.add(new DEFactory.SamplesPerPixelDE(3)); // 277 ifd.add(new DEFactory.RowsPerStripDE(maxrps)); // 278 DEFactory.StripByteCountsDE counts = new DEFactory.StripByteCountsDE(maxstripes); ifd.add(counts); // 279 if (param == null) { ifd.add(new DEFactory.XResolutionDE(72.0)); // 282 ifd.add(new DEFactory.YResolutionDE(72.0)); // 283 } else { ifd.add(new DEFactory.XResolutionDE(param.getXResolution())); // 282 ifd.add(new DEFactory.YResolutionDE(param.getYResolution())); // 283 } ifd.add(new DEFactory.ResolutionUnitDE(Inch)); // 296 ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; JPEGOutputStream jpegos = null; if (comp == JPEG) { // add JPEGTables tag jpegos = new JPEGOutputStream(baos); int quality = (param == null) ? 50 : (int) (param.getCompressionQuality() * 100); jpegos.setZZQuantizationTable(0, JPEGConstants.LQT, quality); jpegos.setRawDCHuffmanTable(0, JPEGConstants.HLDCTable); jpegos.setRawACHuffmanTable(0, JPEGConstants.HLACTable); jpegos.defineQuantizationTables(); jpegos.defineHuffmanTables(); jpegos.close(); DEFactory.JPEGTablesDE jpegtables = new DEFactory.JPEGTablesDE(baos.toByteArray()); ifd.add(jpegtables); // 347 baos.reset(); os = jpegos; } WritableRaster raster = image.getRaster(); DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); int[] imgdata = (int[]) buffer.getData(); int index = 0; for (int y = 0; y < height; y += maxrps) { /* Assume rgb image. Each strip: evaluate r g b colour save in byte array write to image file */ if ((height - y) < maxrps) { maxrps = height - y; } if (jpegos != null) { // jpeg: SOI,SOF,SOS marker jpegos.startOfImage(); int[] hv = {0x11, 0x11, 0x11}; // (Hi<<4)|Vi int[] q = {0, 0, 0}; // quantization table 0 jpegos.startOfFrame(maxrps, width, hv, q); int[] sel = {0, 0, 0}; // DC,AC code table 0 jpegos.startOfScan(sel); } for (int i = 0; i < maxrps; i++) { // write RGB data for (int x = 0; x < width; x++) { int c = imgdata[x + (y + i) * width]; os.write((c >> 16) & 0x000000FF); os.write((c >> 8) & 0x000000FF); os.write(c & 0x000000FF); } } os.close(); // jpeg: EOI marker byte[] data = baos.toByteArray(); counts.setCount(index, data.length); // update ifd strip counter array offsets.setOffset(index, out.getStreamPosition()); // update ifd image data offset array out.write(data); // write to image stream baos.reset(); index++; } return ifd; } catch (Exception e) { e.printStackTrace(); throw new IOException(getClass().getName() + ".writeRGBImage:\n\t" + e.getMessage()); } }
private void writeRasterData( RenderedImage image, Rectangle sourceBounds, Dimension destSize, ImageWriteParam param, boolean interlaceFlag) throws IOException { int sourceXOffset = sourceBounds.x; int sourceYOffset = sourceBounds.y; int sourceWidth = sourceBounds.width; int sourceHeight = sourceBounds.height; int destWidth = destSize.width; int destHeight = destSize.height; int periodX; int periodY; if (param == null) { periodX = 1; periodY = 1; } else { periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); } SampleModel sampleModel = image.getSampleModel(); int bitsPerPixel = sampleModel.getSampleSize()[0]; int initCodeSize = bitsPerPixel; if (initCodeSize == 1) { initCodeSize++; } stream.write(initCodeSize); LZWCompressor compressor = new LZWCompressor(stream, initCodeSize, false); boolean isOptimizedCase = periodX == 1 && periodY == 1 && sampleModel instanceof ComponentSampleModel && image.getNumXTiles() == 1 && image.getNumYTiles() == 1 && image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte; int numRowsWritten = 0; int progressReportRowPeriod = Math.max(destHeight / 20, 1); processImageStarted(imageIndex); if (interlaceFlag) { if (DEBUG) System.out.println("Writing interlaced"); if (isOptimizedCase) { Raster tile = image.getTile(0, 0); byte[] data = ((DataBufferByte) tile.getDataBuffer()).getData(); ComponentSampleModel csm = (ComponentSampleModel) tile.getSampleModel(); int offset = csm.getOffset( sourceXOffset - tile.getSampleModelTranslateX(), sourceYOffset - tile.getSampleModelTranslateY(), 0); int lineStride = csm.getScanlineStride(); writeRowsOpt( data, offset, lineStride, compressor, 0, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += destHeight / 8; writeRowsOpt( data, offset, lineStride, compressor, 4, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 4) / 8; writeRowsOpt( data, offset, lineStride, compressor, 2, 4, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 2) / 4; writeRowsOpt( data, offset, lineStride, compressor, 1, 2, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } else { writeRows( image, compressor, sourceXOffset, periodX, sourceYOffset, 8 * periodY, sourceWidth, 0, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += destHeight / 8; writeRows( image, compressor, sourceXOffset, periodX, sourceYOffset + 4 * periodY, 8 * periodY, sourceWidth, 4, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 4) / 8; writeRows( image, compressor, sourceXOffset, periodX, sourceYOffset + 2 * periodY, 4 * periodY, sourceWidth, 2, 4, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 2) / 4; writeRows( image, compressor, sourceXOffset, periodX, sourceYOffset + periodY, 2 * periodY, sourceWidth, 1, 2, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } } else { if (DEBUG) System.out.println("Writing non-interlaced"); if (isOptimizedCase) { Raster tile = image.getTile(0, 0); byte[] data = ((DataBufferByte) tile.getDataBuffer()).getData(); ComponentSampleModel csm = (ComponentSampleModel) tile.getSampleModel(); int offset = csm.getOffset( sourceXOffset - tile.getSampleModelTranslateX(), sourceYOffset - tile.getSampleModelTranslateY(), 0); int lineStride = csm.getScanlineStride(); writeRowsOpt( data, offset, lineStride, compressor, 0, 1, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } else { writeRows( image, compressor, sourceXOffset, periodX, sourceYOffset, periodY, sourceWidth, 0, 1, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } } if (abortRequested()) { return; } processImageProgress(100.0F); compressor.flush(); stream.write(0x00); processImageComplete(); }
/** * 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(); } }
public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (stream == null) { throw new IllegalStateException(I18N.getString("WBMPImageWriter3")); } if (image == null) { throw new IllegalArgumentException(I18N.getString("WBMPImageWriter4")); } clearAbortRequest(); processImageStarted(0); if (param == null) param = getDefaultWriteParam(); RenderedImage input = null; Raster inputRaster = null; boolean writeRaster = image.hasRaster(); Rectangle sourceRegion = param.getSourceRegion(); SampleModel sampleModel = null; if (writeRaster) { inputRaster = image.getRaster(); sampleModel = inputRaster.getSampleModel(); } else { input = image.getRenderedImage(); sampleModel = input.getSampleModel(); inputRaster = input.getData(); } checkSampleModel(sampleModel); if (sourceRegion == null) sourceRegion = inputRaster.getBounds(); else sourceRegion = sourceRegion.intersection(inputRaster.getBounds()); if (sourceRegion.isEmpty()) throw new RuntimeException(I18N.getString("WBMPImageWriter1")); int scaleX = param.getSourceXSubsampling(); int scaleY = param.getSourceYSubsampling(); int xOffset = param.getSubsamplingXOffset(); int yOffset = param.getSubsamplingYOffset(); sourceRegion.translate(xOffset, yOffset); sourceRegion.width -= xOffset; sourceRegion.height -= yOffset; int minX = sourceRegion.x / scaleX; int minY = sourceRegion.y / scaleY; int w = (sourceRegion.width + scaleX - 1) / scaleX; int h = (sourceRegion.height + scaleY - 1) / scaleY; Rectangle destinationRegion = new Rectangle(minX, minY, w, h); sampleModel = sampleModel.createCompatibleSampleModel(w, h); SampleModel destSM = sampleModel; // If the data are not formatted nominally then reformat. if (sampleModel.getDataType() != DataBuffer.TYPE_BYTE || !(sampleModel instanceof MultiPixelPackedSampleModel) || ((MultiPixelPackedSampleModel) sampleModel).getDataBitOffset() != 0) { destSM = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, w, h, 1, w + 7 >> 3, 0); } if (!destinationRegion.equals(sourceRegion)) { if (scaleX == 1 && scaleY == 1) inputRaster = inputRaster.createChild( inputRaster.getMinX(), inputRaster.getMinY(), w, h, minX, minY, null); else { WritableRaster ras = Raster.createWritableRaster(destSM, new Point(minX, minY)); byte[] data = ((DataBufferByte) ras.getDataBuffer()).getData(); for (int j = minY, y = sourceRegion.y, k = 0; j < minY + h; j++, y += scaleY) { for (int i = 0, x = sourceRegion.x; i < w; i++, x += scaleX) { int v = inputRaster.getSample(x, y, 0); data[k + (i >> 3)] |= v << (7 - (i & 7)); } k += w + 7 >> 3; } inputRaster = ras; } } // If the data are not formatted nominally then reformat. if (!destSM.equals(inputRaster.getSampleModel())) { WritableRaster raster = Raster.createWritableRaster( destSM, new Point(inputRaster.getMinX(), inputRaster.getMinY())); raster.setRect(inputRaster); inputRaster = raster; } // Check whether the image is white-is-zero. boolean isWhiteZero = false; if (!writeRaster && input.getColorModel() instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel) input.getColorModel(); isWhiteZero = icm.getRed(0) > icm.getRed(1); } // Get the line stride, bytes per row, and data array. int lineStride = ((MultiPixelPackedSampleModel) destSM).getScanlineStride(); int bytesPerRow = (w + 7) / 8; byte[] bdata = ((DataBufferByte) inputRaster.getDataBuffer()).getData(); // Write WBMP header. stream.write(0); // TypeField stream.write(0); // FixHeaderField stream.write(intToMultiByte(w)); // width stream.write(intToMultiByte(h)); // height // Write the data. if (!isWhiteZero && lineStride == bytesPerRow) { // Write the entire image. stream.write(bdata, 0, h * bytesPerRow); processImageProgress(100.0F); } else { // Write the image row-by-row. int offset = 0; if (!isWhiteZero) { // Black-is-zero for (int row = 0; row < h; row++) { if (abortRequested()) break; stream.write(bdata, offset, bytesPerRow); offset += lineStride; processImageProgress(100.0F * row / h); } } else { // White-is-zero: need to invert data. byte[] inverted = new byte[bytesPerRow]; for (int row = 0; row < h; row++) { if (abortRequested()) break; for (int col = 0; col < bytesPerRow; col++) { inverted[col] = (byte) (~(bdata[col + offset])); } stream.write(inverted, 0, bytesPerRow); offset += lineStride; processImageProgress(100.0F * row / h); } } } if (abortRequested()) processWriteAborted(); else { processImageComplete(); stream.flushBefore(stream.getStreamPosition()); } }
/* */ void write(ImageOutputStream paramImageOutputStream) /* */ throws IOException /* */ { /* 182 */ this.length = (2 + (this.data != null ? this.data.length : 0)); /* 183 */ writeTag(paramImageOutputStream); /* 184 */ if (this.data != null) /* 185 */ paramImageOutputStream.write(this.data); /* */ }
private IFD writeBModHufImage( ImageOutputStream out, BufferedImage image, TIFFImageWriteParam param) throws IOException { try { int width = image.getWidth(); int height = image.getHeight(); IFD ifd = new IFD(); // entries need to be in tag order ! ifd.add(new DEFactory.NewSubfileTypeDE(2)); // 254 single page of multipage file ifd.add(new DEFactory.ImageWidthDE(width)); // 256 ifd.add(new DEFactory.ImageLengthDE(height)); // 257 ifd.add(new DEFactory.CompressionDE(CCITTGROUP3MODHUFFMAN)); // 259 ifd.add(new DEFactory.PhotometricInterpretationDE(WhiteIsZero)); // 262 int maxrps, maxstripes; // max RowsPerStrip if ((1 << 13) <= width) { maxrps = 1; maxstripes = height; // one row per stripe } else { maxrps = (1 << 13) / width; maxstripes = (height + maxrps - 1) / maxrps; } DEFactory.StripOffsetsDE offsets = new DEFactory.StripOffsetsDE(maxstripes); ifd.add(offsets); // 273 ifd.add(new DEFactory.RowsPerStripDE(maxrps)); // 278 DEFactory.StripByteCountsDE counts = new DEFactory.StripByteCountsDE(maxstripes); ifd.add(counts); // 279 if (param == null) { ifd.add(new DEFactory.XResolutionDE(72.0)); // 282 ifd.add(new DEFactory.YResolutionDE(72.0)); // 283 } else { ifd.add(new DEFactory.XResolutionDE(param.getXResolution())); // 282 ifd.add(new DEFactory.YResolutionDE(param.getYResolution())); // 283 } ifd.add(new DEFactory.ResolutionUnitDE(Inch)); // 296 int index = 0; for (int y = 0; y < height; y += maxrps) { /* Assume bilevel image (black/white[=-1]) Each strip: count run length encode into modified hufman codes swap bits save in byte array write to image file */ ByteArrayOutputStream baos = new ByteArrayOutputStream(); BitSwapOutputStream bsos = new BitSwapOutputStream(baos); ModHuffmanOutputStream mhos = new ModHuffmanOutputStream(bsos); RLEOutputStream rlos = new RLEOutputStream(mhos, 3); // rgb = 3 bytes per sample code word (not needed here) for (int i = 0; i < maxrps; i++) { if ((y + i) == height) { break; } // last strip might have less rows rlos.setStartCodeWord(-1); // white run first for (int x = 0; x < width; x++) { rlos.write(image.getRGB(x, y + i)); } rlos.flush(); // write padding after ever image row } rlos.close(); byte[] data = baos.toByteArray(); counts.setCount(index, data.length); // update ifd strip counter array offsets.setOffset(index, out.getStreamPosition()); // update ifd image data offset array out.write(data); // write to image stream index++; } return ifd; } catch (Exception e) { e.printStackTrace(); throw new IOException(getClass().getName() + ".writeBModHufImage:\n\t" + e.getMessage()); } }
/* */ void writeTag(ImageOutputStream paramImageOutputStream) /* */ throws IOException /* */ { /* 172 */ paramImageOutputStream.write(255); /* 173 */ paramImageOutputStream.write(this.tag); /* 174 */ write2bytes(paramImageOutputStream, this.length); /* */ }
private IFD writeCMYKImage(ImageOutputStream out, BufferedImage image, TIFFImageWriteParam param) throws IOException { try { int width = image.getWidth(); int height = image.getHeight(); IFD ifd = new IFD(); // entries need to be in tag order ! ifd.add(new DEFactory.NewSubfileTypeDE(2)); // 254 single page of multipage file ifd.add(new DEFactory.ImageWidthDE(width)); // 256 ifd.add(new DEFactory.ImageLengthDE(height)); // 257 DEFactory.BitsPerSampleDE bpss = new DEFactory.BitsPerSampleDE(4); bpss.setBitsPerSample(0, 8); // cyan bpss.setBitsPerSample(1, 8); // magneta bpss.setBitsPerSample(2, 8); // yellow bpss.setBitsPerSample(3, 8); // key (black) ifd.add(bpss); // 258 ifd.add(new DEFactory.CompressionDE(NOCOMPRESSION)); // 259 ifd.add(new DEFactory.PhotometricInterpretationDE(CMYK)); // 262 int maxrps, maxstripes; // max RowsPerStrip if ((1 << 13) <= width) { maxrps = 1; maxstripes = height; // one row per strip } else { maxrps = (1 << 13) / width; maxstripes = (height + maxrps - 1) / maxrps; } DEFactory.StripOffsetsDE offsets = new DEFactory.StripOffsetsDE(maxstripes); ifd.add(offsets); // 273 ifd.add(new DEFactory.SamplesPerPixelDE(4)); // 277 ifd.add(new DEFactory.RowsPerStripDE(maxrps)); // 278 DEFactory.StripByteCountsDE counts = new DEFactory.StripByteCountsDE(maxstripes); ifd.add(counts); // 279 if (param == null) { ifd.add(new DEFactory.XResolutionDE(72.0)); // 282 ifd.add(new DEFactory.YResolutionDE(72.0)); // 283 } else { ifd.add(new DEFactory.XResolutionDE(param.getXResolution())); // 282 ifd.add(new DEFactory.YResolutionDE(param.getYResolution())); // 283 } ifd.add(new DEFactory.ResolutionUnitDE(Inch)); // 296 int index = 0; for (int y = 0; y < height; y += maxrps) { /* Assume rgb image. Each strip: evaluate c m y k colour save in byte array write to image file */ ByteArrayOutputStream baos = new ByteArrayOutputStream(); for (int i = 0; i < maxrps; i++) { if ((y + i) == height) { break; } // last strip might have less rows for (int x = 0; x < width; x++) { int c = image.getRGB(x, y + i); int R = (c >> 16) & 0x00FF; int G = (c >> 8) & 0x00FF; int B = (c) & 0x00FF; if ((R == 255) && (G == 255) && (B == 255)) { baos.write(0); baos.write(0); baos.write(0); baos.write(0); } else { double C = 1.0 - R / 255.0; double M = 1.0 - G / 255.0; double Y = 1.0 - B / 255.0; double K = C; if (M < K) { K = M; } if (Y < K) { K = Y; } C = ((C - K) / (1.0 - K)) * 255.0; M = ((M - K) / (1.0 - K)) * 255.0; Y = ((Y - K) / (1.0 - K)) * 255.0; K *= 255.0; baos.write((int) C); baos.write((int) M); baos.write((int) Y); baos.write((int) K); } } } baos.close(); byte[] data = baos.toByteArray(); counts.setCount(index, data.length); // update ifd strip counter array offsets.setOffset(index, out.getStreamPosition()); // update ifd image data offset array out.write(data); // write to image stream index++; } return ifd; } catch (Exception e) { e.printStackTrace(); throw new IOException(getClass().getName() + ".writeCMYKImage:\n\t" + e.getMessage()); } }
/* */ static void write2bytes(ImageOutputStream paramImageOutputStream, int paramInt) /* */ throws IOException /* */ { /* 191 */ paramImageOutputStream.write(paramInt >> 8 & 0xFF); /* 192 */ paramImageOutputStream.write(paramInt & 0xFF); /* */ }
private IFD writeYCbCrImage( ImageOutputStream out, BufferedImage image, int comp, TIFFImageWriteParam param) throws IOException { image = convert(image, BufferedImage.TYPE_INT_RGB); try { int width = image.getWidth(); int height = image.getHeight(); IFD ifd = new IFD(); // entries need to be in tag order ! int ss = (param == null) ? 0x22 : param.getSubSampling(); int ssh = (ss >> 4) & 0x0F; int ssv = ss & 0x0F; if (ssh < ssv) { // YCbCrSubsampleVert shall always be less than or equal to YCbCrSubsampleHoriz. throw new IOException( "Internal error: YCbCrSubsampleVert is not less than YCbCrSubsampleHoriz."); } // int ww=((width +ssh-1)/ssh)*ssh; // [1] p.92 // int hh=((height+ssv-1)/ssv)*ssv; int ww = width; int hh = height; ifd.add(new DEFactory.NewSubfileTypeDE(2)); // 254 single page of multipage file ifd.add(new DEFactory.ImageWidthDE(ww)); // 256 ifd.add(new DEFactory.ImageLengthDE(hh)); // 257 DEFactory.BitsPerSampleDE bpss = new DEFactory.BitsPerSampleDE(3); bpss.setBitsPerSample(0, 8); // Y bpss.setBitsPerSample(1, 8); // Cb bpss.setBitsPerSample(2, 8); // Cr ifd.add(bpss); // 258 ifd.add(new DEFactory.CompressionDE(comp)); // 259 ifd.add(new DEFactory.PhotometricInterpretationDE(YCbCr)); // 262 int maxrps, maxstripes; // max RowsPerStrip if ((1 << 13) <= width) { maxrps = 1; maxstripes = height; // one row per strip } else { maxrps = (1 << 13) / width; maxstripes = (height + maxrps - 1) / maxrps; } if (comp == JPEG) { maxrps = ((maxrps + 8 * ssv - 1) / (8 * ssv)) * (8 * ssv); maxstripes = (height + maxrps - 1) / maxrps; } DEFactory.StripOffsetsDE offsets = new DEFactory.StripOffsetsDE(maxstripes); ifd.add(offsets); // 273 ifd.add(new DEFactory.SamplesPerPixelDE(3)); // 277 ifd.add(new DEFactory.RowsPerStripDE(maxrps)); // 278 DEFactory.StripByteCountsDE counts = new DEFactory.StripByteCountsDE(maxstripes); ifd.add(counts); // 279 if (param == null) { ifd.add(new DEFactory.XResolutionDE(72.0)); // 282 ifd.add(new DEFactory.YResolutionDE(72.0)); // 283 } else { ifd.add(new DEFactory.XResolutionDE(param.getXResolution())); // 282 ifd.add(new DEFactory.YResolutionDE(param.getYResolution())); // 283 } ifd.add(new DEFactory.ResolutionUnitDE(Inch)); // 296 ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream os = baos; JPEGOutputStream jpegos = null; if (comp == JPEG) { jpegos = new JPEGOutputStream(baos); int quality = (param == null) ? 50 : (int) (param.getCompressionQuality() * 100); jpegos.setZZQuantizationTable(0, JPEGConstants.LQT, quality); jpegos.setZZQuantizationTable(1, JPEGConstants.CQT, quality); jpegos.setRawDCHuffmanTable(0, JPEGConstants.HLDCTable); jpegos.setRawACHuffmanTable(0, JPEGConstants.HLACTable); jpegos.setRawDCHuffmanTable(1, JPEGConstants.HCDCTable); jpegos.setRawACHuffmanTable(1, JPEGConstants.HCACTable); jpegos.defineQuantizationTables(); jpegos.defineHuffmanTables(); jpegos.close(); DEFactory.JPEGTablesDE jpegtables = new DEFactory.JPEGTablesDE(baos.toByteArray()); ifd.add(jpegtables); // 347 baos.reset(); os = jpegos; } // CCIR Recommendation 601-1 LumaRed=299/1000 LumaGreen=587/1000 LumeBlue=114/1000 // Y = ( LumaRed * R + LumaGreen * G + LumaBlue * B ) // Cb = ( B - Y ) / ( 2 - 2 * LumaBlue ) // Cr = ( R - Y ) / ( 2 - 2 * LumaRed ) double LumaRed = 299.0 / 1000.0; double LumaGreen = 587.0 / 1000.0; double LumaBlue = 114.0 / 1000.0; DEFactory.YCbCrCoefficientsDE YCbCrCoeff = new DEFactory.YCbCrCoefficientsDE(); YCbCrCoeff.setLumaRed(LumaRed); // Y YCbCrCoeff.setLumaGreen(LumaGreen); // Cb YCbCrCoeff.setLumaBlue(LumaBlue); // Cr ifd.add(YCbCrCoeff); // 529 DEFactory.YCbCrSubSamplingDE YCbCrSubSampling = new DEFactory.YCbCrSubSamplingDE(); YCbCrSubSampling.setHoriz(ssh); YCbCrSubSampling.setVert(ssv); ifd.add(YCbCrSubSampling); // 530 double RfBY = 0; double RfWY = 255; double RfBCb = 128; double RfWCb = 255; double RfBCr = 128; double RfWCr = 255; DEFactory.ReferenceBlackWhiteDE ReferenceBlackWhite = new DEFactory.ReferenceBlackWhiteDE(); ReferenceBlackWhite.setY(RfBY, RfWY); ReferenceBlackWhite.setCb(RfBCb, RfWCb); ReferenceBlackWhite.setCr(RfBCr, RfWCr); ifd.add(ReferenceBlackWhite); // 532 TIFFYCbCrOutputStream ycbcros; if (jpegos == null) { ycbcros = new TIFFYCbCrOutputStream(os, width, ssv, ssh); os = new TIFFSubSamplingOutputStream(ycbcros, width, ssv, ssh); } else { ycbcros = new TIFFYCbCrOutputStream(os, width, 1, 1); // jpeg does own subsampling os = ycbcros; } ycbcros.setPositioning(1); ycbcros.setColourCoefficients(LumaRed, LumaGreen, LumaBlue); ycbcros.setRfBWY(RfBY, RfWY); ycbcros.setRfBWCb(RfBCb, RfWCb); ycbcros.setRfBWCr(RfBCr, RfWCr); WritableRaster raster = image.getRaster(); DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); int[] imgdata = (int[]) buffer.getData(); int c = 0, index = 0; for (int y = 0; y < height; y += maxrps) { if ((height - y) < maxrps) { maxrps = height - y; } if (jpegos != null) { jpegos.startOfImage(); int[] hv = {(ssh << 4) | ssv, 0x11, 0x11}; // (Hi<<4)|Vi int[] q = {0, 1, 1}; // quantization table Y=0, Cb=Cr=1 // jpegos.startOfFrame(((maxrps+ssv-1)/ssv)*ssv,ww,hv,q); jpegos.startOfFrame(maxrps, ww, hv, q); int[] sel = {0, 1, 1}; // DC,AC code table Y=0, Cb=Cr=1 jpegos.startOfScan(sel); } for (int i = 0; i < maxrps; i++) { int x = 0; while (x < width) { c = imgdata[x + (y + i) * width]; // c = image.getRGB(x,y+i); os.write((c >> 16) & 0x000000FF); os.write((c >> 8) & 0x000000FF); os.write(c & 0x000000FF); x++; } while (x < ww) { os.write((c >> 16) & 0x000000FF); os.write((c >> 8) & 0x000000FF); os.write(c & 0x000000FF); x++; } } os.close(); byte[] data = baos.toByteArray(); counts.setCount(index, data.length); // update ifd strip counter array offsets.setOffset(index, out.getStreamPosition()); // update ifd image data offset array out.write(data); // write to image stream baos.reset(); index++; } return ifd; } catch (Exception e) { e.printStackTrace(); throw new IOException(getClass().getName() + ".writeYCbCrImage:\n\t" + e.getMessage()); } }