lzw編碼c語言
Ⅰ 求一個c++的用lzw(字典)演算法來壓縮bmp圖片的代碼
參見gif壓縮演算法源代碼。
1.LZW的全稱是什麼?
Lempel-Ziv-Welch (LZW).
2. LZW的簡介和壓縮原理是什麼?
LZW壓縮演算法是一種新穎的壓縮方法,由Lemple-Ziv-Welch 三人共同創造,用他們的名字命名。它採用了一種先進的串表壓縮,將每個第一次出現的串放在一個串表中,用一個數字來表示串,壓縮文件只存貯數字,則不存貯串,從而使圖象文件的壓縮效率得到較大的提高。奇妙的是,不管是在壓縮還是在解壓縮的過程中都能正確的建立這個串表,壓縮或解壓縮完成後,這個串表又被丟棄。
LZW演算法中,首先建立一個字元串表,把每一個第一次出現的字元串放入串表中,並用一個數字來表示,這個數字與此字元串在串表中的位置有關,並將這個數字存入壓縮文件中,如果這個字元串再次出現時,即可用表示它的數字來代替,並將這個數字存入文件中。壓縮完成後將串表丟棄。如"print" 字元串,如果在壓縮時用266表示,只要再次出現,均用266表示,並將"print"字元串存入串表中,在圖象解碼時遇到數字266,即可從串表中查出266所代表的字元串"print",在解壓縮時,串表可以根據壓縮數據重新生成。
3.在詳細介紹演算法之前,先列出一些與該演算法相關的概念和詞彙
1)'Character': 字元,一種基礎數據元素,在普通文本文件中,它佔用1個單獨的byte,而在圖像中,它卻是 一種代表給定像素顏色的索引值。
2)'CharStream':數據文件中的字元流。
3)'Prefix':前綴。如這個單詞的含義一樣,代表著在一個字元最直接的前一個字元。一個前綴字元長度可以為0,一個prefix和一個character可以組成一個字元串(string),
4)'Suffix': 後綴,是一個字元,一個字元串可以由(A,B)來組成,A是前綴,B是後綴,當A長度為0的時候,代表Root,根
5)'Code:碼,用於代表一個字元串的位置編碼
6)'Entry',一個Code和它所代表的字元串(string)
4.壓縮演算法的簡單示例,不是完全實現LZW演算法,只是從最直觀的角度看lzw演算法的思想
對原始數據ABCCAABCDDAACCDB進行LZW壓縮
原始數據中,只包括4個字元(Character),A,B,C,D,四個字元可以用一個2bit的數表示,0-A,1-B,2-C,3-D,從最直觀的角度看,原始字元串存在重復字元:ABCCAABCDDAACCDB,用4代表AB,5代表CC,上面的字元串可以替代表示為:45A4CDDAA5DB,這樣是不是就比原數據短了一些呢!
5.LZW演算法的適用范圍
為了區別代表串的值(Code)和原來的單個的數據值(String),需要使它們的數值域不重合,上面用0-3來代表A-D,那麼AB就必須用大於3的數值來代替,再舉另外一個例子,原來的數值范圍可以用8bit來表示,那麼就認為原始的數的范圍是0~255,壓縮程序生成的標號的范圍就不能為0~255(如果是0-255,就重復了)。只能從256開始,但是這樣一來就超過了8位的表示範圍了,所以必須要擴展數據的位數,至少擴展一位,但是這樣不是增加了1個字元佔用的空間了么?但是卻可以用一個字元代表幾個字元,比如原來255是8bit,但是現在用256來表示254,255兩個數,還是劃得來的。從這個原理可以看出LZW演算法的適用范圍是原始數據串最好是有大量的子串多次重復出現,重復的越多,壓縮效果越好。反之則越差,可能真的不減反增了。
6.LZW演算法中特殊標記
隨著新的串(string)不斷被發現,標號也會不斷地增長,如果原數據過大,生成的標號集(string table)會越來越大,這時候操作這個集合就會產生效率問題。如何避免這個問題呢?Gif在採用lzw演算法的做法是當標號集足夠大的時候,就不能增大了,乾脆從頭開始再來,在這個位置要插入一個標號,就是清除標志CLEAR,表示從這里我重新開始構造字典,以前的所有標記作廢,開始使用新的標記。
這時候又有一個問題出現,足夠大是多大?這個標號集的大小為比較合適呢?理論上是標號集大小越大,則壓縮比率就越高,但開銷也越高。 一般根據處理速度和內存空間連個因素來選定。GIF規范規定的是12位,超過12位的表達范圍就推倒重來,並且GIF為了提高壓縮率,採用的是變長的字長。比如說原始數據是8位,那麼一開始,先加上一位再說,開始的字長就成了9位,然後開始加標號,當標號加到512時,也就是超過9為所能表達的最大數據時,也就意味著後面的標號要用10位字長才能表示了,那麼從這里開始,後面的字長就是10位了。依此類推,到了2^12也就是4096時,在這里插一個清除標志,從後面開始,從9位再來。
GIF規定的清除標志CLEAR的數值是原始數據字長表示的最大值加1,如果原始數據字長是8,那麼清除標志就是256,如果原始數據字長為4那麼就是16。另外GIF還規定了一個結束標志END,它的值是清除標志CLEAR再加1。由於GIF規定的位數有1位(單色圖),4位(16色)和8位(256色),而1位的情況下如果只擴展1位,只能表示4種狀態,那麼加上一個清除標志和結束標志就用完了,所以1位的情況下就必須擴充到3位。其它兩種情況初始的字長就為5位和9位。此處參照了http://blog.csdn.net/whycadi/
7.用lzw演算法壓縮原始數據的示例分析
輸入流,也就是原始的數據為:255,24,54,255,24,255,255,24,5,123,45,255,24,5,24,54..................
這個正好可以看到是gif文件中像素數組的一部分,如何對它進行壓縮
因為原始數據可以用8bit來表示,故清除標志Clear=255+1 =256,結束標志為End=256+1=257,目前標號集為
0 1 2 3 .................................................................................255 CLEAR END
第一步,讀取第一個字元為255,在標記表裡面查找,255已經存在,我們已經認識255了,不做處理
第二步,取第二個字元,此時前綴為A,形成當前的Entry為(255,24),在標記集合不存在,我們並不認識255,24好,這次你小子來了,我就記住你,把它在標記集合中標記為258,然後輸出前綴A,保留後綴24,並作為下一次的前綴(後綴變前綴)
第三步,取第三個字元為54,當前Entry(24,54),不認識,記錄(24,54)為標號259,並輸出24,後綴變前綴
第四部:取第四個字元255,Entry=(54,255),不認識,記錄(54,255)為標號260,輸出54,後綴變前綴
第五步 取第5個字元24,entry=(255,24),啊,認識你,這不是老258么,於是把字元串規約為258,並作為前綴
第六步 取第六個字元255,entry=(258,255),不認識,記錄(258,255)為261,輸出258,後綴變前綴
.......
一直處理到最後一個字元,
用一個表記錄處理過程
CLEAR=256,END=257
第幾步 前綴 後綴 Entry 認識(Y/N) 輸出 標號
1 255 (,255)
2 255 24 (255,24) N 255 258
3 24 54 (24,54) N 24 259
4 54 255 (54,255) N 54 260
5 255 24 (255,24) Y
6 258 255 (258,255) N 258 261
7 255 255 (255,255) N 255 262
.....
上面這個示例有些不能完整體現,另外一個例子是
原輸入數據為: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 .....
採用LZW演算法對其進行壓縮,壓縮過程用一個表來表述為:
注意原數據中只包含4個character,A,B,C,D
用兩bit即可表述,根據lzw演算法,首先擴展一位變為3為,Clear=2的2次方+1=4; End=4+1=5;
初始標號集因該為
0 1 2 3 4 5
A B C D Clear End
而壓縮過程為:
第幾步 前綴 後綴 Entry 認識(Y/N) 輸出 標號
1 A (,A)
2 A B (A,B) N A 6
3 B A (B,A) N B 7
4 A B (A,B) Y
5 6 A (6,A) N 6 8
6 A B (A,B) Y
7 6 A (6,A) Y
8 8 B (8,B) N 8 9
9 B B (B,B) N B 10
10 B B (B,B) Y
11 10 A (10,A) N 10 11
12 A B (A,B) Y
.....
當進行到第12步的時候,標號集應該為
0 1 2 3 4 5 6 7 8 9 10 11
A B C D Clear End AB BA 6A 8B BB 10A
8.LZW演算法的偽代碼實現
1STRING = get input character
2WHILE there are still input characters DO
3 CHARACTER = get input character
4 IF STRING+CHARACTER is in the string table then
5 STRING = STRING+character
6 ELSE
7 output the code for STRING
8 add STRING+CHARACTER to the string table
9 STRING = CHARACTER
10 END of IF
11END of WHILE
12output the code for STRING
13
Ⅱ 跪求C語言進行哈夫曼編碼、算術編碼和LZW編碼,要求源程序要有注釋。
以下是哈夫曼編碼
#include<iostream>
#include<math.h>
#include<string>
#include<iomanip>
using namespace std;
int n;
int isin(string str,char a)
{
int temp=0;
for(int i=0;i<str.length();i++)
{
if(str[i]==a) temp=1;
}
return temp;
}
void bubble(double p[],string sign[])//排序
{
for(int i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(p[i]<p[j])
{
double temp=p[i];
p[i]=p[j];
p[j]=temp;
string m=sign[i];
sign[i]=sign[j];
sign[j]=m;
}
}
}
}
void huff(double tempp[],string tempstr[])
{
double p[20][20];
string sign[20][20];
sign[0][i]=tempstr[i]; //符號放在sign數組中
for(int i=0;i<n;i++)
{
p[0][i]=tempp[i]; //p數組放對應的概率(第1列中)
}
for(i=0;i<n-1;i++)
{
bubble(p[i],sign[i]); //第一次排序
for(int j=0;j<n-2-i;j++)
{
p[i+1][j]=p[i][j]; //前n-2-i個概率重新放在p數組中(是數組的第2列中)
sign[i+1][j]=sign[i][j];
}
p[i+1][j]=p[i][j]+p[i][j+1];//第一次兩個最小概率求和
sign[i+1][j]=sign[i][j]+sign[i][j+1];//符號跟隨
for(j=n-1-i;j<n;j++)
{
p[i+1][j]=0;
}
}
string final[20];
for(i=n-2;i>=0;i--)
{
for(int k=0;k<n;k++)
{
if(isin(sign[i][n-2-i],sign[0][k][0])) final[k]+="0";
if(isin(sign[i][n-1-i],sign[0][k][0])) final[k]+="1";
}
}
cout<<setw(9)<<"哈弗曼編碼如下:"<<endl;
for(i=0;i<n;i++)
{
cout<<setw(7)<<sign[0][i]<<setw(7)<<p[0][i]<<setw(10)<<final[i]<<
setw(7)<<final[i].length()<<endl;
}
}
void main()
{
char a[50];
cout<<"該字元串符號為:";
cin>>a;
string s=a;
n=s.length();
char b[20][2];
for(int i=0;i<n;i++)
{
b[i][0]=a[i];
b[i][1]='\0';
}
string str[20];
for(i=0;i<n;i++)
{
str[i]=b[i];
}
double tempp[20];
cout<<"字元概率依次為:";
for(i=0;i<n;i++)
{
cin>>tempp[i];
}
huff(tempp,str);
}
Ⅲ LZW是什麼意思
LZW壓縮編碼
LZW(Lempel Ziv Welch)壓縮編碼是一種先進的數據壓縮技術,屬於無損壓縮編碼,該編碼主要用於圖像數據的壓縮。對於簡單圖像和平滑且雜訊小的信號源具有較高的壓縮比,並且有較高的壓縮和解壓縮速度。
1977年,兩位以色列教授Lempel和Ziv提出了查找冗餘字元和用較短的符號標記替代冗餘字元的概念。1985年,由Welch加以充實而形成LZW,簡稱「LZW」技術。
1.LZW壓縮基本原理
LZW壓縮技術把數據流中復雜的數據用簡單的代碼來表示,並把代碼和數據的對應關系建立一個轉換表,又叫「字元串表」。
轉換表是在壓縮或解壓縮過程中動態生成的表,該表只在進行壓縮或解壓縮過程中需要,一旦壓縮和解壓縮結束,該表將不再起任何作用。
2.LZW演算法
LZW演算法基於轉換串表(字典)T,將輸入字元串映射成定長(通常為12位)的碼字。在12位4096種可能的代碼中,256個代表單字元,剩下3840給出現的字元串。
LZW字典中的字元串具有前綴性,即 。
LZW演算法流程:
1)初始化:將所有的單字元串放入串表
2)讀第一個輸入字元給前綴串ω
3)Step: 讀下一個輸入字元K;
if 沒有這樣的K(輸入已窮盡):
碼字(ω) 輸出;結束。
If ωK 已存在於串表中:
ωK:=ω;repeat Step;
else ωK不在於串表中:
碼字(ω) 輸出;
ωK加進串表;
K:=ω;repeat Step.
例子:ababcbababaaaaaaa
LZW編碼:a,b,c,ab,ba,abc,cb,bab,baba,aa,aaa,aaaa
3.LZW壓縮的特點
LZW碼能有效利用字元出現頻率冗餘度進行壓縮,且字典是自適應生成的,但通常不能有效地利用位置冗餘度。
具體特點如下:
l)LZW壓縮技術對於可預測性不大的數據具有較好的處理效果,常用於GIF格式的圖像壓縮,其平均壓縮比在2)1以上,最高壓縮比可達到3:1。
2)對於數據流中連續重復出現的位元組和字串,LZW壓縮技術具有很高的壓縮比。
3)除了用於圖像數據處理以外,LZW壓縮技術還被用於文本程序等數據壓縮領域。
4)LZW壓縮技術有很多變體,例如常見的ARC、RKARC、PKZIP高效壓縮程序。
5)對於任意寬度和像素位長度的圖像,都具有穩定的壓縮過程。壓縮和解壓縮速度較快。
6)對機器硬體條件要求不高,在 Intel 80386的計算機上即可進行壓縮和解壓縮。
Ⅳ LZW演算法問題
LZW演算法全名叫做Lempel-Ziv-Welch Encoding,是一種數據壓縮演算法,它是有專利的,不過現今大部分專利都己經過期。它可以對文本進行簡單的壓縮,壓縮比對於一般場合還是可以適用的,另外使用的比較多的就是GIF圖像了。
LZW演算法中有幾個比較重要的概念:字元,字元串,編碼表。它把數據流看成一個字元序列,並將字元序列組織成一系列的字元串,並給每個字元串一個編碼,最後存儲的就是字元串的編碼,這樣就節省了空間。如將ababba表示為編碼1532,而1523用12bit就可以表示出來,比原來5*8bit就節省了不少空間。LZW的編碼表是動態創建的,並且通過編碼後的數據流可以恢復出與編碼時同樣的編碼表,這樣在數據存儲與傳輸的時候就不需要保存原始的編碼表,這也是與一些在編碼之前就有固定的編碼表的演算法有著巨大的區別。
1.編碼過程:
LZW是一個固長編碼的演算法的,即對於每一個字元或字元串的編碼都是等長的。為了說明的方便,我決定用16bit作為編碼,前255作為字元編碼,256,257另作它用,這將在3中進行說明。所以字元串的編碼將從258開始。
編碼的整個過程如下:
1. 初始化編碼表,編碼起始號,並置當前字元串為空;
2. 讀入一個字元,如果為EOF,輸出當前字元串,並結束,否則進入3;
3. 將新讀入的字元與當前字元串組成新的字元串,如果新的字元串在編碼表中出現,則繼續進行2,否則進入4;
4. 將新的字元串加入到編碼表中,分配編號,設當前字元串的長度為N,輸入新字元串的N-1長度前綴的編碼,並將當前字元串置為當前字元串的一個長度為1的後綴,再執行2。
2.解碼過程:
對於解碼,唯一需要知道的就是編碼的長度了,每次從編碼流中讀取相應bit的長度,就形成一個編碼,再通過該編碼從編碼表中找出相對應的串輸出即可。由於沒有存儲編碼時對應的編碼表,在解碼時需要同時構造編碼表。
解碼過程如下:
1. 初始化編碼表,並置前一個編碼為空;
2. 取一個編碼,如果編碼為結束,則結束。否則進行3;
3. 輸出編碼所代表的字元串,如果前一個編碼不為空,將前一個編碼的字元串與當前字元串的第一個字元作為新的串加入編碼表中,置前一個編碼為當前編碼,並執行2。
Ⅳ LZW演算法的LZW演算法
LZW演算法基於轉換串表(字典)T,將輸入字元串映射成定長(通常為12位)的碼字。在12位4096種可能的代碼中,256個代表單字元,剩下3840給出現的字元串。
LZW字典中的字元串具有前綴性,即 ωK∈T=>;ωT。
LZW演算法流程:
步驟1: 開始時的詞典包含所有可能的根(Root),而當前前綴P是空的;步驟2: 當前字元(C) :=字元流中的下一個字元;步驟3: 判斷綴-符串P+C是否在詞典中(1) 如果「是」:P := P+C // (用C擴展P) ;(2) 如果「否」① 把代表當前前綴P的碼字輸出到碼字流;② 把綴-符串P+C添加到詞典;③ 令P := C //(現在的P僅包含一個字元C);步驟4: 判斷碼字流中是否還有碼字要譯(1) 如果「是」,就返回到步驟2;(2) 如果「否」① 把代表當前前綴P的碼字輸出到碼字流;② 結束。 具體解壓步驟如下:
(1)解碼開始時Dictionary包含所有的根。
(2)讀入在編碼數據流中的第一個碼字 cW(它表示一個Root)。
(3)輸出String.cW到字元數據流Charstream。
(4)使pW=cW 。
(5)讀入編碼數 據流 的下一個碼字cW 。
(6)目前在字典中有String.cW嗎?
YES:1)將String.cW輸出給字元數據流;
2)使P=String.pW;
3)使C=String.cW的第一個字元;
4)將字元 串P+C添 加進Dictionray。
NO :1)使P=String.pW ;
2)使C=String.pW的第一個字元;
3)將字元串P+C輸出到字元數據流並將其添加進Dictionray(現在它與cW相一致)。
(7)在編碼數據 流中還有Codeword嗎?
YES:返回(4)繼 續進行 解碼 。
NO:結束解碼 。
Ⅵ LZW演算法的LZW演算法簡介
字元串和編碼的對應關系是在壓縮過程中動態生成的,並且隱含在壓縮數據中,解壓的時候根據表來進行恢復,算是一種無損壓縮.
根據 Lempel-Ziv-Welch Encoding ,簡稱 LZW 的壓縮演算法,用任何一種語言來實現它.
LZW壓縮演算法 的基本概念:LZW壓縮有三個重要的對象:數據流(CharStream)、編碼流(CodeStream)和編譯表(String Table)。在編碼時,數據流是輸入對象(文本文件的據序列),編碼流就是輸出對象(經過壓縮運算的編碼數據);在解碼時,編碼流則是輸入對象,數據流是輸出對象;而編譯表是在編碼和解碼時都須要用藉助的對象。
字元(Character):最基礎的數據元素,在文本文件中就是一個位元組,在光柵數據中就是一個像素的顏色在指定的顏色列表中的索引值;
字元串(String):由幾個連續的字元組成;
前綴(Prefix):也是一個字元串,不過通常用在另一個字元的前面,而且它的長度可以為0;
根(Root):一個長度的字元串;
編碼(Code):一個數字,按照固定長度(編碼長度)從編碼流中取出,編譯表的映射值;圖案:一個字元串,按不定長度從數據流中讀出,映射到編譯表條目.
LZW壓縮演算法 的基本原理:提取原始文本文件數據中的不同字元,基於這些字元創建一個編譯表,然後用編譯表中的字元的索引來替代原始文本文件數據中的相應字元,減少原始數據大小。看起來和調色板圖象的實現原理差不多,但是應該注意到的是,我們這里的編譯表不是事先創建好的,而是根據原始文件數據動態創建的,解碼時還要從已編碼的數據中還原出原來的編譯表.