Deflate演算法解讀

2021-08-20 15:20:29 字數 2479 閱讀 4267

gzip 使用deflate演算法進行壓縮。

通用類庫為zlib,由lz77+huffman共同實現。

1、 lz77演算法簡介

這一演算法是由jacob ziv 和 abraham lempel 於 1977 年提出,所以命名為 lz77,被一些人稱為字典演算法。

2、 lz77演算法的壓縮原理

如果檔案中有兩塊內容相同的話,那麼只要知道前一塊的位置和大小,我們就可以確定後一塊的內容。

所以我們可以用(兩者之間的距離,相同內容的長度)這樣一對資訊,來替換後一塊內容。

由於(兩者之間的距離,相同內容的長度)這一對資訊的大小,小於被替換內容的大小,所以檔案得到了壓縮。

lz77演算法使用"滑動視窗"的方法,來尋找檔案中的相同部分,也就是匹配串(它是指乙個任意位元組的序列)。

3、 huffman編碼原理

我們把檔案中一定位長的值看作是符號,比如把8位長的256種值,也就是位元組的256種值看作是符號。

根據這些符號在檔案中出現的頻率,對這些符號重新編碼。對於出現次數非常多的用較少的位來表示,對於出現次數非常少的用較多的位來表示。這樣一來檔案的一些部分位數變少了而一部分位數變多了,但由於變小的部分》變大的部分,所以實現了壓縮。

4、huffman樹編碼

進行huffman編碼,首先要把整個檔案讀一遍,在讀的過程中,統計每個符號的出現次數(1個位元組的256種值看作是256種符號)。

然後根據符號的出現次數建立huffman樹,通過huffman樹得到每個符號的新的編碼,然後把檔案中的每個位元組替換成他們新的編碼。

建立huffman樹:父結點組成乙個新的樹,這個新的樹的值為它的兩個子樹的值的和,等於父節點的值。

huffman樹的所有父結點到它的左子結點的路徑標記為0,右子結點的路徑上標為1。

看看網上提供的乙個示例圖,如下所示:

通過最終的huffman樹,我們可以得到每個符號的huffman編碼。

a 為 110、b 為 00、c 為 01、d 為 10、e 為 111

另外:比如,a的編碼為000,b的編碼為0001,c的編碼為1,那麼當遇到0001時,就不知道0001代表ac,還是代表b。

出現這種問題的原因是a的編碼是b的編碼的字首。

由於huffman編碼為根結點到葉子結點路徑上的0和1的序列,而乙個葉子結點的路徑不可能是另乙個葉子結點路徑的字首,所以乙個huffman編碼不可能為另乙個huffman編碼的字首,這就保證了huffman編碼是可以區分的。

5、使用huffman編碼進行壓縮和解壓縮

為了在解壓縮的時候,得到壓縮時所使用的huffman樹,我們需要在壓縮檔案中,儲存樹的資訊,也就是儲存每個符號的出現次數的資訊。

壓縮:讀檔案,統計每個符號的出現次數。根據每個符號的出現次數,建立huffman樹,得到每個符號的huffman編碼。將每個符號的出現次數的資訊儲存在壓縮檔案中,將檔案中的每個符號替換成它的huffman編碼,並輸出。

解壓縮:

得到儲存在壓縮檔案中的,每個符號的出現次數的資訊。根據每個符號的出現次數,建立huffman樹,得到每個符號的huffman編碼。將壓縮檔案中的每個huffman編碼替換成它對應的符號,並輸出。

6、實現摘要

deflate中的huffman編碼:

對lz77得到的壓縮後結果,需要統計字元生成編碼表huffmantree(指示每個編碼代表什麼字元),根據碼表對內容進行編碼,具體的壓縮大小在於精細分配結構體的位域來實現huffman編碼的壓縮效果的。

編碼表huffmantree和編碼後的data都一起放置在檔案中。

deflate中的解壓:

讀取二進位制檔案,構建huffmantree表,讀取資料根據huffmantree生成字元(這些字元是符合lz77演算法的)。

用lz77解碼,這個時候應該需要對視窗生成雜湊表(陣列+鍊錶);對解壓的資料,進行搜尋匹配拷貝替換為相應的串即可。

gzip原始碼分析

main()中呼叫函式 treat_file()。

treat_file()中開啟檔案,呼叫函式 zip()。注意這裡的 work的用法,這是乙個函式指標。

zip()中輸出gzip檔案格式的頭,呼叫 bi_init,ct_init,lm_init,

其中在lm_init中將 head初始化清0。初始化strstart為0。從檔案中讀入64kb的內容到window緩衝區中。

由於計算strstart=0時的ins_h,需要0,1,2這三個位元組和雜湊函式發生關係,所以在lm_init中,預讀0,1兩個位元組,並和雜湊函式發生關係。

然後lm_init呼叫 deflate()。

deflate() gzip的lz77的實現主要deflate()中。

deflate樹與deflate編碼

關於deflate樹,能搜到的資料非常少,這個概念來自gzip的壓縮演算法,是 由huffman樹轉變過來的。這裡簡單記錄下deflate樹的生成過程以及deflate編碼。假設以5 8 9 10 14 15,建立一顆huffman樹,可以是這個樣子的 61 2734 1413 1519 58910...

Retinex演算法解讀

retinex是一種常用的建立在科學實驗和科學分析基礎上的影象增強方法,它是 edwin.h.land 於1963 年提出的。就跟 matlab 是由matrix 和laboratory 合成的一樣,retinex 也是由兩個單詞合成的乙個詞語,他們分別是 retina 和cortex 即 視網膜和...

演算法解讀 基本的演算法

1.執行迴圈操作求1 n的和 要完成這個計算,可以通過以下迴圈步驟求出 a.將求和變數sum的初始值設為0.b.將和sum為計算結果,value為加數 c.value在n以下時,重複執行4 5的操作 d.計算sum value的值並將值存入sum中 e.每次value值加1.1 public sta...