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

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

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




 LZW.zip    

《返璞归真--UNIX技术内幕》
在Linux下如何在程序中获得当前调用栈信息
在Solaris下如何在程序中获得当前调用栈信息
在AIX下如何在程序中获得当前调用栈信息
在Windows下如何在程序中获得当前调用栈信息 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值