1. LZW压缩算法:从“看图猜词”到图像压缩
如果你玩过“你画我猜”或者“看图猜词”这类游戏,其实你已经摸到了LZW压缩算法的门道。想象一下,你和朋友约定好,每次提到“人工智能”这个词,就用“AI”两个字母代替。一开始你们只约定了几个词,但随着聊天深入,你们发现“机器学习”也经常出现,于是又约定用“ML”代替。聊得越久,你们约定的“缩写词典”就越厚,而传递同样信息量所需的字符却越来越少,沟通效率直线上升。LZW压缩干的就是这事儿,它把图像数据中反复出现的“像素模式”或“字节序列”,用一个简短的“代号”替换掉,从而实现压缩。
在TIFF图像的世界里,LZW曾经是当之无愧的“压缩明星”。你可能不知道,我们电脑里很多老式的扫描文档、黑白线稿图,甚至早期的一些彩色图像,背后默默工作的就是LZW。它的全称是Lempel-Ziv-Welch,由三位大神的名字组成。我刚开始接触图像处理时,总觉得这种算法很神秘,直到自己动手写了一遍压缩和解压的代码,才发现它的核心思想其实非常直观和巧妙——动态造一本字典,边看边记,边记边用。
和那种把所有规则都预先定死的压缩方式不同,LZW的字典是在压缩过程中“现场生成”的。压缩程序一边读取图像数据,一边观察:“哎,这个像素序列‘AB’又出现了,给它个新编号258吧,下次再见就直接写258。”解压程序更神奇,它没有这本字典的副本,却能根据收到的压缩数据和算法规则,在现场把同一本字典一模一样地“还原”出来。这种“心有灵犀”的配合,正是LZW最精妙也最让人着迷的地方。虽然现在计算机性能强了,像PNG用的DEFLATE、JPEG用的有损压缩更常见,但理解LZW依然是掌握无损压缩思想的绝佳路径,它能帮你真正看懂数据是怎么被“挤掉水分”的。
2. 核心原理拆解:动态字典的诞生与演化
要搞懂LZW,你必须先忘掉“压缩”这个词,把它想象成一个“模式识别与编码”的游戏。游戏的核心道具是一本空白的字典,以及一套简单的运行规则。
2.1 初始字典:从0到255的起跑线
游戏开始前,我们需要一本最基础的“词汇表”。对于8位的图像数据(比如256色的索引图像或灰度图),每个像素的取值范围是0到255。LZW就把这256个可能的单字节值,作为字典里最初始的256个词条。也就是说,字典的第0号词条是数值0,第1号是1,……,第255号是255。这很好理解,在压缩开始前,任何单个字节都已经是“已知词汇”了。
但字典不能只有256个位置,那样就失去了扩展的意义。LZW算法通常使用12位(bit)来编码一个词条索引,这意味着字典最多可以有2^12 = 4096个位置。所以,编号256到4095的位置都是空的,留给我们去填充新发现的“词组”。这里还有两个特殊的“信号码”:
- 清除码(Clear Code):通常占用编号256。它像一个“重启”按钮。当字典被填满(达到4096条)时,压缩器可以发出这个码,告诉解压器:“字典满了,咱们清空它,从头开始重建一本新的。”这对于压缩内容发生显著变化的图像段落很有用。
- 结束码(End of Information Code):通常占用编号257。顾名思义,它标志着压缩数据流的结束,告诉解压器:“后面没数据了,活儿干完了。”
所以,我们的初始字典,就是从0到257都被占用了的“基础词汇库”。
2.2 压缩过程:像滚雪球一样积累词组
现在,压缩器开始一字节一字节地读取图像数据了。它手里握着两个变量:当前前缀(Current Prefix) 和 当前字符(Current Character)。你可以把当前前缀理解为一个“正在组装的词根”,把当前字符看作下一个要尝试拼接的字母。
压缩过程遵循一个简单的循环规则,我用大白话翻译一下:
- 初始化:
当前前缀设为空。读取第一个字节,放入当前字符。 - 尝试拼接:把
当前前缀和当前字符拼在一起,形成一个新的字符串新词组。 - 查字典:去字典里查,看
新词组是否存在。- 如果存在:太好了!说明这个组合我们之前见过。那么,我们就把
当前前缀更新为这个新词组(相当于把词根变长了)。然后,读取下一个字节作为新的当前字符,回到第2步继续尝试拼接更长的词组。 - 如果不存在:太棒了!我们发现了一个新的模式!这时,我们做三件事: a. 输出:把
当前前缀对应的字典编号输出到压缩流中。因为当前前缀肯定是字典里已有的词条。 b. 登记:把这个新的新词组添加到字典的下一个空闲编号位置(比如从258开始)。 c. 重置:把当前前缀重置为当前字符(因为当前字符是一个单字节,肯定在初始字典里)。然后,读取下一个字节作为新的当前字符,继续循环。
- 如果存在:太好了!说明这个组合我们之前见过。那么,我们就把
- 结束:当所有数据读完,把最后剩下的
当前前缀的编号输出,再输出结束码,压缩完成。
这个过程就像滚雪球。一开始只是单个字节(雪球核心),发现“AB”常见,就登记为258,下次见到“AB”就直接用258代替。接着发现“ABC”也常见,就把“AB”(258)和“C”拼成“ABC”,登记为259……雪球越滚越大,能代表的字节串越来越长,压缩效率也就越来越高。
2.3 解压过程:魔术般的字典同步还原
解压是压缩的逆过程,但更显智慧。解压器并没有压缩时生成的那本完整字典,它只有初始字典(0-255)和压缩流里传来的一串编号。它必须根据规则,现场还原出和压缩器一模一样的字典。
解压规则同样清晰:
- 初始化:建立同样的0-255初始字典。读取压缩流的第一个编号,解码输出对应的字符串,并设为
旧词条(Old Code)。 - 循环解码

:LZW压缩算法原理与实现详解&spm=1001.2101.3001.5002&articleId=153233421&d=1&t=3&u=48948f87612f46aca75a21e8eaeea6cd)
1688

被折叠的 条评论
为什么被折叠?



