/** * Performs OCR operation. * * @param imageList a list of <code>IIOImage</code> objects * @param rect the bounding rectangle defines the region of the image to be recognized. A * rectangle of zero dimension or <code>null</code> indicates the whole image. * @return the recognized text * @throws TesseractException */ public String doOCR(List<IIOImage> imageList, Rectangle rect) throws TesseractException { init(); setTessVariables(); try { StringBuilder sb = new StringBuilder(); for (IIOImage oimage : imageList) { pageNum++; try { setImage(oimage.getRenderedImage(), rect); sb.append(getOCRText()); } catch (IOException ioe) { // skip the problematic image logger.log(Level.SEVERE, ioe.getMessage(), ioe); } } if (hocr) { sb.insert(0, htmlBeginTag).append(htmlEndTag); } return sb.toString(); } finally { dispose(); } }
/** * Gets cloned image files. * * @return the ClonedImageFiles * @throws java.io.IOException */ public List<File> getClonedImageFiles() throws IOException { if (oimages != null) { if (dpiX == 0 || dpiY == 0) { if (rect == null || rect.isEmpty()) { return ImageIOHelper.createTiffFiles(oimages, index); } else { // rectangular region // BufferedImage bi = ((BufferedImage) // oimages.get(index).getRenderedImage()).getSubimage(rect.x, rect.y, rect.width, // rect.height); // On Linux, the standard getSubimage method has generated images that Tesseract does not // like. BufferedImage bi = ImageHelper.getSubImage( (BufferedImage) oimages.get(index).getRenderedImage(), rect.x, rect.y, rect.width, rect.height); List<IIOImage> tempList = new ArrayList<IIOImage>(); tempList.add(new IIOImage(bi, null, null)); return ImageIOHelper.createTiffFiles(tempList, 0); } } else { // scaling if (rect == null || rect.isEmpty()) { List<IIOImage> tempList = new ArrayList<IIOImage>(); for (IIOImage oimage : (index == -1 ? oimages : oimages.subList(index, index + 1))) { BufferedImage bi = (BufferedImage) oimage.getRenderedImage(); Map<String, String> metadata = ImageIOHelper.readImageData(oimage); float scale = dpiX / Float.parseFloat(metadata.get("dpiX")); bi = ImageHelper.getScaledInstance( bi, (int) (bi.getWidth() * scale), (int) (bi.getHeight() * scale)); tempList.add(new IIOImage(bi, null, null)); } return ImageIOHelper.createTiffFiles(tempList, (index == -1 ? index : 0), dpiX, dpiY); } else { // rectangular region // Cut out the subimage first and rescale that BufferedImage bi = ((BufferedImage) oimages.get(index).getRenderedImage()) .getSubimage(rect.x, rect.y, rect.width, rect.height); Map<String, String> metadata = ImageIOHelper.readImageData(oimages.get(index)); float scale = dpiX / Float.parseFloat(metadata.get("dpiX")); bi = ImageHelper.getScaledInstance( bi, (int) (bi.getWidth() * scale), (int) (bi.getHeight() * scale)); List<IIOImage> tempList = new ArrayList<IIOImage>(); tempList.add(new IIOImage(bi, null, null)); return ImageIOHelper.createTiffFiles(tempList, 0, dpiX, dpiY); } } } else { return ImageIOHelper.createTiffFiles(imageFile, index); } }
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()); } }
/** * Reads image meta data. * * @param oimage * @return */ public static Map<String, String> readImageData(IIOImage oimage) { Map<String, String> dict = new HashMap<String, String>(); IIOMetadata imageMetadata = oimage.getMetadata(); if (imageMetadata != null) { IIOMetadataNode dimNode = (IIOMetadataNode) imageMetadata.getAsTree("javax_imageio_1.0"); NodeList nodes = dimNode.getElementsByTagName("HorizontalPixelSize"); int dpiX; if (nodes.getLength() > 0) { float dpcWidth = Float.parseFloat(nodes.item(0).getAttributes().item(0).getNodeValue()); dpiX = (int) Math.round(25.4f / dpcWidth); } else { dpiX = Toolkit.getDefaultToolkit().getScreenResolution(); } dict.put("dpiX", String.valueOf(dpiX)); nodes = dimNode.getElementsByTagName("VerticalPixelSize"); int dpiY; if (nodes.getLength() > 0) { float dpcHeight = Float.parseFloat(nodes.item(0).getAttributes().item(0).getNodeValue()); dpiY = (int) Math.round(25.4f / dpcHeight); } else { dpiY = Toolkit.getDefaultToolkit().getScreenResolution(); } dict.put("dpiY", String.valueOf(dpiY)); } return dict; }
/** * 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); }
/** Constructor to set locales. */ public J2KImageWriteParamJava(IIOImage image, ImageWriteParam param) { super(param.getLocale()); if (image != null) { if (image.hasRaster()) setDefaults(image.getRaster()); else setDefaults(image.getRenderedImage()); } setSourceRegion(param.getSourceRegion()); setSourceBands(param.getSourceBands()); try { setTiling( param.getTileWidth(), param.getTileHeight(), param.getTileGridXOffset(), param.getTileGridYOffset()); } catch (IllegalStateException e) { // tileing is not set do nothing. } setDestinationOffset(param.getDestinationOffset()); setSourceSubsampling( param.getSourceXSubsampling(), param.getSourceYSubsampling(), param.getSubsamplingXOffset(), param.getSubsamplingYOffset()); setDestinationType(param.getDestinationType()); J2KImageWriteParam j2kParam; if (param instanceof J2KImageWriteParam) { j2kParam = (J2KImageWriteParam) param; } else { j2kParam = new J2KImageWriteParam(); } setDecompositionLevel("" + j2kParam.getNumDecompositionLevels()); setEncodingRate(j2kParam.getEncodingRate()); setLossless(j2kParam.getLossless()); setFilters(j2kParam.getFilter()); setEPH("" + j2kParam.getEPH()); setSOP("" + j2kParam.getSOP()); setProgressionName(j2kParam.getProgressionType()); int[] size = j2kParam.getCodeBlockSize(); setCodeBlockSize("" + size[0] + " " + size[1]); enableCT = j2kParam.getComponentTransformation(); setComponentTransformation("" + enableCT); }
public static List<File> createTiffFiles(List<IIOImage> imageList, int index, int dpiX, int dpiY) throws IOException { List<File> tiffFiles = new ArrayList<File>(); // 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); // all if index == -1; otherwise, only index-th for (IIOImage oimage : (index == -1 ? imageList : imageList.subList(index, index + 1))) { if (dpiX != 0 && dpiY != 0) { // Get the default image metadata. ImageTypeSpecifier imageType = ImageTypeSpecifier.createFromRenderedImage(oimage.getRenderedImage()); IIOMetadata imageMetadata = writer.getDefaultImageMetadata(imageType, null); imageMetadata = setDPIViaAPI(imageMetadata, dpiX, dpiY); oimage.setMetadata(imageMetadata); } File tiffFile = File.createTempFile(OUTPUT_FILE_NAME, TIFF_EXT); ImageOutputStream ios = ImageIO.createImageOutputStream(tiffFile); writer.setOutput(ios); writer.write(streamMetadata, oimage, tiffWriteParam); ios.close(); tiffFiles.add(tiffFile); } writer.dispose(); return tiffFiles; }
public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (image == null) throw new IllegalArgumentException("image == null"); if (image.hasRaster()) throw new UnsupportedOperationException("Cannot write rasters"); Object output = getOutput(); if (output == null) throw new IllegalStateException("output was not set"); if (param == null) param = getDefaultWriteParam(); ImageOutputStream ios = (ImageOutputStream) output; RenderedImage ri = image.getRenderedImage(); if (ri instanceof BufferedImage) { BufferedImage bi = (BufferedImage) ri; PPMEncoder encoder = new PPMEncoder(bi, ios); encoder.encode(); } else { throw new IOException("Image not of type BufferedImage"); } }
/** * 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(); } }
@Override public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { if (output == null) { throw new IllegalStateException("output == null"); } OutputStreamAdapter stream; if (output instanceof ImageOutputStream) { stream = new OutputStreamAdapter((ImageOutputStream) output); } else { throw new IllegalArgumentException("!(output instanceof ImageOutputStream)"); } RenderedImage renderedImage = image.getRenderedImage(); // Throws exception if the renderedImage cannot be encoded. ImageUtil.canEncodeImage(this, renderedImage.getColorModel(), renderedImage.getSampleModel()); if (renderedImage.getColorModel() instanceof IndexColorModel) { renderedImage = convertTo3BandRGB(renderedImage); } try { NativeJ2kImage nImage = new NativeJ2kImage(); int[] supportedFormats = new int[] { ImageParameters.CM_GRAY, ImageParameters.CM_S_RGB, ImageParameters.CM_S_YCC, ImageParameters.CM_E_YCC, ImageParameters.CM_CMYK }; formatInputDataBuffer(nImage, renderedImage, param, false, supportedFormats); OpenJpegCodec encoder = getCodec(); String error = encoder.compress(nImage, stream.getStream(), param); if (error != null) { throw new IIOException("Native JPEG encoding error: " + error); } encoder.dispose(); } catch (Exception e) { throw new IIOException("Native JPEG encoding error", e); } }
public void writeToSequence(IIOImage image, ImageWriteParam param) throws IOException { if (stream == null) { throw new IllegalStateException("output == null!"); } if (image == null) { throw new IllegalArgumentException("image == null!"); } if (image.hasRaster()) { throw new UnsupportedOperationException("canWriteRasters() == false!"); } if (!isWritingSequence) { throw new IllegalStateException("prepareWriteSequence() was not invoked!"); } write(!wroteSequenceHeader, false, theStreamMetadata, image, param); if (!wroteSequenceHeader) { wroteSequenceHeader = true; } this.imageIndex++; }
public void write(IIOMetadata sm, IIOImage iioimage, ImageWriteParam p) throws IOException { if (stream == null) { throw new IllegalStateException("output == null!"); } if (iioimage == null) { throw new IllegalArgumentException("iioimage == null!"); } if (iioimage.hasRaster()) { throw new UnsupportedOperationException("canWriteRasters() == false!"); } resetLocal(); GIFWritableStreamMetadata streamMetadata; if (sm == null) { streamMetadata = (GIFWritableStreamMetadata) getDefaultStreamMetadata(p); } else { streamMetadata = (GIFWritableStreamMetadata) convertStreamMetadata(sm, p); } write(true, true, streamMetadata, iioimage, p); }
public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException { hasListeners = (this.progressListeners != null && (!(this.progressListeners.isEmpty()))) ? true : false; if (hasListeners) { clearAbortRequest(); // Broadcast the start of the image write operation processImageStarted(0); } RenderedImage renderedImage = image.getRenderedImage(); // PlanarImage inputRenderedImage = PlanarImage.wrapRenderedImage(renderedImage); // Raster data = renderedImage.getData(); // final RectIter iterator = RectIterFactory.create(data, null); // writing noDataValue = rasterWriter.getNoData(); writeRegion.setCols(renderedImage.getWidth()); writeRegion.setRows(renderedImage.getHeight()); int nColumns = writeRegion.getCols(); int nRows = writeRegion.getRows(); double west = writeRegion.getWest(); double south = writeRegion.getSouth(); double cellsizeX = writeRegion.getWEResolution(); double cellsizeY = writeRegion.getNSResolution(); rasterWriter.writeRaster( renderedImage, nColumns, nRows, west, south, cellsizeX, cellsizeY, noDataValue); if (hasListeners) { // Checking the status of the write operation (aborted/completed) if (rasterWriter.isAborting()) processWriteAborted(); else processImageComplete(); } // rasterWriter.close(); }
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()); } }
public void writeToSequence(IIOImage img, ImageWriteParam param) throws IOException { ImageOutputStream out = (ImageOutputStream) getOutput(); if (!(img.getRenderedImage() instanceof BufferedImage)) { throw new IOException( getClass().getName() + "writeToSequence:\n\tCan only write BufferedImage objects"); } BufferedImage image = (BufferedImage) img.getRenderedImage(); /* // Attempt to convert metadata, if present IIOMetadata imd = img.getMetadata(); TIFFMetadata metadata = null; if(imd!=null){ ImageTypeSpecifier type=ImageTypeSpecifier.createFromRenderedImage(image); metadata=(TIFFMetadata)convertImageMetadata(imd,type,null); } // Output metadata if present if(metadata != null){ Iterator keywordIter = metadata.keywords.iterator(); Iterator valueIter = metadata.values.iterator(); while(keywordIter.hasNext()){ String keyword = (String)keywordIter.next(); String value = (String)valueIter.next(); System.out.println("9\bKEYWORD: "+keyword); System.out.println("9\bVALUE: "+value); } } */ IFD ifd; int pmi = RGB, comp = compNone, tiffComp = NOCOMPRESSION; TIFFImageWriteParam p = null; if ((param != null) && (param instanceof TIFFImageWriteParam)) { p = (TIFFImageWriteParam) param; pmi = p.getPhotometricInterpretation(); if (p.getCompressionType().equals("none")) { comp = compNone; tiffComp = NOCOMPRESSION; } else if (p.getCompressionType().equals("mh")) { comp = compBaselineMH; tiffComp = CCITTGROUP3MODHUFFMAN; } else if (p.getCompressionType().equals("t4mh")) { comp = compT4MH; tiffComp = CCITTFAXT4; } else if (p.getCompressionType().equals("t4mr")) { comp = compT4MR; tiffComp = CCITTFAXT4; } else if (p.getCompressionType().equals("t6mmr")) { comp = compT6MMR; tiffComp = CCITTFAXT6; } else if (p.getCompressionType().equals("packbits")) { comp = compPackBits; tiffComp = PACKBITS; } else if (p.getCompressionType().equals("lzw")) { comp = compLZW; tiffComp = LZW; } else if (p.getCompressionType().equals("jpeg")) { comp = compJPEG; tiffComp = JPEG; } // System.out.println("comp = "+p.getCompressionType()+" "+comp); } switch (pmi) { case WhiteIsZero: switch (comp) { case compBaselineMH: ifd = writeBModHufImage(out, image, p); break; case compT4MH: case compT4MR: case compT6MMR: ifd = TIFFClassFFactory.writeImage(out, image, comp, p); break; default: ifd = writeRGBImage(out, image, NOCOMPRESSION, p); break; // write image data as uncompressed rgb data. } break; case BlackIsZero: switch (comp) { default: ifd = writeGrayImage(out, image, tiffComp, p); break; } break; case RGB: // write image data as uncompressed rgb data. switch (comp) { default: ifd = writeRGBImage(out, image, tiffComp, p); break; } break; case CMYK: switch (comp) { default: ifd = writeCMYKImage(out, image, p); break; } break; case YCbCr: switch (comp) { default: ifd = writeYCbCrImage(out, image, tiffComp, p); break; } break; default: ifd = writeRGBImage(out, image, NOCOMPRESSION, p); break; // write image data as uncompressed rgb data. } ifdptr = ifd.write(out, ifdptr); // write ifd contents, entries and set ifd linked list pointer }
/** * Writes any extension blocks, the Image Descriptor, the image data, and optionally the header * (Signature and Logical Screen Descriptor) and trailer (Block Terminator). * * @param writeHeader Whether to write the header. * @param writeTrailer Whether to write the trailer. * @param sm The stream metadata or <code>null</code> if <code>writeHeader</code> is <code>false * </code>. * @param iioimage The image and image metadata. * @param p The write parameters. * @throws IllegalArgumentException if the number of bands is not 1. * @throws IllegalArgumentException if the number of bits per sample is greater than 8. * @throws IllegalArgumentException if the color component size is greater than 8. * @throws IllegalArgumentException if <code>writeHeader</code> is <code>true</code> and <code>sm * </code> is <code>null</code>. * @throws IllegalArgumentException if <code>writeHeader</code> is <code>false</code> and a * sequence is not being written. */ private void write( boolean writeHeader, boolean writeTrailer, IIOMetadata sm, IIOImage iioimage, ImageWriteParam p) throws IOException { clearAbortRequest(); RenderedImage image = iioimage.getRenderedImage(); // Check for ability to encode image. if (needToCreateIndex(image)) { image = PaletteBuilder.createIndexedImage(image); iioimage.setRenderedImage(image); } ColorModel colorModel = image.getColorModel(); SampleModel sampleModel = image.getSampleModel(); // Determine source region and destination dimensions. Rectangle sourceBounds = new Rectangle(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight()); Dimension destSize = new Dimension(); computeRegions(sourceBounds, destSize, p); // Convert any provided image metadata. GIFWritableImageMetadata imageMetadata = null; if (iioimage.getMetadata() != null) { imageMetadata = new GIFWritableImageMetadata(); convertMetadata(IMAGE_METADATA_NAME, iioimage.getMetadata(), imageMetadata); // Converted rgb image can use palette different from global. // In order to avoid color artefacts we want to be sure we use // appropriate palette. For this we initialize local color table // from current color and sample models. // At this point we can guarantee that local color table can be // build because image was already converted to indexed or // gray-scale representations if (imageMetadata.localColorTable == null) { imageMetadata.localColorTable = createColorTable(colorModel, sampleModel); // in case of indexed image we should take care of // transparent pixels if (colorModel instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel) colorModel; int index = icm.getTransparentPixel(); imageMetadata.transparentColorFlag = (index != -1); if (imageMetadata.transparentColorFlag) { imageMetadata.transparentColorIndex = index; } /* NB: transparentColorFlag might have not beed reset for greyscale images but explicitly reseting it here is potentially not right thing to do until we have way to find whether current value was explicitly set by the user. */ } } } // Global color table values. byte[] globalColorTable = null; // Write the header (Signature+Logical Screen Descriptor+ // Global Color Table). if (writeHeader) { if (sm == null) { throw new IllegalArgumentException("Cannot write null header!"); } GIFWritableStreamMetadata streamMetadata = (GIFWritableStreamMetadata) sm; // Set the version if not set. if (streamMetadata.version == null) { streamMetadata.version = "89a"; } // Set the Logical Screen Desriptor if not set. if (streamMetadata.logicalScreenWidth == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.logicalScreenWidth = destSize.width; } if (streamMetadata.logicalScreenHeight == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.logicalScreenHeight = destSize.height; } if (streamMetadata.colorResolution == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.colorResolution = colorModel != null ? colorModel.getComponentSize()[0] : sampleModel.getSampleSize()[0]; } // Set the Global Color Table if not set, i.e., if not // provided in the stream metadata. if (streamMetadata.globalColorTable == null) { if (isWritingSequence && imageMetadata != null && imageMetadata.localColorTable != null) { // Writing a sequence and a local color table was // provided in the metadata of the first image: use it. streamMetadata.globalColorTable = imageMetadata.localColorTable; } else if (imageMetadata == null || imageMetadata.localColorTable == null) { // Create a color table. streamMetadata.globalColorTable = createColorTable(colorModel, sampleModel); } } // Set the Global Color Table. At this point it should be // A) the global color table provided in stream metadata, if any; // B) the local color table of the image metadata, if any, if // writing a sequence; // C) a table created on the basis of the first image ColorModel // and SampleModel if no local color table is available; or // D) null if none of the foregoing conditions obtain (which // should only be if a sequence is not being written and // a local color table is provided in image metadata). globalColorTable = streamMetadata.globalColorTable; // Write the header. int bitsPerPixel; if (globalColorTable != null) { bitsPerPixel = getNumBits(globalColorTable.length / 3); } else if (imageMetadata != null && imageMetadata.localColorTable != null) { bitsPerPixel = getNumBits(imageMetadata.localColorTable.length / 3); } else { bitsPerPixel = sampleModel.getSampleSize(0); } writeHeader(streamMetadata, bitsPerPixel); } else if (isWritingSequence) { globalColorTable = theStreamMetadata.globalColorTable; } else { throw new IllegalArgumentException("Must write header for single image!"); } // Write extension blocks, Image Descriptor, and image data. writeImage( iioimage.getRenderedImage(), imageMetadata, p, globalColorTable, sourceBounds, destSize); // Write the trailer. if (writeTrailer) { writeTrailer(); } }