图像压缩基础与无损压缩
一张 1920×1080 的 RGB 图像,未经压缩时占据约 6MB 的存储空间。一段 1080p 30fps 的一分钟视频则需要约 10GB。在带宽和存储都有限的现实世界中,压缩技术是数字媒体得以广泛传播的基石。
图像压缩的核心目标是:用尽可能少的比特数表示图像信息,同时在解压后能够恢复出人眼可接受的图像质量。这个目标引出了一个根本性的理论框架——信息论。
本篇作为系列的开篇,将从信息论的基础概念出发,系统讲解无损压缩的核心算法,并以 PNG 格式为例展示这些算法如何在工程中落地。理解这些基础,是理解后续所有有损压缩技术(JPEG、小波变换、视频编码等)的前提。
1948 年,Claude Shannon 在其开创性论文《A Mathematical Theory of Communication》中提出了信息熵的概念,为数据压缩建立了数学基础。
对于一个离散随机变量 $X$,其可能取值为 $\{x_1, x_2, \ldots, x_n\}$,对应概率为 $\{p_1, p_2, \ldots, p_n\}$,香农定义的信息熵为:
熵的单位是比特(bit)。它衡量的是每个符号平均需要多少比特来编码。关键性质:
- 均匀分布时熵最大:当所有符号等概率出现时,$H(X) = \log_2 n$
- 确定性事件熵为零:当某个符号概率为 1 时,$H(X) = 0$
- 熵是无损压缩的理论下界:任何无损编码方案的平均码长不可能低于 $H(X)$
一幅图像中存在三种类型的冗余,压缩的本质就是消除这些冗余:
1. 统计冗余(Statistical Redundancy):像素值的概率分布不均匀。例如,白色背景的图像中像素值 255 出现频率远高于其他值,可以用更短的编码表示高频值。
2. 空间冗余(Spatial Redundancy):相邻像素之间存在强相关性。自然图像中,相邻像素的值通常非常接近。
3. 视觉冗余(Visual Redundancy):人眼对某些信息不敏感。例如,人眼对亮度变化比对色度变化更敏感,对高频细节的感知也有限。
无损压缩只能消除前两种冗余,而有损压缩(后续文章会详细讨论)还可以利用视觉冗余进一步提高压缩比。
Shannon 的率失真理论(Rate-Distortion Theory)回答了一个核心问题:在允许一定失真的前提下,最少需要多少比特来编码信源?
率失真函数定义为:
其中 $D$ 是允许的失真度量(如均方误差),$I(X; \hat{X})$ 是原始信号与重建信号之间的互信息。$R(D)$ 给出了在失真不超过 $D$ 时的最小编码速率。
率失真函数是所有有损压缩算法性能的理论上限。实际的压缩算法(如 JPEG、H.264)都在努力逼近这个理论极限。
David Huffman 在 1952 年提出的 Huffman 编码是最经典的变长编码算法。其核心思想很简单:给高频符号分配短码,给低频符号分配长码。
算法流程1. 统计频率:遍历数据,统计每个符号出现的频率
2. 构建优先队列:将所有符号按频率放入最小堆
3. 构建 Huffman 树:
- 取出频率最小的两个节点,合并为一个新节点(频率为两者之和)
- 将新节点放回堆中
- 重复直到堆中只剩一个节点(即根节点)
4. 生成编码表:从根节点出发,左分支标记为 0,右分支标记为 1,每个叶子节点的路径即为该符号的编码
示例假设有一个包含 5 个符号的信源,频率如下:
| 符号 | A | B | C | D | E |
|---|---|---|---|---|---|
| 频率 | 0.35 | 0.25 | 0.20 | 0.12 | 0.08 |
构建 Huffman 树后,可能得到如下编码:
| 符号 | 编码 | 码长 |
|---|---|---|
| A | 0 | 1 |
| B | 10 | 2 |
| C | 110 | 3 |
| D | 1110 | 4 |
| E | 1111 | 4 |
平均码长 = 0.35×1 + 0.25×2 + 0.20×3 + 0.12×4 + 0.08×4 = 2.12 bit/symbol
而熵 $H(X) = -0.35\log_2 0.35 - 0.25\log_2 0.25 - 0.20\log_2 0.20 - 0.12\log_2 0.12 - 0.08\log_2 0.08 \approx 2.07$ bit/symbol
Huffman 编码的平均码长非常接近理论下界。
局限性- Huffman 编码是整数比特编码:每个符号至少分配 1 bit,即使其概率很高
- 对于二元信源(只有 0 和 1),如果 $P(0) = 0.9$,Huffman 仍需至少 1 bit 来表示 0,而理论最优只需要 $-\log_2 0.9 \approx 0.15$ bit
- 需要两遍扫描:第一遍统计频率构建编码表,第二遍实际编码
算术编码克服了 Huffman 编码的整数比特限制。它将整个消息编码为一个介于 0 和 1 之间的浮点数,而不是为每个符号分配独立的码字。
原理1. 初始化区间为 $[0, 1)$
2. 对于消息中的每个符号,根据其概率将当前区间细分为子区间
3. 选择对应符号的子区间作为新的当前区间
4. 编码完成后,输出当前区间内的一个数作为编码结果
示例假设信源有三个符号 A(0.5)、B(0.3)、C(0.2),要编码消息 "BAB":
| 步骤 | 符号 | 区间划分 | 新区间 |
|---|---|---|---|
| 初始 | - | [0, 1) | [0, 1) |
| 1 | B | A:[0,0.5) B:[0.5,0.8) C:[0.8,1) | [0.5, 0.8) |
| 2 | A | A:[0.5,0.65) B:[0.65,0.74) C:[0.74,0.8) | [0.5, 0.65) |
| 3 | B | A:[0.5,0.575) B:[0.575,0.62) C:[0.62,0.65) | [0.575, 0.62) |
最终编码为 $[0.575, 0.62)$ 区间内的任意值,例如 0.59。
算术编码的优势在于:它可以为符号分配非整数比特的编码,从而更接近熵的理论极限。在实践中,算术编码比 Huffman 编码平均可以节省 5%–10% 的比特数。
LZ77(Lempel-Ziv 1977)是一种基于字典的压缩算法,由 Abraham Lempel 和 Jacob Ziv 在 1977 年提出。其核心思想是利用数据中的重复模式。
LZ77 原理LZ77 使用一个滑动窗口来维护已处理的数据。对于当前位置的数据,算法在窗口中搜索匹配的字符串:
- 如果找到匹配,输出一个 (长度, 距离) 对,表示"从当前位置回退距离个字符,复制长度个字符"
- 如果没找到匹配,输出原始字符
窗口大小决定了可以引用的最大距离,匹配长度决定了可以复制的最大字符数。
DEFLATE 算法DEFLATE 是 LZ77 和 Huffman 编码的组合,由 Phil Katz 在 1993 年为 ZIP 文件格式设计,后来被 gzip、PNG 等广泛采用。
DEFLATE 的工作流程:
1. LZ77 压缩:用滑动窗口查找重复字符串,替换为 (长度, 距离) 对
2. Huffman 编码:对 LZ77 的输出(包括 literal/length 符号和 distance 符号)分别构建 Huffman 树进行编码
3. 动态/静态 Huffman:DEFLATE 支持动态生成 Huffman 表(更优)和使用预定义的静态 Huffman 表(更快)
DEFLATE 的滑动窗口大小为 32KB,匹配长度范围为 3–258 字节。这个设计在压缩比和速度之间取得了良好的平衡。
PNG(Portable Network Graphics)于 1996 年发布,是目前最广泛使用的无损图像格式。它最初的设计目标是替代 GIF(当时 GIF 使用的 LZW 算法存在专利问题),同时提供更好的压缩性能和更丰富的功能。
PNG 的压缩过程分为两个主要阶段:过滤(Filtering)和 DEFLATE 压缩。
第一步:过滤(Filtering)过滤是 PNG 独特的预处理步骤。它在 DEFLATE 压缩之前运行,目的是消除像素间的空间冗余,使数据更适合 DEFLATE 压缩。
PNG 定义了 5 种过滤器类型,对每行像素逐一应用:
| 类型 | 名称 | 算法 | 说明 |
|---|---|---|---|
| 0 | None | $F(x) = x$ | 不做处理 |
| 1 | Sub | $F(x) = x - \text{Raw}(x - \text{bpp})$ | 减去左侧 bpp 个字节处的像素值 |
| 2 | Up | $F(x) = x - \text{Prior}(x)$ | 减去正上方的像素值 |
| 3 | Average | $F(x) = x - \lfloor(\text{Raw}(x - \text{bpp}) + \text{Prior}(x)) / 2\rfloor$ | 减去左侧和上方像素的平均值 |
| 4 | Paeth | $F(x) = x - \text{PaethPredictor}(\text{Raw}(x - \text{bpp}), \text{Prior}(x), \text{Prior}(x - \text{bpp}))$ | 使用 Paeth 预测器 |
其中 Paeth 预测器是 PNG 最精巧的设计之一。它根据左侧、上方、左上方三个邻居像素,选择最接近当前像素值的一个作为预测值。具体规则:
p = a + b - c
if |p - a| <= |p - b| and |p - a| <= |p - c|: 选择 a
elif |p - b| <= |p - c|: 选择 b
else: 选择 c
过滤后的残差值(实际值减去预测值)通常集中在 0 附近,这使得后续的 DEFLATE 压缩效率大幅提升。
第二步:DEFLATE 压缩过滤后的数据被送入 DEFLATE 压缩器。DEFLATE 结合了 LZ77 的字典匹配和 Huffman 编码的熵压缩:
1. LZ77 阶段:在 32KB 的滑动窗口中搜索重复的字节序列,用 (长度, 距离) 对替换
2. Huffman 编码阶段:对 literal/length 符号和 distance 符号分别构建最优 Huffman 树
3. 块输出:DEFLATE 将数据分成多个块,每个块可以选择存储未压缩数据、使用静态 Huffman 表或动态 Huffman 表
第三步:PNG 文件结构PNG 文件由一系列 chunks 组成,每个 chunk 包含 4 字节长度、4 字节类型、数据和 4 字节 CRC 校验:
- IHDR:图像头信息(宽、高、位深、颜色类型等)
- IDAT:压缩后的图像数据(可以有多个 IDAT chunk)
- IEND:图像结束标记
- PLTE:调色板(仅索引色图像)
- tEXt/iTXt:文本元数据
优势:
- 完全无损,适合医疗影像、截图、图标等对精度要求极高的场景
- 支持 Alpha 通道透明度
- 广泛的浏览器和软件支持
- 无专利限制
局限:
- 压缩比通常低于有损格式(JPEG 等)
- 不支持动画(APNG 扩展了这一功能)
- 不支持渐进式加载(标准 PNG 不支持)
- 对于连续色调的自然图像,压缩效率不如 JPEG
根据香农的源编码定理,无损压缩的平均码长 $L$ 满足:
这意味着无损压缩可以把平均码长压缩到接近熵的水平,但永远无法低于熵。对于一个 8bit 灰度图像,如果像素值均匀分布,熵为 8 bit/pixel,此时无损压缩无法减小文件大小。
不同图像类型的无损压缩比差异很大:
| 图像类型 | 典型无损压缩比 | 原因 |
|---|---|---|
| 截图/文字 | 10:1 – 50:1 | 颜色数少,大量重复区域 |
| 图标/UI元素 | 5:1 – 20:1 | 大面积纯色,边缘锐利 |
| 自然照片 | 1.5:1 – 3:1 | 像素值变化丰富,冗余较少 |
| 医学影像 | 2:1 – 4:1 | 高动态范围,细节丰富 |
这就是为什么无损格式(PNG)适合截图和图标,而自然照片通常选择有损格式(JPEG)的原因。
无损压缩的理论极限意味着:对于连续色调的自然图像,仅靠消除统计冗余和空间冗余,压缩比很难超过 3:1。要进一步提高压缩比,必须引入有损压缩——即允许丢失一些视觉冗余信息。
下一篇将深入讲解 JPEG 的有损压缩流程,包括色彩空间转换、DCT 变换、量化等核心步骤,展示有损压缩如何在可接受的质量损失下实现 10:1 甚至 50:1 的压缩比。
参考来源
- Shannon, C. E. (1948). "A Mathematical Theory of Communication". Bell System Technical Journal, 27(3), 379–423.
- Huffman, D. A. (1952). "A Method for the Construction of Minimum-Redundancy Codes". Proceedings of the IRE, 40(9), 1098–1101.
- Ziv, J., & Lempel, A. (1977). "A Universal Algorithm for Sequential Data Compression". IEEE Transactions on Information Theory, 23(3), 337–343.
- Deutsch, L. P. (1996). "DEFLATE Compressed Data Format Specification version 1.3". RFC 1951.
- Roelofs, G. (1999). PNG: The Definitive Guide. O'Reilly Media.
- W3C (2003). "PNG (Portable Network Graphics) Specification". https://www.w3.org/TR/PNG/
- Sayood, K. (2017). Introduction to Data Compression (5th ed.). Morgan Kaufmann.
本篇是"传统图像与视频压缩技术全景"系列的第一篇。接下来的篇章将依次深入:
- 第二篇:JPEG 与 DCT 时代 — 有损压缩的核心算法
- 第三篇:小波变换与 JPEG2000 — 多分辨率分析的压缩革命
- 第四篇:现代图像格式 — WebP、AVIF 与 BPG
- 第五篇:视频压缩基础 — 从 MPEG-1 到 H.264
- 第六篇:H.265/HEVC、AV1 与下一代视频编码
- 第七篇:机器学习在图像/视频压缩中的应用现状