保存大型 BufferedImage 时出现内存不足问题

发布于 11-24 08:05 字数 815 浏览 2 评论 0原文

我在保存大(fe 12 000 x 9 000)图像时遇到问题。

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

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

我知道图像大小的方程式是: X尺寸 * Y尺寸 * 4(红、绿、蓝、alpha) 因此,在本例中我们获得了超过 400 MB 的空间。

我知道我可以将图像保存为多个部分(图块),但用户无论如何都必须以某种方式合并它们。

有没有其他方法可以在不使用 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) {
    }


}

先谢谢您!

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

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

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

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.

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

Code for saving the image:

 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) {
    }


}

Thank you in advance !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柠檬2024-12-01 08:05:19

使用像 image magick 这样的原生图像缩放器。

Using native image resizer like image magick instead.

温柔女人霸气范2024-12-01 08:05:17

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

通过查看您的代码,我认为应该可以破解一个 RenderedImage 实现,该实现将您的 panel 放入其构造函数中,并可以传递给 ImageIO > 用于写作。在此过程中,ImageIO 将从您的图像请求数据。然后,您可以使用该面板动态创建请求的片段(Raster 内容)。这样,整个图像在任何时候都不必存储在内存中。这种方法的出发点是

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 相同的问题。根据应用程序的性质,无论如何,您都必须在内存中至少保存一次图像(使用图块取模)。但这样至少可以避免重复。

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.

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 */

}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文