jpeg編碼規則?
本文簡要概述 JPEG 基本系統的編碼流程。
編碼需要經過 DCT、量化、Z 序列化、系數編碼(DC 差分脈沖調制編碼、DC 系數中間格式計算、AC 差分脈沖調制編碼、AC 系數中間格式計算)、熵編碼五個步驟,最后按指定格式進行封裝,成為一張 JPEG 圖片。
?
圖片被分割為若干 8×8 塊后,每個塊進行離散余弦變換(DCT),其目的是將圖像塊按頻率分解,得到其頻譜。
類似傅里葉變換,DCT 的目的是將圖像分解為不同頻率的基本分量的線性組合。
事實上,DCT 是 DFT 抹去虛(奇)部的特殊形式。由于實偶函數的 DFT 仍然是實偶函數,我們將時域函數倍增延拓成偶函數,于是頻域也成為實偶函數。當然在存儲時可以折半以消除冗余。
?
為何要求 DCT?對每一個圖像塊,如果一定要舍棄,我們會盡可能多保留其低頻分量,而降低高頻分量的分辨率。同時,高頻分量通常也的確是較少的,而直流分量,雖然數值大,但相鄰塊的直流分量差別較小。
?
因此我們對低頻分量取較低的量化系數,而對高頻分量取較高的量化系數。
所謂量化,就是將浮點(實現上可能只是以更高精度的整數表示形式存在)值 x 轉化為階躍的整數值 y 表示的過程,而 y=round(x/q) 中的 q 就是量化系數。
隨后我們進行 Z 序列化,將二維矩陣按 Z 形拍扁成向量。
?
考慮到相鄰塊 DC 分量差異小,我們首先將 DC 分量與上一個塊做差。這個過程稱為差分脈沖調制編碼。
如今,向量中存在大量的 0,而絕對值小的數字出現的概率也遠大于絕對值大者。
我們采用行程編碼(RLE),將序列切成形如 0,0,…,0,x 的若干段,每段由 y(≥0) 個 0 和一個 x(>0) 組成,記作 (y,len(x),x),其中 len(x) 是 x 在反碼二進制表示下的長度。這種三元組表示形式稱為中間格式。
(注:這里圖上將 DC 分量也一把揉進去了,嚴格來說是分開的,RLE 只考慮 AC 分量)
?
現在考慮 (y,l,x) 三元組的編碼。我們用一個字節的高 4 位和低 4 位分別存放 y,l 兩個 uint4,并對這個字節進行哈夫曼編碼。至于 x,一個小多大少的家伙,還被記錄了長度,就直接寫進二進制流里好了。
需要指出,這里我們略去了一些特殊情況。比如連續 0 的個數超過 15 該如何處理,AC 分量末