在 Java 中可以进行极端的图像优化吗?
Posted
技术标签:
【中文标题】在 Java 中可以进行极端的图像优化吗?【英文标题】:Is Extreme Image Optimization Possible in Java? 【发布时间】:2016-01-15 22:40:44 【问题描述】:我正在尝试用 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 实现的吗?
非常感谢您能给我的任何指导和/或资源!
【问题讨论】:
想必tinyjpg有自己的压缩算法。我怀疑你会在标准库中找到它。可能会看看色度二次采样 ed. 当然他们有自己的算法。我的问题是真的,你知道它可以做什么(程序上)吗?可以安全丢弃哪些类型的数据?您如何找出对于特定 jpeg 可以丢弃哪些数据? “像 www.tinyjpg.com 这样的网站声称(并且确实)将 jpeg 图像的文件大小减少了 40%-60%,没有质量损失。” 我非常怀疑。您可能看不到质量损失,这很好,但声称不存在只是......好吧,让我们在一般情况下极不可能。 如果没有,那么在 tinyjpg.com 上 非常非常 最小的质量损失,这真的是任何人都需要的,因为人眼可以只能看到这么多分辨率 【参考方案1】:有一个开源库可以实现无损 JPEG 优化。它叫做 SlimJPG,你可以在这里找到更多信息:https://github.com/Fewlaps/slim-jpg
要使用它,只需像这样调用它:
SlimJpg.file(yourImage).optimize();
yourImage
可以是 byte[]
、InputStream
或 File
。
免责声明:我是委员会成员之一... :·)
【讨论】:
【参考方案2】:来自Wikipedia - JPG - Lossless further compression 我猜Tiny JPG 一直在使用在大多数标准工具创建之后开发的改进算法。改进后的算法在PackJPG 中实现,开源方便。似乎没有 Java 实现。
附带说明:PackJPG 声称提高了 20%,而 Tiny JPG 声称提高了 70%。这可能言过其实,但无论如何您可能都想测试这两种说法。
【讨论】:
PackJPG 是什么语言的?是否可以与Java程序结合使用? 它是一个命令行应用程序,从外观上看是用 C++ 编写的。您可以从 java 调用命令行应用程序。 ***.com/questions/9346077/… 有没有办法让我的程序检查本地机器上是否安装了 PackJPG,如果没有安装它? 听起来很复杂。只需将其捆绑为安装 java 程序的安装程序的一部分。不过你必须自己做。【参考方案3】:在 JPEG 中有三个可优化的步骤:
组件的相对采样。人们以低于 Y 分量的速率对 Cb 或 Cr 分量进行采样。您可以平滑 Cb 和 Cr 值,以便 1、2、4、8 或 16 个像素共享相同的 Cb 或 Cr 值(正式地,JPEG 也支持小数采样率,但大多数解码器不支持它们)。如果您使用 4:1:1 的采样率,那么要压缩的数据量就会减少一半。
(最大也是最难做的)选择优化的量化表。
生成优化的霍夫曼表(很容易做到,但许多编码器不这样做)。
【讨论】:
以上是关于在 Java 中可以进行极端的图像优化吗?的主要内容,如果未能解决你的问题,请参考以下文章