5

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.

Robert
  • 1,745
  • 5
  • 34
  • 61

6 Answers6

11

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;
}
Robert
  • 1,745
  • 5
  • 34
  • 61
  • This brings up an interesting point, BufferedImage "descends" from RenderedImage, so sometimes when you are passing around a RenderedImage, it is actually a BufferedImage. Go figure. – rogerdpack Jul 18 '16 at 17:59
4

Use op1.getAsBufferedImage() to create pg1.

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
Jeffrey
  • 44,417
  • 8
  • 90
  • 141
  • How do I get to getAsBufferedImage() from RenderedImage? – Robert Aug 12 '11 at 18:29
  • Don't declare op1 as a `RenderedImage`, declare it as a `NullOpImage`, or a `PlanarImage`. – Jeffrey Aug 12 '11 at 18:30
  • Ah, okay. I didn't know which object types new NullOpImage could be used with. The PlanarImage version handles it correctly. I didn't notice any difference in speed between it and the convertRenderedImage function I linked to in my answer, but it doesn't require reinventing the wheel and more likely to be optimized. – Robert Aug 12 '11 at 18:38
2

If you are stuck with a RenderedImage, you can use

PlanarImage.wrapRenderedImage(renderedImage).getAsBufferedImage() 

see here for documentation

heisbrandon
  • 1,180
  • 7
  • 8
2

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

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
0

Try this :

   RenderedImage im =  dec.decodeAsRenderedImage();
   BufferedImage bi = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();
Saurabh Mistry
  • 12,833
  • 5
  • 50
  • 71
0

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.

Sandeep Kumar
  • 596
  • 5
  • 7