二、解碼過程簡述
8. 一個數(shù)據(jù)單元 Y 的解碼 (其余類同)
在整個圖片解碼的開始, 你需要先初始化 DC 值為 0.
1) 先解碼 DC: a) 取得一個 Huffman 碼 (使用 Huffman DC 表) b) Huffman解碼, 看看后面的數(shù)據(jù)位數(shù) N c) 取得 N 位, 計算 Diff 值 d) DC + = Diff e) 寫入 DC 值: " vector[0]=DC "
2) 解碼 63 個 AC:
------- 循環(huán)處理每個 AC 直到 EOB 或者處理到 64 個 AC
a) 取得一個 Huffman 碼 (使用 Huffman AC 表) b) Huffman 解碼, 得到 (前面 0 數(shù)量, 組號) [記住: 如果是(0,0) 就是 EOB 了]
c) 取得 N 位(組號) 計算 AC d) 寫入相應數(shù)量的 0 e) 接下來寫入 AC
下一步的解碼:
上一步我們得到了 64 個矢量. 下面我們還需要做一些解碼工作:
1) 反量化 64 個矢量 : "for (i=0;i<=63;i++) vector[i]*=quant[i]" (注意防止溢出) 2) 重排列 64 個矢量到 8x8 的塊中 3) 對 8x8 的塊作 IDCT
對 8x8 塊的 (Y,Cb,Cr) 重復上面的操作 [Huffman 解碼, 步驟 1), 2), 3)]
4) 將所有的 8bit 數(shù)加上 128 5) 轉(zhuǎn)換 YCbCr 到 RGB
9. JPG 文件(Byte 級)里怎樣組織圖片信息
注意 JPEG/JFIF 文件格式使用 Motorola 格式, 而不是 Intel 格式, 就是說, 如果是一個字的話, 高字節(jié)在前, 低字節(jié)在后.
JPG 文件是由一個個段 (segments) 構(gòu)成的. 每個段長度 <=65535. 每個段從一個標記字開始. 標記字都是 0xff 打頭的, 以非 0 字節(jié)和 0xFF 結(jié)束. 例如 'FFDA' , 'FFC4', 'FFC0'. 每個標記有它特定意義, 這是由第2字節(jié)指明的. 例如, SOS (Start Of Scan = 'FFDA') 指明了你應該開始解碼. 另一個標記 DQT (Define QuantizationTable = 0xFFDB) 就是說它后面有 64 字節(jié)的 quantization 表
在處理 JPG 文件時, 如果你碰到一個 0xFF, 而它后面的字節(jié)不是 0, 并且這個字節(jié)沒有意義. 那么你遇到的 0xFF 字節(jié)必須被忽略. (一些 JPG 里, 常用用 0xFF 做某些填充用途) 如果你在做 huffman 編碼時碰巧產(chǎn)生了一個 0xFF, 那么就用 0xFF0x00 代替. 就是說在 jpeg 圖形解碼時碰到 FF00 就把它當作 FF 處理.
另外在 huffman 編碼區(qū)域結(jié)束時, 碰到幾個 bit 沒有用的時候, 應該用 1 去填充.然后后面跟 FF.
下面是幾個重要的標記:
SOI = Start Of Image = 'FFD8' 這個標記只在文件開始出現(xiàn)一次 EOI = End Of Image = 'FFD9' JPG 文件都以 FFD9 結(jié)束
RSTi = FFDi ( i = 0..7) [ RST0 = FFD0, RST7=FFD7] = 復位標記
通常穿插在數(shù)據(jù)流里, 我想是擔心 JPG 解碼出問題吧(應該配合 DRI 使用). RST 將Huffman 的解碼數(shù)據(jù)流復位. DC 也重新從 0 開始計
(SOS --- RST0 --- RST1 -- RST2 --... ...-- RST6 --- RST7 -- RST0 --...)
10. 標記
下面是必須處理的標記
SOF0 = Start Of Frame 0 = FFC0 SOS = Start Of Scan = FFDA APP0 = it's the marker used to identify a JPG file which uses the JFIF specification = FFE0 COM = Comment = FFFE DNL = Define Number of Lines = FFDC DRI = Define Restart Interval = FFDD DQT = Define Quantization Table = FFDB DHT = Define Huffman Table = FFC4
11. JPG 文件中 Haffman 表的儲存
JPEG 里定義了一張表來描述 Haffman 樹. 定義在 DHT 標記后面. 注意: Haffman 代碼的長度限制在 16bit 內(nèi).
一般一個 JPG 文件里會有 2 類 Haffman 表: 一個用于 DC 一個用于 AC (實際有 4個表, 亮度的 DC,AC 兩個, 色度的 DC,AC 兩個)
這張表是這樣保存的: 1) 16 字節(jié): 第 i 字節(jié)表示了 i 位長的 Huffman 代碼的個數(shù) (i= 1 到 16)
2) 這表的長度 (字節(jié)數(shù)) = 這 16 個數(shù)字之和 現(xiàn)在你可以想象這張表怎么存放的吧? 對應字節(jié)就是對應 Haffman 代碼等價數(shù)字. 我 不多解釋, 這需要你先了解 Canonical Huffman Code. 這里只舉一個例子:
Haffman 表的表頭是 0,2,3,1,1,1,0,1,0,0,0,0,0,0,0,0 就是說長度為 1 的代碼沒有 長度為 2 的代碼為 00 01 長度為 3 的代碼是 100 101 110 長度為 4 的代碼是 1110 長度為 5 的代碼是 11110 長度為 6 的代碼是 111110 長度為 7 的代碼沒有 (如果有一個的話應該是 1111110) 長度為 8 的代碼是 11111100 ..... 后面都沒有了.
如果表下面的數(shù)據(jù)是 45 57 29 17 23 25 34 28
就是說 45 = 00 57 = 01 29 = 100 17 = 101 23 = 110 等等...
使用 Canonical Huffman Code 的好處在于可以很簡潔的重建對應關(guān)系表.
12. 采樣系數(shù)
下面講解的都是真彩 JPG 的解碼, 灰度 JPG 的解碼很簡單, 因為圖形中只有亮度信息. 而彩色圖形由 (Y, Cr, Cb) 構(gòu)成, 前面提到過, Y 通常是每點采樣一次, 而 Cr,Cb 一般是 2x2 點采樣一次, 當然也有的 JPG 是逐點采樣, 或者每兩點采樣 (橫向兩點, 縱向一點) 采樣系數(shù)均被定義成對比最高采樣系數(shù)的相對值.
一般情況 (即: Y 逐點采樣, Cr Cb 每 2x2 點一次) 下: Y 有最高的采樣率, 橫向采樣系數(shù)HY=2 縱向采樣系數(shù) VY=2; Cb 的橫向采樣系數(shù) HCb=1, 縱向采樣系數(shù) VCb=1;同樣 HCr=1, VCr=1
在 Jpeg 里, 8x8 個原始數(shù)據(jù), 經(jīng)過 RLE, Huffman 編碼后的一串數(shù)據(jù)流稱為一個 Data Unit (DU) JPG 里按 DU 為單位的編碼次序如下:
1) for (counter_y=1;counter_y<=VY;counter_y++) for (counter_x=1;counter_x<=HY;counter_x++) { 對 Y 的 Data Unit 編碼 }
2) for (counter_y=1;counter_y<=VCb ;counter_y++) for (counter_x=1;counter_x<=HCb;counter_x++) { 對 Cb 的 Data Unit 編碼 }
3) for (counter_y=1;counter_y<=VCr;counter_y++) for (counter_x=1;counter_x<=HCr;counter_x++) { 對 Cr 的 Data Unit 編碼 }
按我上面的例子: (HY=2, VY=2 ; HCb=VCb =1, HCr,VCr=1) 就是這樣一個次序 YDU,YDU,YDU,YDU,CbDU,CrDU 這些就描述了一塊 16x16 的圖形. 16x16 = (Hmax*8 x Vmax*8) 這里 Hmax=HY=2 Vmax=VY=2
一個 (Hmax*8,Vmax*8) 的塊被稱作 MCU (Minimun Coded Unix) 前面例子中一個 MCU = YDU,YDU,YDU,YDU,CbDU,CrDU
如果 HY =1, VY=1 HCb=1, VCb=1 HCr=1, VCr=1 這樣 (Hmax=1,Vmax=1), MCU 只有 8x8 大, MCU = YDU,CbDU,CrDU
對于灰度 JPG, MCU 只有一個 DU (MCU = YDU)
JPG 文件里, 圖象的每個組成部分的采樣系數(shù)定義在 SOF0 (FFC0) 標記后
13. 簡單說一下 JPG 文件的解碼
解碼程序先從 JPG 文件中讀出采樣系數(shù), 這樣就知道了 MCU 的大小, 算出整個圖象 有幾個 MCU. 解碼程序再循環(huán)逐個對 MCU 解碼, 一直到檢查到 EOI 標記. 對于每個 MCU, 按正規(guī)的次序解出每個 DU, 然后組合, 轉(zhuǎn)換成 (R,G,B) 就 OK 了
出處:云風工作室
責任編輯:moby
上一頁 JPEG 簡易文檔 V2.14 [2] 下一頁 JPEG 簡易文檔 V2.14 [4]
◎進入論壇網(wǎng)絡編程版塊參加討論
|