使用BufferedImage和ImageIO保存图像时内存不足问题

时间:2009-08-02 15:40:07

标签: java out-of-memory jai

我想将一些java.awt.Image对象保存到磁盘中。但是,当我尝试:

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(null)和image.getHeight(null)返回有效结果。

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

2 个答案:

答案 0 :(得分: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 :(得分:1)

您的问题是扫描仪图像是巨大 - 在600 dpi时,我们说的是每张A4彩页未压缩的100 MB。好的扫描仪可以在数千DPI上进行扫描 - 在2000 DPI时,单个未压缩的彩色页面将超过1 GB。高质量扫描的大小让大多数人在第一次开始使用它们时毫无准备。

除非你在运行带有演出和演出的64位操作系统,否则你永远不会在内存中安装多个图像。扫描黑色&白色或灰度以及较低的分辨率会有所帮助,但最佳解决方案是更改处理图像的方式。

不要在内存中获取图像集合 - 一次获取每个图像的部分,然后写出图像直到完成。让你的TWAIN驱动程序和API工作 - 让它通过你的缓冲区与图像的一部分,直到完成。您可能最好使用Java库来完成此操作,而不是滚动自己的图像处理


编辑:Java TWAIN库的链接