PNG文件解讀(2):PNG格式文件結構與數據結構解讀—解碼PNG數據


PNG文件識別

之前寫過《JPEG/Exif/TIFF格式解讀(1):JEPG圖片壓縮與存儲原理分析》,JPEG文件是以,FFD8開頭,FFD9結尾,中間存儲着以0xFFE0~0xFFEF 為標志的數據段。

對於一個PNG文件來說,其文件頭總是由位固定的字節來描述的,HEX: 89 50 4E 47 0D 0A 1A 0A

png文件源碼解讀

其中第一個字節0x89超出了ASCII字符的范圍,這是為了避免某些軟件將PNG文件當做文本文件來處理。文件中剩余的部分由3個以上的PNG的數據塊(Chunk)按照特定的順序組成,因此,一個標准的PNG文件結構應該如下:

 

PNG文件標志

PNG數據塊

……

PNG數據塊

png文件數據源碼數據塊分析

 

與JPEG格式如下

SOI Marker Marker XX size=SSSS Marker YY size=TTTT SOS Marker size=UUUU Image stream EOI Marker
FFD8 FFXX SSSS DDDD...... FFYY TTTT DDDD...... FFDA UUUU DDDD.... I I I I.... FFD9

jpeg二進制代碼示范 

何其相似,但卻相差甚遠。png數據結構個人覺得比jpeg復雜

jpeg:段標識(FF)+段類型(1字節)+段長度(2字節)+數據塊

png:段長度(4字節)+段類型/類型標志(4字節)+數據塊+校驗碼(4字節)

png的每一段,稱之為數據塊。

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 圖像結束數據 最后一個數據塊

我們目前只需關注標紅的關鍵數據塊即可。

數據塊中有 4 個關鍵數據塊:

  1. 文件頭數據塊 IHDR(header chunk):包含有圖像基本信息,作為第一個數據塊出現並只出現一次。

  2. 調色板數據塊 PLTE(palette chunk):必須放在圖像數據塊之前。

  3. 圖像數據塊 IDAT(image data chunk):存儲實際圖像數據。PNG 數據允許包含多個連續的圖像數據塊。

  4. 圖像結束數據 IEND(image trailer chunk):放在文件尾部,表示 PNG 數據流結束。

數據塊連起來,大概這個樣子:

PNG 標識符 PNG 數據塊(IHDR) PNG 數據塊(其他類型數據塊) PNG 結尾數據塊(IEND)

就是一段段數據按照固定格式填充,頭尾必要,中間填充圖片的壓縮數據。所以解讀png的所有數據,就需要解讀每個數據塊

PNG數據塊結構

PNG文件中,每個數據塊由4個部分組成,如下:

名稱 字節數 說明
Length (長度) 4字節 指定數據塊中數據域的長度,其長度不超過(231-1)字節
Chunk Type Code (數據塊類型碼) 4字節 數據塊類型碼由ASCII字母(A-Z和a-z)組成
Chunk Data (數據塊數據) 可變長度 存儲按照Chunk Type Code指定的數據
CRC (循環冗余檢測) 4字節 存儲用來檢測是否有錯誤的循環冗余碼
  • Length 值的是除:length 本身,Chunk Type Code,CRC 外的長度,也就是 Chunk Data 的長度。

  • CRC: 一種校驗算法。僅僅用來校驗數據的正確性的

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

 

下面,我們依次來了解一下各個關鍵數據塊的結構吧。

文件頭數據塊IHDR

文件頭數據塊IHDR(header chunk):它包含有PNG文件中存儲的圖像數據的基本信息,並要作為第一個數據塊出現在PNG數據流中,而且一個PNG數據流中只能有一個文件頭數據塊。

文件頭數據塊由13字節組成,它的格式如下表所示。

域的名稱
字節數
說明
Width 4 bytes 圖像寬度,以像素為單位
Height 4 bytes 圖像高度,以像素為單位
Bit depth 1 byte 圖像深度:
索引彩色圖像:1,2,4或8
灰度圖像:1,2,4,8或16
真彩色圖像:8或16
ColorType 1 byte 顏色類型:
0:灰度圖像, 1,2,4,8或16
2:真彩色圖像,8或16
3:索引彩色圖像,1,2,4或8
4:帶α通道數據的灰度圖像,8或16
6:帶α通道數據的真彩色圖像,8或16
Comdivssion method 1 byte 壓縮方法(LZ77派生算法)
Filter method 1 byte 濾波器方法
Interlace method 1 byte 隔行掃描方法:
0:非隔行掃描
1: Adam7(由Adam M. Costello開發的7遍隔行掃描方法)

由於我們研究的是手機上的PNG,因此,首先我們看看MIDP1.0對所使用PNG圖片的要求吧:

  • 在MIDP1.0中,我們只可以使用1.0版本的PNG圖片。並且,所以的PNG關鍵數據塊都有特別要求:IHDR

  • 文件大小:MIDP支持任意大小的PNG圖片,然而,實際上,如果一個圖片過大,會由於內存耗盡而無法讀取。

  • ColorType/顏色類型:所有顏色類型都有被支持,雖然這些顏色的顯示依賴於實際設備的顯示能力。同時,MIDP也能支持alpha通道,但是,所有的alpha通道信息都會被忽略並且當作不透明的顏色對待。

  • Bit depth/色深:所有的色深都能被支持。

  • Comdivssion method/壓縮方法:僅支持壓縮方式0(deflate壓縮方式),這和jar文件的壓縮方式完全相同,所以,PNG圖片數據的解壓和jar文件的解壓可以使用相同的代碼。(其實這也就是為什么J2ME能很好的支持PNG圖像的原因:))

  • Filter method/濾波器方法:盡管在PNG的白皮書中僅定義了方法0,然而所有的5種方法都被支持!

  • 隔行掃描:雖然MIDP支持0、1兩種方式,然而,當使用隔行掃描時,MIDP卻不會真正的使用隔行掃描方式來顯示。

  • PLTE chunk:支持

  • IDAT chunk:圖像信息必須使用5種過濾方式中的方式0 (None, Sub, Up, Average, Paeth)

  • IEND chunk:當IEND數據塊被找到時,這個PNG圖像才認為是合法的PNG圖像。

  • 可選數據塊:MIDP可以支持下列輔助數據塊,然而,這卻不是必須的。

關於更多的信息,可以參考http://www.w3.org/TR/REC-png.html

用十六進制查看器打開一個 PNG 文件:

查看16進制png文件分析IHDR

分析如下:

十六進制 說明
00 00 00 0D 數據塊長度 13 字節
49 48 44 52 數據塊類型碼 “IHDR” 的 ASCII 字母
00 00 04 1D 圖像寬度 1053
00 00 02 B3 圖像高度 691
08 圖像深度 8
06 帶α通道數據的真彩色圖
00 壓縮方法
00 濾波器方法
00 隔行掃描方法:00非隔行掃描
52 C3 75 3A CRC (循環冗余檢測)

 數據塊-調色板數據塊PLTE

調色板數據塊PLTE(palette chunk)包含有與索引彩色圖像(indexed-color image)相關的彩色變換數據,它僅與索引彩色圖像有關,而且要放在圖像數據塊(image data chunk)之前

PLTE數據塊是定義圖像的調色板信息,PLTE可以包含1~256個調色板信息,每一個調色板信息由3個字節組成:

顏色 字節 意義

Red

1 byte

0 = 黑色, 255 = 紅

Green

1 byte

0 = 黑色, 255 = 綠色

Blue

1 byte

0 = 黑色, 255 = 藍色

因此,調色板的長度應該是3的倍數,否則,這將是一個非法的調色板。

對於索引圖像,調色板信息是必須的,調色板的顏色索引從0開始編號,然后是1、2……,調色板的顏色數不能超過色深中規定的顏色數(如圖像色深為4的時候,調色板中的顏色數不可以超過2^4=16),否則,這將導致PNG圖像不合法。

真彩色圖像和帶α通道數據的真彩色圖像也可以有調色板數據塊,目的是便於非真彩色顯示程序用它來量化圖像數據,從而顯示該圖像。

用十六進制查看器打開一個索引圖像 PNG 文件:

png-indexed-color-hex-plte

分析如下:

 

十六進制 說明
00 00 00 27 數據塊長度 39 字節
50 4C 54 45 數據塊類型碼 “PLTE” 的 ASCII 字母

B7 00 34 FF 99 00 60 00 73 FF 0F 00 FF ED 00 09 00 B2 FF 66 00 FF 3B 00 E2 00 15 

8B 00 54 FF C1 00 33 00 99 FF FF 00

調色板顏色 13 個
48 29 75 2C CRC (循環冗余檢測)

 

 

預覽調色板中的顏色:

indexed-color-plte-colors

pHYs

物理像素數據塊,它表示了圖片的像素尺寸,或者是高寬比,它的結果如下

 

Pixels per unit, X axis 4 bytes (PNG unsigned integer)

Pixels per unit, Y axis

4 bytes (PNG unsigned integer)

Unit specifier

1 byte

unit specifier的定義如下:

 

  • 0:unit is unknown

  • 1:unit is the metre

數據塊-圖像數據塊 IDAT

圖像數據塊IDAT(image data chunk):它存儲實際的數據,在數據流中可包含多個連續順序的圖像數據塊。

IDAT存放着圖像真正的數據信息,因此,如果能夠了解IDAT的結構,我們就可以很方便的生成PNG圖像。

 

用十六進制查看器打開一個索引圖像 PNG 文件:

png-hex-idat.png

十六進制 說明
00 00 00 D3 數據塊長度 211 字節
49 44 41 54 數據塊類型碼 “IDAT” 的 ASCII 字母
78 9C ...... 壓縮的數據 211 字節,LZ77 派生壓縮方法
52 98 5D 9D CRC (循環冗余檢測)

 

數據塊-圖像結束數據IEND

圖像結束數據IEND(image trailer chunk):它用來標記PNG文件或者數據流已經結束,並且必須要放在文件的尾部。

如果我們仔細觀察PNG文件,我們會發現,文件的結尾12個字符看起來總應該是這樣的:

00 00 00 00 49 45 4E 44 AE 42 60 82

圖像結束數據IEND

不難明白,由於數據塊結構的定義,IEND數據塊的長度總是0(00 00 00 00,除非人為加入信息),數據標識總是IEND(49 45 4E 44),因此,CRC碼也總是AE 42 60 82。

IHDR cHRM pHYs IEND

IHDR cHRM pHYs IEND

 

至此,我們已經能夠從一個PNG文件中識別出各個數據塊了。由於PNG中規定除關鍵數據塊外,其它的輔助數據塊都為可選部分,因此,有了這個標准后,我們可以通過刪除所有的輔助數據塊來減少PNG文件的大小。(當然,需要注意的是,PNG格式可以保存圖像中的層、文字等信息,一旦刪除了這些輔助數據塊后,圖像將失去原來的可編輯性。)

刪除了輔助數據塊后的PNG文件,現在文件大小為147字節,原文件大小為261字節,文件大小減少后,並不影響圖像的內容。

其實,我們可以通過改變調色板的色值來完成一些又趣的事情,比如說實現雲彩/水波的流動效果,實現圖像的淡入淡出效果等等,在此,給出一個鏈接給大家看也許更直接:http://blog.csdn.net/flyingghost/archive/2005/01/13/251110.aspx,我寫此文也就是受此文的啟發的。

如上說過,IDAT數據塊是使用了LZ77壓縮算法生成的,由於受限於手機處理器的能力,因此,如果我們在生成IDAT數據塊時仍然使用LZ77壓縮算法,將會使效率大打折扣,因此,為了效率,只能使用無壓縮的LZ77算法,關於LZ77算法的具體實現,此文不打算深究,如果你對LZ77算法的JAVA實現有興趣,可以參考以下兩個站點:

 

參考文章:

音視頻入門-11-PNG文件格式詳解 https://www.cnblogs.com/binglingziyu/p/audio-video-basic-11-png-file-format-detail.html

PNG文件結構 https://www.cnblogs.com/Yuuki-/p/7868858.html

http://read.newbooks.com.cn/info/173555.html

 

 

 

轉載本站文章《PNG文件解讀(2):PNG格式文件結構與數據結構解讀—解碼PNG數據》,
請注明出處:https://www.zhoulujun.cn/html/theory/multimedia/CG-CV-IP/8410.html


免責聲明!

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



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