lzw编码:
/***************************************************************************************************以下摘自Hevcer的csdn博客:
LZW是一个字典式压缩算法,他在压缩原始数据时,对每一个新出现的原始数据串赋一个数值作为标号,那么下次又出现了这个串后,就可以用这个值来代替了。比如
A B A B A B A B B B A B A B A A C D A C D A D C A B A A A B A B .....
A B A B A B A B B B A B A B A A C D A C D A D C A B A A A B A B ....输入流.
\/\/---/-----/\/---/-------/\/ \/ \ /\/---/---/\ /\/-----/---/---/
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 标号
6 8 10 9 14 16 8 13 7 前缀
Color Code Prefix Suffix String Output 位数
A 0 -
B 1 -
C 2 -
D 3 -
Clear 4 -
End 5 -
A \ A A First color is a special case.
B / \ 6 A B AB A 3
A | / 7 B A BA B 3
B |
A / | 8 6 A ABA 6 3
B |
A |
B \ / 9 8 B ABAB 8 4
B / | 10 B B BB B 4
B |
A | / 11 10 A BBA 10 …
B |
A |
B |
A / \ 12 9 A ABABA 9
A \ / 13 A A AA A
C / \ 14 A C AC A
D \ / 15 C D CD C
A / | 16 D A DA D 4
C |
D | / 17 14 D ACD 14 5
A |
D / \ 18 16 D DAD 16
C \ / 19 D C DC D
A / | 20 C A CA C
B |
A |
A | / 21 8 A ABAA 8
A |
B / | 22 13 B AAB 13
A |
B / 23 7 B BAB 7
*****************************************************************************************************/
以下为笔者自述:
LZW解码:
lzw解码过程中的要点:
因为编码过程是动态的,编码长度慢慢变成,所以解码过程中,在读取编码流的时候要注意读取的位数.例如GIF色深是4,那么每次 要从GIF中读取5位开始解码,等到编码表写到32项的时候,每次要从GIF读6位开始解码,依次类推直到读到12位,编码最大长度.
lzw解码过程:
clear(清除标志):假设B=原始码位数,N=2^B,那么初始化码表(字典)从0-N-1项,清除标志位数N,遇到清除标志,则整个码表要被复位,下一个解码要读B+1位.
块结束标志:N+1,表示读到一副图像编码的末尾,本帧图像解码结束.
解码流程(接上例A B 6 8 B 10 9 A A C D 14 16 D C 8 13 7):
1,色深位2,则每次读3位码流,读码字A,则本次前缀prefix=A,因为有输出,必然会添加字典,字典从6开始添加,则,本次添加字典6(A,?),读下一码字B,注意每次输出为前缀,即为上一次的后缀,所以,字典6(A,B),此次prefix=B,添加字典7(B,?);
2,下一个读出为6(字典7出现,开始读4位),prefix=(AB),suffix=?,添加字典8(AB,?),显然(AB)不能作为上次编码后缀(后缀只能位单个字符),所以上一次编码无输出,上次编码suffix=B,则prefix=A,A只有一位,则可作为上上次编码后缀,suffix=A,补齐字典7(B,A);
3,下一个读出为8,8为(AB,?),AB不能作为后缀,所以上次编码无输出,(AB)为字符串,suffix=B,prefix=A,A可以作为后缀,所以上上次string为8(AB,A),下次string(A,?),此次9=string(ABA,?);
4,下一个读出为B,string(B,?),上次string(?,B),由过程3知道上次string(A,B);
5,......................
如果不理解上述所讲,则看如下表格:
字典 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
读码流位数 | 3 | 3 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | 5 |
读出码值 | A | B | 6 | 8 | B | 10 | 9 | A | A | C | D | 14 | 16 | D | C | 8 | 13 | 7 |
上次字符串 | (-,B) | (A,B) | (A,B) | (AB,?) | (8,B) | (10) | (9) | (9,A) | (A,A) | (A,C) | (C,D) | (14) | (16) | (16,D) | (D,C) | (8) | (13) | (7) |
本次字符串 | (A,?) | (B,?) | (AB,?) | (AB?,?) | (B,?) | (10,?) | (9,?) | (A,?) | (A,?) | (C,?) | (D,?) | (14,?) | (16,?) | (D,?) | (C,?) | (8,?) | (13,?) | (7,?) |
得出字典值 | 6=AB | 7=BA | 8=ABA | 9=ABAB | 10=BB | 11=BBA | 12=ABABA | 13=AA | 14=AC | 15=CD | 16=DA | 17=ACD | 18=DAD | 19=DC | 20=CA | 21=ABAA | 22=AAB |
提示:此解码表要一列一列看,每一列有且只能得出上一个字典值,后缀只能位单个字符;根据字典编号读相应的位数;如不理解此表,请对照编码流程自行思考.