Java - 在没有质量损失的情况下压缩图像

标签 java image compression

我有一个大小为 2.1mb 的 jpeg 图像。我试图尽可能地压缩图像数据。可能低于 1mb。目前我已经对该主题进行了一些研究,并且编写了一些代码来尝试压缩数据。我偶然发现了这个答案:

https://stackoverflow.com/a/4535883/3011902

基于此,我将图像文件转换为字节数组,然后将字节数组转换为其等效的二进制文件。然后我对二进制数据使用运行长度编码。但是,这会使尺寸变大。

我试图将文件转换为 png。但这大大增加了文件大小; 9mb。

那么在 Java 中压缩和图像文件大小而不损失质量的最佳方法是什么?

最佳答案

JPEG 是原始源图像的有损图像压缩。 加载 JPEG 压缩图像时,它具有与原始图像相同的大小 (W x H) 和每个像素的数据 (BPP) - 尽管信息已经损坏/原始信息的量化。这意味着相同数量的数据代表较少的原始信息。

尝试对恢复的图像应用无损压缩(无论是 PNG 还是手动 RLE)1 将导致更大文件大小,因为新的压缩将忠实地保留工件和现有信息丢失4。由于 JPEG 会引入额外的噪声,恢复的数据甚至可能会降低应用无损压缩技术的效率。

要获得最佳压缩/质量权衡,请从原始原始图像信息(RAW、BMP、TIFF)开始;并根据需要应用图像压缩格式。这可能是选择一种无损格式(如 PNG、WEBP),也可能是选择一种具有不同压缩设置的有损格式,如 JPEG(其中有多种变体)。 如果图像已经是有损 JPEG,最好的解决方案(不减小图像/数据大小)可能只是让它保持原状。

不同的压缩算法将根据图像的内容获得不同的结果 - 包括有损格式的明显质量损失。例如,一个简单的 RLE2 压缩可以很好地处理许多大的相同颜色区域的图像,但 JPEG 可以更好地处理 照片3


1 如果对字节流应用一般压缩(例如 DEFLATE、bzip2),它已经代表压缩良好的数据,可能会节省几个百分比的空间。但是,由于图像不是在这种情况下首先恢复,因此与将无损图像压缩重新应用到加载的“完整数据”图像时不会产生相同的膨胀。

2 在 PNG 的其他技巧中,应用了几种 RLE 风格的算法,可能与手动实现一样好或更好。 PNG 特别适合通常相对简单(与照片相比)并且在恢复时必须像素完美的图标。

3 JPEG 可以很好地压缩照片的部分原因是它有目的地丢弃对人类视觉不太重要的信息,并对压缩 block 应用“足以让人类感知”的近似值。

4 即使重新保存 JPEG 图像(修改后)也会导致图像质量进一步下降;有一些关于“JPEG 转码”的论文,读起来可能很有趣。

关于Java - 在没有质量损失的情况下压缩图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32106459/

相关文章:

java - Spring Security - 尽管允许所有请求但未经授权

Java:YAML 文件处理

java - 查找队列中名称的唯一计数

Java - 如何对java对象进行Gzip压缩

algorithm - 有没有 "special"人脸案例的图片压缩算法?

ffmpeg - 使用 Imagemagick convert 将 zip 中的所有图像减少到处于修复状态 (KB)

java - 查找 k - 最小元素(Java 代码)

image - 在 AngularJS 中使用包含 base64 数据的变量加载图像 src

ios - Assets 目录编译错误 - TDDItiller 实例只能提取一次

android - 如何在 React Native 中为 IOS 和 Android 缓存图像?