Java - 无质量损失地压缩图像

Java - Compressing an Image without Quality Loss

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

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

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

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

JPEG 是原始源图像的有损 图像压缩。 加载 JPEG 压缩图像后,它 具有与原始图像相同的大小 (W x H) 和每个像素的数据 (BPP) - 尽管该信息已经是原始信息的corruption/quantization。也就是说等量的数据代表的原始信息

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

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

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


1 如果对已经代表压缩良好的数据的字节流应用一般压缩(例如 DEFLATE、bzip2),可能会有几个百分比的 space 保存。但是,由于图像 不是 在这种情况下首次恢复,因此 inflation 与对加载的 'full data' 图像重新应用无损图像压缩不同。

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

3 JPEG 可以很好地压缩照片的部分原因是它有目的地丢弃对人类视觉不太重要的信息,并对压缩块应用 'good enough for human perception' 近似值。

4 即使重新保存 JPEG 图像(修改后)也会导致图像进一步退化; 'JPEG transcoding' 上有一些论文,读起来可能很有趣。