内存不足问题,保存大型BufferedImage [英] Out of memory problem saving large BufferedImage

查看:392
本文介绍了内存不足问题,保存大型BufferedImage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在保存大型(12 000 x 9 000)图像方面遇到了问题。

I have a problem saving large (f.e. 12 000 x 9 000 ) images.

我正在开发一个图形编辑软件(类似于简单的Photoshop)和
用户显然必须能够保存图像。

I'm developing a graphical editing software ( something like simple Photoshop ) and The user obviously has to have to ability to save the image.

假设我想将图像另存为.png。
JAVA是否总是需要使用BufferedImage来保存绘制的东西?

Lets say I would like to save the image as .png. Does JAVA always need to use the BufferedImage for saving drawn stuff ?

我知道图像大小的等式是:
Xsize * Ysize * 4(红色,绿色,蓝色,阿尔法)
所以在这种情况下我们得到超过400 MB。

I know the equation for size of the image is: Xsize * Ysize * 4 ( red, green, blue, alpha ) So in this case we get over 400 MB.

我知道我可以将图像保存在部分中(但是用户必须以某种方式合并它们。

I know I could save the image in parts ( tiles ) but the user would have to merge them somehow anyway.

有没有其他方法可以在不使用BufferedImage的情况下保存这么大的图像?

Is there any other way to save such a large image without using the BufferedImage ?

保存图片的代码:

 public static void SavePanel() {

    BufferedImage image = null;
    image =  new BufferedImage(
            (int) (Main.scale * sizeX ),
            (int) (Main.scale * sizeY ),
            BufferedImage.TYPE_INT_RGB);

    g2 = image.createGraphics();
    panel.paint(g2);


    try {
        ImageIO.write(image, "png", new File(FactoryDialog.ProjectNameTxt.getText() + ".png"));
    } catch (IOException e) {
    }


}

提前谢谢!

推荐答案

ImageIO.write(。 。)方法接受 RenderedImage ,而不仅仅是 BufferedImage 。我前段时间成功地利用了这个事实来写出非常大的图像。通常,编写器实现按顺序写出图像,并仅针对他们当前需要的部分询问 RenderedImage

The ImageIO.write(..) methods accept an RenderedImage, not just a BufferedImage. I successfully exploited this fact some time ago to write out really large images. Generally, the writer implementations write out the image sequentially, and ask the RenderedImage only for the pieces they currently need.

从查看代码开始,我认为应该可以破解 RenderedImage 实现,其中包含面板构造函数,可以传递给 ImageIO 进行编写。在此过程中, ImageIO 将从您的图像中请求数据。然后,您可以使用该面板动态创建所请求的部分( Raster 内容)。这样,整个图像不必在任何点存储在存储器中。这种方法的出发点是

From looking at your code, I think it should be possible to hack a RenderedImage implementation which takes your panel in it's constructor and can be passed to ImageIO for writing. During the process, ImageIO will request data from your image. You can then use the panel to create the requested pieces (Raster contents) on the fly. This way, the whole image does not have to be stored in memory at any point. A starting point for this approach is

public class PanelImage implements RenderedImage {

   private final Panel panel;

   public PanelImage(Panel panel) {
      this.panel = panel;
   }

   /* implement all the missing methods, don't be afraid, most are trivial */

}

显然,您还应该检查面板是否没有遇到同样的问题作为 BufferedImage 。根据应用程序的性质,您必须至少将图像保存在内存中一次(使用图块模数)。但这样你至少可以避免重复。

Obviously, you should also check if your panel doesn't suffer from the same problem as the BufferedImage. Depending on the nature of you application, you'll have to hold the image in memory at least once anyway (modulo using tiles). But this way you can at least avoid the duplication.

这篇关于内存不足问题,保存大型BufferedImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆