压缩技术

Google 一直在寻找提高网页加载速度的方法。 一种方式是缩小网页图片。在大多数网页上,图片会占据 60%-65% 的字节,并且页面大小是影响总呈现时间的主要因素。页面大小对移动设备尤为重要,因为移动设备的图片较小,可以同时节省带宽和电池续航时间。

WebP 是一种由 Google 开发的新图片格式,在 Chrome、Opera 和 Android 中受支持,经过优化,可以在网页上实现更快、更小的图片。与同等视觉质量的 PNG 和 JPEG 图片相比,WebP 图片的尺寸缩小了约 30%。此外,WebP 图片格式的功能也与其他格式相同。它支持:

  • 有损压缩:有损压缩基于 VP8 关键帧编码。VP8 是一种视频压缩格式,由 On2 Technologies 创建,是继 VP6 和 VP7 格式后推出的一种格式。

  • 无损压缩:无损压缩格式由 WebP 团队开发。

  • 透明度:8 位 Alpha 通道对于图形图片很有用。Alpha 通道可与有损 RGB 结合使用,有损 RGB 目前尚不支持任何其他格式。

  • 动画:支持真彩色动画图片。

  • 元数据:它可能包含 EXIF 和 XMP 元数据(例如,供相机使用)。

  • 颜色配置文件:可能会包含嵌入式 ICC 配置文件。

WebP 可以更好地压缩图片,并且支持所有这些功能,因此可以很好地替代大多数图片格式:PNG、JPEG 或 GIF。更棒的是,您是否知道 WebP 提供了新的图片优化机会,例如支持具有透明度的有损图片?有!WebP 是瑞士军刀格式的图片

那么,这个神奇的功能是如何实现的呢?让我们卷起袖子,一探究竟。

有损 WebP

WebP 的有损压缩使用与 VP8 相同的方法来预测(视频)帧。VP8 基于块预测,并且与任何基于块的编解码器一样,VP8 会将帧划分为称为宏块的较小片段。

在每个宏块内,编码器可以根据先前处理的块预测冗余的运动和颜色信息。图像帧是“关键”帧,因为它仅使用已在每个宏块的直接空间社区中解码的像素,并尝试填充它们的未知部分。这称为预测编码(请参阅 VP8 视频的帧内编码)。

然后,可以从块中删除冗余数据,从而提高压缩效率。我们只留下微小的差异(称为残差),以压缩形式进行传输。

在经过数学上可逆转换(著名的 DCT,代表离散余弦转换)后,残差通常包含许多零值,可以更有效地压缩。然后,对结果进行量化和熵编码。有趣的是,量化步骤是唯一一个以有损方式舍弃位的步骤(在下图中搜索除 QPj 所得的值)。所有其他步骤都是可逆的,并且无损!

下图显示了 WebP 有损压缩所涉及的步骤。与 JPEG 相比,区分特征的特征用红色圆圈标出。

WebP 采用块量化,并以自适应方式跨不同的图像段分配位:低熵段的位数更少,而熵高段的高位数的位数。WebP 使用算术熵编码,与 JPEG 中使用的霍夫曼编码相比,这种编码方式可以提供更好的压缩效果。

VP8 帧内预测模式

VP8 帧内预测模式可与以下三种类型的宏块搭配使用:

  • 4x4 亮度
  • 16x16 亮度
  • 8x8 色度

这些宏块共有四种常见的帧内预测模式:

  • H_PRED(横向预测)。使用左列的副本 L 填充代码块的每一列。

  • V_PRED(行业预测)。使用上面一行 A 的副本填充代码块的每一行。

  • DC_PRED(DC 预测)。使用 A 上方一行和 L 左侧一列的像素平均值,在块中填充一个值。

  • TM_PRED(TrueMotion 预测)。此模式得名于 On2 Technologies 开发的一种压缩技术。除了 A 行和 L 列之外,TM_PRED 还会使用块上方和左侧的像素 P。A 中像素之间的水平差异(从 P 开始)使用来自 L 的像素开始传播。

下图说明了 WebP 有损压缩中使用的不同预测模式。

对于 4x4 亮度块,还有六种其他内部模式(类似于 V_PRED 和 H_PRED),但它们对应于在不同方向上预测像素。如需详细了解这些模式,请参阅 VP8 Bitstream 指南

自适应块量化

为了提高图片质量,系统会将图片分割为具有明显相似特征的区域。对于其中每个区段,压缩参数(量化步骤、过滤强度等)都会独立调整。这样可以通过将位重新分配到最有用的位置来实现有效的压缩。VP8 允许最多四个片段(VP8 比特流的限制)。

为什么 WebP(有损)优于 JPEG

预测编码是 WebP 胜过 JPEG 的主要原因。块自适应量化也大不同。过滤有助于处理中/低比特率。 与霍夫曼编码相比,布尔算术编码提供的压缩增益为 5%-10%。

无损 WebP

WebP 无损编码基于使用多种不同的技术转换图片。然后,对转换参数和转换后的图片数据执行熵编码。应用于图像的转换包括像素空间预测、颜色空间转换、使用本地新出现的调色板、将多个像素打包到一个像素中,以及 alpha 替换。对于熵编码,我们使用 LZ77-霍夫曼编码的变体,它使用距离值和紧凑稀疏值的 2D 编码。

预测器(空间)转换

空间预测利用相邻像素通常具有相关性这一事实来降低熵。在预测器转换中,当前像素值是根据已解码的像素预测的(按扫描行顺序),并且只对残差值(实际值 - 预测值)进行编码。预测模式决定了要使用的预测类型。该图像分成多个方形区域,一个方形中的所有像素使用相同的预测模式。

有 13 种不同的可能的预测模式。常用的像素包括左侧像素、顶部像素、左上角像素和右上角像素。其余样式是“左侧”“顶部”“左上角”和“右上角”的组合(平均值)。

颜色(去相关性)转换

颜色转换的目标是装饰每个像素的 R、G 和 B 值。颜色转换会使绿色 (G) 值保持原样,根据绿色转换红色 (R),根据绿色转换蓝色 (B),然后根据红色转换。

与 Predictor 转换一样,首先将图片分成多个块,并对块中的所有像素使用相同的转换模式。每个块都有三种类型的颜色转换元素:绿色到红色、绿色到蓝色和红色到蓝色。

减绿色转换

“减绿色转换”会从每个像素的红色和蓝色值中减去绿色值。如果存在此转换,解码器需要将绿色值同时添加到红色和蓝色。这是上述一般颜色装饰关系转换的一个特殊情况,其频率足够高,可以保证临界值。

颜色索引(调色板)转换

如果没有很多唯一像素值,则更高效的做法是创建一个颜色索引数组并通过该数组的索引替换像素值。颜色索引转换可以实现这一点。颜色索引转换会检查图片中唯一 ARGB 值的数量。如果该数字低于阈值 (256),它会创建一个包含这些 ARGB 值的数组,然后使用该数组将像素值替换为相应的索引。

颜色缓存编码

无损 WebP 压缩使用已见过的图片片段来重建新像素。如果没有找到感兴趣的匹配项,它也可以使用本地调色板。此调色板会不断更新,以重复使用最近用过的颜色。 在下图中,您可以看到本地颜色缓存的实际应用情况随着扫描时间的减少,使用最近用过的 32 种颜色逐步更新。

LZ77 向后引用

向后引用是长度和距离代码的元组。长度表示要复制的扫描行顺序的像素数。距离代码是一个数字,表示先前看到的像素的位置,即要从中复制这些像素的位置。长度和距离值使用 LZ77 前缀编码进行存储。

LZ77 前缀编码将大整数值分为两部分:前缀代码和额外位。前缀代码使用熵代码存储,而额外位则按原样存储(没有熵代码)。

下图展示了使用字词匹配(而非像素)的 LZ77(2D 变体)。

有损 WebP(Alpha 版)

除了有损 WebP(RGB 颜色)和无损 WebP(使用 alpha 通道的无损 RGB)之外,还有一种 WebP 模式允许对 RGB 通道进行有损编码,支持对 alpha 通道进行无损编码。目前,任何现有的图片格式都没有这种可能性(有损 RGB 和无损 alpha)。目前,需要透明度的网站站长必须以 PNG 格式对图片进行无损编码,从而导致图片大小显著膨胀。WebP alpha 能够以较低的每像素位数对图片进行编码,可以有效缩减此类图片的大小。与有损(质量 90)WebP 编码相比,Alpha 通道的无损压缩仅会导致 22% 的字节

总体而言,使用有损 + Alpha 版 WebP 替换透明 PNG 后,平均大小会缩减 60-70%。事实证明,对于图标丰富的移动网站(例如 everything.me)来说,这是一项很有吸引力的功能。