在 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[]InputStreamFile

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

【讨论】:

【参考方案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 中可以进行极端的图像优化吗?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 5 优化要求 - 启动图像真的有必要吗?

canvas简介以及常用性能优化

使用 OpenCV C++ 从黑白图像中提取四边形的角(极端角点)

MFC在运行时在优化校准中显示图像[重复]

使用NEON优化ARM的卷积运算

火炉炼AI机器学习051-视觉词袋模型+极端随机森林建立图像分类器