【问题标题】:How can I compress jpeg images in Java without losing any metadata in that image?如何在 Java 中压缩 jpeg 图像而不会丢失该图像中的任何元数据?
【发布时间】:2012-11-28 14:36:57
【问题描述】:

我想使用 Java 压缩 jpeg 文件。我是这样做的:

  1. 将图像读取为BufferedImage
  2. 将图像写入另一个具有压缩率的文件。

好的,这看起来很简单,但是我发现新文件中没有 ICC 颜色配置文件和 EXIF 信息,并且图像的 DPI 从 240 下降到 72。它看起来与原始图像不同。我在 OS X 中使用了预览之类的工具。它可以完美地改变图像的质量,而不会影响其他信息。

我可以在 Java 中做到这一点吗?至少保留 ICC 颜色配置文件,让图像颜色看起来与原始照片相同?

【问题讨论】:

    标签: java image-processing compression jpeg


    【解决方案1】:
    /**
     * @param inputFilenameWithPath : binary filepath
     * @param outputFilepath        : output image path
     * @param start                 : from where the image start in binary file
     * @param len                   : length of the image
     * @throws ImageAccessException
     */
    public void extractImageFromBinaryFile(String inputFilenameWithPath, String outputFilepath, int start, int len) throws ImageAccessException
    {
        try
        {
            File file = new File(inputFilenameWithPath);
            FileImageInputStream iis = new FileImageInputStream(file);
    
            // Added
            byte[] b = new byte[start];
            iis.read(b, 0, start);
    
            byte[] fb = new byte[]{};
            iis.read(fb);
    
            IIOByteBuffer iiob = new IIOByteBuffer(fb, start, len);
            iis.readBytes(iiob, len);
    
            OutputStream os = new FileOutputStream(outputFilepath);
            os.write(iiob.getData());
            iis.close();
            os.close();
    
        }
        catch (IOException ioe)
        {`enter code here`
            throw new ImageAccessException("Image File read/write error");
        }
    }
    

    【讨论】:

    • 这似乎可以作为读出图像并输出它,但我认为这不支持改变图像的质量来压缩它。
    【解决方案2】:

    终于找到办法了。

    使用 javax.imageio.IIOImage。可以被JpegImageReader读取。

    但其中有一个错误,一个持续了 6 年的错误。 :(

    http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4924909

    幸运的是,如果你做了一些 hack(伪造 JFIF 部分),它就可以工作。 :D

    所以,这个问题可以这样解决:

    1. 使用 ImageIO 获取适用于 jpeg 的 ImageReader
    2. 将 jpeg 图像读入内存缓冲区
    3. 如果在错误 4924909 处失败,则使用伪造的 JFIF 信息修复图像缓冲区
    4. 使用 ImageWriter 写入文件,让 ImageWriterParam 完成任务。

    嗯,似乎没问题(保存了所有信息),除了一件事,输出图像比原始图像更亮(或者更确切地说,苍白)(当我使用 OS X 的预览时不会发生这种情况压缩照片,所以问题一定出在我的代码或java中,或者我的错误用法:()。

    所以,我在java中压缩jpeg的问题还没有解决。

    有什么建议吗?

    【讨论】:

    • 好吧,我放弃了。 ImageIO 不能很好地工作(至少对我来说)。我只想更改图像的质量以在不丢失任何信息的情况下对其进行压缩,并且看起来与原始照片尽可能相同。 Java 让我失望了,我将使用 ImageMagic 和 JNI 来做到这一点。也许我错了。 oracle 的任何人都可以提供帮助吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多