保存大型 BufferedImage 时出现内存不足问题
我在保存大(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用像 image magick 这样的原生图像缩放器。
Using native image resizer like image magick instead.
ImageIO.write(..)
方法接受RenderedImage
,而不仅仅是BufferedImage
。不久前我成功地利用了这个事实来写出非常大的图像。通常,编写器实现会按顺序写出图像,并仅向 RenderedImage 询问它们当前需要的片段。通过查看您的代码,我认为应该可以破解一个
RenderedImage
实现,该实现将您的panel
放入其构造函数中,并可以传递给ImageIO
> 用于写作。在此过程中,ImageIO
将从您的图像请求数据。然后,您可以使用该面板动态创建请求的片段(Raster
内容)。这样,整个图像在任何时候都不必存储在内存中。这种方法的出发点是显然,您还应该检查您的面板是否没有遇到与 BufferedImage 相同的问题。根据应用程序的性质,无论如何,您都必须在内存中至少保存一次图像(使用图块取模)。但这样至少可以避免重复。
The
ImageIO.write(..)
methods accept anRenderedImage
, not just aBufferedImage
. 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 theRenderedImage
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 yourpanel
in it's constructor and can be passed toImageIO
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 isObviously, you should also check if your
panel
doesn't suffer from the same problem as theBufferedImage
. 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.