Robert
Robert

Reputation: 1794

RenderedImage to BufferedImage for multipage-tiff reading

I am using JAI to load in multipage TIFF images

File file = workArea[0];
SeekableStream s = new FileSeekableStream(file);

TIFFDecodeParam param = null;

ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);

//first page
RenderedImage op1 =
    new NullOpImage(dec.decodeAsRenderedImage(0),
                    null,
                    OpImage.OP_IO_BOUND,
                    null);

BufferedImage pg1 = new BufferedImage(op1.getWidth(), op1.getHeight(),
                                      BufferedImage.TYPE_INT_RGB);
pg1.getGraphics().drawImage((Image) op1, 0, 0, null);

However, in the last line I get a runtime error of:

 Exception in thread "main" java.lang.ClassCastException: 
      javax.media.jai.MullOpImage cannot be cast to java.awt.Image

I clear the RenderedImage after attempting to set the BufferedImage so I don't exactly "need" the RenderedImage if there is another method of doing this.

I attempted:

 pg1.setData(op1.getData());

and that gives an ArrayIndexOutOfBoundsException. I'm not sure why exactly as pg1's width and height are set by op1's, but there is probably a very valid reason.

Upvotes: 5

Views: 20004

Answers (6)

Sandeep Kumar
Sandeep Kumar

Reputation: 682

The easiest way to load TIFF is using Twelve Monkey with provide plugin to support TIFF format into Standard Java ImageIO.

Just add below Maven dependency,

<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.5</version>
</dependency>

Now, you will be able to load TIFF file directly Using ImageIO.

ImageReader imageReader1 = SPI.createReaderInstance();
ImageInputStream iis1 = ImageIO.createImageInputStream(new File("1.tif"));
imageReader1.setInput(iis1);
BufferedImage = imageReader1.read(0); 

It is very easy and reliable because it uses standard Java ImageIO API for all processing.

Only the Plugin from Twelve Monkey provide the SPI plugin to provide support of TIFF.

Adding here one example program which is running is Java 8 and it reads TIFF files and create a single multi-page TIFF file:

BufferedImage b1 = null;
BufferedImage b2 = null;

TIFFImageReaderSpi SPI = new TIFFImageReaderSpi();

ImageReader imageReader1 = SPI.createReaderInstance();
ImageInputStream iis1 = ImageIO.createImageInputStream(new File("1.tif"));
imageReader1.setInput(iis1);
b1 = imageReader1.read(0); 

ImageReader imageReader2 = SPI.createReaderInstance();
ImageInputStream iis2 = ImageIO.createImageInputStream(new File("2.tif"));
imageReader2.setInput(iis2);
b2 = imageReader2.read(0);

ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();

writer.setOutput(ImageIO.createImageOutputStream(new File("3.tif")));

ImageWriteParam writeParam = writer.getDefaultWriteParam();
//writeParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
//writeParam.setCompressionType("Deflate");

writer.prepareWriteSequence(null);

IIOImage i1 = new IIOImage(b1, null, null);
IIOImage i2 = new IIOImage(b2, null, null);

writer.writeToSequence(i1, writeParam);
writer.writeToSequence(i2, writeParam);


writer.endWriteSequence();
writer.dispose();

It is working with Java 8, if someone wants to add compression just comment the line and add appropriate compression name.

Upvotes: 0

Ankursonikajen
Ankursonikajen

Reputation: 61

Try this :

   RenderedImage im =  dec.decodeAsRenderedImage();
   BufferedImage bi = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();

Upvotes: 0

rogerdpack
rogerdpack

Reputation: 66711

JAI apparently has a "converter" class in there:

ImageDecoder dec = ImageCodec.createImageDecoder("PNM", new File(input), null);
return new RenderedImageAdapter(dec.decodeAsRenderedImage()).getAsBufferedImage()

ref: http://www.programcreek.com/java-api-examples/index.php?api=com.sun.media.jai.codec.ImageDecoder

Upvotes: 2

Jeffrey
Jeffrey

Reputation: 44798

Use op1.getAsBufferedImage() to create pg1.

Upvotes: 4

heisbrandon
heisbrandon

Reputation: 1220

If you are stuck with a RenderedImage, you can use

PlanarImage.wrapRenderedImage(renderedImage).getAsBufferedImage() 

see here for documentation

Upvotes: 2

Robert
Robert

Reputation: 1794

I found a solution at http://www.jguru.com/faq/view.jsp?EID=114602

The first one didn't work, however, the convertRenderedImage function did work.

public BufferedImage convertRenderedImage(RenderedImage img) {
    if (img instanceof BufferedImage) {
        return (BufferedImage)img;  
    }   
    ColorModel cm = img.getColorModel();
    int width = img.getWidth();
    int height = img.getHeight();
    WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
    Hashtable properties = new Hashtable();
    String[] keys = img.getPropertyNames();
    if (keys!=null) {
        for (int i = 0; i < keys.length; i++) {
            properties.put(keys[i], img.getProperty(keys[i]));
        }
    }
    BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
    img.copyData(raster);
    return result;
}

Upvotes: 12

Related Questions