Donnerstag, 23. Juni 2016

Java: Load TIFF images into BufferedImage

One can believe that loading TIFF images in Java is quite simple as accessing jpg or png via the ImageIO factory:

BufferedImage img = ImageIO.read(new File("/path/to/tiff"));

Unfortunately TIFF ist not supported in vanilla JRE or JDK. So ImageIO.read returns just null.

To get a list of the built-in image formats just query:


for (String format: ImageIO.getReaderFormatNames()) {
  System.out.println(format);
}


Output is:

JPG
jpg
bmp
BMP
gif
GIF
WBMP
png
PNG
jpeg
wbmp
JPEG


In fact TIFF has many options concerning compression, multi-page ...

I need to open GROUP-4 compressed TIFFs with multiple pages to scan individual pages for barcodes.
I tried ImageJ together with bio-formats which was able to deal with multi-page tiffs. In the end the ImageJ library could not process the group-4 compression which is state of the art in TIFF scans.


Java Advanced Imaging (JAI)


I early read about JAI but it seems to be retired and web resources pointed out that installation is required. This is not the case.
After some hard search it was sufficiend to place two jars in the classpath:
  • jai-core.jar
  • jai-codec.jar

The latest version seems to be 1.1.3 and I found the jars on www.java2s.com . I have no idea why there is no offical binary distribution available.

Now I was able to load the TIFF file, get page count and convert single pages to BufferedImage:


import javax.media.jai.PlanarImage;

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.SeekableStream;

File file = new File("/path/to/tiff");

SeekableStream stream = new FileSeekableStream(file);
String[] names = ImageCodec.getDecoderNames(stream);
ImageDecoder decoder = ImageCodec.createImageDecoder(names[0], stream, null);

for (int i=0; i<decoder.getNumPages(); i++) {
  RenderedImage im = decoder.decodeAsRenderedImage(i);
  
  BufferedImage img = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();

  // Do somthing with the BufferedImage
}

In the end quite easy.



Keine Kommentare:

Kommentar veröffentlichen