在 Java 中是否可以进行极端图像优化?

Is Extreme Image Optimization Possible in Java?

我正在尝试在 Java 中编写图像优化软件。第一步也是最明显的一步是剥离 EXIF 元数据,我已成功完成。我还尝试使用 ImageIO 和压缩质量参数压缩图像,如下所示:

filepath=chosen.getCanonicalPath()+"-temp.jpg";
file=new File(filepath);
Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
if (!writers.hasNext()){
    throw new IllegalStateException("No writers found");
}
OutputStream os = new FileOutputStream(file);
ImageWriter writer = (ImageWriter) writers.next();
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
writer.setOutput(ios);

ImageWriteParam param = writer.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setCompressionQuality(0.9f);
writer.write(null, new IIOImage(optimized, null, null), param);

然而,这真的不是那么好用。当源图像是不同的格式(即不是 jpeg)时它工作得很好,但是当从 jpeg 压缩到 jpeg 时,它有时甚至会使文件大小 变大.

像 www.tinyjpg.com 这样的网站声称(并且确实)将 jpeg 图像的文件大小减少了 40%-60% 没有质量损失。他们究竟是如何做到这一点的(程序上和程序上)?他们正在删除哪些类型的数据,以及如何在不损失质量的情况下删除这些数据?这是我在 Java 中可能实现的目标吗?

非常感谢您能给我的任何指导and/or资源!

来自 Wikipedia - JPG - Lossless further compression I would guess that Tiny JPG has been using improved algorithms that were developed after the creation of most standard tools. The improved algorithms are implemented in PackJPG,方便 open-sourced。似乎没有 Java 实现。

附带说明:PackJPG 声称提高了 20%,而 Tiny JPG 声称提高了 70%。这可能是夸大其词,但无论如何您可能都想测试这两种说法。

在 JPEG 中,有三个可优化的步骤:

  1. 组件的相对采样。人们以低于 Y 分量的速率对 Cb 或 Cr 分量进行采样。您平滑 Cb 和 Cr 值,以便 1、2、4、8 或 16 个像素共享相同的 Cb 或 Cr 值(正式地,JPEG 也支持分数采样率,但大多数解码器不支持它们)。如果您使用 4:1:1 采样率,则可以将要压缩的数据量减半。

  2. (最大最难做)选择优化量化table.

  3. 生成优化的 Huffman tables(很容易做到,但许多编码器做不到)。

有一个开源库可以实现无损 JPEG 优化。它称为 SlimJPG,您可以在此处找到更多信息:https://github.com/Fewlaps/slim-jpg

要使用它,只需这样调用它:

SlimJpg.file(yourImage).optimize();

yourImage 可以是 byte[]InputStreamFile

免责声明:我是委员之一...:·)