我有一个大的swing组件要写入TIFF。该组件太大,无法在内存中加载TIFF,因此我需要制作一个大的BufferedImage,它由基于磁盘的WritableRaster支持(如here所述)或使用JAI。
除了项目的完全混淆之外,JAI似乎是更好的答案。鉴于此,有人可以概述将我的swing组件写入平铺TIFF而不会耗尽内存的步骤吗?
图像大小可能是10000x700
理想情况下,我会创建某种基于磁盘的映像,并将组件的一部分写入其中,每次写入都会刷新到磁盘。
修改
我想我可以使用ImageWriter执行此操作,但是当我调用时,我收到NoSuchElementException:
ImageWriter imageWriter = ImageIO.getImageWritersByFormatName("tif").next();
我的classpath上有jai_code.jar和jai_core.jar jar,还有什么我需要做的吗?
修改 我可以使用JAI创建一个非常大的TIFF,但是JAI不支持TIFF压缩,所以文件是92 MB。
如果我安装了JAI-ImageIO,我可以使用ImageWriter创建一个压缩的TIFF,但只能使用Raster或BufferedImage,而我没有足够的内存。
有没有办法做两步法,使用JAI创建大TIFF,然后压缩大TIFF而不将整个内容加载到内存中?
答案 0 :(得分:2)
我不得不加载并存储一个大的tiff(59392x40192px)和JAI。我的解决方案是:TiledImages。
我使用了TiledImage,因为我需要tile和subimages。 要使用TiledImage效率,您应该使用您喜欢的磁贴大小来构建它。 JAI使用TileCache,因此当不需要时,不会将整个Image放在内存中。
要在文件中写入TiledImage,请使用“writeTiled”选项(避免使用OutOfMemory,因为它会逐层写入):
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);
答案 1 :(得分:1)
我有同样的情况,我使用了这些步骤:
以JAI
将BufferedImage 大小调整为优选大小(600x600px),保持宽高比
使用Graphics2d.drawImage(..)方法中的JComponent#paintComponent(java.awt.Graphics)方法绘制图片
这帮助我显示和操作TIFF图像~50MB(5000x5000px)。