RenderedImage to BufferedImage for multipage-tiff reading

时间:2011-08-12 18:17:21

标签: java jai

我正在使用JAI加载多页TIFF图像

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);

但是,在最后一行中我得到一个运行时错误:

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

我在尝试设置BufferedImage后清除了RenderedImage,所以如果有另一种方法,我不会“需要”RenderedImage。

我试过了:

 pg1.setData(op1.getData());

,这给出了一个ArrayIndexOutOfBoundsException。我不确定为什么pg1的宽度和高度完全由op1设置,但可能有一个非常正确的原因。

6 个答案:

答案 0 :(得分:10)

我在http://www.jguru.com/faq/view.jsp?EID=114602

找到了解决方案

第一个没有用,但是convertRenderedImage函数确实有效。

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;
}

答案 1 :(得分:4)

使用op1。getAsBufferedImage()创建pg1。

答案 2 :(得分:2)

如果您遇到RenderedImage,可以使用

PlanarImage.wrapRenderedImage(renderedImage).getAsBufferedImage() 

请参阅here了解文档

答案 3 :(得分:1)

JAI显然有一个“转换器”类:

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

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

答案 4 :(得分:0)

试试这个:

params

答案 5 :(得分:0)

加载TIFF的最简单方法是使用带有提供插件的Twelve Monkey,以将TIFF格式支持到标准Java ImageIO中。

只需在Maven依赖项下面添加

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

现在,您将能够使用ImageIO直接加载TIFF文件。

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

这非常简单且可靠,因为它使用标准的Java ImageIO API进行所有处理。

只有十二只猴子的插件提供SPI插件才能提供对TIFF的支持。

在此处添加了一个正在运行的示例程序,即Java 8,它读取TIFF文件并创建一个多页TIFF文件:

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();

它与Java 8一起使用,如果有人想添加压缩,只需在行中注释并添加适当的压缩名称即可。