在 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 中,有三个可优化的步骤:
组件的相对采样。人们以低于 Y 分量的速率对 Cb 或 Cr 分量进行采样。您平滑 Cb 和 Cr 值,以便 1、2、4、8 或 16 个像素共享相同的 Cb 或 Cr 值(正式地,JPEG 也支持分数采样率,但大多数解码器不支持它们)。如果您使用 4:1:1 采样率,则可以将要压缩的数据量减半。
(最大最难做)选择优化量化table.
生成优化的 Huffman tables(很容易做到,但许多编码器做不到)。
有一个开源库可以实现无损 JPEG 优化。它称为 SlimJPG,您可以在此处找到更多信息:https://github.com/Fewlaps/slim-jpg
要使用它,只需这样调用它:
SlimJpg.file(yourImage).optimize();
yourImage
可以是 byte[]
、InputStream
或 File
。
免责声明:我是委员之一...:·)
我正在尝试在 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 中,有三个可优化的步骤:
组件的相对采样。人们以低于 Y 分量的速率对 Cb 或 Cr 分量进行采样。您平滑 Cb 和 Cr 值,以便 1、2、4、8 或 16 个像素共享相同的 Cb 或 Cr 值(正式地,JPEG 也支持分数采样率,但大多数解码器不支持它们)。如果您使用 4:1:1 采样率,则可以将要压缩的数据量减半。
(最大最难做)选择优化量化table.
生成优化的 Huffman tables(很容易做到,但许多编码器做不到)。
有一个开源库可以实现无损 JPEG 优化。它称为 SlimJPG,您可以在此处找到更多信息:https://github.com/Fewlaps/slim-jpg
要使用它,只需这样调用它:
SlimJpg.file(yourImage).optimize();
yourImage
可以是 byte[]
、InputStream
或 File
。
免责声明:我是委员之一...:·)