读取和写入大图像

Abd*_*tir 2 java bufferedimage image out-of-memory

我需要逐像素读取和写入图像(我正在生成分形)。当我尝试使用图像大小时,我意识到当图像大小很大(例如 24000x18000)时写入图像BufferedImage会导致OutOfMemoryError. 为了解决这个问题,我曾经-Xmx -Xms增加堆大小。

有没有一种方法可以按像素写入图像,而无需将整个图像加载到内存中?读取(和修改)大图像也是如此。

编辑

我从左到右、从上到下逐个像素地进行操作。

har*_*ldK 5

最简单的解决方案通常就是添加更多内存。:-)

但是,有一些选项(我在您的问题中没有找到足够的信息来决定哪一个是最好的,请考虑更新它):

  • 为您的图像编写一个最小格式标头(BMP 很容易,TIFF 也可以),以该格式分配图像所需的磁盘空间,并在内存中映射该区域。这与使用虚拟内存类似。系统一次会将文件的区域复制到内存中,因此您应该一次在有限的区域上工作,以避免过多的交换。

  • 我编写了一些类来允许使用这样的文件(相当慢)BufferedImage,MappedImageFactoryMappedFileBuffer. 这些可以与上面的结合起来,得到一个“实时”更新文件,或者使用更熟悉的ImageIOAPI 来读/写大文件(读入此类图像需要特殊代码,请参阅MappedImageFactory.createCompatibleMappedImage(w, h, type)ImageReadParam.setDestination(image))。

  • 使用ImageIOAPI 读取和写入图块(固定大小的区域)。据我所知,唯一本身支持图块的图像格式是 TIFF。我认为TIFFImageReaderTIFFImageWriterfromja_imageio.jar将支持平铺。API中还支持RenderedImage平铺。平铺可能还可以与内存映射技术相结合,以获得更好的性能(即将平铺复制到正常状态BufferedImage以实现更快的 Java2D 操作)。

  • 使用ImageIOAPI​​读取和写入任意子区域。使用 读取区域很容易ImageReadParam.setSourceRegion(...)。该ImageWriter.canReplacePixels()方法会告诉您 writer 是否支持写入区域。不幸的是,我不知道ImageWriter目前有任何支持此功能的实现,但理论上,如果您想自己实现的话,对于任何未压缩的格式来说,它应该很容易。

该列表可能并不详尽。