Java RenderImage到BuffereImage用于多页tiff读取

Java RenderImage到BuffereImage用于多页tiff读取,java,jai,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

我正在使用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
我在尝试设置BuffereImage后清除了RenderImage,因此如果有其他方法,我不需要RenderImage

我试图:

 pg1.setData(op1.getData());
这就产生了一种ArrayIndexOutOfBoundsException。我不确定为什么pg1的宽度和高度是由op1设置的,但可能有一个非常合理的原因。

使用op1。创建pg1。

我在

第一个不起作用,但是ConvertRenderImage函数起作用了

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;
}
公共缓冲区图像转换器渲染图像(渲染图像img){
if(img instanceof BuffereImage){
返回(缓冲图像)img;
}   
ColorModel cm=img.getColorModel();
int width=img.getWidth();
int height=img.getHeight();
WritableRaster raster=cm.createCompatibleWritableRaster(宽度、高度);
布尔值isAlphaPremultiplied=cm.isAlphaPremultiplied();
Hashtable属性=新的Hashtable();
String[]keys=img.getPropertyNames();
如果(键!=null){
for(int i=0;i
如果您被渲染图像卡住,可以使用

PlanarImage.wrapRenderedImage(renderedImage).getAsBufferedImage() 
有关文档,请参见

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

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

试试这个:

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

加载TIFF的最简单方法是使用十二猴子和提供插件,以支持将TIFF格式加载到标准Java ImageIO中

只需在Maven依赖项下面添加

<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.5</version>
</dependency>
它非常简单和可靠,因为它使用标准的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,如果有人想添加压缩,只需注释行并添加适当的压缩名称。

如何从RenderImage获取AsBufferedImage()?不要将op1声明为
RenderImage
,将其声明为
NullOpImage
PlanariImage
。啊,好的。我不知道新的NullOpImage可以与哪些对象类型一起使用。PlanarImage版本可以正确处理它。我没有注意到它与我在回答中链接的ConvertRenderImageFunction在速度上有任何差异,但它不需要重新设计轮子,更可能被优化。这带来了一个有趣的点,BufferedImages从RenderImages“下降”,所以有时候当你在一个RenderImages周围经过时,它实际上是一个BuffereImage。如图所示。作为说明,我假设它是在代码的后面,但不要忘记那里有一个
s.close
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();