如何在Java中加载大图像
我正尝试在Java中加载大图像文件,如果文件太大(我已经尝试通过命令行标记增加堆大小),我正在收到内存错误消息。如何在Java中加载大图像
我加载与以下方式图片:
如果图像是不是我用这个代码TIFF图像:
BufferedImage img = ImageIO.read(fileToOpen);
如果该文件是一个TIFF我使用这个代码:
BufferedImage img = JAI.create("fileload",
fileToOpen.getAbsolutePath()).getAsBufferedImage();
我的问题实际上归结为:图像处理程序(如Photoshop)如何加载数百兆字节的文件而不会出现内存错误?
这是我的理解,20MB jpeg难以加载到内存中的原因是,因为当加载到BufferedImage例如您保存图像以未压缩的方式。所以一个可能的解决方案是拥有一个Java类,该类继承了Image抽象类的子类,但将数据存储为压缩格式。但是这可能会带来速度问题,因为运行时机器在绘图时不得不解压缩数据。另一种选择是将未压缩的原始数据缓存到磁盘并从中无缝读取,但速度问题仍然存在。
那么大男孩们怎么做呢? Photoshop如何在内存中加载200MB jpeg并绘制所有分辨率而不会出现任何明显问题?
(最后提示:在我因为速度问题的应用程序后,我让我的BufferedImage我画的内容到具有相同尺寸的VolatileImage这增加了拉丝速度大大)
未压缩RGBA图像所需的内存是宽*高* 4字节。尝试根据此设置你的记忆。底层JDK/DirectX /等可能会有大小限制。系统。
大男孩利用JPG图像的结构,他们不需要将其加载到内存中。也许他们每次都直接从文件中提取它。
BufferedImage具有类似于易失性图像的自动加速功能。将加速优先级设置为1,第一个绘图将在最新的JDK上将其移至VRAM。
编辑我假设你正在运行一个32位系统。如果您的未压缩映像很大,超过1.4GB,由于JVM限制,您将无法在内存中处理它。如果图像不是一次性图像,那么您可以找到工具将其解压缩为临时原始图像,并使用随机文件访问来抓取部分图像。
诀窍是不处理全尺寸的图像。将其分为可管理的片段,例如当前分辨率的50 x 50像素,并在需要时从原始文件生成内容。如果不需要给定片段(例如,关闭屏幕),则可以将其删除(弱参考将是完美的)或者持续到磁盘。
解决方案是BigBufferedImage。它可以加载和存储比内存限制大得多的图像。诀窍是它的缓冲区被替换为基于文件的DataBuffer实现。它将图像存储在硬盘上。没有使用RAM。这可以防止OutOfMemoryException。
从图像文件创建一个BigBufferedImage:
BigBufferedImage image = BigBufferedImage.create(
inputFile, tempDir, TYPE_INT_RGB);
创建一个空BigBufferedImage:
BigBufferedImage image = BigBufferedImage.create(
tempDir, width, height, TYPE_INT_RGB);
有关大图像处理read this article更多信息。
谢谢你的回答。尤其是设定的加速度部分。我保留正确的投票按钮,以防有人提出更适用的(对我的情况)回答 – 2009-07-13 14:11:45
您的意思是接受答案。投票赞成有用的答案是免费的,您可以为每个答案做到这一点,不需要保留答案,除非您已经因为限额而用完选票。您也可以选择优化您的问题,也许我(或其他人)可以提出更准确的答案。 – akarnokd 2009-07-13 14:16:17