當前位置:編程學習大全網 - 編程語言 - 求JPEG圖象文件頭部的格式

求JPEG圖象文件頭部的格式

JPEG是聯合圖象專家組(Joint Photographic Expert Group)的英文縮寫,是國際標準化組織(ISO)和CCITT聯合制定的靜態圖象的壓縮編碼標準。

JPEG 的圖片使用的是 YCrCb 顏色模型, 而不是計算機上最常用的 RGB. 關於色彩模型, 這裏不多闡述. 只是說明, YCrCb 模型更適合圖形壓縮. 因為人眼對圖片上的亮度 Y 的變化遠比色度 C 的變化敏感. 我們完全可以每個點保存壹個 8bit 的亮度值, 每 2x2 個點保存壹個 Cr Cb 值, 而圖象在肉眼中的感覺不會起太大的變化. 所以, 原來用 RGB 模型, 4 個點需要 4x3=12 字節. 而現在僅需要 4+2=6 字節; 平均每個點占 12bit. 當然 JPEG 格式裏允許每個點的 C 值都記錄下來; 不過 MPEG 裏都是按 12bit 壹個點來存放的, 我們簡寫為 YUV12.

從RGB到YCrCb的轉化是通過壹些矩陣運算完成的,在網上可以搜到。

JPEG的壓縮比高,因而廣泛在互聯網上使用。JPEG有幾種模式,其中最常用的是基於DCT變換的順序型模式,又稱為基線系統(Baseline),以下將針對這種格式進行討論。

1. JPEG的壓縮原理

JPEG 裏, 要對數據壓縮,先要做壹次DCT變換.DCT 變換的原理, 涉及到數學知識,這裏我們不必深究. 反正和傅立葉變換(學過高數的都知道) 是差不多了. 經過這個變換, 就把圖片裏點和點間的規律呈現出來了,更方便壓縮.JPEG裏是對每8x8個點為壹個單位處理的.所以如果原始圖片的長寬不是8的倍數,都需要先補成8的倍數,好壹塊塊的處理.另外,記得剛才我說的Cr Cb都是2x2記錄壹次嗎?所以大多數情況,是要補成16x16的整數塊.按從左到右,從上到下的次序排列(和我們寫字的次序壹樣).JPEG 裏是對Y Cr Cb分別做DCT變換的.這裏進行DCT變換的Y, Cr, Cb值的範圍都是- 128~127.(Y 被減去 128)

JPEG 編碼時使用的是 Forward DCT (FDCT) 解碼時使用的 Inverse DCT(IDCT)

經過DCT變換後,低頻分量集中在左上角,其中F(0,0)(即第壹行第壹列元素)代表了直流(DC)系數,即8×8子塊的平均值,要對它單獨編碼。由於兩個相鄰的8×8子塊的DC系數相差很小,所以對它們采用差分編碼DPCM,可以提高壓縮比,也就是說對相鄰的子塊DC系數的差值進行編碼。8×8的其它63個元素是交流(AC)系數,采用行程編碼。這裏出現壹個問題:這63個系數應該按照怎麽樣的順序排列?為了保證低頻分量先出現,高頻分量後出現,以增加行程中連續“0”的個數,這63個元素采用了“之”字型(Zig-Zag)的排列方法

0, 1, 5, 6, 14, 15, 27, 28,

2, 4, 7, 13, 16, 26, 29, 42,

3, 8, 12, 17, 25, 30, 41, 43,

9, 11, 18, 24, 31, 40, 44, 53,

10, 19, 23, 32, 39, 45, 52, 54,

20, 22, 33, 38, 46, 51, 55, 60,

21, 34, 37,47, 50, 56, 59, 61,

35, 36, 48, 49, 57, 58, 62, 63

為了進壹步提高壓縮比,需要對其再進行熵編碼,這裏選用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 與原始圖象幾乎壹樣

2. JPEG的文件格式 JPEG文件大體上可以分成以下兩個部分:標記碼(Tag)加壓縮數據。先介紹標記碼部分。 標記碼部分給出了JPEG圖象的所有信息(有點類似於BMP中的頭信息,但要復雜的多),如圖象的寬、高、Huffman表、量化表等等。標記碼有很多,但絕大多數的JPEG文件只包含幾種。

註意 JPEG/JFIF 文件格式使用 Motorola 格式,而不是Intel格式,就是說,如果是壹個字的話, 高字節在前, 低字節在後.

JPG文件是由壹個個段(segments)構成的.每個段長度<=65535.每個段從壹個標記字開始.標記字都是0xff打頭的,以非0字節和 0xFF 結束.例如"FFDA","FFC4","FFC0".每個標記有它特定意義,這是由第2字節指明的.例如,SOS(StartOf Scan= "FFDA")指明了妳應該開始解碼.另壹個標記DQT(Define Quantization Table = 0xFFDB)就是說它後面有64字節的quantization表在處理JPG文件時,如果妳碰到壹個0xFF,而它後面的字節不是0,並且這個字節沒有意義.那麽妳遇到的0xFF字節必須被忽略.(壹些JPG 裏,常用用0xFF做某些填充用途)如果妳在做huffman編碼時碰巧產生了壹個0xFF,那麽就用0xFF 0x00代替.就是說在jpeg圖形解碼時碰到FF00就把它當作FF處理.另外在huffman編碼區域結束時,碰到幾個bit沒有用的時候,應該用1去填充.然後後面跟 FF.

下面是必須處理的標記

SOF0 = Start Of Frame 0 = FFC0

SOS = Start Of Scan = FFDA

APP0 = it"s the marker used to identify a JPG file which uses the JFIF

specification = FFE0

COM = Comment = FFFE

DNL = Define Number of Lines = FFDC

DRI = Define Restart Interval = FFDD

DQT = Define Quantization Table = FFDB

DHT = Define Huffman Table = FFC4

段的類型:

SOF0: Start Of Frame 0:

~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $c0 (SOF0)

- 長度 (高字節, 低字節), 8+components*3

- 數據精度 (1 byte) 每個樣本位數, 通常是 8 (大多數軟件不支持 12 和 16)

- 圖片高度 (高字節, 低字節), 如果不支持 DNL 就必須 >0

- 圖片寬度 (高字節, 低字節), 如果不支持 DNL 就必須 >0

- components 數量(1 byte), 灰度圖是 1, YCbCr/YIQ 彩色圖是 3, CMYK 彩色圖

是 4

- 每個 component: 3 bytes

- component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q)

- 采樣系數 (bit 0-3 vert., 4-7 hor.)

- quantization table 號

DRI: Define Restart Interval:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $dd (DRI)

- 長度 (高字節, 低字節), 必須是 4

- MCU 塊的單元中的重新開始間隔 (高字節, 低字節),

意思是說, 每 n 個 MCU 塊就有壹個 RSTn 標記.

第壹個標記是 RST0, 然後是 RST1 等, RST7 後再從 RST0 重復

DQT: Define Quantization Table:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $db (DQT)

- 長度 (高字節, 低字節)

- QT 信息 (1 byte):

bit 0..3: QT 號(0..3, 否則錯誤)

bit 4..7: QT 精度, 0 = 8 bit, 否則 16 bit

- n 字節的 QT, n = 64*(精度+1)

備註:

- 壹個單獨的 DQT 段可以包含多個 QT, 每個都有自己的信息字節

- 當精度=1 (16 bit), 每個字都是高位在前低位在後

DAC: Define Arithmetic Table:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

法律原因, 現在的軟件不支持 arithmetic 編碼.

不能生產使用 arithmetic 編碼的 JPEG 文件

DHT: Define Huffman Table:

~~~~~~~~~~~~~~~~~~~~~~~~~~

- $ff, $c4 (DHT)

- 長度 (高字節, 低字節)

- HT 信息 (1 byte):

bit 0..3: HT 號 (0..3, 否則錯誤)

bit 4 : HT 類型, 0 = DC table, 1 = AC table

bit 5..7: 必須是 0

- 16 bytes: 長度是 1..16 代碼的符號數. 這 16 個數的和應該 <=256

- n bytes: 壹個包含了按遞增次序代碼長度排列的符號表

(n = 代碼總數)

COM: 註釋:

~~~~~~~~~~

- $ff, $fe (COM)

- 註釋長度 (高字節, 低字節) = L+2

- 註釋為長度為 L 的字符流

SOS: Start Of Scan:

~~~~~~~~~~~~~~~~~~~

- $ff, $da (SOS)

- 長度 (高字節, 低字節), 必須是 6+2*(掃描行內組件的數量)

- 掃描行內組件的數量 (1 byte), 必須 >= 1 , <=4 (否則是錯的) 通常是 3

- 每個組件: 2 bytes

- component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q), 見 SOF0

- 使用的 Huffman 表:

- bit 0..3: AC table (0..3)

- bit 4..7: DC table (0..3)

- 忽略 3 bytes ()

  • 上一篇:Vba編程操作
  • 下一篇:有沒有好的關於嵌入式Linux方面的書籍?大家給推薦推薦
  • copyright 2024編程學習大全網