使用JAI将swing组件写入大TIFF图像

我有一个大的swing组件写入TIFF。 组件太大而无法在内存中加载TIFF,因此我需要制作一个大的BufferedImage,它由基于磁盘的WritableRaster(如此处所述)支持或使用JAI。

除了项目的完全混乱之外,JAI似乎是更好的答案。

鉴于此,有人可以概述将我的swing组件写入平铺TIFF而不会耗尽内存的步骤吗?

图像大小可能是10000×700

理想情况下,我会创建某种基于磁盘的映像,并将组件的一部分写入其中,每次写入都会刷新到磁盘。

编辑

我想我可以用ImageWriter做到这一点,但是当我调用时,我得到一个NoSuchElementException:

ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tif").next(); 

我的classpath上有jai_code.jar和jai_core.jarjar子,还有什么我需要做的吗?

编辑我可以使用JAI创建一个非常大的TIFF,但JAI不支持TIFF压缩,因此文件是92 MB。

如果我安装JAI-ImageIO,我可以使用ImageWriter创建一个压缩的TIFF,但只能使用Raster或BufferedImage,而我没有足够的内存。

有没有办法做两步法,使用JAI创建大TIFF,然后压缩大TIFF而不将整个内容加载到内存中?

我不得不加载并存储一个大的tiff(59392x40192px)与JAI。 我的解决方案是:TiledImages。

我使用了TiledImage,因为我需要tile和subimages。 要使用TiledImage效率,您应该使用您喜欢的磁贴大小来构建它。 JAI使用TileCache,因此当不需要时,整个Image都不会在内存中。

要在文件中编写TiledImage,请使用选项“writeTiled”(避免使用OutOfMemory,因为它逐个tile地写入):

 public void storeImage(TiledImage img, String filepath) { TIFFEncodeParam tep = new TIFFEncodeParam(); //important to avoid OutOfMemory tep.setTileSize(256, 256); tep.setWriteTiled(true); //fast compression tep.setCompression(TIFFEncodeParam.COMPRESSION_PACKBITS); //write file JAI.create("filestore", img, filepath, "TIFF", tep); } 

它适用于高达690mb(压缩)的图像,对于尚未测试的较大图像。

但是,如果你正在使用32位WinXP,你可能无法拥有更多的1280m HeapSpace大小,这仍然是Java VM的限制。

我的TiledImage是使用我的图像源数据中的IndexedColorModel构建的:

 //here you create a ColorModel for your Image ColorModel cm = source.createColorModel(); //then create a compatible SampleModel, with the tilesize SampleModel sm = cm.createCompatibleSampleModel(tileWidth,tileHeight); TiledImage image = new TiledImage(0, 0, imageWidth, imageHeight, 0, 0, sm, cm); 

我有相同的情况,我使用这些步骤:

  • 使用JAI 加载为BufferedImage

  • 使用Image#getScaledInstance(int w,int h,Image.SCALE_SMOOTH)将 BufferedImage大小调整为优选大小(600x600px)以保持宽高比

  • 使用JComponent#paintComponent(java.awt.Graphics)方法中的Graphics2d.drawImage(..)方法绘制图像

这帮助我显示和操作TIFF图像~50MB(5000x5000px)。