如何通过 BufferedImage 将巨大的图像加载到 Java?
Posted
技术标签:
【中文标题】如何通过 BufferedImage 将巨大的图像加载到 Java?【英文标题】:How do I load an enormous image to Java via BufferedImage? 【发布时间】:2013-02-28 17:10:46 【问题描述】:我想将大图像 (18000 x 18000) 加载到我的应用程序中。如果我使用BufferedImage
类型为int_rgb
,我需要大约1235mb 的堆内存来加载。这是一个非常大的内存量,最终用户的内存可能会更少(1GB 或更少)。
在我的开发 PC 上,当我从 MyEclipse IDE 加载图像时,它会引发内存不足 Exception
。当我将代码打包到可执行 jar 并在 Eclipse 外部的 PC 上运行时,它仍然会引发异常。
如何在不使用 1235mb 内存的情况下使用缓冲图像将如此大的图像加载到我的应用程序中?有没有什么技巧,比如将图像分割成更小的部分,比如图像分割?
我找到了this thread on SO,但它对我没有用;我想将图像加载到BufferedImage
,然后使用Graphics
类将其绘制在Panel
上。
【问题讨论】:
【参考方案1】:您可以使用来自ImageIO
包的ImageReadParam 读取和显示图像片段。这是一个基本示例,说明如何使用ImageReadParam
读取单个片段而不读取整个图像:
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.*;
public class TestImageChunks
private static void createAndShowUI()
try
URL url = new URL(
"http://duke.kenai.com/wave/.Midsize/Wave.png.png");
Image chunk = readFragment(url.openStream(), new Rectangle(150,
150, 300, 250));
JOptionPane.showMessageDialog(null, new ImageIcon(chunk), "Duke",
JOptionPane.INFORMATION_MESSAGE);
catch (IOException e)
JOptionPane.showMessageDialog(null, e.getMessage(), "Failure",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
public static BufferedImage readFragment(InputStream stream, Rectangle rect)
throws IOException
ImageInputStream imageStream = ImageIO.createImageInputStream(stream);
ImageReader reader = ImageIO.getImageReaders(imageStream).next();
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(rect);
reader.setInput(imageStream, true, true);
BufferedImage image = reader.read(0, param);
reader.dispose();
imageStream.close();
return image;
public static void main(String[] args)
SwingUtilities.invokeLater(new Runnable()
public void run()
createAndShowUI();
);
结果如下所示:
【讨论】:
感谢您宝贵的 cmets,我会试试这个并告诉您。 我成功地实施了您的解决方案并且它奏效了。请在这个问题上帮助我***.com/questions/15438506/…【参考方案2】:通常,您需要执行以下操作:
将图像分解为可管理大小的图像文件,并将它们与您的应用程序一起存储在磁盘上。 显示此图像的特定部分时,仅加载和显示与您的视口重叠的图像片段。 在您平移图像时,适当地更新加载和显示的图像片段。 要么让 GC 收集不必要的图像片段,要么以覆盖旧图像的方式加载新的图像片段。 (这最后主张加载到池化内存缓冲区中的相同大小的图像片段。)【讨论】:
我同意你的理论。事实上我很高兴我一直在朝同一个方向思考,但是你能给我一个例子或代码 sn-ps 吗?以上是关于如何通过 BufferedImage 将巨大的图像加载到 Java?的主要内容,如果未能解决你的问题,请参考以下文章
java:BufferedImage判断图像通道顺序并转RGB/BGR