读取和写入大图像
Posted
技术标签:
【中文标题】读取和写入大图像【英文标题】:Read and Write a large Image 【发布时间】:2016-05-30 05:09:46 【问题描述】:我需要逐个像素地读取和写入图像(我正在生成分形)。当我尝试使用图像尺寸时,我意识到当图像尺寸很大(比如 24000x18000)时使用BufferedImage
写入图像会导致OutOfMemoryError
。为了解决这个问题,我使用了-Xmx -Xms
来增加堆大小。
有没有办法以像素方式写入图像而不必将整个图像加载到内存中?读取(和修改)大图像也是如此。
编辑
我正在逐个像素,从左到右,从上到下。
【问题讨论】:
您是从左到右、从上到下逐像素生成图像吗?如果是这样,您也许可以安排连续编写它。但是,如果您需要在写入之前完全生成图像,则必须先将其存储在内存中。你的问题不清楚... @JimGarrison 是的,我从左到右,从上到下逐个像素地进行操作。能否请您回答如何连续执行? 您可能不得不绕过标准图像代码并直接编写图像格式。这可能是相当多的工作,并且超出了我的专业知识范围。也许其他人会回答。我建议您重写问题以更清楚地解释您在做什么,而不是进行编辑。 看看:***.com/questions/18466513/… 【参考方案1】:最简单的解决方案通常只是添加更多内存。 :-)
但是,有一些选项(我在您的问题中没有找到足够的信息来决定哪个是最好的,请考虑更新它):
为您的图像编写一个最小格式标题(BMP 很容易,TIFF 也可行),为您的图像分配该格式所需的磁盘空间,并对该区域进行内存映射。这将类似于使用虚拟内存。系统会一次将文件的区域复制到内存中,因此您应该一次在有限的区域上工作,以避免过多的交换。
我已经编写了一些类来允许使用像BufferedImage
、MappedImageFactory
和MappedFileBuffer
这样的文件(相当慢)。这些可以与上述结合,以获得“实时”更新文件,或者使用更熟悉的ImageIO
API 来读取/写入大文件(读入此类图像所需的特殊代码,请参阅MappedImageFactory.createCompatibleMappedImage(w, h, type)
和 @987654328 @)。
使用ImageIO
API 读取和写入切片(固定大小的区域)。我所知道的唯一支持图块的图像格式是 TIFF。我认为来自ja_imageio.jar
的TIFFImageReader
和TIFFImageWriter
将支持平铺。 RenderedImage
API 也支持平铺。平铺也可以与内存映射技术结合使用,以获得更好的性能(即将平铺复制到正常的BufferedImage
以获得更快的 Java2D 操作)。
使用ImageIO
API 读取和写入任意子区域。使用ImageReadParam.setSourceRegion(...)
读取区域很容易。 ImageWriter.canReplacePixels()
方法会告诉你作者是否支持写入区域。不幸的是,我不知道当前支持此功能的任何ImageWriter
实现,但从理论上讲,如果您想自己实现它,任何未压缩格式都应该很容易。
这个列表可能并不详尽。
【讨论】:
感谢您的回答。这是一个相当详细的。我会等待一段时间,如果我没有得到更好的答案,我会将此标记为答案。【参考方案2】:我同意 haraldK 提出的解决方案。 18Kx24K 可以轻松加载到内存中。
但是当你逐个像素地进行时,你也可以使用BigBufferedImage,它被呈现在this post中。图像不会加载到内存中,而是存储到文件中。
【讨论】:
以上是关于读取和写入大图像的主要内容,如果未能解决你的问题,请参考以下文章