隨筆-65  評論-68  文章-4  trackbacks-0

          JPEG文件格式簡單分析

          作者:小爽

          摘要:

          這篇文章大體上介紹了JPEG文件的結(jié)構(gòu)信息以及它的壓縮算法和編碼方式。使讀者能夠?qū)?/SPAN>JPEG文件格式有大體上的了解。為讀者進(jìn)一步進(jìn)行學(xué)習(xí)JPEG文件壓縮做好準(zhǔn)備

           

          關(guān)鍵字:十六進(jìn)制,段格式,編碼

           

          一、    JPEG文件格式概述:

          圖像和動(dòng)畫的存儲(chǔ)方式是一個(gè)很重要的問題。幸好我們有了數(shù)據(jù)壓縮,有了JPEG等多種壓縮存儲(chǔ)圖像的文件格式,我們今天才能夠拿著小小的一個(gè)存儲(chǔ)器,卻存上許多張色彩鮮艷的圖片。如果沒有圖像壓縮算法,也許我們的多媒體時(shí)代就會(huì)晚到來許多年。

          JPEG圖像存儲(chǔ)格式一個(gè)比較成熟的圖像有損壓縮格式,雖然一個(gè)圖片經(jīng)過轉(zhuǎn)化為JPEG圖像后,一些數(shù)據(jù)會(huì)丟失,但是,人眼是很不容易分辨出來這種差別的。也就是說,JPEG圖像存儲(chǔ)格式既滿足了人眼對色彩和分辨率的要求,又適當(dāng)?shù)娜コ藞D像中很難被人眼所分辨出的色彩,在圖像的清晰與大小中JPEG找到了一個(gè)很好的平衡點(diǎn)。

          雖然圖像轉(zhuǎn)化為JPEG格式會(huì)減小很多,但是并不是文件就變得簡單了,相反,JPEG文件的格式是比較復(fù)雜的。不經(jīng)過認(rèn)真地分析,是不容易弄懂它的。

           

          二、    JPEG文件的存儲(chǔ)方式:

          JPEG文件的格式是分為一個(gè)一個(gè)的段來存儲(chǔ)的(但并不是全部都是段),段的多少和長度并不是一定的。只要包含了足夠的信息,該JPEG文件就能夠被打開,呈現(xiàn)給人們。JPEG文件的每個(gè)段都一定包含兩部分一個(gè)是段的標(biāo)識(shí),它由兩個(gè)字節(jié)構(gòu)成:第一個(gè)字節(jié)是十六進(jìn)制0xFF,第二個(gè)字節(jié)對于不同的段,這個(gè)值是不同的。緊接著的兩個(gè)字節(jié)存放的是這個(gè)段的長度(除了前面的兩個(gè)字節(jié)0xFF0xXXX表示不確定。他們是不算到段的長度中的)。注意:這個(gè)長度的表示方法是按照高位在前,低位在后的,與Intel的表示方法不同。比方說一個(gè)段的長度是0x12AB,那么它會(huì)按照0x120xAB的順序存儲(chǔ)。但是如果按照Intel的方式:高位在后,低位在前的方式會(huì)存儲(chǔ)成0xAB0x12,而這樣的存儲(chǔ)方法對于JPEG是不對的。這樣的話如果一個(gè)程序不認(rèn)識(shí)JPEG文件某個(gè)段,它就可以讀取后兩個(gè)字節(jié),得到這個(gè)段的長度,并跳過忽略它。

          本人曾經(jīng)編寫過一個(gè)讀取JPEG文件信息的程序,該程序能夠讀取JPEG文件中包含的段的信息并顯示出來。下面是一個(gè)JPEG圖片的信息片斷:

           

          SOI

                  APP0    Length: 0x10

                  DQT

                          DQT [0]:

                  8       6       5       8       12      20      26      31

                  6       6       7       10      13      29      30      28

                  7       7       8       12      20      29      35      60

                  7       9       11      15      26      44      50      31

                  9       11      19      28      34      56      52      0

                  12      18      28      32      61      52      0       46

                  25      32      39      57      52      0       60      0

                  36      46      39      49      253     50      0       50

                  Length: 0x43

                  DQT

                          DQT [1]:

                  9       9       12      24      50      50      50      50

                  9       11      13      33      50      50      50      50

                  12      13      28      50      50      50      50      50

                  24      33      50      50      50      50      50      50

                  50      50      50      50      50      50      50      0

                  50      50      50      50      50      50      0       50

                  50      50      50      50      50      0       50      0

                  50      50      50      50      253     50      0       50

                  Length: 0x43

                  SOF0

                          Image Height: 173

                          Image Width: 401

                          Number of Frame(s): 3

                          ****************

                          Content ID: 1

                          H Factor: 2

                          V Factor: 2

                          QT ID: 0

                          ****************

                          Content ID: 2

                          H Factor: 1

                          V Factor: 1

                          QT ID: 1

                          ****************

                          Content ID: 3

                          H Factor: 1

                          V Factor: 1

                          QT ID: 1

                  Length: 0x11

                  DHT

                          Type: DC TABLE

                          ID: 0

                  Length: 0x1f

                  DHT

                          Type: AC TABLE

                          ID: 0

                  Length: 0xb5

                  DHT

                          Type: DC TABLE

                          ID: 1

                  Length: 0x1f

                  DHT

                          Type: AC TABLE

                          ID: 1

                  Length: 0xb5

                  SOS     Length: 0xc     <-Will Not Process This Seg.

          FATAL ERROR: File Structure Does NOT Support.

           

          你首先會(huì)想到為什么最后會(huì)出現(xiàn)一個(gè)錯(cuò)誤的信息呢?這是因?yàn)椋?/SPAN>SOSStart Of Scan)段的后面,就是編碼后的一行一行的圖像信息。不再是段的結(jié)構(gòu)了。在開始的SOIStart Of Image)不是一個(gè)段,它是文件的開始,它的值也是類似于0xFF0xXX的結(jié)構(gòu)(SOI的具體數(shù)值清自己察看相關(guān)書籍,本文章中將不作重點(diǎn)介紹),但是后面沒有段的長度。在文件的最后,有一個(gè)EOIEnd Of Image)的標(biāo)識(shí),它的結(jié)構(gòu)和SOI是類似的。它標(biāo)志著文件的結(jié)束。

          在這中間,包含了APP0段,DQT段,SOF0段,DHT段,SOS段。有的段的個(gè)數(shù)是不唯一的,比方說DQT段。我們現(xiàn)在重點(diǎn)地介紹各個(gè)段的作用。

           

          三、    JPEG文件中段的介紹:

          APP0段中主要存儲(chǔ)的是圖片的識(shí)別信息(字符串”JFIF\0”)、一些分辨率的信息以及縮略圖的信息。在我的實(shí)際測試中,發(fā)現(xiàn)并不是所有的JPEG文件都有APP0段的,有的僅是有APP2之類的其他段,但是每個(gè)文件中肯定是包含APPX的段(X可以取得的值可以查閱相關(guān)文檔)。我個(gè)人估計(jì),這些APPX的段的信息應(yīng)該是大同小異。這個(gè)的驗(yàn)證還有待本人進(jìn)一步的學(xué)習(xí),目前只能說到這里。

          DQT段的內(nèi)容是量化表的信息。眾所周知,一個(gè)顏色可以分為RGB(紅、綠、蘭)三個(gè)分量,這三色光組成了我們可以見到的所有色彩。但是,在JPEG文件中,RGB色彩格式需要先轉(zhuǎn)化為YUV的格式。Y分量代表了亮度信息,UV分量代表了色差信息。相比之下,人眼對于Y分量更為敏感。量化表的作用就是對于一些不需要的量進(jìn)行去除,這也是JPEG有損壓縮損失數(shù)據(jù)的關(guān)鍵。上面的輸出可以看到兩個(gè)量化表,一個(gè)給Y分量,另一個(gè)給UV分量。其實(shí),他們也可以共用一個(gè)量化表。一個(gè)量化的結(jié)果如下所示(摘自《JPEG壓縮編碼標(biāo)準(zhǔn)》):

          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

          我們可以看到,量化后出現(xiàn)了大量的0,這種結(jié)果很有利于我們進(jìn)行下一步的數(shù)據(jù)壓縮的。至于為什么是8x8的大小,待會(huì)你就知道了。

          SOF0段的內(nèi)容是圖像的大小信息,每個(gè)像素的位數(shù)信息,以及YUV每個(gè)分量分別得的采樣信息(這部分如果讀者想要進(jìn)一步學(xué)習(xí),請參考相應(yīng)書籍和文檔)。JPEG文件圖像的編碼是一個(gè)方塊一個(gè)方塊進(jìn)行的,每塊的大小為8x8大小(如果圖像不是整數(shù)個(gè)方塊的大小那么就對圖像補(bǔ)齊為整數(shù)個(gè)大小)。簡略地說采樣信息,就是如何按組記錄YUV的信息,即若干個(gè)Y方塊,若干個(gè)U方塊,若干個(gè)V方塊經(jīng)過量化的數(shù)據(jù)再次經(jīng)過編碼后組成一組記錄,保存在SOS段結(jié)束后。

          DHT段的內(nèi)容是一個(gè)重頭戲,如果沒有它,JPEG壓縮效率就不會(huì)那么高了。它內(nèi)部定義的是一個(gè)Huffman表,不同的DHT段定義不同的Huffman表,有的是直流量的表,有的是交流量的表。什么是直流量,什么是交流量呢?待會(huì)我再作介紹。最多的Huffman表示幾個(gè)呢?YUV各一個(gè),直流交流各一個(gè),因?yàn)?/SPAN>YUV每個(gè)分量都有直流和交流,所以最多時(shí),Huffman表有3x2個(gè),也就是可以有6個(gè)DHT段。該文件中有4個(gè)DHT表,您可以大概猜出來是哪幾個(gè)表么?Y的直流和交流各一個(gè)Huffman表,UV和起來直流和交流各一個(gè)Huffman表。這樣說應(yīng)該比較合理吧。

          好了,現(xiàn)在我們應(yīng)該弄明白什么是交流量,什么是直流量了。還舉上面那個(gè)有許多個(gè)08x8的表的例子說,所謂交流量,是經(jīng)過量化后的塊內(nèi)部除了左上角15那個(gè)值的其余值。實(shí)際上,塊與塊之間左上角那個(gè)值是用直流Huffman表來單獨(dú)編碼的。不與塊內(nèi)部一同編碼。雖然不同的編碼,但是要注意的事,不同的編碼方式并不意味著它們是不在一起的,具體的存儲(chǔ)編碼后的數(shù)據(jù)的時(shí)候,還是按照若干個(gè)Y方塊,若干個(gè)U方塊,若干個(gè)V方塊經(jīng)過量化的數(shù)據(jù)再次經(jīng)過編碼后組成一組記錄來存儲(chǔ)的。

          SOS段的內(nèi)容是關(guān)于YUV每個(gè)分量的直流和交流各使用那個(gè)Huffman表來編碼的。

                

          四、    JPEG文件十六進(jìn)制代碼解析

          我覺得,如果想要的了解JPEG,對十六進(jìn)制代碼的觀察是必不可少的。不要認(rèn)為這樣有多難,我會(huì)讓你知道這是很簡單的。目前我們只需要了解我們能夠了解的東西就可以了。要記住,每個(gè)段的開始是0xFF0xXX,緊接著兩個(gè)字節(jié)是長度信息。

          可以看到,上圖被選定的標(biāo)記是SOI標(biāo)記。

          上圖被選定的段是APP0段。

           

          緊接著的段是DQT段,這個(gè)JPEG文件有兩個(gè)DQT段。這里需要強(qiáng)調(diào)一點(diǎn)的是,包括量化表在內(nèi)8x8的塊的值是按照Z形來保存量化表8x8的數(shù)據(jù)的。而不是按照一行一行的保存的。這樣做的好處是,能夠讓實(shí)際上相鄰的像素點(diǎn)保存后也排列得比較近,便于壓縮和編碼。如下圖所示:

          (摘自《JPEG壓縮編碼標(biāo)準(zhǔn)》)

           

           

          上圖標(biāo)記的段是DHT段,一共有4個(gè)DHT段。

           

          這個(gè)段是SOS段,在這個(gè)段的后面就是所有壓縮后的數(shù)據(jù)。

          每段的具體信息在這里我就不詳細(xì)介紹了,網(wǎng)上有很多相關(guān)的文章,如果有興趣的話,可以去查找閱讀。

           

          五、    圖像數(shù)據(jù)塊內(nèi)的編碼方式

          其實(shí),圖像數(shù)據(jù)塊的編碼是比較麻煩的,它涉及到了行程編碼,Huffman編碼等編碼方式。這部分很多文檔說得都不是很清楚,我力求去除內(nèi)部比較麻煩的部分,再通過簡單的語言讓大家明白原理,這樣大家如果有興趣進(jìn)行下一步的研究,也會(huì)比較容易上手的。

          我們還是使用那剛才那個(gè)包含很多0的量化后的8x8的數(shù)據(jù)塊來說明。我們把塊內(nèi)剩余的63個(gè)數(shù)據(jù)用行程編碼來編碼。經(jīng)過行程編碼后的數(shù)據(jù)的格式是:(x,y)。x表示的是從當(dāng)前位置開始有多少個(gè)連續(xù)的零,y表示這些連續(xù)的0的后面的第一個(gè)非零的數(shù)是多少。但是為了解決存儲(chǔ)的問題和進(jìn)行進(jìn)一步的壓縮。最后的壓縮格式變?yōu)椋海?/SPAN>x,yzxy占有一個(gè)字節(jié)的長度。z的長度不固定,需要根據(jù)y的值來判斷。x仍代表從當(dāng)前位置開始有幾個(gè)連續(xù)的零,但是因?yàn)?/SPAN>x只能占有四位的長度,也就是它的最大值是15,所以,當(dāng)多于16個(gè)連續(xù)的零的時(shí)候。會(huì)用一個(gè)字節(jié)的(15,0)來代替前面的16個(gè)0,然后繼續(xù)編碼(注意:這時(shí)候沒有z部分)。當(dāng)塊結(jié)束或者當(dāng)前塊后面剩余的都是零的時(shí)候,就用(0,0)即EOB代替(同樣也是沒有z部分)。前面說到z的長度不固定,需要根據(jù)y的值來判斷,這是為什么呢?簡單的來說,z的長度是不一定的,在1~15的范圍內(nèi)。Y的作用簡單的來說表示的是z的二進(jìn)制位數(shù)(1~15),也正好是4位二進(jìn)制的值能夠表示的。然后,把xy合成的一個(gè)字節(jié)單獨(dú)提取出來,利用DHT里面的Huffman表來進(jìn)行編碼。這樣,編碼的長度又能夠被壓縮了。

           

          六、    總結(jié)

          敘述了這么多,相信大家對于JPEG已經(jīng)有了一個(gè)大概的了解了吧,如果你通過閱讀這篇文章,對JPEG文件的結(jié)構(gòu)和算法有了一個(gè)大體上的認(rèn)識(shí),那么這篇文章的目的也就達(dá)到了。下一步進(jìn)行具體研究就不會(huì)有太大問題了。祝愿大家能夠在數(shù)據(jù)壓縮的路上走好。

           

          參考文獻(xiàn):

          1.             JPEG壓縮編碼標(biāo)準(zhǔn)》

          2.             JPEG格式》

          3.             JPEG簡易文檔》        作者:風(fēng)云

          posted on 2005-07-01 15:09 小爽 閱讀(48440) 評論(19)  編輯  收藏 所屬分類: 我的經(jīng)驗(yàn)

          評論:
          # re: JPEG文件格式簡單分析 2006-12-28 14:14 | 李運(yùn)博
          基本對該編碼有一定的認(rèn)識(shí)了,謝謝  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2007-01-15 14:41 | ysm
          有沒有JPEG文件格式解析編碼給一個(gè),yangsm318@126.com 謝謝!  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2007-07-26 14:09 | wyz

          謝謝你的文章

          如何從網(wǎng)絡(luò)上讀取jpeg信息,并實(shí)時(shí)的顯示出來?(即不能全部讀到本地之后再顯示), 能告知嗎? 謝謝,

          wangyuanzhenghf@163.com  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析[未登錄] 2007-08-03 17:20 | 過客
          不錯(cuò)的文章,謝謝你,辛苦了!  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2007-08-06 20:22 | 暢達(dá)
          通俗易懂!謝謝你的文章!  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2007-08-06 20:24 | 暢達(dá)
          作者是否編寫過c++程序來處理JPEG圖像?
          我的郵箱xuzhengnan@163.com
          期待您的指導(dǎo)!  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2007-10-30 02:34 | Wilson
          我編寫過,但是因?yàn)楝F(xiàn)在在美國學(xué)習(xí),所以沒有辦法給你發(fā)送一份拷貝,不好意思了@暢達(dá)
            回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析[未登錄] 2008-01-05 11:55 | xiaoxin
          首先非常感謝你的文章,辛苦了!
          不好意思我是新手,我想知道通過什么軟件或編輯器能知道一圖像的格式信息的?像你上面顯示出的圖片那樣,謝謝!
          還有請問你知道如何讀取jp2格式文件信息嗎?知道的話能方便告知嗎?不勝感激!
          我的郵箱是chenmo1013@126.com  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析[未登錄] 2008-03-29 19:31 | 學(xué)習(xí)者
          謝謝你
          你的圖我覺得是比較好地
          十分感謝  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2008-04-07 09:38 | t
          很有收獲
          順便問一下jp2和漸進(jìn)式j(luò)peg怎么分辨?  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析[未登錄] 2008-04-23 22:32 | xiaoxiao
          很急 樓主有沒有將接受到的數(shù)據(jù)轉(zhuǎn)換成JPEG的VC軟件程序或C軟件方面的資料,cxml84@163.com 謝謝  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析[未登錄] 2008-05-15 13:39 | wolf
          good  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2008-08-05 10:02 | Sandwi
          非常好,感謝分享。  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2008-09-23 16:44 | 年建杰
          HI,小爽你好
          能把你那個(gè)讀取并顯示JPEG文件的程序發(fā)給我嗎? 我現(xiàn)在正在做這個(gè)文件的解析和顯示,比較迷茫。謝謝了  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2008-09-23 16:49 | 年建杰
          HI,小爽你好
          能把你那個(gè)讀取并顯示JPEG文件的程序發(fā)給我嗎? 我現(xiàn)在正在做這個(gè)文件的解析和顯示,比較迷茫。謝謝了
          我的MSN:nianjianjie@hotmail.com  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2009-01-16 08:51 | 理標(biāo)電子
          詳細(xì)  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2009-03-24 08:35 | 小陳
          非常感謝你的文章!  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析 2009-08-24 08:50 | 敏敏
          不錯(cuò),多謝分享!

          文中提到“JPEG文件圖像的編碼是一個(gè)方塊一個(gè)方塊進(jìn)行的,每塊的大小為8x8大小(如果圖像不是整數(shù)個(gè)方塊的大小那么就對圖像補(bǔ)齊為整數(shù)個(gè)大小)”,很疑惑當(dāng)圖像不是整數(shù)個(gè)方塊的大小如何將圖像補(bǔ)齊為整數(shù)個(gè)大小,例如一個(gè)大小為10(行)×7(列)像素大小的圖像(記為A11、A12、…A17,A21、A22、…,A71、A72、A73、…A77)該如何補(bǔ)成8x8的塊呢?  回復(fù)  更多評論
            
          # re: JPEG文件格式簡單分析[未登錄] 2010-01-17 00:07 | dboy
          不錯(cuò),學(xué)習(xí)了  回復(fù)  更多評論
            
          主站蜘蛛池模板: 吐鲁番市| 东莞市| 托里县| 康马县| 广德县| 万全县| 任丘市| 怀来县| 凌海市| 黄大仙区| 洛南县| 龙里县| 铜山县| 都昌县| 灵丘县| 万载县| 新泰市| 新野县| 兴国县| 蓝山县| 张家口市| 正宁县| 通州市| 怀来县| 灌阳县| 舞钢市| 江门市| 昌吉市| 富民县| 河池市| 渝北区| 迁安市| 观塘区| 德庆县| 临清市| 松桃| 麟游县| 田阳县| 临安市| 乌审旗| 仙居县|