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