PNG文件的組成
一個PNG文件可以看作是由多個數據塊(chunk)部分組成,如同積木一樣,一個數據塊就是一個小積木,不同類型的積木組合搭建成了我們的PNG圖像。
PNG圖像至少由文件署名域和三個關鍵數據塊IHDR,IDAT,IEND組成,因此一個最小PNG圖像可以抽象的表示成如下圖像

我們結合png圖像來了解png文件格式,用16進制編輯器打開該圖片來分析。

上圖包含的三個關鍵數據塊的主要作用如下
1.PNG文件署名域(magic number)
png文件在開頭用署名域標志了該文件的類型,長度為8個字節。因此一個文件只要前8個字節值為89 50 4E 47 0D 0A 1A 0A,我們就可以認為該文件為png
[署名域(8Bytes)]:標識文件類型為png格式

PS:試着在C用字符類型打印50 4E 47,你會發現打印出PNG三個字符
2.IHDR(Image Header) chunk:描述影像的維度、色彩深度、色彩格式、壓縮類型等
3.IDAT(Image Data)chunk:存儲影像的像素數據
4.IEND(Image End)chunk:PNG數據流結束
PNG的Chunk有很多類型,這里只介紹了最關鍵的三種
數據塊結構
PNG中一個Chunk的結構通常如下
| 名稱 | 大小(字節) | 說明 |
|---|---|---|
| Length(長度) | 4 | 標識了數據塊的長度(包括長度域) |
| Chunk Type Code(數據塊類型) | 4 | 標志了該數據塊的類型 |
| Chunk Data(數據庫長度) | 可變 | 根據不同的類型數據塊長度不一樣,取決於Chunk Type Code |
| CRC(循環冗余檢驗) | 4 | 檢驗數據塊是否出錯 |
IHDR數據塊

將上圖圖像文件的IHDR表示如上,BD(Bit Depth),CT(Color Type),CM(Compression method),FM(fjlter method),IM(Insterlace Method)具體介紹如下
| 域名 | 字節數(Byte) | 說明 |
|---|---|---|
| Width | 4 | 圖像寬度,以像素為單位 |
| Height | 4 | 圖像高度,以像素為單位 |
| Bit Depth | 1 | 圖像深度: 索引彩色圖像:1,2,4或8 灰度圖像:1,2,4,8或16 真彩色圖像:8或16 |
| Color Type | 1 | 顏色類型: 0:灰度圖像, 1,2,4,8或16 2:真彩色圖像,8或16 3索引彩色圖像,1,2,4或8 4:帶α通道數據的灰度圖像,8或16 6:帶α通道數據的真彩色圖像,8或16 |
| Compression method | 1 | 壓縮方法(LZ77派生算法) |
| Filter Method | 1 | 濾波器方法 |
| Interlace method | 1 | 隔行掃描方法: 0:非隔行掃描 1: Adam7(由Adam M. Costello開發的7遍隔行掃描方法) |
我們從上可以得到該圖像的分辨率為128*128,圖像深度為彩色圖像,沒有使用壓縮、濾波器等信息。
LZ77壓縮算法和rar的壓縮方式是一致的
IDAT數據塊
IDAT數據塊存儲的格式取決於PNG的格式以及是否壓縮。
PNG文件格式分為PNG-24和PNG-8,其最大的區別是PNG-24是用24位來保存一個像素值,是真彩色,而PNG-8是用8位索引值來在調色盤 中索引一個顏色,因為一個索引值的最大上限為2的8次方既128,故調色盤中顏色數最多為128種,
一旦使用了壓縮我們必須使用zlib解壓才能看見它的具體顏色。
IEND數據塊
值得注意的是,IEND區塊雖然也按照數據塊的結構,但Chunk Data是沒有的,所以是固定的96個字節:0x00000000 0x49454e44 0xae426082
IEND數據塊的長度總是0(00 00 00 00,除非人為加入信息),數據標識總是IEND(49 45 4E 44),因此,CRC碼也總是AE 42 60 82

參考資料
(Yolo的svpng)[https://zhuanlan.zhihu.com/p/26525083]
(PNG文件格式分析)[http://blog.csdn.net/hherima/article/details/45847043]
