如何在 Java 中压缩 jpeg 图像而不丢失该图像中的任何元数据?

发布于 2024-07-23 07:31:02 字数 301 浏览 5 评论 0原文

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

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

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

我可以用 Java 来做这个吗? 至少保留ICC颜色配置文件并让图像颜色看起来与原始照片相同?

I want compress jpeg files using Java. I do it like this:

  1. Read the image as BufferedImage
  2. Write the image to another file with compression rate.

OK, that seems easy, but I find the ICC color profile and the EXIF information are gone in the new file and the DPI of the image is dropped from 240 to 72. It looks different from the origin image. I use a tool like preview in OS X. It can perfectly change the quality of the image without affecting other information.

Can I done this in Java? At least keep the ICC color profile and let the image color look the same as the origin photo?

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

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

发布评论

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

评论(2

痞味浪人 2024-07-30 07:31:02
/**
 * @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");
    }
}
/**
 * @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");
    }
}
放低过去 2024-07-30 07:31:02

终于找到一种方法来做到这一点。

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

但其中有一个bug,一个bug持续了6年。 :(

https://bugs.java.com/bugdatabase/view_bug?bug_id=4924909< /a>

幸运的是,如果你做了一些 hack(伪造 JFIF 部分),并且它有效:D

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

  1. 使用 ImageIO 获取 jpeg 的 ImageReader 将
  2. jpeg 图像读入内存缓冲区
  3. 如果。它在错误 4924909 处失败,然后用假 JFIF 信息修复图像缓冲区
  4. 使用 ImageWriter 写入文件,让 ImageWriterParam 完成这个技巧

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

那么,我在java中压缩jpeg的问题还没有解决,

有什么建议吗?

Finally find a way to do this.

Use javax.imageio.IIOImage. It can be readed by JpegImageReader.

But there was a bug in it, a bug last for 6 years. :(

https://bugs.java.com/bugdatabase/view_bug?bug_id=4924909

Luckily, if you do some hack(Fake the JFIF section), and it works. :D

So, this problem can be solved like this:

  1. Use ImageIO to get the ImageReader for jpeg
  2. Read the jpeg image into a memory buffer
  3. If it fails at bug 4924909 then fix the image buffer with a fake JFIF information
  4. Use ImageWriter to write the file, let the ImageWriterParam to do the trick.

Well, it seems to be ok(Every information saved), except for one thing, the output image is brighter(or rather say, pale) than the original image(It won't happen when I use preview of OS X to compressed photo, so the problem must be in my code or java, or my wrong usage :( ).

So, my problem for compressing jpeg in java is not solved yet.

Any suggestions?

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