JPEG文件編/解碼詳解

JPEGJoint Photographic Experts Group)是聯合圖像專家小組的英文縮寫。它由國際電話與電報諮詢委員會

CCITTThe International Telegraph and Telephone Consultative Committee)與國際標準化組織ISO1986年聯合

成立的一個小組,負責制定靜態數字圖像的編碼標準。

小組一直致力於標準化工作,開發研製出連續色調、多級灰度、靜止圖像的數字圖像壓縮編碼方法,即JPEG

算法。JPEG算法被確定爲國際通用標準,其適用範圍廣泛,除用於靜態圖像編碼外,還推廣到電視圖像序列的幀

內圖像壓縮。而用JPEG算法壓縮出來的靜態圖片文件稱爲JPEG文件,擴展名通常爲*.jpg*.jpe*.jpeg

JPEG專家組開發了兩種基本的壓縮算法、兩種數據編碼方法、四種編碼模式。具體如下:

壓縮算法:

l 有損的離散餘弦變換(Discrete Cosine TransformDCT);

l 無損的預測技術壓縮。

數據編碼方法:

l 哈夫曼編碼;

l 算術編碼;

編碼模式:

l 基於DCT順序模式:編/解碼通過一次掃描完成;

l 基於DCT遞進模式:編/解碼需要多次掃描完成,掃描效果從粗糙到精細,逐級遞進;

l 無損模式:基於DPCM,保證解碼後完全精確恢復到原圖像採樣值;

l 層次模式:圖像在多個空間多種分辨率進行編碼,可以根據需要只對低分辨率數據作解碼,放棄高分辨率信息。

在實際應用中,JPEG圖像使用的是離散餘弦變換、哈夫曼編碼、順序模式。

 

JPEG壓縮編碼算法的主要計算步驟如下:

(0) 8*8分塊。

(1) 正向離散餘弦變換(FDCT)

(2) 量化(quantization)

(3) Z字形編碼(zigzag scan)

(4) 使用差分脈衝編碼調製(DPCM)對直流係數(DC)進行編碼。

(5) 使用行程長度編碼(RLE)對交流係數(AC)進行編碼。

(6) 熵編碼。

 

筆者在實踐過程中查閱了大量的資料,發現大多數書籍資料和網上資料都是從編碼角度分析JPEG的編/解碼方式,

並且都只是介紹編碼過程中的主要方法。所以,本文從解碼角度詳細分析JPEG的編/解碼過程,並且加入許多筆

者實踐過程中遇到的問題和解決方法,希望從另一個角度說明問題,以更好幫助讀者結合其他資料解決問題。

不過,介紹解碼過程之前,首先要了解JPEG文件中數據的存儲格式。


一、JPEG文件格式介紹

JPEG文件使用的數據存儲方式有多種。最常用的格式稱爲JPEG文件交換格式(JPEG File Interchange FormatJFIF

)。而JPEG文件大體上可以分成兩個部分:標記碼(Tag)和壓縮數據。

標記碼由兩個字節構成,其前一個字節是固定值0xFF,後一個字節則根據不同意義有不同數值。在每個標記碼之前

還可以添加數目不限的無意義的0xFF填充,也就說連續的多個0xFF可以被理解爲一個0xFF,並表示一個標記碼

的開始。而在一個完整的兩字節的標記碼後,就是該標記碼對應的壓縮數據流,記錄了關於文件的諸種信息。

常用的標記有SOIAPP0DQTSOF0DHTDRISOSEOI

注意,SOI等都是標記的名稱。在文件中,標記碼是以標記代碼形式出現。例如SOI的標記代碼爲0xFFD8

,即在JPEG文件中的如果出現數據0xFFD8,則表示此處爲一個SOI標記。

本文附錄列出一張完整的JPEG定義的標記表,供讀者查閱。這裏僅列出幾個常用標記的標記代碼、佔用字

節長度和表示的意義。

 

l         SOIStart of Image,圖像開始

標記代碼                                 2字節     固定值0xFFD8

 

l       APP0Application,應用程序保留標記0

標記代碼                                 2字節     固定值0xFFE0

包含9個具體字段:
  數據長度                         2字節     ~⑨9個字段的總長度
                                                            即不包括標記代碼,但包括本字段
  標識符                             5字節    固定值0x4A46494600,即字符串“JFIF0”
 
版本號                             2字節    一般是0x0102,表示JFIF的版本號
1.2
                                                           
可能會有其他數值代表其他版本

  XY的密度單位           1字節     只有三個值可選
                                                            0:無單位;1:點數/英寸;2:點數/釐米
  X方向像素密度               2字節     取值範圍未知
  Y方向像素密度               2字節     取值範圍未知  
 
縮略圖水平像素數目        1字節     取值範圍未知

  縮略圖垂直像素數目        1字節     取值範圍未知
  縮略圖RGB位圖             長度可能是3的倍數           縮略圖RGB位圖數據

 

本標記段可以包含圖像的一個微縮版本,存爲24位的RGB像素。如果沒有微縮圖像(這種情況更常見),則

字段縮略圖水平像素數目和字段縮略圖垂直像素數目的值均爲0

 

l       APPnApplication,應用程序保留標記n,其中n=115(任選)

標記代碼                                 2字節     固定值0xFFE1~0xFFF

包含2個具體字段:
  數據長度                         2字節     ~②2個字段的總長度
                                                            即不包括標記代碼,但包括本字段
  詳細信息            數據長度-2字節   內容不定
                                                    

例如,Adobe Photoshop生成的JPEG圖像中就用了APP1APP13兩個標記段分別存儲了一幅圖像的副本。

 

l       DQTDefine Quantization Table,定義量化表

標記代碼                          2字節            固定值0xFFDB

包含9個具體字段:
  數據長度                  2字節            字段①和多個字段②的總長度
                                                            即不包括標記代碼,但包括本字段
  量化表        數據長度-2字節

a)         精度及量化表ID   1字節            4位:精度,只有兩個可選值
                                                              08位;116
                                                4位:量化表ID,取值範圍爲03

b)        表項       (64×(精度+1))字節              例如8位精度的量化表
                                                其表項長度爲64×0+1=64字節

 

本標記段中,字段②可以重複出現,表示多個量化表,但最多隻能出現4次。

 

l       SOF0Start of Frame,幀圖像開始

標記代碼                   2字節     固定值0xFFC0

包含9個具體字段:
  數據長度           2字節     ~六個字段的總長度
                                              即不包括標記代碼,但包括本字段
  精度                 1字節     每個數據樣本的位數
                                              通常是8位,一般軟件都不支持 12位和16
  圖像高度           2字節     圖像高度(單位:像素),如果不支持 DNL 就必須 >0
 
圖像寬度           2字節     圖像寬度(單位:像素),如果不支持 DNL 就必須
>0
 
顏色分量數        1字節     只有3個數值可選

                                              1:灰度圖;3YCrCbYIQ4CMYK
                                             
JFIF中使用YCrCb,故這裏顏色分量數恆爲
3
 
顏色分量信息      顏色分量數×3字節(通常爲9字節)

a)         顏色分量ID                 1字節    

b)        水平/垂直採樣因子      1字節            4位:水平採樣因子
                                                       4位:垂直採樣因子
                                                       (曾經看到某資料把這兩者調轉了)

c)        量化表                         1字節            當前分量使用的量化表的ID

本標記段中,字段⑥應該重複出現,有多少個顏色分量(字段⑤),就出現多少次(一般爲3次)。

 

l       DHTDifine Huffman Table,定義哈夫曼表

標記代碼                                 2字節            固定值0xFFC4

包含2個具體字段:
 數據長度                             2字節            字段①和多個字段②的總長度
                                                                   即不包括標記代碼,但包括本字段
  哈夫曼表              數據長度-2字節

a)       ID和表類型            1字節            4位:類型,只有兩個值可選
                                                                     0DC直流;1AC交流
                                                        4位:哈夫曼表ID
                                                                     注意,DC表和AC表分開編碼

b)      不同位數的碼字數量    16字節

c)      編碼內容       16個不同位數的碼字數量之和(字節)

本標記段中,字段②可以重複出現(一般4次),也可以致出現1次。例如,Adobe Photoshop 生成

的JPEG圖片文件中只有1個DHT標記段,裏邊包含了4個哈夫曼表;而Macromedia Fireworks生成

的JPEG圖片文件則有4個DHT標記段,每個DHT標記段只有一個哈夫曼表。

 

l       DRIDefine Restart Interval定義差分編碼累計復位的間隔

標記代碼                                 2字節     固定值0xFFDD

包含2個具體字段:
 數據長度                             2字節     固定值0x0004~兩個字段的總長度
                                                            即不包括標記代碼,但包括本字段
 MCU塊的單元中的重新開始間隔
                                              2字節     設其值爲n,則表示每nMCU塊就有一個
                                                           RSTn標記。第一個標記是RST0,第二個是
                                                            RST1等,RST7後再從RST0重複。

 

如果沒有本標記段,或間隔值爲0時,就表示不存在重開始間隔和標記RST

 

l       SOSStart of Scan,掃描開始 12字節

標記代碼                          2字節     固定值0xFFDA

包含2個具體字段:
 數據長度                      2字節     ~兩個字段的總長度
                                                     即不包括標記代碼,但包括本字段
 顏色分量數                 1字節     應該和SOF中的字段⑤的值相同,即:
                                                     1:灰度圖是;3 YCrCbYIQ4CMYK

                                                         JFIF中使用YCrCb,故這裏顏色分量數恆爲3
   
顏色分量信息

        a) 顏色分量ID           1字節
        b) 直流/交流係數表號 1字節     4位:直流分量使用的哈夫曼樹編號
                                                        4位:交流分量使用的哈夫曼樹編號

  壓縮圖像數據
        a)譜選擇開始                     1字節     固定值0x00
        b)譜選擇結束                     1字節     固定值
0x3F
        c)譜選擇                            1字節     在基本JPEG中總爲00

 

本標記段中,字段③應該重複出現,有多少個顏色分量(字段②),就出現多少次(一般爲3次)。

本段結束後,緊接着就是真正的圖像信息了。圖像信息直至遇到一個標記代碼就自動結束,一般就是以EOI標記表示結束。

 

l        EOIEnd of Image,圖像結束 2字節

標記代碼                   2字節     固定值0xFFD9

 

這裏補充說明一下,由於在JPEG文件中0xFF具有標誌性的意思,所以在壓縮數據流(真正的圖像信息)

出現0xFF,就需要作特別處理。具體方法是,在數據0xFF後添加一個沒有意義的0x00。換句話說,如果在圖像數

據流中遇到0xFF,應該檢測其緊接着的字符,如果是

10x00,則表示0xFF是圖像流的組成部分,需要進行譯碼;

20xD9,則與0xFF組成標記EOI,則圖像流結束,同時圖像文件結束;

30xD0~0xD7,則組成RSTn標記,則要忽視整個RSTn標記,即不對當前0xFF和緊接的0xDn兩個字節進行譯碼,並按RST標記的規則調整譯碼變量;

30xFF,則忽視當前0xFF,對後一個0xFF再作判斷;

4)其他數值,則忽視當前0xFF,並保留緊接的此數值用於譯碼。

 

二、        JPEG解碼過程詳解

 

下面來詳細講述JPEG文件的解碼過程。

 

1.讀入文件的相關信息

按照上述的JPEG文件數據存儲方式,把要解碼的文件的相關信息一一讀出,爲接下來的解碼工作做好準備。

參考方法是,設計一系列的結構體對應各個標記,並存儲標記內表示的信息。其中圖像長寬、多個量化

表和哈夫曼表、水平/垂直採樣因子等多項信息比較重要。以下給出讀取過程中的兩個問題。

 

1)整個文件的大體結構

JFIF格式的JPEG文件(*.jpg)的一般順序爲:

SOI(0xFFD8)

APP0(0xFFE0)

[APPn(0xFFEn)]可選

DQT(0xFFDB)

SOF0(0xFFC0)

DHT(0xFFC4)

SOS(0xFFDA)

壓縮數據

EOI(0xFFD9)

 

2)字的高低位問題

JPEG文件格式中,一個字(16位)的存儲使用的是 Motorola 格式, 而不是 Intel 格式。也就是說, 一個字的

高字節(高8位)在數據流的前面, 低字節(低8位)在數據流的後面,與平時習慣的Intel格式不一樣。.

 

3)讀出哈夫曼表數據

a)理論說明

在標記段DHT內,包含了一個或者多個的哈夫曼表。對於單一個哈夫曼表,應該包括了三部分:

l 哈夫曼表ID和表類型
這個字節的值爲一般只有四個0x000x010x100x11
0x00表示DC直流0號表;
0x01表示DC直流1號表;
0x10表示AC交流0號表;
0x11表示AC交流1號表。

l 不同位數的碼字數量

JPEG文件的哈夫曼編碼只能是1~16位。這個字段的16個字節分別表示1~16位的編碼碼字在哈夫曼樹中的個數。

l 編碼內容

這個字段記錄了哈夫曼樹中各個葉子結點的權。所以,上一字段(不同位數的碼字數量)的16個數

值之和就應該是本字段的長度,也就是哈夫曼樹中葉子結點個數。

 

b)舉例說明

以下面一段哈夫曼表數據舉例說明(數據全部以16進製表示):

11 00 02 02 00 05 01 06 01 00 00 00 00 00 00 00 00
00 01 11 02 21 03 31 41 12 51   61 71 81 91 22 13 32

紅色部分(第1字節)爲哈夫曼表ID和表類型,其值0x11表示此部分數據描述的是AC交流1號表。

藍色部分2~17字節)爲不同位數的碼字的數量。這16個數值實際意義爲:沒有1位和4

位的哈夫曼碼字;2位和3位的碼字各有2個;5位碼字有5個;6位和8位碼字各有1個;7位碼字各有6個;沒有9位或以上的碼字。

綠色部分18~34字節)爲編碼內容。由藍色部分數據知道,此哈夫曼樹有0+2+2+0+5+1+6+1=17個葉子結點,

即本字段應該有17個字節。這段數據表示17個葉子結點按從小到大排列,其權值依次爲011122133141……

 

4)建立哈夫曼樹

a)理論說明

在讀出哈夫曼表的數據後,就要建立哈夫曼樹。具體方法爲:

1)第一個碼字必定爲0
如果第一個碼字位數爲1,則碼字爲0
如果第一個碼字位數爲2,則碼字爲00
如此類推。

2)從第二個碼字開始,
如果它和它前面的碼字位數相同,則當前碼字爲它前面的碼字加1
如果它的位數比它前面的碼字位數大,則當前碼字是前面的碼字加1後再在後邊添若干個0,直至滿足位數長度爲止。

b)舉例說明

繼續以上邊的例子說明問題。

n           由於沒有1位的碼字,所以第一個碼字的位數爲2,即碼字爲00

n           由於2位的碼字有兩個,所以第二個碼字位數仍爲2,即碼字爲00+1=01

n           第三個碼字爲3位,比第二個碼字長1位,所以第三個碼字爲:01+1=10,然後再添1個“0”,得100

n           ……

如此類推,最後得到這個哈夫曼樹如下:

序號

碼字長度

碼字

權值

1

2

00

0x00

2

2

01

0x01

3

3

100

0x11

4

3

101

0x02

5

5

11000

0x21

6

5

11001

0x03

7

5

11010

0x31

8

5

11011

0x41

9

5

11100

0x12

10

6

111010

0x51

11

7

1110110

0x61

12

7

1110111

0x71

13

7

1111000

0x81

14

7

1111001

0x91

15

7

1111010

0x22

16

7

1111011

0x13

17

8

11111000

0x32

 

特別注意的是,如果中間有某個位數的碼字缺失,例如沒有4位碼字,則應該在3位碼字加1後,添加“00”補足5位,形成下一個5位碼字。

 

在準備好所有的圖片信息後,就可以對圖片數據進行解碼了。

 

2初步瞭解圖像數據流的結構

1)理論說明

分析圖像數據流的結構,筆者準備以一個從宏觀到微觀的順序爲讀者詳細剖析,即:

 

數據流à最小編碼單元à數據單元與顏色分量。

 

a)         在圖片像素數據流中,信息可以被分爲一段接一段的最小編碼單元(Minimum Coded UnitMCU)數據流。

所謂MCU,是圖像中一個正方矩陣像素的數據。

矩陣的大小是這樣確定的:

查閱標記SOF0,可以得到圖像不同顏色分量的採樣因子,即YCrCb三個分量各自的水平採樣因子和垂直採

樣因子。大多圖片的採樣因子爲411111。其中,411即(2*2):(1*1):(1*1));111

即(1*1):(1*1):(1*1)。記三個分量中水平採樣因子最大值爲Hmax,垂直採樣因子最大值爲Vmax,那麼

單個MCU矩陣的寬就是Hmax*8像素,高就是Vmax*8像素。

如果,整幅圖像的寬度和高度不是MCU

寬度和高度的整數倍,那麼編碼時會用某些數值填充進去,保證解碼過程中MCU的完整性(解碼完成後,可直接

忽視圖像寬度和高度外的數據)。

在數據流中,MCU的排列方法是從左到右,從上到下。

 

b)        每個MCU又分爲若干個數據單元。數據單元的大小必定爲8*8,所以每個MCU的數據單元個數爲Hmax*Vmax

另外JPEG的壓縮方法與BMP

文件有所不同,它不是把每個像素的顏色分量連續存儲在一起的,而是把圖片分成YCrCb三張子圖,然後分

別壓縮。而三個顏色分量的採樣密度(即採樣因子)可能一樣(例如111)也可能不一樣(例如411)。

每個MCU內部,數據的順序是YCrCb。如果一個顏色分量有多個數據單元,則順序是從左到右,從上到下。

 

2)舉例說明

下面通過一幅32*35的圖像,對上面兩個問題列出兩種採樣因子的具體說明。

         

1 整張完整的圖像(411                            2 將圖像的MCU1放大

 

1及圖3中灰色部分爲實際圖像大小(32px*35px);粗虛線表示各個MCU的分界;細虛線表示MCU內部數據單元的分界。

 

a)    採樣因子爲411

此時,Hmax=max211=2Vmax=max211=2。所以,MCU的寬爲Hmax*8=16

像素,高爲Vmax*8=16像素。圖像實際的寬剛好是2MCU,但高則稍稍大於2MCU的高度,所以要補足3MCU

在數據流中,MCU的順序是MCU1àMCU2àMCU3àMCU4àMCU5àMCU6

每個MCU又分爲Hmax*Vmax=2*2=4個數據單元。由於採樣因子是411,即(2*2):(1*1):(1*1

),所以Y分量的水平和垂直方向都是每2個像素採樣2次;Cr分量和Cb分量的水平和垂直方向都是每2個像素採樣1次。

因此,在一個MCU來裏邊,Y分量有256個採樣點,即4個完整的數據單元;Cr分量和Cb分量各自只有64個採樣點。

如果以MCU1說明MCU數據的次序,則依次爲Y1 Y2 Y5 Y6 Cr1256 Cb1256 。圖2中全部256個點均是Y的採樣點,紅色部分爲Cr分量和Cr分量的採樣點。

換句話說,對於整張圖片來說,數據流的數據依次是:
[Y1 Y2 Y5 Y6 Cr1256 Cb1256] [Y3 Y4 Y7 Y8 Cr3478 Cb3478] [Y9 Y10 Y13 Y14 Cr9101314 Cb9101314 ]、……

3 整張完整的圖像(111

 

b)    採樣因子爲111

如圖3Hmax=max111=1Vmax=max111=2。所以,MCU的寬爲Hmax*8=8像素,高爲Vmax*8=8像素。

圖像實際的寬剛好是4MCU,但高則稍稍大於4MCU的高度,所以要補足5MCU

在數據流中,MCU的順序是:
MCU1àMCU2àMCU3àMCU4à ………… àMCU18àMCU19àMCU20

每個MCU又分爲Hmax*Vmax=1*1=1個數據單元,也就是一個數據單元就是一個MCU。由於採樣因子是111

即(1*1):(1*1):(1*1),所以Y分量、Cr分量和Cb分量的水平和垂直方向都是每1個像素採樣1次,也就是

圖象的每一個像素都是採樣點。因此,在一個MCU來裏邊,Y分量、Cr分量和Cb分量各自有64個採樣點。有

因此,對於整張圖片來說,數據流的數據依次是:
[Y1 Cr1Cb1] [Y2  Cr2 Cb2] [Y3 Cr3Cb3] 、………… [Y19 Cr19Cb19][Y20 Cr20Cb20]

 

3.顏色分量單元的內部解碼

1)理論說明

“顏色分量單元”是筆者爲說明問題而建立的概念,指的是MCU中某個顏色分量中的一個8*8數據塊,例如上面提到的Y1 Cr1Cb1 都是一個顏色分量單元。

圖像數據流是以位(bit)爲單位存儲信息的。並且內部的數據都是在編碼時通過正向離散餘弦變換(FDCT)進

行時空域向頻率域變換而得到的結果,所以對於每個顏色分量單元都應該由兩部分組成:1個直流分量和63個交流分量。

解碼的過程其實就是哈夫曼樹的查找過程。

首先查閱標記段SOS中的顏色分量信息,可以得出各個顏色分量對應使用的直流分量和交流分量使用的哈夫曼樹編號。一般來說,
Y分量:直流分量:直流0號哈夫曼樹,交流分量:交流0號哈夫曼樹;

Cr分量:直流分量:直流1號哈夫曼樹,交流分量:交流1號哈夫曼樹;

Cb分量:直流分量:直流1號哈夫曼樹,交流分量:交流1號哈夫曼樹。

 

顏色分量單元內部綜合運用了RLE行程編碼和哈夫曼編碼來壓縮數據。每個像素的數據流由兩部分構成:編碼和數值,並且

兩者基本以互相隔開方式出現(除非該編碼的權值爲零)。具體讀入單個顏色分量單元的步驟如下:

a)從此顏色分量單元數據流的起點開始一位一位的讀入,直到讀入的編碼與該分量直流哈夫曼樹的某個碼字(葉子結點)一

致,然後用直流哈夫曼樹查得該碼字對應的權值。權值(共8位)表示該直流分量數值的二進制位數,也就是接下來需要讀入的位數。

b)繼續讀入位數據,直到讀入的編碼與該分量交流哈夫曼樹的某個碼字(葉子結點)一致,然後用交流哈夫曼樹查得該碼字

對應的權值。權值的高4位表示當前數值前面有多少個連續的零,低4位表示該交流分量數值的二進制位數,也就是接下來需要讀入的位數。

c)不斷重複步驟b,直到滿足交流分量數據結束的條件。而結束條件有兩個,只要滿足其中一個即可:

當讀入碼字的權值爲零,表示往後的交流變量全部爲零;

②已經讀入63個交流分量。

d)各個數值的譯碼是按下表進行的:

                  實際數值

編碼長度

編碼

0

-

-1,1

1

0,1

-3,-2,2,3 

2

00,01,10,11

-7,-6,-5,-4,4,5,6,7 

3

000,001,010,011,100,101,110,111

-15,……,-8,8,……,15

4

0000,……,0111,1000,……,1111

-31,……,-16,16,……,31

5

00000,……,01111,10000,……,11111

-63,……,-32,32,……,63

6

……

-127,……,-64,64,……,127 

7

……

-255,……,-128,128,……,255

8

……

-511,……,-256,256,……,511

9

……

-1023,……,-512,512,……,1023

10

……

-2047,……,-1024,1024,……,2047

11

……

-4095,……,-2048,2048,……,4095

12

……

-8191,……,-4096,4096,……,8191

13

……

-16383,……,-8192,8192,……,16383

14

……

-32767,……,-16384,16384,……,32767 

15

……

 

2)舉例說明

下面舉例說明以上幾點。某個顏色分量單元數據如下:

D3 5E 6E 4D 35 f5 8A

若以二進制表示,則爲:

1101 0011 0101 1110 0110 1110 0100 1101 0011 0101 1111 0101 1000 1010

假設該顏色分量單元對應以下直流哈夫曼樹和交流哈夫曼樹,則可將各個以位爲單位的數據流拆分如下:

110 1001101 01 1 11001 101 11001 001 101 00 11010 1 1111010 11 00 01010

 

直流哈夫曼樹                                                               交流哈夫曼樹

序號

碼字長度

碼字

權值

1

2

00

0x00

2

2

01

0x01

3

2

10

0x02

4

3

110

0x07

5

4

1110

0x1e

6

5

11110

0x2e

序號

碼字長度

碼字

權值

1

2

00

0x00

2

2

01

0x01

3

3

100

0x11

4

3

101

0x02

5

5

11000

0x21

6

5

11001

0x03

7

5

11010

0x31

8

5

11011

0x41

9

5

11100

0x12

10

6

111010

0x51

11

7

1110110

0x61

12

7

1110111

0x71

13

7

1111000

0x81

14

7

1111001

0x91

15

7

1111010

0x22

16

7

1111011

0x13

17

8

11111000

0x32

 

詳細說明一下:

讀入數據流並對照直流哈夫曼樹,第一個哈夫曼編碼爲110,其權值爲6,所以往後讀入6位數據“1001101”,譯碼成數值爲77。因爲每個顏色分量單元只有一個直流分量,所以下一個就是第一個交流分量了。

繼續讀入數據流並對照交流哈夫曼樹,得哈夫曼編碼爲01,其權值爲1,所以它的前面沒有零,並往後讀如1位數據“1”,譯碼成數值爲1。如此往復,最後讀到哈夫曼編碼“00”,其權值爲0,所以滿足交流變量結束條件(最後剩餘的“01010”對本顏色分量單元來說是冗餘的,它可能屬於下一個顏色分量單元)。

實際上,這段數據譯碼爲:

77,(01),(05),(0-6),(0-3),(51),(23

因此,把它置於18*8的矩陣中應爲:

77

1

5

-6

-3

0

0

0

0

0

1

0

0

3

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

 

4.直流係數的差分編碼

把所有的顏色分量單元按顏色分量(YCrCb)分類。每一種顏色分量內,相鄰的兩個顏色分量單元的直流變

量是以差分來編碼的。也就是說,通過步驟3解碼出來的直流變量數值只是當前顏色分量單元的實際直流變量減去

前一個顏色分量單元的實際直流變量。也就是說,當前直流變量要通過前一個顏色分量單元的實際(非解碼)直流分量來校正:

DCn=DCn-1+Diff

其中Diff爲差分校正變量,也就是直接解碼出來的直流係數。但如果當前顏色分量單元是第一個單元,則解碼出來的直流數值就是真正的直流變量。

再次提醒的是,3個顏色分量的直流變量是分開進行差分編碼的。也就是說,爲1張圖片解碼時應設置3個獨立的直

流校正變量。另一個問題是,當數據流中出現標記RSTn,則3個顏色分量的直流差分校正變量Diff都需要重新復位到0

 

5.反量化

不同的顏色分量使用不同的量化表,這個可以從標記段SOF中的顏色分量信息字段查得。一般是Y分量使用量化表0,而CrCb兩個分量共同使用量化表1

反量化的過程比較簡單。只需要對8*8的顏色分量單元的64個值逐一乘以對應的量化表內位置相同的值則可。圖像內全部的顏色分量單元都要進行反量化。

 

6Zig-zag編碼

如果將反量化後的每個8*8顏色分量單元的每個元素編號,如下圖4,那麼各反Zig-zag編碼的過程就是把矩陣元素按圖5重新排列。

       

4 將顏色分量單元元素編碼                          5 Zig-zag編碼

 

關於量化和反Zig-zag編碼的先後順序,筆者查閱的幾份資料有不同的見解。經過實踐試驗,解碼的過程中,是應該直

接用文件提供的量化表反量化矩陣數據,再將其反Zig-zag編碼才能正確解碼。

 

7.隔行的正負糾正

這個問題比較特別,因爲在筆者認真閱讀的幾份資料中都沒有提及此問題。而是筆者通過對已知圖像進行JPEG編碼壓縮,

然後和該圖的JPEG文件數據對比發現的問題。具體原因不明。

實際上,就是必須對每個顏色分量單元的奇數行(每個顏色分量單元有8行,假設把它按01、……、67編出行號)

,即1357行,進行取相反數操作(正的變負,負的變正)。

 

8.反離散餘弦變換

之前提到,文件中的數據是在編碼時通過正向離散餘弦變換(FDCT)進行時空域向頻率域變換而得到的結果,所以

現在解碼就必須將其反向離散餘弦變換(IDCT),就是把顏色分量單元矩陣中的頻率域數值向時空域轉換。並且,原

來的頻率域的矩陣大小爲8*8,則經過反向離散餘弦變換後,時空域的矩陣仍然是8*8

設正負糾正後的頻率域矩陣爲F[u][v],而反向離散餘弦變換後的矩陣爲f[i][j],其中0≤u,v,i,j≤7。具體使用的公式如下:

,其中

Cu= (當u=0),Cu=1(當u0);

Cv= (當v=0),Cu=1(當v0);

 

另外補充一下正向離散餘弦變換的公式,用於編碼:

 

9YCrCbRGB轉換

要在屏幕上顯示圖像,就必須以RGB模式表示圖像的顏色。所以,解碼時需要把YCrCb模式向RGB模式轉換。

正如前面提到,並不是每種顏色分量的採樣因子都一樣,所以轉換時需要注意。如果採樣因子是111,則每一個

像素點的3個顏色分量都被採樣,所以沒有問題。但411的採樣因子就不一樣了。由“初步瞭解圖像數據流的結構”

一節中對411的採樣因子的分析,可以知道一個MCU裏有4Y分量單元,而Cr分量和Cb分量各自只有1個分量單元

。以圖2爲例,僅有的一個Cr分量單元(紅色的64個採樣點)應該平鋪用於4Y分量單元,即左上角16個值用於Y1,右

上角16個值用於Y2,左下角16個值用於Y5,右下角16個值用於Y6。換句話說,一個Cr採樣點服務於4Y採樣點。對於Cb分量,道理一樣。

另外,由於離散餘弦變化要求定義域的對稱,所以在編碼時把RGB的數值範圍從[0255]統一減去128偏移成[-128127]

因此解碼時必須爲每個分量加上128。具體公式如下:

R=Y                       +1.402*Cb     +128;

G=Y-0.34414*Cr    -0.71414*Cb   +128;

B=Y                      +1.772*Cb     +128;

還有一個問題,通過變換得出的RGB值可能超出了其定義域,所以要作出檢查。如果大於255,則截斷爲255;如果小於0,則截斷爲0

 

下面補充RGB模式向YCrCb模式的公式:

Y =0.299*R            +0.587*G       +0.114*B    ;

Cr=   -0.1687*R      - 0.3313*G     +0.5*B +128;

Cb=0.5 *R              - 0.4187*G     - 0.0813*B+128;

 

至此,每個MCU的解碼已經完成。而每一個MCU如何組成一幅完整的圖像,請參考初步瞭解圖像數據流的結構分析。


參考文獻

[1] 李才偉,中山大學計算機系多媒體課程教學課件.

[2]     張益貞,Visual C++實現MPEG/JPEG編解碼技術.北京:人民郵電出版社

[3] CCITInformation Technology-digital Compression and Conding of Continuous-ton Still Images-requirements and Guidelineshttp://www.wotsit.org/download.asp?f=itu-1150PDF (訪問日期:2007-1-1

[4] 公子御風,JFIF文件格式即JPEG文件交換格式(JPEG File Interchonge Format)http://cat1226.bokee.com/4574350.html (訪問日期:2006-12-29

[5] 雲風,JPEG 簡易文檔 V2.11http://rtornados.bokee.com/2442419.html (訪問日期:2006-12-30


附錄:JPEG定義的標記

標記名

標記代碼

說明

幀開始標記,Start of Frame,非層次哈夫曼編碼

SOF0

0xFFC0

基線離散餘弦變換

SOF1

0xFFC1

擴展順序離散餘弦變換

SOF2

0xFFC2

遞進離散餘弦變換

SOF3

0xFFC3

空間順序無損

幀開始標記,Start of Frame,層次哈夫曼編碼

SOF5

0xFFC5

差分離散餘弦變換

SOF6

0xFFC6

差分層次離散餘弦變換

SOF7

0xFFC7

差分空間無損

幀開始標記,Start of Frame,非層次算術編碼

JPEG

0xFFC8

爲JPEG擴展保留

SOF9

0xFFC9

擴展順序離散餘弦變換

SOF10

0xFFCA

遞進離散餘弦變換

SOF11

0xFFCB

空間順序無損

幀開始標記,Start of Frame,層次算術編碼

SOF13

0xFFCD

差分離散餘弦變換

SOF14

0xFFCE

差分層次離散餘弦變換

SOF15

0xFFCF

差分空間無損

其他標記

DHT

0xFFC4

定義哈夫曼樹表

DAC

0xFFCC

定義算術編碼表

RST0

OxFFD0

差分編碼累計復位,共8個

……

……

RST7

OxFFD7

SOI

OxFFD8

圖像開始

EOI

OxFFD9

圖像結束

SOS

0xFFDA

開始掃描,圖像數據開始

DQT

0xFFDB

定義量化表

DNL

0xFFDC

定義線數

DRI

0xFFDD

定義差分編碼累計復位的間隔

DHP

0xFFDE

定義層次級數

EXP

0xFFDF

展開參考圖像

APP0

0xFFE0

爲應用程序保留,共15個

……

……

APP15

0xFFEE

JPG0

0xFFF0

爲JPEG擴展保留,共14個

……

……

JPG13

0xFFFD

COM

0xFFFE

註釋

TEM

0xFF01

算術編碼中作臨時之用

RES

0xFF02

保留,共189個

……

……

RES

0xFFBF

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章