【问题标题】:RenderedImage to BufferedImage for multipage-tiff readingRenderedImage 到 BufferedImage 用于多页 tiff 读取
【发布时间】:2011-08-12 18:17:20
【问题描述】:

我正在使用 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 设置,但可能有一个非常正当的理由。

【问题讨论】:

  • 作为一个注释,我认为它稍后会出现在代码中,但不要忘记s.close :)

标签: java jai


【解决方案1】:

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

【讨论】:

  • 这就引出了一个有趣的点,BufferedImage 是从 RenderedImage “下降”的,所以有时当你绕过一个 RenderedImage 时,它​​实际上是一个 BufferedImage。去图吧。
【解决方案2】:

使用 op1.getAsBufferedImage() 创建 pg1。

【讨论】:

  • 如何从 RenderedImage 获取 getAsBufferedImage()?
  • 不要将 op1 声明为 RenderedImage,将其声明为 NullOpImage 或 PlanarImage。
  • 啊,好吧。我不知道可以使用哪些对象类型 new NullOpImage。 PlanarImage 版本可以正确处理它。我没有注意到它与我在答案中链接到的 convertRenderedImage 函数之间的速度有任何差异,但它不需要重新发明轮子并且更有可能被优化。
【解决方案3】:

如果你被 RenderedImage 卡住了,你可以使用

PlanarImage.wrapRenderedImage(renderedImage).getAsBufferedImage() 

请参阅 here 获取文档

【讨论】:

    【解决方案4】:

    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

    【讨论】:

      【解决方案5】:

      试试这个:

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

      【讨论】:

        【解决方案6】:

        加载 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 进行所有处理。

        只有 Twelve Monkey 的 Plugin 提供 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,如果有人想添加压缩,只需注释该行并添加适当的压缩名称。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-28
          • 1970-01-01
          • 1970-01-01
          • 2017-03-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多