如何从大型图像中删除图像元数据而又不会用Java占用内存 [英] How to remove image metadata from large images without out of memory in Java
问题描述
我需要从图像中删除元数据,但是当图像太大时,我得到了OOM.现在我正在使用ImageIO.
I need to remove metadata from images but when images are too large I get OOM. Right now I'm using ImageIO for that.
BufferedImage image = ImageIO.read(new File("image.jpg"));
ImageIO.write(image, "jpg", new File("image.jpg"));
问题是 ImageIO.read(...)会将整个文件读入内存,这在我处理太大的图像时会导致内存不足.
Problem is that ImageIO.read(...) will read the whole file into memory, which causes OutOfMemory when I'm processing images that are too big.
我可以尝试使用CommonsImaging( https://commons.apache.org/正确/commons-imaging/sampleusage.html ),但看起来它仅支持JPEG(ExifRewriter类).
I could try using CommonsImaging (https://commons.apache.org/proper/commons-imaging/sampleusage.html) but looks like it supports only JPEG (ExifRewriter class).
不能更改VM的内存配置,我需要支持的不仅仅是JPEG文件.
Changing the memory config for the VM is not an option and I need to support more than just JPEG files.
有什么想法可以做到这一点而又不会导致内存不足吗?
Any ideas how to do that without incurring into Out of Memory?
推荐答案
您可以尝试通过流式传输复制图像,并在流式传输期间应用过滤器以删除元数据来进行尝试.
You could try it by making a copy of the image via streaming and during the streaming apply a filter to remove the metadata.
可以按照以下步骤进行复制:
The copying could be done as follows:
InputStream is = null;
OutputStream os = null;
try {
// Source and Destination must be different
is = new FileInputStream(new File("path/to/img/src"));
os = new FileOutputStream(new File("path/to/img/dest"));
// Limit buffer size further is necessary!
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
// Apply removal of metadata here!!!
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
请注意,原始文件和克隆文件不能相同,因此可能有必要删除原始文件,然后再重命名目标文件(如果您希望它们相同).
Note that the original and clone can't be the same so it might be necessary to delete the original and rename the destination file afterwards (if you want to the them the same).
代替普通的 outputstream
,您还可以创建自己的 FilteredOutputstream
并使用它.
Instead of a normal outputstream
you could also create your own FilteredOutputstream
and use that instead.
这篇关于如何从大型图像中删除图像元数据而又不会用Java占用内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!