在Java中,如何在不耗尽内存的情况下从大型图像中删除图像元数据

在Java中,如何在不耗尽内存的情况下从大型图像中删除图像元数据,java,Java,我需要从图像中删除元数据,但当图像太大时,我会得到OOM。 现在我用ImageIO来做这个 BufferedImage image = ImageIO.read(new File("image.jpg")); ImageIO.write(image, "jpg", new File("image.jpg")); 问题是ImageIO.read(…)会将整个文件读入内存,这会在处理太大的图像时导致OutOfMemory 我可以尝试使用commonImaging(),但看起来它只支持JPEG(Ex

我需要从图像中删除元数据,但当图像太大时,我会得到OOM。 现在我用ImageIO来做这个

BufferedImage image = ImageIO.read(new File("image.jpg"));
ImageIO.write(image, "jpg", new File("image.jpg"));
问题是ImageIO.read(…)会将整个文件读入内存,这会在处理太大的图像时导致OutOfMemory

我可以尝试使用commonImaging(),但看起来它只支持JPEG(ExifRewriter类)

更改VM的内存配置不是一个选项,我需要支持的不仅仅是JPEG文件


您知道如何在不导致内存不足的情况下执行此操作吗?

您可以尝试通过流媒体制作图像副本,并在流媒体期间应用过滤器删除元数据

可按如下方式进行复制:

    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();
    }
请注意,原始文件和克隆文件不能相同,因此可能需要删除原始文件并在以后重命名目标文件(如果希望将其重命名为相同文件)


除了正常的
输出流
之外,您还可以创建自己的
过滤器输出流
并使用它。

运行此代码的机器的RAM是多少?图像的大小是多少?您是否在IDE中运行程序?您是否尝试过在IDE中运行它?即使内存足够,重新压缩也可能会降低图像质量。只处理元数据的API会更好。@user2864740:如何关闭
文件
对象?为什么?它只是一个字符串的包装器。@Siddharth:图像大约是100MB,大约是20000 x 20000。这种方法的问题是每个图像都有自己的元数据存储方式,如果在这里应用这种逻辑,代码会变得太复杂。我必须知道每个支持的映像如何存储元数据,然后计算读取的字节数。。。太容易出错。