原文地址:http://blog.csdn.net/u012611878/article/details/52215985
圖片格式詳解
不知道大家有沒有注意過網頁里,手機里,平板里的圖片,事實上,圖片格式多樣,不同平台對不同格式的圖片支持也不一樣,所以需要根據不同場合,使用不同格式的圖片。
一.PNG格式
便攜式網絡圖形(Portable Network Graphics,PNG)是一種無損壓縮的位圖圖形格式,支持索引、灰度、RGB三種顏色方案以及Alpha通道等特性。
PNG格式有8位、24位、32位三種形式,其中8位PNG支持兩種不同的透明形式(索引透明和alpha透明),24位PNG不支持透明,32位PNG在24位基礎上增加了8位透明通道,因此可展現256級透明程度。
PNG8和PNG24后面的數字則是代表這種PNG格式最多可以索引和存儲的顏色值。”8″代表2的8次方也就是256色,而24則代表2的24次方大概有1600多萬色。
| 格式 | 最高支持色彩通道 | 索引色編輯支持 | 透明支持 |
|---|---|---|---|
| PNG8 | 256索引色 | 支持 | 支持設定特定索引色為透明色(布爾透明) 支持為索引色附加8位透明度(256階alpha透明) |
| PNG24 | 約1600萬色 | 不支持 | 不支持 |
| PNG32 | 約1600萬色 | 不支持 | 支持8位透明度(256階alpha透明) |
1.PNG的文件結構
對於一個PNG文件來說,其文件頭總是由位固定的字節來描述的:
| 進制 | 編碼 |
|---|---|
| 十六進制數 | 89 50 4E 47 0D 0A 1A 0A |
其中第一個字節0x89超出了ASCII字符的范圍,這是為了避免某些軟件將PNG文件當做文本文件來處理。文件中剩余的部分由3個以上的PNG的數據塊(Chunk)按照特定的順序組成,因此,一個標准的PNG文件結構應該如下:
PNG文件標志 | PNG數據塊 …… | PNG數據塊
2.PNG數據塊(Chunk)
PNG定義了兩種類型的數據塊,一種是稱為關鍵數據塊(critical chunk),這是標准的數據塊,另一種叫做輔助數據塊(ancillary chunks),這是可選的數據塊。關鍵數據塊定義了4個標准數據塊,每個PNG文件都必須包含它們,PNG讀寫軟件也都必須要支持這些數據塊。雖然PNG文件規范沒有要求PNG編譯碼器對可選數據塊進行編碼和譯碼,但規范提倡支持可選數據塊。
下表就是PNG中數據塊的類別,其中,關鍵數據塊部分我們使用_前綴加以區分。
| 數據塊符號 | 數據塊名稱 | 多數據塊 | 可選否 | 位置限制 |
|---|---|---|---|---|
| _IHDR | 文件頭數據塊 | 否 | 否 | 第一塊 |
| cHRM | 基色和白色點數據塊 | 否 | 是 | 在PLTE和IDAT之前 |
| gAMA | 圖像γ數據塊 | 否 | 是 | 在PLTE和IDAT之前 |
| sBIT | 樣本有效位數據塊 | 否 | 是 | 在PLTE和IDAT之前 |
| _PLTE | 調色板數據塊 | 否 | 是 | 在IDAT之前 |
| bKGD | 背景顏色數據塊 | 否 | 是 | 在PLTE之后IDAT之前 |
| hIST | 圖像直方圖數據塊 | 否 | 是 | 在PLTE之后IDAT之前 |
| tRNS | 圖像透明數據塊 | 否 | 是 | 在PLTE之后IDAT之前 |
| oFFs | (專用公共數據塊) | 否 | 是 | 在IDAT之前 |
| pHYs | 物理像素尺寸數據塊 | 否 | 是 | 在IDAT之前 |
| sCAL | (專用公共數據塊) | 否 | 是 | 在IDAT之前 |
| _IDAT | 圖像數據塊 | 是 | 否 | 與其他IDAT連續 |
| tIME | 圖像最后修改時間數據塊 | 否 | 是 | 無限制 |
| tEXt | 文本信息數據塊 | 是 | 是 | 無限制 |
| zTXt | 壓縮文本數據塊 | 是 | 是 | 無限制 |
| fRAc | (專用公共數據塊) | 是 | 是 | 無限制 |
| gIFg | (專用公共數據塊) | 是 | 是 | 無限制 |
| gIFt | (專用公共數據塊) | 是 | 是 | 無限制 |
| gIFx | (專用公共數據塊) | 是 | 是 | 無限制 |
| _IEND | 圖像結束數據 | 否 | 否 | 最后一個數據塊 |
為了簡單起見,我們假設在我們使用的PNG文件中,這4個數據塊按以上先后順序進行存儲,並且都只出現一次。
(1)IHDR
文件頭數據塊IHDR(header chunk):它包含有PNG文件中存儲的圖像數據的基本信息,並要作為第一個數據塊出現在PNG數據流中,而且一個PNG數據流中只能有一個文件頭數據塊。
文件頭數據塊由13字節組成,它的格式如下表所示。
| 域的名稱 | 字節數 | 說明 |
|---|---|---|
| Width | 4 bytes | 圖像寬度,以像素為單位 |
| Height | 4 bytes | 圖像寬度,以像素為單位 |
| Bit depth | 1 bytes | 顏色類型:: 0:灰度圖像, 1,2,4,8或16 2:真彩色圖像,8或16 3:索引彩色圖像,1,2,4或8 4:帶α通道數據的灰度圖像,8或16 6:帶α通道數據的真彩色圖像,8或16 |
| ColorType | 1 bytes | 圖像深度: 索引彩色圖像:1,2,4或8 灰度圖像:1,2,4,8或16 真彩色圖像:8或16 |
| Compression method | 1 bytes | 壓縮方法(LZ77派生算法) |
| Filter method | 1 bytes | 濾波器方法 |
| Interlace method | 1 bytes | 隔行掃描方法: 0:非隔行掃描 1:Adam7(由Adam M. Costello開發的7遍隔行掃描方法) |
(2)PLTE
對於索引圖像,調色板信息是必須的,調色板的顏色索引從0開始編號,然后是1、2……,調色板的顏色數不能超過色深中規定的顏色數(如圖像色深為4的時候,調色板中的顏色數不可以超過2^4=16),否則,這將導致PNG圖像不合法。
真彩色圖像和帶α通道數據的真彩色圖像也可以有調色板數據塊,目的是便於非真彩色顯示程序用它來量化圖像數據,從而顯示該圖像。
PLTE數據塊是定義圖像的調色板信息,PLTE可以包含1~256個調色板信息,每一個調色板信息由3個字節組成:
| 顏色 | 字節 | 說明 |
|---|---|---|
| Red | 1byte | 0 = 黑色, 255 = 紅 |
| Green | 1byte | 0 = 黑色, 255 = 綠 |
| Blue | 1byte | 0 = 黑色, 255 = 藍 |
(3)IDAT
圖像數據塊IDAT(image data chunk):它存儲實際的數據,在數據流中可包含多個連續順序的圖像數據塊。
IDAT存放着圖像真正的數據信息,因此,如果能夠了解IDAT的結構,我們就可以很方便的生成PNG圖像。
(4)IEND
圖像結束數據IEND(image trailer chunk):它用來標記PNG文件或者數據流已經結束,並且必須要放在文件的尾部。
如果我們仔細觀察PNG文件,我們會發現,文件的結尾12個字符看起來總應該是這樣的:
00 00 00 00 49 45 4E 44 AE 42 60 82
不難明白,由於數據塊結構的定義,IEND數據塊的長度總是0(00 00 00 00,除非人為加入信息),數據標識總是IEND(49 45 4E 44),因此,CRC碼也總是AE 42 60 82
3.數據塊結構
PNG文件中,每個數據塊由4個部分組成,如下:
| 名稱 | 字節數 | 說明 |
|---|---|---|
| Length (長度) | 4字節 | 指定數據塊中數據域的長度,其長度不超過(231-1)字節 |
| Chunk Type Code (數據塊類型碼) | 4字節 | 數據塊類型碼由ASCII字母(A-Z和a-z)組成 |
| Chunk Data (數據塊數據) | 可變長度 | 存儲按照Chunk Type Code指定的數據 |
| CRC (循環冗余檢測) | 4字節 | 存儲用來檢測是否有錯誤的循環冗余碼 |
CRC(cyclic redundancy check)域中的值是對Chunk Type Code域和Chunk Data域中的數據進行計算得到的。CRC具體算法定義在ISO 3309和ITU-T V.42中,其值按下面的CRC碼生成多項式進行計算:
x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
二.JPEG格式
其實JPEG 和JPG沒有區別,JPG的全名、正式擴展名是JPEG。但因DOS、Windows 95等早期系統采用的8.3命名規則只支持最長3字符的擴展名,為了兼容采用了.jpg。也因歷史習慣和兼容性考慮,.jpg目前更流行。
總的來說:JPEG是文件格式,JPG是擴展名。
JPG即使用JPEG文件交換格式存儲的編碼圖像文件擴展名。 JPEG聯合圖象專家組,是一種壓縮標准。兩種文件應該沒有區別,如果做文件擴展名嚴格地說應是JPG。
JPEG是一個壓縮標准,又可分為標准 JPEG、漸進式JPEG及JPEG2000三種:
①標准JPEG:以24位顏色存儲單個光柵圖像,是與平台無關的格式,支持最高級別的壓縮,不過,這種壓縮是有損耗的。此類型圖片在網頁下載時只能由上而下依序顯示圖片,直到圖片資料全部下載完畢,才能看到全貌。
②漸進式 JPEG:漸進式JPG為標准JPG的改良格式,支持交錯,可以在網頁下載時,先呈現出圖片的粗略外觀后,再慢慢地呈現出完整的內容,漸進式JPG的文件 比標准JPG的文件要來得小。
③JPEG2000:新一代的影像壓縮法,壓縮品質更好,其壓縮率比標准JPEG高約30%左右,同時支持有損 和無損壓縮。一個極其重要的特征在於它能實現漸進傳輸,即先傳輸圖像的輪廓,然后逐步傳輸數據,讓圖像由朦朧到清晰顯示。
JPEG(Joint Photographic Experts Group)是聯合圖像專家小組的英文縮寫。它由國際電話與電報咨詢委員會CCITT(The International Telegraph and Telephone Consultative Committee)與國際標准化組織ISO於1986年聯合成立的一個小組,負責制定靜態數字圖像的編碼標准。
JPEG專家組開發了兩種基本的壓縮算法、兩種數據編碼方法、四種編碼模式。具體如下:
壓縮算法:
(1)有損的離散余弦變換(Discrete Cosine Transform,DCT);
(2)無損的預測技術壓縮。
數據編碼方法:
(1)哈夫曼編碼;
(2)算術編碼;
編碼模式:
(1)基於DCT順序模式:編/解碼通過一次掃描完成
(2)基於DCT遞進模式:編/解碼需要多次掃描完成,掃描效果從粗糙到精細,逐級遞進
(3)無損模式:基於DPCM,保證解碼后完全精確恢復到原圖像采樣值
(4)層次模式:圖像在多個空間多種分辨率進行編碼,可以根據需要只對低分辨率數據作解碼,放棄高分辨率信息
1.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標記。
下面附錄列出完整的JPEG定義的標記碼表:
(1)SOI,Start of Image,圖像開始
標記代碼|2字節|固定值0xFFD8
(2)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。
(3)APPn,Application,應用程序保留標記n,其中n=1~15(任選)
標記代碼|2字節|固定值0xFFE1~0xFFF
包含2個具體字段:
① 數據長度|2字節|①~②2個字段的總長度,即不包括標記代碼,但包括本字段
② 詳細信息|數據長度-2字節|內容不定
(4)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次。
(5)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次)。
(6)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標記段只有一個哈夫曼表。
(7)DRI,Define Restart Interval,定義差分編碼累計復位的間隔
標記代碼|2字節|固定值0xFFDD
包含2個具體字段:
①數據長度|2字節|固定值0x0004,①~②兩個字段的總長度, 即不包括標記代碼,但包括本字段
②MCU塊的單元中的重新開始間隔|2字節|設其值為n,則表示每n個MCU塊就有一個,RSTn標記。第一個標記是RST0,第二個是RST1等,RST7后再從RST0重復。
如果沒有本標記段,或間隔值為0時,就表示不存在重開始間隔和標記RST
(8)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標記表示結束。
(9)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,並保留緊接的此數值用於譯碼。
2.JPEG圖像編碼
在實際應用中,JPEG圖像編碼算法使用的大多是離散余弦變換、Huffman編碼、順序編碼模式。這樣的方式,被人們稱為JPEG的基本系統。這里介紹的JPEG編碼算法的流程,也是針對基本系統而言。基本系統的JPEG壓縮編碼算法一共分為11個步驟:顏色模式轉換、采樣、分塊、離散余弦變換(DCT)、Zigzag 掃描排序、量化、DC系數的差分脈沖調制編碼、DC系數的中間格式計算、AC系數的游程長度編碼、AC系數的中間格式計算、熵編碼。
(1)顏色模式轉換
JPEG采用的是YCrCb顏色空間,而BMP采用的是RGB顏色空間,要想對BMP圖片進行壓縮,首先需要進行顏色空間的轉換。YCrCb顏色空間中,Y代表亮度,Cr,Cb則代表色度和飽和度(也有人將Cb,Cr兩者統稱為色度),三者通常以Y,U,V來表示,即用U代表Cb,用V代表Cr。RGB和YCrCb之間的轉換關系如下所示:
Y = 0.299R+0.587G+0.114B
Cb = -0.1687R-0.3313G+0.5B+128
Cr = 0.5R=0.418G-0.0813B+128
一般來說,C 值 (包括 Cb Cr) 應該是一個有符號的數字, 但這里通過加上128,使其變為8位的無符號整數,從而方便數據的存儲和計算。反之:
R = Y+1.402(Cr-128)
G = Y-0.34414(Cb-128)-0.71414(Cr-128)
B = Y+1.772(Cb-128)
(2)采樣
研究發現,人眼對亮度變換的敏感度要比對色彩變換的敏感度高出很多。因此,我們可以認為Y分量要比Cb,Cr分量重要的多。在BMP圖片中,RGB三個分量各采用一個字節進行采樣,也就是我們常聽到的RGB888的模式;而JPEG圖片中,通常采用兩種采樣方式:YUV411和YUV422,它們所代表的意義是Y,Cb,Cr三個分量的數據取樣比例一般是4:1:1或者4:2:2(4:1:1含義就是:在2x2的單元中,本應分別有4個Y,4個U,4個V值,用12個字節進行存儲。經過4:1:1采樣處理后,每個單元中的值分別有4個Y、1個U、1個V,只要用6個字節就可以存儲了)。這樣的采樣方式,雖然損失了一定的精度但也在人眼不太察覺到的范圍內減小了數據的存儲量。當然,JPEG格式里面也允許將每個點的U,V值都記錄下來。
(3)分塊
由於后面的DCT變換是是對8x8的子塊進行處理的,因此,在進行DCT變換之前必須把源圖象數據進行分塊。源圖象中每點的3個分量是交替出現的,先要把這3個分量分開,存放到3張表中去。然后由左及右,由上到下依次讀取8x8的子塊,存放在長度為64的表中,即可以進行DCT變換。注意,編碼時,程序從源數據中讀取一個8x8的數據塊后,進行DCT變換,量化,編碼,然后再讀取、處理下一個8*8的數據塊。
JPEG 編碼是以每8x8個點為一個單位進行處理的. 所以如果原始圖片的長寬不是 8 的倍數, 都需要先補成8的倍數, 使其可以進行一塊塊的處理。將原始圖像數據分為8*8的數據單元矩陣之后,還必須將每個數值減去128,然后一一帶入DCT變換公式,即可達到DCT變換的目的。圖像的數據值必須減去128,是因為DCT公式所接受的數字范圍是-128到127之間。
(4)離散余弦變換
DCT(Discrete Cosine Transform,離散余弦變換),是碼率壓縮中常用的一種變換編碼方法。任何連續的實對稱函數的傅里葉變換中只含有余弦項,因此,余弦變換同傅里葉變換一樣具有明確的物理意義。DCT是先將整體圖像分成N*N的像素塊,然后針對N*N的像素塊逐一進行DCT操作。需要提醒的是,JPEG的編碼過程需要進行正向離散余弦變換,而解碼過程則需要反向離散余弦變換。
正向離散余弦變換計算公式:
F(u,v)=c(u)c(v)∑N−1i=0∑N−1j=0f(i,j)cos[(2i+1)π2Nu]cos[(2j+1)π2Nv]
c(u)=1N−−√,當u=0
c(u)=2N−−√,當u≠0
反向離散余弦變換計算公式:
f(i,j)=∑N−1u=0∑N−1v=0c(u)c(v)F(u,v)cos[(2i+1)π2Nu]cos[(2j+1)π2Nv]
c(u)=1N−−√,當u=0
c(u)=2N−−√,當u≠0
這里的N是水平、垂直方向的像素數目,一般取值為8。8 * 8的二維像素塊經過DCT操作之后,就得到了8 * 8的變換系數矩陣。這些系數,都有具體的物理含義,例如,U=0,V=0時的F(0,0)是原來的64個數據的均值,相當於直流分量,也有人稱之為DC系數或者直流系數。隨着U,V的增加,相另外的63個系數則代表了水平空間頻率和垂直空間頻率分量(高頻分量)的大小,多半是一些接近於0的正負浮點數,我們稱之為交流系數AC。DCT變換后的8*8的系數矩陣中,低頻分量集中在矩陣的左上角。高頻成分則集中在右下角。
由於大多數圖像的高頻分量比較小,相應的圖像高頻分量的DCT系數經常接近於0,再加上高頻分量中只包含了圖像的細微的細節變化信息,而人眼對這種高頻成分的失真不太敏感,所以,可以考慮將這一些高頻成分予以拋棄,從而降低需要傳輸的數據量。這樣一來,傳送DCT變換系數的所需要的編碼長度要遠遠小於傳送圖像像素的編碼長度。到達接收端之后通過反離散余弦變換就可以得到原來的數據,雖然這么做存在一定的失真,但人眼是可接受的,而且對這種微小的變換是不敏感的。
(5)Zigzag掃描排序
DCT 將一個 8x8 的數組變換成另一個 8x8 的數組. 但是內存里所有數據都是線形存放的, 如果我們一行行的存放這 64 個數字, 每行的結尾的點和下行開始的點就沒有什么關系, 所以 JPEG 規定按如下圖中的數字順序依次保存和讀取64 個DCT的系數值。

這樣數列里的相鄰點在圖片上也是相鄰的了。不難發現,這種數據的掃描、保存、讀取方式,是從8*8矩陣的左上角開始,按照英文字母Z的形狀進行掃描的,一般將其稱之為Zigzag掃描排序。如下圖所示:

(6)量化
圖像數據轉換為DCT頻率系數之后,還要進行量化階段,才能進入編碼過程。量化階段需要兩個8*8量化矩陣數據,一個是專門處理亮度的頻率系數,另一個則是針對色度的頻率系數,將頻率系數除以量化矩陣的值之后取整,即完成了量化過程。當頻率系數經過量化之后,將頻率系數由浮點數轉變為整數,這才便於執行最后的編碼。不難發現,經過量化階段之后,所有的數據只保留了整數近似值,也就再度損失了一些數據內容。在JPEG算法中,由於對亮度和色度的精度要求不同,分別對亮度和色度采用不同的量化表。前者細量化,后者粗量化。
下圖給出JPEG的亮度量化表和色度量化表,該量化表是從廣泛的實驗中得出的。當然,你也可以自定義量化表。
JPEG亮度量化表
JPEG色度量化表
這兩張表依據心理視覺閥制作, 對 8bit 的亮度和色度的圖象的處理效果不錯。量化表是控制 JPEG 壓縮比的關鍵,這個步驟除掉了一些高頻量, 損失了很多細節信息。但事實上人眼對高頻信號的敏感度遠沒有低頻信號那么敏感。所以處理后的視覺損失很小,從上面的量化表也可以看出,低頻部分采用了相對較短的量化步長,而高頻部分則采用了相對較長的量化步長,這樣做,也是為了在一定程度上得到相對清晰的圖像和更高的壓縮率。另一個重要原因是所有的圖片的點與點之間會有一個色彩過渡的過程,而大量的圖象信息被包含在低頻率空間中,經過DCT處理后, 在高頻率部分, 將出現大量連續的零。
(7)DC系數的差分脈沖調制編碼
8*8的圖像塊經過DCT變換之后得到的DC系數有兩個特點:
(1)系數的數值比較大;
(2)相鄰的8*8圖像塊的DC系數值變化不大;
根據這兩個特點,DC系數一般采用差分脈沖調制編碼DPCM(Difference Pulse Code Modulation),即:取同一個圖像分量中每個DC值與前一個DC值的差值來進行編碼。對差值進行編碼所需要的位數會比對原值進行編碼所需要的位數少了很多。假設某一個8*8圖像塊的DC系數值為15,而上一個8*8圖像塊的DC系數為12,則兩者之間的差值為3。
(8)DC系數的中間格式計算
JPEG中為了更進一步節約空間,並不直接保存數據的具體數值,而是將數據按照位數分為16組,保存在表里面。這也就是所謂的變長整數編碼VLI。即,第0組中保存的編碼位數為0,其編碼所代表的數字為0;第1組中保存的編碼位數為1,編碼所代表的數字為-1或者1……,如下面的表格所示,這里,暫且稱其為VLI編碼表:

前面提到的那個DC差值為3的數據,通過查找VLI可以發現,整數3位於VLI表格的第2組,因此,可以寫成(2)(3)的形式,該形式,稱之為DC系數的中間格式。
(9)AC系數的行程長度編碼(RLC)
量化之后的AC系數的特點是,63個系數中含有很多值為0的系數。因此,可以采用行程編碼RLC(Run Length Coding)來更進一步降低數據的傳輸量。利用該編碼方式,可以將一個字符串中重復出現的連續字符用兩個字節來代替,其中,第一個字節代表重復的次數,第二個字節代表被重復的字符串。例如,(4,6)就代表字符串“6666”。但是,在JPEG編碼中,RLC的含義就同其原有的意義略有不同。在JPEG編碼中,假設RLC編碼之后得到了一個(M,N)的數據對,其中M是兩個非零AC系數之間連續的0的個數(即,行程長度),N是下一個非零的AC系數的值。采用這樣的方式進行表示,是因為AC系數當中有大量的0,而采用Zigzag掃描也會使得AC系數中有很多連續的0的存在,如此一來,便非常適合於用RLC進行編碼。
例如,現有一個字符串,如下所示:
57,45,0,0,0,0,23,0,-30,-8,0,0,1,000…..
經過RLC之后,將呈現出以下的形式:
(0,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-8) ; (2,1) ; (0,0)
注意,如果AC系數之間連續0的個數超過16,則用一個擴展字節(15,0)來表示16連續的0。
(10)AC系數的中間格式
根據前面提到的VLI表格,對於前面的字符串:
(0,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-8) ; (2,1) ; (0,0)
只處理每對數右邊的那個數據,對其進行VLI編碼: 查找上面的VLI編碼表格,可以發現,57在第6組當中,因此,可以將其寫成(0,6),57的形式,該形式,稱之為AC系數的中間格式。
同樣的(0,45)的中間格式為:(0,6),45;
(1,-30)的中間格式為:(1,5),-30;
(11)熵編碼
在得到DC系數的中間格式和AC系數的中間格式之后,為進一步壓縮圖象數據,有必要對兩者進行熵編碼。JPEG標准具體規定了兩種熵編碼方式:Huffman編碼和算術編碼。JPEG基本系統規定采用Huffman編碼(因為不存在專利問題),但JPEG標准並沒有限制JPEG算法必須用Huffman編碼方式或者算術編碼方式。
Huffman編碼:對出現概率大的字符分配字符長度較短的二進制編碼,對出現概率小的字符分配字符長度較長的二進制編碼,從而使得字符的平均編碼長度最短。Huffman編碼的原理請參考數據結構中的Huffman樹或者最優二叉樹。
Huffman編碼時DC系數與AC系數分別采用不同的Huffman編碼表,對於亮度和色度也采用不同的Huffman編碼表。因此,需要4張Huffman編碼表才能完成熵編碼的工作。具體的Huffman編碼采用查表的方式來高效地完成。然而,在JPEG標准中沒有定義缺省的Huffman表,用戶可以根據實際應用自由選擇,也可以使用JPEG標准推薦的Huffman表。或者預先定義一個通用的Huffman表,也可以針對一副特定的圖像,在壓縮編碼前通過搜集其統計特征來計算Huffman表的值。
下面我們舉例來說明8*8圖像子塊經過DCT及量化之后的處理過程:
假設一個圖像塊經過量化以后得到以下的系數矩陣:
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系數為15,假設前一個8*8的圖像塊的DC系數量化值為12,則當前DC系統同上一個DC系數之間的差值為3,通過查找VLI編碼表,可以得到DC系數的中間格式為(2)(3),這里的2代表后面的數字(3)的編碼長度為2位;之后,通過Zigzag掃描之后,遇到第一個非0的AC系數為-2,遇到0的個數為1,AC系數經過RLC編碼后可表示為(1,-2),通過查找VLI表發現,-2在第2組,因此,該AC系數的中間格式為(1,2)-2;
其余的點類似,可以求得這個8*8子塊熵編碼的中間格式為
(DC)(2)(3);AC(1,2)(-2),(0,1)(-1),(0,1)(-1),(0,1)(-1),(2,1)(-1),(EOB)(0,0)
對於DC系數的中間格式(2)(3)而言,數字2查DC亮度Huffman表得到011,數字3通過查找VLI編碼表得到其被編碼為11;
對於AC系數的中間格式(1,2)(-2)而言,(1,2)查AC亮度Huffman表得到11011,-2通過查找VLI編碼表得到其被編碼為01;
對於AC系數的中間格式(0,1)(-1)而言,(0,1)查AC亮度Huffman表得到00,數字-1通過查找VLI編碼表得到其被編碼為0;
對於AC系數的中間格式(2,1)(1)而言,(2,1)查AC亮度Huffman表得到11100,數字-1通過查找VLI編碼表得到其被編碼為0;
對於AC系數的中間格式(0,0)而言,查AC亮度Huffman表得到1010;
因此,最后這個8 * 8子塊亮度信息壓縮后的數據流為01111,1101101,000,000,000,111000,1010。總共31比特,其壓縮比是64 * 8/31=16.5,大約每個像素用半個比特。
JPEG解碼過程在此不再贅述,與編碼過程對稱。
三.BMP格式
BMP(Bitmap-File)圖形文件是Windows采用的圖形文件格式,在Windows環境下運行的所有圖象處理軟件都支持BMP圖象文件格式。Windows系統內部各圖像繪制操作都是以BMP為基礎的。Windows 3.0以前的BMP圖文件格式與顯示設備有關,因此把這種BMP圖象文件格式稱為設備相關位圖DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP圖象文件與顯示設備無關,因此把這種BMP圖象文件格式稱為設備無關位圖DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系統中仍然存在DDB位圖,象BitBlt()這種函數就是基於DDB位圖的,只不過如果你想將圖像以BMP格式保存到磁盤文件中時,微軟極力推薦你以DIB格式保存),目的是為了讓Windows能夠在任何類型的顯示設備上顯示所存儲的圖象。BMP位圖文件默認的文件擴展名是BMP或者bmp(有時它也會以.DIB或.RLE作擴展名)。
1.BMP格式結構
BMP文件的數據按照從文件頭開始的先后順序分為四個部分:
(1)位圖文件頭(bmp file header): 提供文件的格式、大小等信息
(2)位圖信息頭(bitmap information):提供圖像數據的尺寸、位平面數、壓縮方式、顏色索引等信息
(3)調色板(color palette):可選,如使用索引來表示圖像,調色板就是索引與其對應的顏色的映射表
(4)位圖數據(bitmap data):圖像數據區
| 數據段名稱 | 大小(byte) | 開始地址 | 結束地址 |
|---|---|---|---|
| 位圖文件頭(bitmap-file header) | 14 | 0000h | 000Dh |
| 位圖信息頭(bitmap-information header) | 40 | 000Eh | 0035h |
| 調色板(color table) | 由biBitCount決定 | 0036h | 未知 |
| 圖片點陣數據(bitmap data) | 由圖片大小和顏色定 | 未知 | 未知 |
2.BMP文件頭
BMP文件頭結構體定義如下:
typedef struct tagBITMAPFILEHEADER { UINT16 bfType; //2Bytes,必須為"BM",即0x424D 才是Windows位圖文件 DWORD bfSize; //4Bytes,整個BMP文件的大小 UINT16 bfReserved1; //2Bytes,保留,為0 UINT16 bfReserved2; //2Bytes,保留,為0 DWORD bfOffBits; //4Bytes,文件起始位置到圖像像素數據的字節偏移量 } BITMAPFILEHEADER;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
| 變量名 | 地址偏移 | 大小 | 作用說明 |
|---|---|---|---|
| bfType | 0000h | 2Bytes | 文件標識符,必須為”BM”,即0x424D才是Windows位圖文件 |
| bfSize | 0002h | 4Bytes | 整個BMP文件的大小(以位B為單位) |
| bfReserved1 | 0006h | 2Bytes | 保留,必須設置為0 |
| bfReserved2 | 0008h | 2Bytes | 保留,必須設置為0 |
| bfOffBits | 000Ah | 4Bytes | 說明從文件頭0000h開始到圖像像素數據的字節偏移量(以字節Bytes為單位),以為位圖的調色板長度根據位圖格式不同而變化,可以用這個偏移量快速從文件中讀取圖像數據 |
3.BMP信息頭
BMP信息頭結構體定義如下:
typedef struct _tagBMP_INFOHEADER { DWORD biSize; //4Bytes,INFOHEADER結構體大小,存在其他版本I NFOHEADER,用作區分 LONG biWidth; //4Bytes,圖像寬度(以像素為單位) LONG biHeight; //4Bytes,圖像高度,+:圖像存儲順序為Bottom2Top,-:Top2Bottom WORD biPlanes; //2Bytes,圖像數據平面,BMP存儲RGB數據,因此總為1 WORD biBitCount; //2Bytes,圖像像素位數 DWORD biCompression; //4Bytes,0:不壓縮,1:RLE8,2:RLE4 DWORD biSizeImage; //4Bytes,4字節對齊的圖像數據大小 LONG biXPelsPerMeter; //4 Bytes,用象素/米表示的水平分辨率 LONG biYPelsPerMeter; //4 Bytes,用象素/米表示的垂直分辨率 DWORD biClrUsed; //4 Bytes,實際使用的調色板索引數,0:使用所有的調色板索引 DWORD biClrImportant; //4 Bytes,重要的調色板索引數,0:所有的調色板索引都重要 }BMP_INFOHEADER;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
BMP信息頭數據表如下:
| 變量名 | 地址偏移 | 大小 | 作用說明 |
|---|---|---|---|
| biSize | 000Eh | 4Bytes | BNP信息頭即BMP_INFOHEADER結構體所需要的字節數(以字節為單位) |
| biWidth | 0012h | 4Bytes | 說明圖像的寬度(以像素為單位) |
| biHeight | 0016h | 4Bytes | 說明圖像的高度(以像素為單位)。這個值還有一個用處,指明圖像是正向的位圖還是倒向的位圖,該值是正數說明圖像是倒向的即圖像存儲是由下到上;該值是負數說明圖像是倒向的即圖像存儲是由上到下。大多數BMP位圖是倒向的位圖,所以此值是正值。 |
| biPlanes | 001Ah | 2Bytes | 為目標設備說明位面數,其值總設置為1 |
| biBitCount | 001Ch | 2Bytes | 說明一個像素點占幾位(以比特位/像素位單位),其值可為1,4,8,16,24或32 |
| biCompression | 001Eh | 4Bytes | 說明圖像數據的壓縮類型,取值范圍為: 0 BI_RGB 不壓縮(最常用) 1 BI_RLE8 8比特游程編碼(BLE),只用於8位位圖 2 BI_RLE4 4比特游程編碼(BLE),只用於4位位圖 3 BI_BITFIELDS比特域(BLE),只用於16/32位位圖 |
| biSizeImage | 0022h | 4Bytes | 說明圖像的大小,以字節為單位。當用BI_RGB格式時,總設置為0 |
| biXPelsPerMeter | 0026h | 4Bytes | 說明水平分辨率,用像素/米表示,有符號整數 |
| biYPelsPerMeter | 002Ah | 4Bytes | 說明垂直分辨率,用像素/米表示,有符號整數 |
| biClrUsed | 002Eh | 4Bytes | 說明位圖實際使用的調色板索引數,0:使用所有的調色板索引 |
| biClrImportant | 0032h | 4Bytes | 說明對圖像顯示有重要影響的顏色索引的數目,如果是0,表示都重要。 |
4.BMP調色板
BMP調色板結構體定義如下:
typedef struct _tagRGBQUAD { BYTE rgbBlue; //指定藍色強度 BYTE rgbGreen; //指定綠色強度 BYTE rgbRed; //指定紅色強度 BYTE rgbReserved; //保留,設置為0 } RGBQUAD;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
1,4,8位圖像才會使用調色板數據,16,24,32位圖像不需要調色板數據,即調色板最多只需要256項(索引0 - 255)。
顏色表的大小根據所使用的顏色模式而定:2色圖像為8字節;16色圖像位64字節;256色圖像為1024字節。其中,每4字節表示一種顏色,並以B(藍色)、G(綠色)、R(紅色)、alpha(32位位圖的透明度值,一般不需要)。即首先4字節表示顏色號1的顏色,接下來表示顏色號2的顏色,依此類推。
顏色表中RGBQUAD結構數據的個數有biBitCount來確定,當biBitCount=1,4,8時,分別有2,16,256個表項。
當biBitCount=1時,為2色圖像,BMP位圖中有2個數據結構RGBQUAD,一個調色板占用4字節數據,所以2色圖像的調色板長度為2*4為8字節。
當biBitCount=4時,為16色圖像,BMP位圖中有16個數據結構RGBQUAD,一個調色板占用4字節數據,所以16像的調色板長度為16*4為64字節。
當biBitCount=8時,為256色圖像,BMP位圖中有256個數據結構RGBQUAD,一個調色板占用4字節數據,所以256色圖像的調色板長度為256*4為1024字節。
當biBitCount=16,24或32時,沒有顏色表。
5.BMP圖像數據區
位圖數據記錄了位圖的每一個像素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。位圖的一個像素值所占的字節數:
當biBitCount=1時,8個像素占1個字節;
當biBitCount=4時,2個像素占1個字節;
當biBitCount=8時,1個像素占1個字節;
當biBitCount=24時,1個像素占3個字節;
Windows規定一個掃描行所占的字節數必須是4的倍數(即以long為單位),不足的以0填充,
一個掃描行所占的字節數計算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一個掃描行所占的字節數
DataSizePerLine= DataSizePerLine/4*4; // 字節數必須是4的倍數
位圖數據的大小(不壓縮情況下):
DataSize= DataSizePerLine* biHeight;
顏色表接下來位為位圖文件的圖像數據區,在此部分記錄着每點像素對應的顏色號,其記錄方式也隨顏色模式而定,既2色圖像每點占1位(8位為1字節);16色圖像每點占4位(半字節);256色圖像每點占8位(1字節);真彩色圖像每點占24位(3字節)。所以,整個數據區的大小也會隨之變化。究其規律而言,可的出如下計算公式:圖像數據信息大小=(圖像寬度圖像高度記錄像素的位數)/8。
四.JIF格式
GIF是圖像交換格式(Graphics Interchange Format)的簡稱,它是由美國CompuServe公司在1987年所提出的圖像文件格式,它最初的目的是希望每個BBS的使用者能夠通過GIF圖像 文件輕易存儲並交換圖像數據,這也就是它為什么被稱為圖像交換格式的原因了。
GIF文件格式采用了一種經過改進的LZW壓縮算法,通常我們稱 之為GIF-LZW算法。這是一種無損的壓縮算法,壓縮效率也比較高,並且GIF支持在一幅GIF文件中存放多幅彩色圖像,並且可以按照一定的順序和時間 間隔將多幅圖像依次讀出並顯示在屏幕上,這樣就可以形成一種簡單的動畫效果。盡管GIF最多只支持256色,但是由於它具有極佳的壓縮效率並且可以做成動 畫而早已被廣泛接納采用。下面筆者詳細介紹GIF文件的格式。
GIF圖像文件是以塊的形式來存儲圖像信息,其中的塊又稱為區域結構。按照其中 塊的特征又可以將所有的塊分成三大類,分別是控制塊(Control Block)、圖像描述塊(Graphic Rendering Block)和特殊用途塊(Special Purpose Block)。控制塊包含了控制數據流的處理以及硬件參數的設置,其成員主要包括文件頭信息、邏輯屏幕描述塊、圖像控制擴充塊和文件結尾塊。圖像描述塊包 含了在顯示設備上描述圖像所需的信息,其成員包括圖像描述塊、全局調色板、局部調色板、圖像壓縮數據和圖像說明擴充塊。特殊用途塊包含了與圖像數據處理無直接關系的信息,其成員包括圖像注釋擴充塊和應用程序擴充塊。下面詳細介紹每一個塊的詳細結構。
1. 文件頭信息
GIF的文件頭只有六個字節,其結構定義如下:
typedef struct gifheader { BYTE bySignature[3]; BYTE byVersion[3]; } GIFHEADER;
- 1
- 2
- 3
- 4
- 5
其中,bySignature為GIF文件標示碼,其固定值為“GIF”,使用者可以通過該域來判斷一個圖像文件是否是GIF圖像格式的文件。 byVersion表明GIF文件的版本信息。其取值固定為“87a”和“89a”。分別表示GIF文件的版本為GIF87a或GIF89a。這兩個版本 有一些不同,GIF87a公布的時間為1987年,該版本不支持動畫和一些擴展屬性。GIF89a是1989年確定的一個版本標准,只有89a版本才支持 動畫、注釋擴展和文本擴展。
2. 邏輯屏幕描述塊
邏輯屏幕(Logical Screen)是一個虛擬屏幕(Virtual Screen),它相當於畫布,所有的操作都是在它的基礎上進行的,同時它也決定了圖像的長度和寬度。邏輯屏幕描述塊共占有七個字節,其具體結構定義如下:
typedef struct gifscrdesc
{
WORD wWidth;
WORD wDepth;
struct globalflag
{
BYTE PalBits : 3; BYTE SortFlag : 1; BYTE ColorRes : 3; BYTE GlobalPal : 1; } GlobalFlag; BYTE byBackground; BYTE byAspect; } GIFSCRDESC;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
其中,wWidth用來指定邏輯屏幕的寬度,wDepth用來指定邏輯屏幕的高度,glaobalflag為全域性數據,它的總長度為一個字節,其中前 三位(第0位到第2位)指定全局調色板的位數,可以通過該值來計算全局調色板的大小。第3位表明全局調色板中的RGB顏色值是否按照使用率進行從高到底的 次序排序的。第4到第6位指定圖像的色彩分辨率。第7位指明GIF文件中是否具有全局調色板,其值取1表示有全局調色板,為0表示沒有全局調色板。一個 GIF文件可以有全局調色板也可以沒有全局調色板,如果定義了全局調色板並且沒有定義某一幅圖像的局部調色板,則本幅圖像采用全局調色板;如果某一幅圖像 定義的自己的局部調色板,則該幅圖像使用自己的局部調色板。如果沒有定義全局調色板,則GIF文件中的每一幅圖像都必須定義自己的局部調色板。全局調色板 必須緊跟在邏輯屏幕描述塊的后面,其大小由GlobalFlag.PalBits決定,其最大長度為768(3*256)字節。全局調色板的數據是按照 RGBRGB…..RGB的方式存儲的。byBackground用來指定邏輯屏幕的背景顏色,也就相當於是畫布的顏色。當圖像長寬小於邏輯屏幕的大小 時,未被圖像覆蓋部分的顏色值由該值對應的全局調色板中的索引顏色值確定。如果沒有全局調色板,該值無效,默認背景顏色為黑色。byAspect用來指定 邏輯屏幕的像素的長寬比例。
3. 圖像描述塊
一幅GIF圖像文件中可以存儲多幅圖像,並且這些圖像沒有固定的存放次序。為了區分兩幅 圖像,GIF采用了一個字節的識別碼(Image Separator)來判斷下面的數據是否是圖像描述塊。圖像描述塊以0x2C開始,定義緊接着它的圖像的性質,包括圖像相對於邏輯屏幕邊界的偏移量、圖 像大小以及有無局部調色板和調色板的大小。圖像描述塊由10個字節組成:
typedef struct gifimage
{
WORD wLeft;
WORD wTop;
WORD wWidth;
WORD wDepth;
struct localflag
{
BYTE PalBits : 3; BYTE Reserved : 2; BYTE SortFlag : 1; BYTE Interlace : 1; BYTE LocalPal : 1; } LocalFlag; } GIFIMAGE;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
其中,wLeft用來指定圖像相對邏輯屏幕左上角的X坐標,以象素為單位。wTop用來指定圖像相對邏輯屏幕左上角的Y坐標。wWdith和 wDepth分別用來指定圖像的寬度和高度。LocalFlag用來指定區域性數據,也就是具體一幅圖像的屬性。LocalFlag的總長度為一個字節, 其中的前三位用來指定局部調色板的位數,可以根據該值來計算局部調色板的大小。第4位到第5位為保留位,沒有使用,其值固定為0。第6位指明局部調色板中 的RGB顏色值是否經過排序,其值為1表示調色板中的RGB顏色值是按照其使用率從高到底的次序進行排序。第7位表示GIF圖像是否以交錯方式存儲,其取 值為1表示以交錯的方式進行存儲。當圖像是按照交錯方式存儲時,其圖像數據的處理可以分為4個階段:第一階段從第0行開始,每次間隔8行進行處理;第二階 段從第4行開始,每次間隔8行進行處理;第三階段從第2行開始,每次間隔4行進行處理;第四階段從第1行開始,每次間隔2行進行處理,這樣當完成第一階段 時就可以看到圖像的概貌,當處理完第二階段時,圖像會變得清晰一些;當處理完第三階段時,圖像處理完成一半,清晰效果也進一步增強,當完成第四階段,圖像 處理完畢,顯示出完整清晰的整幅圖像。以交錯方式存儲是GIF文件格式的一個重要的特點,也是GIF文件格式的一個重要的優點。以交錯方式存儲的圖像的好 處就是無需將整個圖像文件解壓完成就可以看到圖像的概貌,這樣可以減少用戶的等待時間。第8位指明GIF圖像是否含有局部調色板,如果含有局部調色板,則 局部調色板的內容應當緊跟在圖像描述塊的后面。
4. 圖像壓縮數據
圖像壓縮數據是按照GIF-LZW壓縮編碼后存儲於圖像壓縮數據塊 中的。GIF-LZW編碼是一種經過改良的LZW編碼方式,它是一種無損壓縮的編碼方法。GIF-LZW編碼方法是將原始數據中的重復字符串建立一個字符 串表,然后用該重復字符串在字符串表中的索引來替代原始數據以達到壓縮的目的。由於GIF-LZW壓縮編碼的需要,必須首先存儲GIF-LZW的最小編碼 長度以供解碼程序使用,然后再存儲編碼后的圖像數據。編碼后的圖像數據是一個個數據子塊的方式存儲的,每個數據子塊的最大長度為256字節。數據子塊的第 一個字節指定該數據子塊的長度,接下來的數據為數據子塊的內容。如果某個數據子塊的第一個字節數值為0,即該數據子塊中沒有包含任何有用數據,則該子塊稱 為塊終結符,用來標識數據子塊到此結束。
5. 圖像控制擴充塊
圖像控制擴充塊是可選的,只應用於89a版本,它描述了與圖像控制相關 的參數。一般情況下,圖像控制擴充塊位於一個圖像塊(包括圖像標識符、局部顏色列表和圖像數據)或文本擴展塊的前面,用來控制跟在它后面的第一個圖像(或 文本)的渲染(Render)形式,組成結構如下:
typedef struct gifcontrol
{
BYTE byBlockSize;
struct flag
{
BYTE Transparency : 1; BYTE UserInput : 1; BYTE DisposalMethod : 3; BYTE Reserved : 3; } Flag; WORD wDelayTime; BYTE byTransparencyIndex; BYTE byTerminator; } GIFCONTROL;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
其中,byBlockSize用來指定該圖像控制擴充塊的長度,其取值固定為4。Flag用來描述圖像控制相關數據,它的長度為1個字節。它的第0位用 來指定圖像中是否具有透明性的顏色,如果該位為1,這表明圖像中某種顏色具有透明性,該顏色由參數byTransparencyIndex指定。第一位用 來判斷在顯示一幅圖像后,是否需要用戶輸入后再進行下一個動作。如果該位為1,則表示應用程序在進行下一個動作之前需要用戶輸入。第2-4位用來指定圖像 顯示后的處理方式,當該值為0時,表示沒有指定任何處理方式;當該值為1時,表明不進行任何處理動作;當該值為2時,表明圖像顯示后以背景色擦去;當該值 為3時,表明圖像顯示后恢復原先的背景圖像。第5-7位為保留位,沒有任何含義,固定為0。wDelayTime用來指定應用程序進行下一步操作之前延遲 的時間,單位為0.01秒。如果Flag.UserInput和wDelayTime都設定了,則以先發者為主,如果沒有到指定的延遲時間即有用戶輸入, 則應用程序直接進行下一步操作。如果到達延遲時間后還沒有用戶輸入,應用程序也直接進入下一步操作。byTransparenceIndex用來指定圖像 中透明色的顏色索引,指定的透明色將不在顯示設備上顯示。byTerminator為塊終結符,其值固定為0。
6. 圖像說明擴充塊
圖像說明擴充塊又可以稱為圖像文本擴展塊,它用來繪制一個簡單的文本圖像,這一部分由用來繪制的純文本數據(7位的 ASCII字符)和控制繪制的參數等組成。繪制文本借助於一個文本框(Text Grid)來定義邊界,在文本框中划分多個單元格,每個字符占用一個單元,繪制時按從左到右、從上到下的順序依次進行,直到最后一個字符或者占滿整個文本 框(之后的字符將被忽略,因此定義文本框的大小時應該注意到是否可以容納整個文本),繪制文本的顏色使用全局顏色列表,沒有則可以使用一個已經保存的前一 個顏色列表。另外,圖形文本擴展塊也屬於圖形塊(Graphic Rendering Block),可以在它前面定義圖形控制擴展對它的表現形式進一步修改。圖像說明擴充塊的組成:
typedef struct gifplaintext { BYTE byBlockSize; WORD wTextGridLeft; WORD wTextGridTop; WORD wTextGridWidth; WORD wTextGridDepth; BYTE byCharCellWidth; BYTE byCharCellDepth; BYTE byForeColorIndex; BYTE byBackColorIndex; } GIFPLAINTEXT;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
其中,byBlockSize用來指定該圖像擴充塊的長度,其取值固定為13。wTextGridLeft用來指定文字顯示方格相對於邏輯屏幕左上角的 X坐標(以像素為單位)。wTextGridTop用來指定文字顯示方格相對於邏輯屏幕左上角的Y坐標。wTextGridWidth用來指定文字顯示方 格的寬度。wTextGridDepth用來指定文字顯示方格的高度。byCharCellWidth用來指定字符的寬度, byCharCellDepth用來指定字符的高度。byForeColorIndex用來指定字符的前景色,byBackColorIndex用來指定 字符的背景色。
7. 圖像注釋擴充塊
圖像注釋擴充塊包含了圖像的文字注釋說明,可以用來記錄圖形、版權、描述等任何的非圖形和控制的 純文本數據(7位的ASCII字符),注釋擴展並不影響對圖象數據流的處理,解碼器完全可以忽略它。存放位置可以是數據流的任何地方,最好不要妨礙控制和 數據塊,推薦放在數據流的開始或結尾。在GIF中用識別碼0xFE來判斷一個擴充塊是否為圖像注釋擴充塊。圖像注釋擴充塊中的數據子塊個數不限,必須通過 塊終結符來判斷該擴充塊是否結束。
8. 應用程序擴充塊
應用程序擴充塊包含了制作該GIF圖像文件的應用程序的信息,GIF中用識別碼0xFF來判斷一個擴充塊是否為應用程序擴充塊。它的結構定義如下:
typedef struct gifapplication { BYTE byBlockSize; BYTE byIdentifier[8]; BYTE byAuthentication[3]; } GIFAPPLICATION;
- 1
- 2
- 3
- 4
- 5
- 6
其中,byBlockSize用來指定該應用程序擴充塊的長度,其取值固定為12。byIdentifier用來指定應用程序名稱。byAuthentication用來指定應用程序的識別碼。
9. 文件結尾塊
文件結尾塊為GIF圖像文件的最后一個字節,其取值固定為0x3B。
總結
PNG格式圖片分析
PNG這種圖片格式包括了許多子類,但是在實踐中大致可以分為256色的PNG(PNG8)和全色的PNG(PNG24、 PNG32),你完成可以用256色的PNG代替GIF,用全色的PNG代替JPEG
透明性:
PNG是完全支持alpha透明的(透明,半透明,不透明)
動畫:
它不支持動畫
無損耗性:
PNG是一種無損耗的圖像格式,這也意味着你可以對PNG圖片做任何操作也不會使 得圖像質量產生損耗。這也使得PNG可以作為JPEG編輯的過渡格式
水平掃描像GIF一樣,PNG也是水平掃描的,這樣意味着水平重復顏色比垂直重復顏色的圖片更小
間隔漸進顯示:
它支持間隔漸進顯示,但是會造成圖片大小變得更大
優點:
* 支持256色調色板技術以產生小體積文件
* 最高支持48位真彩色圖像以及16位灰度圖像。
* 支持Alpha通道的半透明特性。
* 支持圖像亮度的gamma校正信息。
* 支持存儲附加文本信息,以保留圖像名稱、作者、版權、創作時間、注釋等信息。
* 使用無損壓縮。
* 漸近顯示和流式讀寫,適合在網絡傳輸中快速顯示預覽效果后再展示全貌。
* 使用CRC循環冗余編碼防止文件出錯。
* 最新的PNG標准允許在一個文件內存儲多幅圖像。
缺點:
但也有一些軟件不能使用適合的預測,而造成過分臃腫的PNG文件。
JPEG格式圖片特點
透明性、動畫:
它並不支持透明,也不支持動畫。
損耗性:
除了一些比如說旋轉(僅僅是90、180、270度旋轉),裁切,從標准類型到先進類型,編輯圖片的原數據之外,所有其它操作對JPEG圖像的處理 都會使得它的質量損失。所以我們在編輯過程一般用PNG作為過渡格式。
隔行漸進顯示:
它支持隔行漸進顯示(但是ie瀏覽器並不支持這個屬性,但是ie會在整個圖像信息完全到達的時候顯示)。
由上可以看出JPEG是最適web上面的攝影圖片和數字照相機中。
優點:
JPEG/JFIF是最普遍在萬維網(World Wide Web)上被用來儲存和傳輸照片的格式。JPEG在色調及顏色平滑變化的相片或是寫實繪畫(painting)上可以達到它最佳的效果。在這種情況下,它通常比完全無失真方法作得更好,仍然可以產生非常好看的影像(事實上它會比其他一般的方法像是GIF產生更高品質的影像,因為GIF對於線條繪畫(drawing)和圖示的圖形是無失真,但針對全彩影像則需要極困難的量化)。
缺點:
它並不適合於線條繪圖(drawing)和其他文字或圖示(iconic)的圖形,因為它的壓縮方法用在這些圖形的型態上,會得到不適當的結果;
GIF格式圖片的特點
透明性:
Gif是一種布爾透明類型,既它可以是全透明,也可以是全不透明,但是它並沒有半透明(alpha 透明)。
動畫:
Gif這種格式支持動畫。
無損耗性:
Gif是一種無損耗的圖像格式,這也意味着你可以對gif圖片做任何操作也不會使 得圖像質量產生損耗。
水平掃描:
Gif是使用了一種叫作LZW的算法進行壓縮的,當壓縮gif的過程中,像素是由上到下水平壓縮的,這也意味着同等條件下,橫向的gif圖片比豎向 的gif圖片更加小。例如500*10的圖片比10*500的圖片更加小
間隔漸進顯示:
Gif支持可選擇性的間隔漸進顯示
由以上特點看出只有256種顏色的gif圖片不適合照片,但它適合對顏色要求不高的圖形(比如說圖標,圖表等),它並不是最優的選擇
優點:
1. 優秀的壓縮算法使其在一定程度上保證圖像質量的同時將體積變得很小。
2. 可插入多幀,從而實現動畫效果。
3. 可設置透明色以產生對象浮現於背景之上的效果。
缺點:
由於采用了8位壓縮,最多只能處理256種顏色(2的8次方),故不宜應用於真彩圖像。
BMP格式圖片的特點
透明性:
32位BMP有透明分量,可以通過添加通道使圖片具有透明效果
動畫:
不支持動畫
無損耗性:
它采用位映射存儲格式,除了圖像深度可選以外,不采用其他任何壓縮,因此,BMP文件所占用的空間很大
優點:
由於BMP文件格式是Windows環境中交換與圖有關的數據的一種標准,因此在Windows環境中運行的圖形圖像軟件都支持BMP圖像格式。
BMP格式的圖像,其優點是不采用任何壓縮,無損,顏色准確,有2色、16色、256色、真彩色各種選擇。
缺點:
缺點就是文件占用的空間很大,不支持文件壓縮,不適用於 Web 頁,不受 Web 瀏覽器支持。
