【轉載】轉載自http://www.cnblogs.com/leaven/archive/2010/04/06/1705846.html
JPEG壓縮編碼算法的主要計算步驟如下:
(0) 8*8分塊。
(1) 正向離散余弦變換(FDCT)。
(2) 量化(quantization)。
(3) Z字形編碼(zigzag scan)。
(4) 使用差分脈沖編碼調制(DPCM)對直流系數(DC)進行編碼。
(5) 使用行程長度編碼(RLE)對交流系數(AC)進行編碼。
(6) 熵編碼。
一、JPEG文件格式介紹
JPEG文件使用的數據存儲方式有多種。最常用的格式稱為JPEG文件交換格式(JPEG File Interchange Format,JFIF)。而JPEG文件大體上可以分成兩個部分:標記碼(Tag)和壓縮數據。
標記碼由兩個字節構成,其前一個字節是固定值0xFF,後一個字節則根據不同意義有不同數值。在每個標記碼之前還可以添加數目不限的無意義的0xFF填充,也就說連續的多個0xFF可以被理解為一個0xFF,並表示一個標記碼的開始。而在一個完整的兩字節的標記碼後,就是該標記碼對應的壓縮數據流,記錄了關於文件的諸種信息。
常用的標記有SOI、APP0、DQT、SOF0、DHT、DRI、SOS、EOI。
注意,SOI等都是標記的名稱。在文件中,標記碼是以標記代碼形式出現。例如SOI的標記代碼為0xFFD8,即在JPEG文件中的如果出現數據0xFFD8,則表示此處為一個SOI標記。
SOI,Start of Image,圖像開始
標記代碼 2字節 固定值0xFFD8
APP0,Application,應用程序保留標記0
標記代碼 2字節 固定值0xFFE0
包含9個具體字段:
① 數據長度 2字節 ①~⑨9個字段的總長度
即不包括標記代碼,但包括本字段
② 標識符 5字節 固定值0x4A46494600,即字符串“JFIF0”
③ 版本號 2字節 一般是0x0102,表示JFIF的版本號1.2
可能會有其他數值代表其他版本
④ X和Y的密度單位 1字節 只有三個值可選
0:無單位;1:點數/英寸;2:點數/厘米
⑤ X方向像素密度 2字節 取值范圍未知
⑥ Y方向像素密度 2字節 取值范圍未知
⑦ 縮略圖水平像素數目 1字節 取值范圍未知
⑧ 縮略圖垂直像素數目 1字節 取值范圍未知
⑨ 縮略圖RGB位圖 長度可能是3的倍數 縮略圖RGB位圖數據
本標記段可以包含圖像的一個微縮版本,存為24位的RGB像素。如果沒有微縮圖像(這種情況更常見),則字段⑦“縮略圖水平像素數目”和字段⑧“縮略圖垂直像素數目”的值均為0。
APPn,Application,應用程序保留標記n,其中n=1~15(任選)
標記代碼 2字節 固定值0xFFE1~0xFFF
包含2個具體字段:
① 數據長度 2字節 ①~②2個字段的總長度
即不包括標記代碼,但包括本字段
② 詳細信息 數據長度-2字節 內容不定
例如,Adobe Photoshop生成的JPEG圖像中就用了APP1和APP13兩個標記段分別存儲了一幅圖像的副本。
DQT,Define Quantization Table,定義量化表
標記代碼 2字節 固定值0xFFDB
包含9個具體字段:
① 數據長度 2字節 字段①和多個字段②的總長度
即不包括標記代碼,但包括本字段
② 量化表 數據長度-2字節
a)精度及量化表ID 1字節 高4位:精度,只有兩個可選值
0:8位;1:16位
低4位:量化表ID,取值范圍為0~3
b)表項 (64×(精度+1))字節 例如8位精度的量化表
其表項長度為64×(0+1)=64字節
本標記段中,字段②可以重復出現,表示多個量化表,但最多只能出現4次。
SOF0,Start of Frame,幀圖像開始
標記代碼 2字節 固定值0xFFC0
包含9個具體字段:
① 數據長度 2字節 ①~⑥六個字段的總長度
即不包括標記代碼,但包括本字段
② 精度 1字節 每個數據樣本的位數
通常是8位,一般軟件都不支持 12位和16位
③ 圖像高度 2字節 圖像高度(單位:像素),如果不支持 DNL 就必須 >0
④ 圖像寬度 2字節 圖像寬度(單位:像素),如果不支持 DNL 就必須 >0
⑤ 顏色分量數 1字節 只有3個數值可選
1:灰度圖;3:YCrCb或YIQ;4:CMYK
而JFIF中使用YCrCb,故這裡顏色分量數恆為3
⑥顏色分量信息 顏色分量數×3字節(通常為9字節)
a)顏色分量ID 1字節
b)水平/垂直采樣因子 1字節 高4位:水平采樣因子
低4位:垂直采樣因子
(曾經看到某資料把這兩者調轉了)
c) 量化表 1字節 當前分量使用的量化表的ID
本標記段中,字段⑥應該重復出現,有多少個顏色分量(字段⑤),就出現多少次(一般為3次)。
DHT,Difine Huffman Table,定義哈夫曼表
標記代碼 2字節 固定值0xFFC4
包含2個具體字段:
①數據長度 2字節 字段①和多個字段②的總長度
即不包括標記代碼,但包括本字段
② 哈夫曼表 數據長度-2字節
a)表ID和表類型 1字節 高4位:類型,只有兩個值可選
0:DC直流;1:AC交流
低4位:哈夫曼表ID,
注意,DC表和AC表分開編碼
b)不同位數的碼字數量 16字節
c)編碼內容 16個不同位數的碼字數量之和(字節)
本標記段中,字段②可以重復出現(一般4次),也可以致出現1次。例如,Adobe Photoshop 生成的JPEG圖片文件中只有1個DHT標記段,裡邊包含了4個哈夫曼表;而Macromedia Fireworks生成的JPEG圖片文件則有4個DHT標記段,每個DHT標記段只有一個哈夫曼表。
DRI,Define Restart Interval,定義差分編碼累計復位的間隔
標記代碼 2字節 固定值0xFFDD
包含2個具體字段:
①數據長度 2字節 固定值0x0004,①~②兩個字段的總長度
即不包括標記代碼,但包括本字段
②MCU塊的單元中的重新開始間隔
2字節 設其值為n,則表示每n個MCU塊就有一個
RSTn標記。第一個標記是RST0,第二個是
RST1等,RST7後再從RST0重復。
如果沒有本標記段,或間隔值為0時,就表示不存在重開始間隔和標記RST
SOS,Start of Scan,掃描開始 12字節
標記代碼 2字節 固定值0xFFDA
包含2個具體字段:
①數據長度 2字節 ①~④兩個字段的總長度
即不包括標記代碼,但包括本字段
②顏色分量數 1字節 應該和SOF中的字段⑤的值相同,即:
1:灰度圖是;3: YCrCb或YIQ;4:CMYK。
而JFIF中使用YCrCb,故這裡顏色分量數恆為3
③顏色分量信息
a) 顏色分量ID 1字節
b) 直流/交流系數表號 1字節 高4位:直流分量使用的哈夫曼樹編號
低4位:交流分量使用的哈夫曼樹編號
④ 壓縮圖像數據
a)譜選擇開始 1字節 固定值0x00
b)譜選擇結束 1字節 固定值0x3F
c)譜選擇 1字節 在基本JPEG中總為00
本標記段中,字段③應該重復出現,有多少個顏色分量(字段②),就出現多少次(一般為3次)。本段結束後,緊接著就是真正的圖像信息了。圖像信息直至遇到一個標記代碼就自動結束,一般就是以EOI標記表示結束。
EOI,End of Image,圖像結束 2字節
標記代碼 2字節 固定值0xFFD9
這裡補充說明一下,由於在JPEG文件中0xFF具有標志性的意思,所以在壓縮數據流(真正的圖像信息)中出現0xFF,就需要作特別處理。具體方法是,在數據0xFF後添加一個沒有意義的0x00。換句話說,如果在圖像數據流中遇到0xFF,應該檢測其緊接著的字符,如果是
1)0x00,則表示0xFF是圖像流的組成部分,需要進行譯碼;
2)0xD9,則與0xFF組成標記EOI,則圖像流結束,同時圖像文件結束;
3)0xD0~0xD7,則組成RSTn標記,則要忽視整個RSTn標記,即不對當前0xFF和緊接的0xDn兩個字節進行譯碼,並按RST標記的規則調整譯碼變量;
3)0xFF,則忽視當前0xFF,對後一個0xFF再作判斷;
4)其他數值,則忽視當前0xFF,並保留緊接的此數值用於譯碼。