JPEG圖像密寫研究(一) JPEG圖像文件結構


【轉載】轉載自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 FormatJFIF)。而JPEG文件大體上可以分成兩個部分:標記碼(Tag)和壓縮數據。

標記碼由兩個字節構成,其前一個字節是固定值0xFF,后一個字節則根據不同意義有不同數值。在每個標記碼之前還可以添加數目不限的無意義的0xFF填充,也就說連續的多個0xFF可以被理解為一個0xFF,並表示一個標記碼的開始。而在一個完整的兩字節的標記碼后,就是該標記碼對應的壓縮數據流,記錄了關於文件的諸種信息。

常用的標記有SOIAPP0DQTSOF0DHTDRISOSEOI

注意,SOI等都是標記的名稱。在文件中,標記碼是以標記代碼形式出現。例如SOI的標記代碼為0xFFD8,即在JPEG文件中的如果出現數據0xFFD8,則表示此處為一個SOI標記。

 

SOIStart of Image,圖像開始

標記代碼                                 2字節     固定值0xFFD8

 

APP0Application,應用程序保留標記0

標記代碼                                 2字節     固定值0xFFE0

包含9個具體字段:
  數據長度                         2字節     ~⑨9個字段的總長度
                                                            即不包括標記代碼,但包括本字段
  標識符                             5字節    固定值0x4A46494600,即字符串“JFIF0”
  
 版本號                             2字節    一般是0x0102,表示JFIF的版本號1.2
                                                            
可能會有其他數值代表其他版本
  XY的密度單位           1字節     只有三個值可選
                                                            0:無單位;1:點數/英寸;2:點數/厘米
  X方向像素密度               2字節     取值范圍未知
  Y方向像素密度               2字節     取值范圍未知   
  
 縮略圖水平像素數目        1字節     取值范圍未知
  縮略圖垂直像素數目        1字節     取值范圍未知
  縮略圖RGB位圖             長度可能是3的倍數           縮略圖RGB位圖數據

 

本標記段可以包含圖像的一個微縮版本,存為24位的RGB像素。如果沒有微縮圖像(這種情況更常見),則字段⑦“縮略圖水平像素數目”和字段⑧“縮略圖垂直像素數目”的值均為0。

 

APPnApplication,應用程序保留標記n,其中n=115(任選)

標記代碼                                 2字節     固定值0xFFE1~0xFFF

包含2個具體字段:
  數據長度                         2字節     ~②2個字段的總長度
                                                            即不包括標記代碼,但包括本字段
  詳細信息            數據長度-2字節   內容不定
                                                    

例如,Adobe Photoshop生成的JPEG圖像中就用了APP1APP13兩個標記段分別存儲了一幅圖像的副本。

 

DQTDefine Quantization Table,定義量化表

標記代碼                          2字節            固定值0xFFDB

包含9個具體字段:
  數據長度                  2字節            字段①和多個字段②的總長度
                                                            即不包括標記代碼,但包括本字段
  量化表        數據長度-2字節

a)精度及量化表ID   1字節            4位:精度,只有兩個可選值
                                                              08位;116
                                                4位:量化表ID,取值范圍為03

b)表項       (64×(精度+1))字節              例如8位精度的量化表
                                                其表項長度為64×0+1=64字節

 

本標記段中,字段②可以重復出現,表示多個量化表,但最多只能出現4次。

 

SOF0Start of Frame,幀圖像開始

標記代碼                   2字節     固定值0xFFC0

包含9個具體字段:
  數據長度           2字節     ~六個字段的總長度
                                              即不包括標記代碼,但包括本字段
  精度                 1字節     每個數據樣本的位數
                                              通常是8位,一般軟件都不支持 12位和16
  圖像高度           2字節     圖像高度(單位:像素),如果不支持 DNL 就必須 >0
  
 圖像寬度           2字節     圖像寬度(單位:像素),如果不支持 DNL 就必須 >0
  
 顏色分量數        1字節     只有3個數值可選
                                              1:灰度圖;3YCrCbYIQ4CMYK
                                              
JFIF中使用YCrCb,故這里顏色分量數恆為3
  
顏色分量信息      顏色分量數×3字節(通常為9字節)

a)顏色分量ID                 1字節    

b)水平/垂直采樣因子      1字節            4位:水平采樣因子
                                                       4位:垂直采樣因子
                                                       (曾經看到某資料把這兩者調轉了)

c) 量化表                         1字節            當前分量使用的量化表的ID

本標記段中,字段⑥應該重復出現,有多少個顏色分量(字段⑤),就出現多少次(一般為3次)。

 

DHTDifine Huffman Table,定義哈夫曼表

標記代碼                                 2字節            固定值0xFFC4

包含2個具體字段:
 數據長度                             2字節            字段①和多個字段②的總長度
                                                                   即不包括標記代碼,但包括本字段
  哈夫曼表              數據長度-2字節

a)ID和表類型            1字節            4位:類型,只有兩個值可選
                                                                     0DC直流;1AC交流
                                                        4位:哈夫曼表ID
                                                                     注意,DC表和AC表分開編碼

b)不同位數的碼字數量    16字節

c)編碼內容       16個不同位數的碼字數量之和(字節)

本標記段中,字段②可以重復出現(一般4次),也可以致出現1次。例如,Adobe Photoshop 生成的JPEG圖片文件中只有1個DHT標記段,里邊包含了4個哈夫曼表;而Macromedia Fireworks生成的JPEG圖片文件則有4個DHT標記段,每個DHT標記段只有一個哈夫曼表。

 

DRIDefine Restart Interval定義差分編碼累計復位的間隔

標記代碼                                 2字節     固定值0xFFDD

包含2個具體字段:
 數據長度                             2字節     固定值0x0004~兩個字段的總長度
                                                            即不包括標記代碼,但包括本字段
 MCU塊的單元中的重新開始間隔
                                              2字節     設其值為n,則表示每nMCU塊就有一個
                                                           RSTn標記。第一個標記是RST0,第二個是
                                                            RST1等,RST7后再從RST0重復。

 

如果沒有本標記段,或間隔值為0時,就表示不存在重開始間隔和標記RST

 

SOSStart of Scan,掃描開始 12字節

標記代碼                          2字節     固定值0xFFDA

包含2個具體字段:
 數據長度                      2字節     ~兩個字段的總長度
                                                     即不包括標記代碼,但包括本字段
 顏色分量數                 1字節     應該和SOF中的字段⑤的值相同,即:
                                                     1:灰度圖是;3 YCrCbYIQ4CMYK

                                                         JFIF中使用YCrCb,故這里顏色分量數恆為3
   
顏色分量信息
        a) 顏色分量ID           1字節
        b) 直流/交流系數表號 1字節     4位:直流分量使用的哈夫曼樹編號
                                                        4位:交流分量使用的哈夫曼樹編號

  壓縮圖像數據
        a)譜選擇開始                     1字節     固定值0x00
        b)譜選擇結束                     1字節     固定值0x3F
        c)譜選擇                            1字節     在基本JPEG中總為00

 

本標記段中,字段③應該重復出現,有多少個顏色分量(字段②),就出現多少次(一般為3次)。本段結束后,緊接着就是真正的圖像信息了。圖像信息直至遇到一個標記代碼就自動結束,一般就是以EOI標記表示結束。

 

EOIEnd of Image,圖像結束 2字節

標記代碼                   2字節     固定值0xFFD9

 

這里補充說明一下,由於在JPEG文件中0xFF具有標志性的意思,所以在壓縮數據流(真正的圖像信息)出現0xFF,就需要作特別處理。具體方法是,在數據0xFF后添加一個沒有意義的0x00。換句話說,如果在圖像數據流中遇到0xFF,應該檢測其緊接着的字符,如果是

10x00,則表示0xFF是圖像流的組成部分,需要進行譯碼;

20xD9,則與0xFF組成標記EOI,則圖像流結束,同時圖像文件結束;

30xD0~0xD7,則組成RSTn標記,則要忽視整個RSTn標記,即不對當前0xFF和緊接的0xDn兩個字節進行譯碼,並按RST標記的規則調整譯碼變量;

30xFF,則忽視當前0xFF,對后一個0xFF再作判斷;

4)其他數值,則忽視當前0xFF,並保留緊接的此數值用於譯碼。

 

為了造福大眾,我把自己定義的文件頭結構體給他家參考一下,歡迎討論~

 1 typedef struct APP0                            //應用程序保留標記0
 2 {
 3     //char    value[2];                        //標記代碼
 4     unsigned char    d_length[2];                    //數據長度
 5     unsigned char    symbol[5];                        //標識符
 6     unsigned char    version[2];                        //版本號
 7     unsigned char    density;                        //X和Y的密度單位
 8     unsigned char    x_density[2];                    //X方向像素密度
 9     unsigned char    y_density[2];                    //Y方向像素密度
10     unsigned char    x_num;                            //縮略圖水平像素數目
11     unsigned char    y_num;                            //縮略圖垂直像素數目
12     unsigned char*    RGB_bitmap;                        //縮略圖RGB位圖 
13 }APP0; APP0 app0;
14 
15 typedef struct APPn                            //應用程序保留標記n,其中n=1~15(任選)
16 {
17     //char    value[2];                                //標記代碼
18     unsigned char    d_length[2];                    //數據長度
19     unsigned char*    info;                            //詳細信息,數據長度-2字節
20 }APPn; APPn appn;
21 
22 typedef struct DQT                                    //定義量化表
23 {
24     //char    value[2];                                //標記代碼
25     unsigned char    d_length[2];                    //數據長度
26     unsigned char*    table;                            //量化表,數據長度-2字節
27                                                     //a.精度及量化表ID   1字節            
28                                                     //高4位:精度,只有兩個可選值,0:8位;1:16位
29                                                     //低4位:量化表ID,取值范圍為0~3
30                                                     //b.表項(64×(精度 + 1))字節
31                                                     //例如8位精度的量化表,其表項長度為64×(0 + 1) = 64字節
32 }DQT; DQT dqt;
33 
34 typedef struct SOF0                                    //幀圖像開始
35 {
36     //char    value[2];                                //標記代碼
37     unsigned char    d_length[2];                    //數據長度
38     unsigned char    accuracy;                        //精度
39     unsigned char    height[2];                        //圖像高度
40     unsigned char    width[2];                        //圖像寬度
41     unsigned char    color;                            //顏色分量數
42     unsigned char*    color_info;                        //顏色分量信息
43 }SOF0; SOF0 sof0;
44 
45 typedef struct DHT                                    //定義哈夫曼表
46 {
47     //char    value[2];                                //標記代碼
48     unsigned char    d_length[2];                    //數據長度
49     unsigned char*    H_table;                        //哈夫曼表,數據長度-2字節
50                                                     //a.表ID和表類型,1字節,
51                                                     //高4位:0:DC直流;1:AC交流
52                                                     //低4位:哈夫曼表ID,注意,DC表和AC表分開編碼
53                                                     //b.不同位數的碼字數量,16字節
54                                                     //c.編碼內容,16個不同位數的碼字數量之和(字節)
55 }DHT; DHT dht;
56 
57 typedef struct DRI                                    //定義差分編碼累計復位的間隔
58 {
59     //char    value[2];                                //標記代碼
60     unsigned char    d_length[2];                    //數據長度
61     unsigned char    interval[2];                    //MCU塊的單元中的重新開始間隔
62                                                     //設其值為n,則表示每n個MCU塊就有一個RSTn標記。
63 }DRI; DRI dri;
64 
65 typedef struct SOS                                    //掃描開始,12字節
66 {
67     //char    value[2];                                //標記代碼
68     unsigned char    d_length[2];                    //數據長度
69     unsigned char    color;                            //顏色分量數
70     unsigned char*    color_info;                        //顏色分量信息
71     unsigned char    image_data[3];                    //壓縮圖像數據
72 }SOS; SOS sos;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM