JPEG壓縮編碼標(biāo)準(zhǔn)
Posted on 2006-10-29 15:22 neter 閱讀(3651) 評(píng)論(5) 編輯 收藏 引用 所屬分類: 數(shù)字圖像JPEG 是聯(lián)合圖象專家組 (Joint Picture Expert Group) 的英文縮寫(xiě),是國(guó)際標(biāo)準(zhǔn)化組織 (ISO) 和 CCITT 聯(lián)合制定的靜態(tài)圖象的壓縮編碼標(biāo)準(zhǔn)。和相同圖象質(zhì)量的其它常用文件格式 ( 如 GIF , TIFF , PCX) 相比, JPEG 是目前靜態(tài)圖象中壓縮比最高的。我們給出具體的數(shù)據(jù)來(lái)對(duì)比一下。例圖采用 Windows95 目錄下的 Clouds.bmp ,原圖大小為 640*480 , 256 色。用工具 SEA(version1.3) 將其分別轉(zhuǎn)成 24 位色 BMP 、 24 位色 JPEG 、 GIF( 只能轉(zhuǎn)成 256 色 ) 壓縮格式、 24 位色 TIFF 壓縮格式、 24 位色 TGA 壓縮格式。得到的文件大小 ( 以字節(jié)為單位 ) 分別為: 921,654 , 17,707 , 177,152 , 923,044 , 768,136 。可見(jiàn) JPEG 比其它幾種壓縮比要高得多,而圖象質(zhì)量都差不多 (JPEG 處理的顏色只有真彩和灰度圖 ) 。
正是由于 JPEG 的高壓縮比,使得它廣泛地應(yīng)用于多媒體和網(wǎng)絡(luò)程序中,例如 HTML 語(yǔ)法中選用的圖象格式之一就是 JPEG( 另一種是 GIF) 。這是顯然的,因?yàn)榫W(wǎng)絡(luò)的帶寬非常寶貴,選用一種高壓縮比的文件格式是十分必要的。
JPEG 有幾種模式,其中最常用的是基于 DCT 變換的順序型模式,又稱為基線系統(tǒng) (Baseline) ,以下將針對(duì)這種格式進(jìn)行討論。
1.???????? JPEG 的壓縮原理
JPEG 的壓縮原理其實(shí)上面介紹的那些原理的綜合,博采眾家之長(zhǎng),這也正是 JPEG 有高壓縮比的原因。其編碼器的流程為:
圖9.3???? JPEG 編碼器流程
解碼器基本上為上述過(guò)程的逆過(guò)程:
圖9.4???? 解碼器流程
8 × 8 的圖象經(jīng)過(guò) DCT 變換后,其低頻分量都集中在左上角,高頻分量分布在右下角 (DCT 變換實(shí)際上是空間域的低通濾波器 ) 。由于該低頻分量包含了圖象的主要信息 ( 如亮度 ) ,而高頻與之相比,就不那么重要了,所以我們可以忽略高頻分量,從而達(dá)到壓縮的目的。如何將高頻分量去掉,這就要用到量化,它是產(chǎn)生信息損失的根源。這里的量化操作,就是將某一個(gè)值除以量化表中對(duì)應(yīng)的值。由于量化表左上角的值較小,右上角的值較大,這樣就起到了保持低頻分量,抑制高頻分量的目的。 JPEG 使用的顏色是 YUV 格式。我們提到過(guò), Y 分量代表了亮度信息, UV 分量代表了色差信息。相比而言, Y 分量更重要一些。我們可以對(duì) Y 采用細(xì)量化,對(duì) UV 采用粗量化,可進(jìn)一步提高壓縮比。所以上面所說(shuō)的量化表通常有兩張,一張是針對(duì) Y 的;一張是針對(duì) UV 的。
上面講了,經(jīng)過(guò) DCT 變換后,低頻分量集中在左上角,其中 F(0 , 0)( 即第一行第一列元素 ) 代表了直流 (DC) 系數(shù),即 8 × 8 子塊的平均值,要對(duì)它單獨(dú)編碼。由于兩個(gè)相鄰的 8 × 8 子塊的 DC 系數(shù)相差很小,所以對(duì)它們采用差分編碼 DPCM ,可以提高壓縮比,也就是說(shuō)對(duì)相鄰的子塊 DC 系數(shù)的差值進(jìn)行編碼。 8 × 8 的其它 63 個(gè)元素是交流 (AC) 系數(shù),采用行程編碼。這里出現(xiàn)一個(gè)問(wèn)題:這 63 個(gè)系數(shù)應(yīng)該按照怎么樣的順序排列?為了保證低頻分量先出現(xiàn),高頻分量后出現(xiàn),以增加行程中連續(xù)“ 0 ”的個(gè)數(shù),這 63 個(gè)元素采用了“之”字型 (Zig-Zag) 的排列方法,如圖 9.5 所示。
圖9.5???? Zig-Zag
這 63 個(gè) AC 系數(shù)行程編碼的碼字用兩個(gè)字節(jié)表示,如圖 9.6 所示。
圖9.6???? 行程編碼
上面,我們得到了 DC 碼字和 AC 行程碼字。為了進(jìn)一步提高壓縮比,需要對(duì)其再進(jìn)行熵編碼,這里選用 Huffman 編碼,分成兩步:
(1) 熵編碼的中間格式表示
對(duì)于 AC 系數(shù),有兩個(gè)符號(hào)。符號(hào) 1 為行程和尺寸,即上面的 (RunLength , Size) 。 (0 , 0) 和 (15 , 0) 是兩個(gè)比較特殊的情況。 (0 , 0) 表示塊結(jié)束標(biāo)志 (EOB) , (15 , 0) 表示 ZRL ,當(dāng)行程長(zhǎng)度超過(guò) 15 時(shí),用增加 ZRL 的個(gè)數(shù)來(lái)解決,所以最多有三個(gè) ZRL(3 × 16+15=63) 。符號(hào) 2 為幅度值 (Amplitude) 。
對(duì)于 DC 系數(shù),也有兩個(gè)符號(hào)。符號(hào) 1 為尺寸 (Size) ;符號(hào) 2 為幅度值 (Amplitude) 。
(2) 熵編碼
對(duì)于 AC 系數(shù),符號(hào) 1 和符號(hào) 2 分別進(jìn)行編碼。零行程長(zhǎng)度超過(guò) 15 個(gè)時(shí),有一個(gè)符號(hào) (15 , 0) ,塊結(jié)束時(shí)只有一個(gè)符號(hào) (0 , 0) 。
對(duì)符號(hào) 1 進(jìn)行 Hufffman 編碼 ( 亮度,色差的 Huffman 碼表不同 ) 。對(duì)符號(hào) 2 進(jìn)行變長(zhǎng)整數(shù) VLI 編碼。舉例來(lái)說(shuō): Size=6 時(shí), Amplitude 的范圍是 -63~-32 ,以及 32~63 ,對(duì)絕對(duì)值相同,符號(hào)相反的碼字之間為反碼關(guān)系。所以 AC 系數(shù)為 32 的碼字為 100000 , 33 的碼字為 100001 , -32 的碼字為 011111 , -33 的碼字為 011110 。符號(hào) 2 的碼字緊接于符號(hào) 1 的碼字之后。
對(duì)于 DC 系數(shù), Y 和 UV 的 Huffman 碼表也不同。
掉了這么半天的書(shū)包,你可能已經(jīng)暈了,呵呵。舉個(gè)例子來(lái)說(shuō)明上述過(guò)程就容易明白了。
下面為 8 × 8 的亮度 (Y) 圖象子塊經(jīng)過(guò)量化后的系數(shù)。
15??? 0???? -1??? 0???? 0???? 0???? 0???? 0
-2??? -1??? 0???? 0???? 0???? 0???? 0???? 0
-1??? -1??? 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
可見(jiàn)量化后只有左上角的幾個(gè)點(diǎn) ( 低頻分量 ) 不為零,這樣采用行程編碼就很有效。
第一步,熵編碼的中間格式表示:先看 DC 系數(shù)。假設(shè)前一個(gè) 8 × 8 子塊 DC 系數(shù)的量化值為 12 ,則本塊 DC 系數(shù)與它的差為 3 ,根據(jù)下表
Size???????????????????????????? Amplitude
0??????????????????????????????????????? 0
1??????????????????????????????????????? –1,1
2??????????????????????????????????????? –3,-2,2,3
3??????????????????????????????????????? –7~-4,4~7
4??????????????????????????????????????? –15~-8,8~15
5??????????????????????????????????????? –31~-16,16~31
6??????????????????????????????????????? –63~-32,32~63
7??????????????????????????????????????? –127~-64,64~127
8??????????????????????????????????????? –255~-128,128~255
9??????????????????????????????????????? –511~-256,256~511
10?????????????????????????????????????? –1023~512,512~1023
11?????????????????????????????????????? –2047~-1024,1024~2047
查表得 Size=2 , Amplitude=3 ,所以 DC 中間格式為 (2)(3) 。
下面對(duì) AC 系數(shù)編碼。經(jīng)過(guò) Zig-Zag 掃描后,遇到的第一個(gè)非零系數(shù)為 -2 ,其中遇到零的個(gè)數(shù)為 1( 即 RunLength) ,根據(jù)下面這張 AC 系數(shù)表:
Size???????????????????????????? Amplitude
1??????????????????????????????????????? –1,1
2??????????????????????????????????????? –3,-2,2,3
3??????????????????????????????????????? –7~-4,4~7
4??????????????????????????????????????? –15~-8,8~15
5??????????????????????????????????????? –31~-16,16~31
6??????????????????????????????????????? –63~-32,32~63
7??????????????????????????????????????? –127~-64,64~127
8??????????????????????????????????????? –255~-128,128~255
9??????????????????????????????????????? –511~-256,256~511
10?????????????????????????????????????? –1023~512,512~1023
查表得 Size=2 。所以 RunLength=1,Size=2,Amplitude=3 ,所以 AC 中間格式為 (1,2)(-2) 。
其余的點(diǎn)類似,可以求得這個(gè) 8 × 8 子塊熵編碼的中間格式為
(DC)(2)(3),(1,2)(-2),(0,1)(-1),(0,1)(-1),(0,1)(-1),(2,1)(-1),(EOB)(0,0)
第二步,熵編碼:
對(duì)于 (2)(3) : 2 查 DC 亮度 Huffman 表得到 11 , 3 經(jīng)過(guò) VLI 編碼為 011 ;
對(duì)于 (1,2)(-2) : (1,2) 查 AC 亮度 Huffman 表得到 11011 , -2 是 2 的反碼,為 01 ;
對(duì)于 (0,1)(-1) : (0,1) 查 AC 亮度 Huffman 表得到 00 , -1 是 1 的反碼,為 0 ;
……
最后,這一 8 × 8 子塊亮度信息壓縮后的數(shù)據(jù)流為 11011, 1101101, 000, 000, 000, 111000,1010 。總共 31 比特,其壓縮比是 64 × 8/31=16.5 ,大約每個(gè)象素用半個(gè)比特。
可以想見(jiàn),壓縮比和圖象質(zhì)量是呈反比的,以下是壓縮效率與圖象質(zhì)量之間的大致關(guān)系,可以根據(jù)你的需要,選擇合適的壓縮比。
表9.1??? 壓縮比與圖象質(zhì)量的關(guān)系
壓縮效率 ( 單位: bits/pixel) |
圖象質(zhì)量 |
0.25~0.50 |
中 ~ 好,可滿足某些應(yīng)用 |
0.50~0.75 |
好 ~ 很好,滿足多數(shù)應(yīng)用 |
0.75~1.5 |
極好,滿足大多數(shù)應(yīng)用 |
1.5~2.0 |
與原始圖象幾乎一樣 |
以上我們介紹了 JPEG 壓縮的原理,其中 DC 系數(shù)使用了預(yù)測(cè)編碼 DPCM , AC 系數(shù)使用了變換編碼 DCT ,二者都使用了熵編碼 Huffman ,可見(jiàn)幾乎所有傳統(tǒng)的壓縮方法在這里都用到了。這幾種方法的結(jié)合正是產(chǎn)生 JPEG 高壓縮比的原因。順便說(shuō)一下,該標(biāo)準(zhǔn)是 JPEG 小組從很多種不同中方案中比較測(cè)試得到的,并非空穴來(lái)風(fēng)。
上面介紹了 JPEG 壓縮的基本原理,下面介紹一下 JPEG 的文件格式。
2.???????? JPEG 的文件格式
JPEG 文件大體上可以分成以下兩個(gè)部分:標(biāo)記碼 (Tag) 加壓縮數(shù)據(jù)。先介紹標(biāo)記碼部分。
標(biāo)記碼部分給出了 JPEG 圖象的所有信息 ( 有點(diǎn)類似于 BMP 中的頭信息,但要復(fù)雜的多 ) ,如圖象的寬、高、 Huffman 表、量化表等等。標(biāo)記碼有很多,但絕大多數(shù)的 JPEG 文件只包含幾種。標(biāo)記碼的結(jié)構(gòu)為:
SOI
DQT
???????????? DRI
??????????????????? SOF0
?????????????????????????? DHT
????????????????????????????????? SOS
????????????????????????????????? …
????????????????????????????????? EOI
標(biāo)記碼由兩個(gè)字節(jié)組成,高字節(jié)為 0XFF ,每個(gè)標(biāo)記碼之前可以填上個(gè)數(shù)不限的填充字節(jié) 0XFF 。
下面介紹一些常用的標(biāo)記碼的結(jié)構(gòu)及其含義。
(1)SOI(Start of Image)
標(biāo)記結(jié)構(gòu) ????? 字節(jié)數(shù)
0XFF???????????? 1
0XD8???????????? 1
可作為 JPEG 格式的判據(jù) (JFIF 還需要 APP0 的配合 )
(2)APP0(Application)
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XE0???????????? 1
Lp???????????????? 2??????????? APP0標(biāo)記碼長(zhǎng)度,不包括前兩個(gè)字節(jié)0XFF,0XE0
Identifier 5??????????? JFIF識(shí)別碼 0X4A,0X46,0X49,0X46,0X00
Version?????????? 2??????????? JFIF版本號(hào)可為0X0101或者0X0102
Units????????????? 1??????????? 單位,等于零時(shí)表示未指定,為1表示英寸,為2表示
厘米
Xdensity? 2??????????? 水平分辨率
Ydensity? 2??????????? 垂直分辨率
Xthumbnail???? 1??????????? 水平點(diǎn)數(shù)
Ythumbnail???? 1??????????? 垂直點(diǎn)數(shù)
RGB0???????????? 3??????????? RGB的值
RGB1???????????? 3??????????? RGB的值
…
RGBn???????????? 3??????????? RGB的值,n=Xthumbnail*Ythumbnail
APP0 是 JPEG 保留給 Application 所使用的標(biāo)記碼,而 JFIF 將文件的相關(guān)信息定義在此標(biāo)記中。
(3)DQT(Define Quantization Table)
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XDB??????????? 1
Lq???????????????? 2??????????? DQT標(biāo)記碼長(zhǎng)度,不包括前兩個(gè)字節(jié)0XFF,0XDB
(Pq,Tq)????????? 1???? ?????? 高四位Pq為量化表的數(shù)據(jù)精確度,Pq=0時(shí),Q0~Qn的
值為 8 位, Pq=1 時(shí), Qt 的值為 16 位, Tq 表示量化表的
編號(hào),為 0~3 。在基本系統(tǒng)中, Pq=0 , Tq=0~1 ,也就是
說(shuō)最多有兩個(gè)量化表。
Q0???????????????? 1或2????? 量化表的值,Pq=0時(shí);為一個(gè)字節(jié),Pq=1時(shí),為兩個(gè)
字節(jié)
Q1???????????????? 1或2????? 量化表的值,Pq=0時(shí);為一個(gè)字節(jié),Pq=1時(shí),為兩個(gè)
字節(jié)
…
Qn???????????????? 1或2????? 量化表的值,Pq=0時(shí),為一個(gè)字節(jié);Pq=1時(shí),為兩個(gè)
字節(jié)。 n 的值為 0~63 ,表示量化表中 64 個(gè)值 ( 之字形排
列 )
(4)DRI(Define Restart Interval)
此標(biāo)記需要用到最小編碼單元 (MCU , Minimum Coding Unit) 的概念。前面提到, Y 分量數(shù)據(jù)重要, UV 分量的數(shù)據(jù)相對(duì)不重要,所以可以只取 UV 的一部分,以增加壓縮比。目前支持 JPEG 格式的軟件通常提供兩種取樣方式 YUV411 和 YUV422 ,其含義是 YUV 三個(gè)分量的數(shù)據(jù)取樣比例。舉例來(lái)說(shuō),如果 Y 取四個(gè)數(shù)據(jù)單元,即水平取樣因子 Hy 乘以垂直取樣因子 Vy 的值為 4 ,而 U 和 V 各取一個(gè)數(shù)據(jù)單元,即 Hu×Vu=1,Hv×Vv=1 。那么這種部分取樣就稱為 YUV411 。如圖 9.7 所示:
圖9.7???? YUV411 的示意圖 |
圖9.8???? YUV111 的排列順序 |
易知 YUV411 有 50% 的壓縮比 ( 原來(lái)有 12 個(gè)數(shù)據(jù)單元,現(xiàn)在有 6 個(gè)數(shù)據(jù)單元 ) , YUV422 有 33% 的壓縮比 ( 原來(lái)有 12 個(gè)數(shù)據(jù)單元,現(xiàn)在有 8 個(gè)數(shù)據(jù)單元 ) 。
那么你可能會(huì)想, YUV911 , YUV1611 壓縮比不是更高嘛?但是要考慮到圖象質(zhì)量的因素。所以 JPEG 標(biāo)準(zhǔn)規(guī)定了最小編碼單元 MCU ,要求 Hy×Vy+Hu×Vu+Hv×Vv ≤ 10 。
MCU 中塊的排列方式與 H , V 的值有密切關(guān)系,如圖 9.8 、圖 9.9 、圖 9.10 所示。
圖9.9???? YUV211 的排列順序
圖9.10?? YUV411 的排列順序
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XDD??????????? 1
Lr????????????????? 2??????????? DRI標(biāo)記碼長(zhǎng)度,不包括前兩個(gè)字節(jié)0XFF,0XDD
Ri????????? ?????? 2??????????? 重入間隔的MCU個(gè)數(shù),Ri必須是一MCU行中MCU
個(gè)數(shù)的整數(shù),最后一個(gè)零頭不一定剛好是 Ri 個(gè) MCU 。
每個(gè)重入間隔各自獨(dú)立編碼。
(5)SOF(Start of Frame) 在基本系統(tǒng)中,只處理 SOF0
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XC0???????????? 1
Lf????????????????? 2??????????? SOF標(biāo)記碼長(zhǎng)度,不包括前兩個(gè)字節(jié)0XFF,0XC0
P?????????????????? 1??????????? 基本系統(tǒng)中,為0X08
Y?????????????????? 2 ?????????? 圖象高度
X?????????????????? 2??????????? 圖象寬度
Nf????????? ?????? 1??????????? Frame中的成分個(gè)數(shù),一般為1或3,1代表灰度圖,3
代表真彩圖
C1???????????????? 1??????????? 成分編號(hào)1
(H1,V1)?? 1??????????? 第一個(gè)水平和垂直采樣因子
Tq1??????? 1??????????? 該量化表編號(hào)
C2???????????????? 1??????????? 成分編號(hào)2
(H2,V2)?? 1??????????? 第二個(gè)水平和垂直采樣因子
Tq2??????? 1??????????? 該量化表編號(hào)
…
Cn???????????????? 1??????????? 成分編號(hào)n
(Hn,Vn)?? 1??????????? 第n個(gè)水平和垂直采樣因子
Tqn??????? 1??????????? 該量化表編號(hào)
(6)DHT(Define Huffman Table)
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XC4???????????? 1
Lh???????????????? 2??????????? DHT標(biāo)記碼長(zhǎng)度,不包括前兩個(gè)字節(jié)0XFF,0XC4
(Tc,Th)????????? 1???????????
L1???????????????? 1
L2???????????????? 1
…?????????????????
L16???????? 1
V1???????????????? 1
V2???????????????? 1
…
Vt????????????????? 1
Tc 為高 4 位, Th 為低 4 位。在基本系統(tǒng)中, Tc 為 0 或 1 ,為 0 時(shí),指 DC 所用的 Huffman 表,為 1 時(shí),指 AC 所用的 Huffman 表。 Th 表示 Huffman 表的編號(hào),在基本系統(tǒng)中,其值為 0 或 1 。所以,在基本系統(tǒng)中,最多有 4 個(gè) Huffman 表,如下所示:
Tc?? Th?? Huffman表編號(hào)(2×Tc+Th)
0???? 0
1???? 1
0???? 2
1???? 1???? 3
Ln 表示每個(gè) n 比特的 Huffman 碼字的個(gè)數(shù), n=1~16
Vt 表示每個(gè) Huffman 碼字所對(duì)應(yīng)的值,也就是我們前面所講的符號(hào) 1 ,對(duì) DC 來(lái)說(shuō)該值為 (Size) ,對(duì) AC 來(lái)說(shuō)該值為 (RunLength , Size) 。
t=L1+L2+…L16
(7)SOS(Start of Scan)
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XDA??????????? 1
Ls????????????????? 2??????????? DHT標(biāo)記碼長(zhǎng)度,不包括前兩個(gè)字節(jié)0XFF,0XDA
Ns???????????????? 1
Cs1???????? 1
(Td1,Ta1)?????? 1
Cs2???????? 1
(Td2,Ta2)?????? 1
…
CsNs???????????? 1
(TdNs,TaNs)? 1
Ss????????????????? 1
Se????????????????? 1
(Ah ,Al) 1
Ns 為 Scan 中成分的個(gè)數(shù),在基本系統(tǒng)中, Ns=Nf(Frame 中成分個(gè)數(shù) ) 。 CSNs 為在 Scan 中成分的編號(hào)。 TdNs 為高 4 位, TaNs 為低 4 位,分別表示 DC 和 AC 編碼表的編號(hào)。在基本系統(tǒng)中 Ss=0 , Se=63 , Ah=0 , Al=0 。
(8)EOI(End of Image)?? 結(jié)束標(biāo)志
標(biāo)記結(jié)構(gòu) ?????? 字節(jié)數(shù) ??? 意義
0XFF???????????? 1
0XD9???????????? 1
3.???????? JPEG 基本系統(tǒng)解碼器的實(shí)現(xiàn)
筆者曾經(jīng)實(shí)現(xiàn)了一個(gè) Windows 下 JPEG 基本系統(tǒng)的解碼器,限于篇幅,這里就不給源程序了,只給出大體上的程序流程圖 ( 見(jiàn)圖 9.11) 。
圖9.11??? JPEG 解碼器的程序流程圖 |
圖9.12?? 程序運(yùn)行時(shí)的畫(huà)面 |
由于沒(méi)有用到什么優(yōu)化算法,該解碼器的速度并不高,在用 VC 的性能評(píng)測(cè)工具 Profile 評(píng)測(cè)該程序時(shí)我發(fā)現(xiàn)最耗時(shí)的地方是反離散余弦變換 (IDCT) 那里,其實(shí)這是顯然的,浮點(diǎn)數(shù)的指令條數(shù)要比整數(shù)的多得多,因此采用一種快速的 IDCT 算法能很大的提高性能,我這里采用是目前被認(rèn)為比較好的一種快速 IDCT 算法,其主要思想是把二維 IDCT 分解成行和列兩個(gè)一維 IDCT 。圖 9.12 是程序運(yùn)行時(shí)的畫(huà)面。