LZW压缩(解压缩)算法详解及源码

转自http://blog.chinaunix.net/uid-23741326-id-3124208.html



LZW压缩算法是Lempel-Ziv-Welch 3个人共同发明的,简称 LZW 的压缩算法,可以用任何一种语言来实现它.
LZW是GIF图片文件的压缩算法,而且zip压缩的思想也是基于LZW实现的,所以LZW对文本文件具有很好的压缩性能。

LZW压缩算法的基本原理:提取原始文本文件数据中的不同字符,基于这些字符创建一个编码表,然后用编码表中的字符的索引来替代原始文本文件数据中的相应字符,减少原始数据大小。看起来和调色板图象的实现原理差不多,但是应该注意到的是,我们这里的编码表不是事先创建好的,而是根据原始文件数据动态创建的,解码时还要从已编码的数据中还原出原来的编码表.

编码表中每一项的大小一般为12位,用来代表一个字符串。这样编码表有2**12=4096项,编码值是0~4095。通常情况下0~255是固定的,用来代表单个字符0~255。而值256通常用来表示开始新的编码表,因为如果编码表的4096项都用完了,而待压缩文件还没有处理完,那么就需要生成新的编码表继续压缩;257表示压缩结束,用来写到压缩文件尾。从258开始,每个值都代表一个字符串(至少2个字符)。
举个例子,有下面的字符串:ababcdefgefg。(a的ascii码是0x61=97)
压缩后的数据是:97 98 258 99 100 101 102 103 263 103。

其中第二个ab被压缩成258,第二个ef被压缩成263,因为这之前在ab和ef第一次出现的时候就已经被按顺序编入到编码表中。
编码项结构为:

  1. typedef struct
  2. {
  3.     char used ; //该项已被编码。
  4.     UINT prev; //前向编码索引(0~4095)
  5.     BYTE c; //本项对应字符。
  6. }ENTRY;

编码表是(该编码表只在压缩过程中使用,并不会被写入到最终的压缩文件):
  1. ENTRY string_tab[4096];

具体压缩过程是:
1. 初始化编码表string_tab[0~257]。258~4095为空。即

  1. string_tab[i].used=TRUE, string_tab[i].prev=-1,string_tab[i].c=i(0<=i<=257)
  2. string_tab[j].used = FALSE(258<=j<=4095)

2. 程序读入第一个字符a,到编码表中查找到对应编码97,记录临时前向编码索引prevcode=97,再读入下一个字符b,然后在编码表中查找prev=97、c='b'的编码项,没有找到, 则表明'ab'没有对应的编码项,则把当前prevcode的值--97写入压缩缓存(该缓存最后会被写入压缩文件);再创建新的编码项string_tab[258],且string_tab[258].prev=97,string_tab[258].c='b'。最后更新临时前向编码索引prevcode=当前字符'b'=98。
3. 程序读入下一个字符a,在编码表中查找prev=prevcode(98)、c='a'的编码项,没有找到,则把当前prevcode的值98写入压缩缓存;再创建新的编码项string_tab[259],且string_tab[259].prev=98, string_tab[259].c='a'。最后更新临时前向编码索引prevcode=当前字符'a'=97。
4.程序读入下一个字符b,在编码表中查找prev=prevcode(97)、c='b'的编码项,找到了为258!则跳转到第3步,继续读入下一个字符c处理。
程序如此按照以上步骤处理,到ababcdefgefg都读完时,编码表数据是:
  1. string_tab[258].prev=97('a'), .c='b'
  2. string_tab[259].prev=98('b'), .c='a'
  3. string_tab[260].prev=258, .c='c'
  4. string_tab[261].prev=99('c'), .c='d'
  5. string_tab[262].prev=100('d'), .c='e'
  6. string_tab[263].prev=101('e'), .c='f'
  7. string_tab[264].prev=102('f'), .c='g'
  8. string_tab[265].prev=103('g'), .c='e'; 
  9. string_tab[266].prev=263, .c='g'
 最终压缩文件中的数据是:
 256 97 98 258 99 100 101 102 103 263 103 257。      
下面是LZW压缩算法的流程图:
LZW压缩(解压缩)算法详解及源码_第1张图片

LZW的解压缩过程则刚好相反,具体请参见附件中的源码。
对于文本文件,LZW算法的压缩率(压缩率=压缩后文件大小/压缩前文件大小)可以达到30%~50%。
对于二进制文件,LZW算法的压缩率则不太好,一般在50%以上。

附件是作者用C语言编写的LZW算法源码,LZWCOM3是压缩源码,LZWUNCOM3是解压缩源码。它们在Windows的Visual Studio下都已通过编译测试,移植到其他平台也很容易。该代码遵循GPL(GNU Public License)开源许可,且引用请标明出处。
使用如下:
LZW压缩(解压缩)算法详解及源码_第2张图片


LZW压缩(解压缩)算法详解及源码_第3张图片
 LZW.zip    源码请到原作者页面下载



你可能感兴趣的:(C++)