多次压缩位图

Compressing a bitmap multiple times

Android API提供了Bitmap.compress(format, quality, output)保存位图对象的方法。我创建了一个示例应用程序,它将 jpeg 图像(一些嘈杂的相机照片)加载到位图中,然后将其压缩回同一个文件。然后再做5次

显然,我的位图积累了压缩伪像。令我惊讶的是,这种伪像的数量以一种奇怪的方式取决于压缩质量。当我将质量设置为 100(我希望这是最好的质量)时,伪像清晰可见。当我将质量降到 90 时,伪像明显不那么明显了。 80 的质量设置给了我最好的结果。质量设置为 70 及以下时,图像质量下降得很快。

当我压缩质量为 100 的位图时,生成的文件的大小在每次压缩时都线性增加。对于 90 和 80 的质量设置,生成的文件的大小在每次传递时保持大致相同。

我已经在 Android 5 设备 (HTC One) 和 Android 6 设备 (Motorola Moto G) 上测试了此行为,结果非常一致。不过,在 Android 7 上,(三星 S7)我无法发现生成的图像有任何差异。

所以,我的问题是为什么压缩质量 = 80 比质量 = 90,尤其是质量 = 100 的压缩效果更好。我真的希望保存质量为 100 的图像几乎无损(就像它们在,比如说,GIMP)

JPEG 是一种有损压缩算法。即使您使用 100% 质量,解码后的图像也不会与原始图像完全相同。因此,如果您对同一图像进行多次编码和解码,通常会发现伪像。

不想损失就用PNG算法

我的回答有点不完整,因为 80% 的质量不应该比 100% 好,如果您遇到这种情况,我不知道为什么。

使用 Photoshop 或 GIMP 编码时无法观察到损失,这可能是因为它们改进了算法。 Android 7 中比低版本更好的结果也可能是相同的结果。

如果不看示例很难判断,但我假设您注意到的伪影是高频分量(其特征是亮度急剧变化,仅持续一两个像素)。虽然不是强制性的,但许多 .jpeg 压缩算法将使用特定的 quantization matrices 衰减高频分量 morelower 质量设置,从而使为您可能考虑更多 "fundamental" 图像的低频内容留出空间。

因此,不难想象,在较低质量的设置下,高频分量将成为图像的 "cut out",从而降低渐变并产生整体 "smoother" 外观。而且,也不难想象,在高质量(但不完美)的情况下,一些高频分量可能会在连续运行中被夸大甚至放大(由于量化误差)。

换句话说,JPEG 宏块由以下 8x8 图元的线性组合组成,在较低质量设置下,靠近右侧和底部的图元不太可能出现,因此:没有锐利的边缘.

(来自维基媒体的原始图片,see here