2009-08-02 201 views
1

我想将一些java.awt.Image对象保存到磁盘中。但是当我尝试像:使用BufferedImage和ImageIO保存图像时内存不足问题

for (Image image : images) { 
    image = new ImageIcon(image).getImage(); 
    BufferedImage temp = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB); 
    Graphics2D g = temp.createGraphics(); 
    g.drawImage(image, 0, 0, null); 
    g.dispose(); 
    File tempFile = null; 
    try { 
     tempFile = File.createTempFile("img", ".jpg"); 
     ImageIO.write(temp, "jpg", tempFile); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    files.add(tempFile); 
} 

我得到java堆空间错误。

我需要把

image = new ImageIcon(image).getImage(); 

得到加载,这样image.getwidth(空)和image.getHeight(空)返回有效结果的所有像素。

除了增加堆大小之外,还有其他的方法吗?

+0

多大的图像?你用Xmx来增加内存吗?为什么不使用ImageIO.read(URL)和朋友来获取BufferedImage的图像? – akarnokd 2009-08-02 17:14:17

+0

我很困惑,为什么你需要ImageIcon,以及为什么你需要用图形上下文绘制图像。如果只用`try/catch`块迭代`images`会发生什么? – banjollity 2009-08-02 17:15:47

+0

@ kd304 图像可以是任意大小。我从扫描仪中提取它们。我用来从扫描仪获取图像的代码返回对java.awt.Image对象的引用。 我无法通过向JVM传递参数来增加内存,因为我在applet中执行此操作,而且我不想打扰用户进行配置。 – 2009-08-02 20:10:28

回答

1

你可以通过不把所有的图像保存在一个集合中然后迭代来保存一些堆。相反,检索和写入每个图像,你得到它。我建议的代码中的hasMoreImages()scanner.getNextImage()部分是这样的一个可能的实现。

我也会质疑用Graphics上下文绘制图像的智慧,当它可能已经处于可以用ImageIO编写的状态时。 ImageIO.write()需要一个RenderedImage,所以快速实例检查可能已经足够好了。

while(hasMoreImages()) { 
    Image image = scanner.getNextImage(); 

    if (image instanceof RenderedImage)) { 
     File tempFile = File.createTempFile("img", ".jpg"); 
     ImageIO.write((RenderedImage)image, "jpg", tempFile); 
     files.add(tempFile); 
    } else { 
     // Do your ImageIcon code thing here. 
    } 
} 
1

您的问题是图像扫描仪是巨大 - 以600 dpi,我们谈论了100 MB每色A4页面压缩。良好的扫描仪可以以数千DPI扫描 - 在2000 DPI时,单个未压缩的彩色页面将超过1 GB。高质量扫描的大小会吸引大多数人在第一次开始与他们合作时没有做好准备。

除非您正在运行带有演出和演出的RAM的64位操作系统,否则您永远不会在内存中放入超过几张图片。扫描黑色&白色或灰度和较低的分辨率将有所帮助,但最好的解决方案是改变处理图像的方式。

不要在内存中获取图像集合 - 一次获取每张图像的,并写出图像直至完成。把你的TWAIN驱动程序和API工作 - 让它通过你的缓冲区与图像的一部分,直到完成。你可能是关闭使用Java库更好地做到这一点比滚动自己的图像处理


编辑:链接的Java库TWAIN