在介紹圖象的壓縮編碼之前,先考慮一個問題:為什麼要壓縮?其實這個問題不用我回答,你也能想得到。因為圖象資訊的資料量實在是太驚人了。舉一個例子就明白了,一張A4(210mm*297mm) 幅面的照片,若用中等解析度(300dpi)的掃描器按真彩掃描,其資料量為多少?讓我們來計算一下:共有(300*210/25.4)*(300*297/25.4)個像素,每個像素佔3個位元組,其資料量為26M位元組,其資料量之大可見一斑了。如今在Internet上,傳統基於字元介面的應用逐漸被能夠瀏覽圖象資訊的WWW(World Wide Web)方式所取代。WWW儘管漂亮,但是也帶來了一個問題:圖象資訊的資料量太大了,本來就已經非常緊張的網路頻寬變得更加不堪重負,使得World Wide Web變成了World Wide Wait。
總之,大資料量的圖象資訊會給儲存空間的儲存容量,通訊幹線通道的頻寬,以及電腦的處理速度增加極大的壓力。單純靠增加儲存空間容量,提高通道頻寬以及電腦的處理速度等方法來解決這個問題是不現實的,這時就要考慮壓縮。壓縮的理論基礎是資訊理論。從資訊理論的角度來看,壓縮就是去掉資訊中的冗餘,即保留不確定的資訊,去掉確定的資訊(可推知的),也就是用一種更接近資訊本質的描述來代替原有冗餘的描述。這個本質的東西就是資訊量(即不確定因素)。
壓縮可分為兩大類,第一類壓縮過程是可逆的,也就是說,從壓縮後的圖象能夠完全恢複出原來的圖象,資訊沒有任何丟失,稱為無損壓縮;第二類壓縮過程是無法復原的,無法完全恢複出原圖象,資訊有一定的丟失,成為有損壓縮。選擇哪一類壓縮,要折中考慮,儘管我們希望能夠無損壓縮,但是通常有損壓縮的壓縮比(即原圖象占的位元組數與壓縮後圖象占的位元組數之比,壓縮比越大,說明壓縮效率越高)比無損壓縮的高。
圖象壓縮一般是通過改變圖象的表示方式來達到,因此壓縮和編碼是分不開的。圖象壓縮的主要應用是圖象資訊的傳輸和儲存,可廣泛地應用於廣播電視,電視會議,電腦通訊,傳真,多媒體系統,醫學圖象,衛星圖象等領域。
壓縮編碼的方法有很多,主要分成以下4大類:1.像素編碼;2.預測性編碼;3.變換編碼;4.其它方法。
所謂像素編碼是指,編碼時對每個像素單獨處理,不考慮像素之間的相關性。在像素編碼中常用的幾種方法有:1.脈衝編碼調製(Pulse Code Modulation,PCM);2.熵編碼(Entropy Coding);3.行程編碼(Run Length Coding);4.位平面編碼(Bit Plane Coding)。這裡面,我們要介紹的是熵編碼中的哈夫曼(Huffman)編碼,行程編碼(以讀取.PCX檔案為例)。
所謂預測性編碼是指,去掉相鄰像素之間的相關性和冗餘性,只對新的資訊進行編碼。舉個簡單的例子,因為像素的灰階是連續的,所以在一片地區中,相鄰像素之間灰階值的差別可能很小。如果我們只記錄第一個像素的灰階,其它像素的灰階都用它與前一個像素灰階之差來表示,就能起到壓縮的目的。如248,2,1,0,1,3,實際上這6個像素的灰階是248,250,251,251,252,255。表示250需要8個位元,而表示2隻需要兩個位元,這樣就實現了壓縮。常用的預測性編碼有Δ調製(Delta Modulation,簡稱DM);微分預測性編碼(Differential Pulse Code Modulation,DPCM),具體的細節,我們就不詳述了。
所謂變換編碼是指,將給定的圖象變換到另一個資料域(如頻域)上,使得大量的資訊能用較少的資料來表示,從而達到壓縮的目的。變換編碼有很多,如1.離散傅立葉變換(Discrete Fourier Transform,DFT);2.離散餘弦變換(Discrete Cosine Transform,DCT);3.離散哈達瑪變換(Discrete Hadamard Transform,DHT)。
其它的編碼方法也有很多,如混合編碼(Hybird Coding),向量量化(Vector Quantize,VQ),LZW演算法。在這裡,我們只介紹LZW演算法的大體思想。值得注意的是,近些年來出現了很多新的壓縮編碼方法,如使用人工神經元網路(Artificial Neural Network,ANN)的壓縮編碼演算法;分形(Fractl);小波(Wavelet);基於對象(Object -Based)的壓縮編碼演算法;基於模型(Model -Based)的壓縮編碼演算法(應 用在MPEG4及未來的視頻壓縮編碼通訊協定中)。這些都超出了本講座的範圍。
本講的最後,我們將以JPEG壓縮編碼通訊協定為例,看看上面的幾種編碼方法在實際的壓縮編碼中是怎樣應用的。
1. 哈夫曼(Huffman)編碼
Huffman編碼是一種常用的壓縮編碼方法,是Huffman於1952年為壓縮文字檔建立的。它的基本原理是頻繁使用的資料用較短的代碼代替,較少使用的資料用較長的代碼代替,每個資料的代碼各不相同。這些代碼都是二進位碼,且碼的長度是可變的。舉個例子:假設一個檔案中出現了8種符號S0,S1,S2,S3,S4,S5,S6,S7,那麼每種符號要編碼,至少需要3位元,假設編碼成000,001,010,011,100,101,110,111(稱做碼字)。那麼符號序列S0S1S7S0S1S6S2S2S3S4S5S0S0S1編碼後變成000001111000001110010010011100101000000001,共用了42位元。我們發現S0,S1,S2這三個符號出現的頻率比較大,其它符號出現的頻率比較小,如果我們採用一種編碼方案使得S0,S1,S2的碼字短,其它符號的碼字長,這樣就能夠減少佔用的位元數。
例如,我們採用這樣的編碼方案:S0到S7的碼字分別01,11,101,0000,0001,0010,0011,100,那麼上述符號序列變成011110001110011101101000000010010010111,共用了39位元,儘管有些碼字如S3,S4,S5,S6變長了(由3位變成4位),但使用頻繁的幾個碼字如S0,S1變短了,所以實現了壓縮。
上述的編碼是如何得到的呢?隨意亂寫是不行的。編碼必須保證不能出現一個碼字和另一個的前幾位相同的情況,比如說,如果S0的碼字為01,S2的碼字為011,那麼當序列中出現011時,你不知道是S0的碼字後面跟了個1,還是完整的一個S2的碼字。我們給出的編碼能夠保證這一點。
下面給出具體的Huffman編碼演算法。
1.首先統計出每個符號出現的頻率,上例S0到S7的出現頻率分別為4/14,3/14,2/14,1/14,1/14,1/14,1/14,1/14。
2.從左至右把上述頻率按從小到大的順序排列。
3.每一次選出最小的兩個值,作為二叉樹的兩個葉子節點,將和作為它們的根節點,這兩個葉子節點不再參與比較,新的根節點參與比較。
4.重複3,直到最後得到和為1的根節點。
5.將形成的二叉樹的左節點標0,右節點標1。把從最上面的根節點到最下面的葉子節點途中遇到的0,1序列串起來,就得到了各個符號的編碼。
上面的例子用Huffman編碼的過程如所示,其中圓圈中的數字是新節點產生的順序。可見,我們上面給出的編碼就是這麼得到的。
圖1. Huffman編碼的
產生霍夫曼編碼需要對未經處理資料掃描兩遍,第一遍掃描要精確地統計出未經處理資料中,每個值出現的頻率,第二遍是建立霍夫曼樹並進行編碼,由於需要建立二叉樹並遍曆二叉樹產生編碼,因此資料壓縮和還原速度都較慢,但簡單有效,因而得到廣泛的應用。
2.行程編碼(Run Length Coding)
行程編碼的原理也很簡單:將一行中顏色值相同的相鄰像素用一個計數值和該顏色值來代替。例如:aaabccccccddeee可以表示為3a1b6c2d3e。如果一幅圖象是由很多塊顏色相同的大面積地區組成,那麼採用行程編碼的壓縮效率是驚人的。然而,該演算法也導致了一個致命弱點,如果圖象中每兩個相鄰點的顏色都不同,用這種演算法不但不能壓縮,反而資料量增加一倍。所以現在單純採用行程編碼的壓縮演算法用得並不多,PCX檔案算是其中的一種.PCX檔案最早是PC Paintbrush軟體所採用的一種檔案格式,由於壓縮比不高,現在用的並不是很多了。它也是由頭資訊,調色盤,實際的圖象資料三個部分組成。其中頭資訊的結構為:
typedef struct{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
WORD xmin,ymin;
WORD xmax,ymax;
WORD hres;
WORD vres;
char palette[48];
char reserved;
char colour_planes;
WORD bytes_per_line;
WORD palette_type;
char filler[58];
} PCXHEAD;
其中值得注意的是以下幾個資料:manufacturer為PCX檔案的標識,必須為0x0a;xmin為最小的x座標,xmax最大的x座標,所以圖象的寬度為xmax-xmin+1,同樣圖象的高度為ymax-yin+1;bytes_per_line為每個編碼行所佔的位元組數,過一會兒詳細介紹。
PCX的調色盤在檔案的最後。以256色PCX檔案為例,倒數第769個位元組為顏色數的標識,256時該位元組必須為12,剩下的768(256*3)為調色盤的RGB值。
為了講起來方便,下面我們針對256色PCX檔案,介紹一下它的解碼過程。編碼是解碼的逆過程,有興趣的讀者可以試著自己來完成。
解碼是以行為單位的,該行所佔的位元組數由bytes_per_line給定。為此,我們開一個大小為bytes_per_line的解碼緩衝區。一開始,將緩衝區的所有內容清零。從檔案中讀出一個位元組C,若C>0xc0,說明是行程(Run Length)資訊,即C的低6位表示後面連續的位元組個數(所以最多63個連續顏色相同的像素,若還有顏色相同的像素,將在下一個行程處理),檔案的下一個位元組就是實際的圖象資料(即該顏色在調色盤中的索引值);若C<0xc0,則表示C是實際的圖象資料。如此反覆,直到這bytes_per_line個位元組處理完,這一行的解碼完成。PCX就是有若干個這樣的解碼行組成。
實現256色PCX檔案解碼的來源程式
3. LZW演算法的大體思想
LZW是一種比較複雜的壓縮演算法,其壓縮效率也比較高。我們在這裡只介紹一下它的基本原理:LZW把每一個第一次出現的字串用一個數值來編碼,在還原程式中再將這個數值還成原來的字串。例如:用數值0x100代替字串"abccddeee",每當出現該字串時,都用0x100代替,這樣就起到了壓縮的作用。至於0x100與字串的對應關係則是在壓縮過程中動態產生的,而且這種對應關係隱含在壓縮資料中,隨著解壓縮的進行,這張編碼錶會從壓縮資料中逐步得到恢複,後面的壓縮資料再根據前面資料產生的對應關係產生更多的對應關係,直到壓縮檔結束為止。LZW是無損的。GIF檔案採用了這種壓縮演算法。
要注意的是,LZW演算法由Unisys公司在美國申請了專利,要使用它首先要獲得該公司的認可。
4.JPEG壓縮編碼通訊協定
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),以下都是針對這種格式進行討論。
JPEG的壓縮原理
JPEG的壓縮原理其實上面介紹的那些原理的綜合,博採眾家之長,這也正是JPEG有高壓縮比的原因。其編碼器的流程為
圖3. 編碼器流程
解碼器基本上為上述過程的逆過程:
圖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)的排列方法,如所示:
圖5. Zig-Zag
這63個AC係數行程編碼的碼字用兩個位元組表示,如
圖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,大約每個像素用半個位元。
可以想見,壓縮比和圖象品質是呈反比的,以下是壓縮效率與圖象品質之間的大致關係,可以根據你的需要,選擇合適 的壓縮比。
壓縮效率(單位: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的檔案格式。
JPEG的檔案格式
JPEG檔案大體上可以分成以下兩個部分:標記碼(Tag)加壓縮資料。先介紹標記碼部分。
標記碼部分給出了JPEG圖象的所有資訊(有點類似於BMP中的頭資訊,但要複雜的多),象的寬,高,Huffman表,量化表等等。標記碼有很多,但絕大多數的JPEG檔案只包含幾種。標記碼的結構為:
SOI
DQT
DRI
SOF0
DHT
SOS
…
EOI
標記碼由兩個位元組組成,高位元組為0XFF,每個標記碼之前可以填上個數不限的填充位元組0XFF。
下面介紹一些常用的標記碼的結構及其含義。
SOI(Start of Image)
標記結構 位元組數
0XFF 1
0XD8 1
可作為JPEG格式的判據(JFIF還需要APP0的配合)
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將檔案的相關資訊定義在此標記中。
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個值(之字形排列)
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。如所示:
圖7. YUV411的
易知YUV411有50%的壓縮比(原來有12個資料單元,現在有6個資料單元),YUV422
有33%的壓縮比(原來有12個資料單元,現在有8個資料單元)。 那麼你可能會想,YUV911,YUV1611壓縮比不是更高嘛?但是要考慮到圖象品質的因素。所以JPEG標準規定了最小編碼單元MCU,要求Hy*Vy+Hu*Vu+Hv*Vv≤10。
MCU中塊的相片順序與H,V的值有密切關係。如以下幾幅圖所示:
圖8. YUV111的排列順序
圖9. YUV211的排列順序
圖10. YUV411的排列順序
標記結構 位元組數 意義
0XFF 1
0XDD 1
Lr 2 DRI標記碼長度,不包括前兩個位元組0XFF,0XDD
Ri 2 重入間隔的MCU個數,Ri必須是一MCU行中MCU個數的整數,最後一個零頭不一定剛好是Ri個MCU。每個重入間隔各自獨立編碼。
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 該量化表編號
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 0
0 1 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
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。
EOI(End of Image) 結束標誌
標記結構 位元組數 意義
0XFF 1
0XD9 1
JPEG基本系統解碼器的程式流程圖。
圖11. JPEG基本系統解碼器的程式流程圖
由於沒有用到什麼最佳化演算法,該解碼器的速度並不高,在用VC的效能評測工具Profile評測該程式時我發現最耗時的地方是反離散餘弦變換(IDCT)那裡,其實這是顯然的,浮點數的指令條數要比整數的多得多,因此採用一種快速的IDCT演算法能很大的提高效能,我這裡採用是目前被認為比較好的一種快速IDCT演算法,其主要思想是把二維IDCT分解成行和列兩個一維IDCT。