LZW压缩算法原理和实现

LZW算法

LZW编码算法,一种实现方式是对单一字符进行编码,压缩后数据需包含单一字符编码词典;另一种实现方式不需要包含词典,解压时由压缩后数据还原词典。 这里使用的是第二种实现方法,词典不需要同被压缩后的数据一同发送。这种方法中,0~255类似第一种实现方法中的单个字符词典;以下这段摘自维基百科

与霍夫曼编码相比,LZW编码被视作将不同长度字串以固定长的码编辑(霍夫曼编码将固定长度字元用不同长度的码编辑)。其优点在于此方法只需储存一个相当小的表格,即可储存资料还原时相对应的值,所以所需成本相对地低;然而,这种算法的设计著重在实现的速度,由于它并没有对数据做任何分析,所以并不一定是最好的演算法。

一些约定

因为LZW广泛用于GIF图片格式压缩,且可用于(可选)TIFF图片压缩,在GIF中使用的LZW压缩定义了256为CLEAR,257为END,这里遵循此约定;</br> GIF中采用的编码长度为12位,LZW允许9位到16位可变,待实现时依据效率等因素调整

基本实现

压缩

每次读到下一个字符时,在编码表内查找当前的prevcode与当前字符,如果找到,则更新prevcode为找到的编码表位置,否则将prevcode和当前字符写入编码表下一个位置并更新prevcode为当前字符;编码表满后,写入CLEAR,并重新初始化编码表;进行到文件末尾时,写入当前字符和END

解压缩

每次读到下一个编码时,判断该编码是否在0~255内</br> 如果在,则直接输出,并将前一个编码与其写入编码表下一个位置;</br> 如果不在,则再判断该编码是否在编码表内</br> 如果在,则输出其对应字符或字符串,输出时遇到0~255外的编码则继续向编码表内查找</br> 如果不在,则该字符串必然为其前一个编码所对应字符串+该字符串第一个字符</br> 遇到CLEAR时,清空并重新初始化编码表,遇到END时写入文件。

注意

这个笔记仅说明了LZW编码的原理,实际实现过程中可能还会遇到一些细节问题;在项目中,对于该算法可以根据需要进行相应改进

压缩和解压过程示例

编码 解码
prevcode 输入 位置 prev c 输出 输入 位置 prev c 输出
a a a a a
a b 258 a b a b 258 a b b
b b 259 b b b b 259 b b b
b a 260 b a b 258 260 b 258 ab
a b 261 261 258 260 aba
258 a 261 258 a 258 c 262 261 c c
a b 257
258 a
261 c 262 261 c 261
c EOF c
编码 解码
prevcode 输入 位置 prev c 输出 输入 位置 prev c 输出
a a a a
a b 258 a b a b 258 a b b
b a 259 b a b 258 259 b 258 ab
a b c 260 258 c c
258 c 260 258 c 258 d 261 c d d
c d 261 c d c e 262 d e e
d e 262 d e d f 263 e f f
e f 263 e f e g 264 f g g
f g 264 f g f 263 265 g 263 ef
g e 265 g e g g 266 263 g g
e f 257
263 g 266 263 g 263
g EOF g

压缩和解压流程图

(图片为矢量图形[每张50KB左右],看不清可以在新页面打开放大)



blog comments powered by Disqus
本作品采用知识共享署名-相同方式共享 3.0 未本地化版本许可协议进行许可。
Theme by [Codepiano], First Modified Version by [pengx17], Latest Modified Version by [iHamsterball]