【轉】png檔案格式

來源:互聯網
上載者:User

標籤:

前言

我們都知道,在進行J2ME的手機應用程式開發的時候,在圖片的使用上,我們可以使用PNG格式的圖片(甚至於在有的手機上,我們只可以使用PNG 格式的圖片),儘管使用圖片可以為我們的應用程式增加不少亮點,然而,只支援PNG格式的圖片卻又限制了我們進一步發揮的可能性(其實,應該說是由於手機 平台上的處理能力有限)。 在MIDP2中,或者某些廠商(如NOKIA)提供的API中,提供了drawPixels/getPixels的方法,這些方法進一步提高了開發人員處理 圖片的靈活性,然而,在MIDP2還未完全普及的今天,我們需要在MIDP1 .0中實現這類方法還屬於異想天開,因此,為了實現更進階的應用,我們必須充分挖掘PNG的潛力。

PNG的檔案結構

對於一個PNG檔案來說,其檔案頭總是由位固定的位元組來描述的:

十進位數 137 80 78 71 13 10 26 10
十六進位數 89 50 4E 47 0D 0A 1A 0A

其中第一個位元組0x89超出了ASCII字元的範圍,這是為了避免某些軟體將PNG檔案當做文字檔來處理。檔案中剩餘的部分由3個以上的PNG的資料區塊(Chunk)按照特定的順序組成,因此,一個標準的PNG檔案結構應該如下:

PNG檔案標誌 PNG資料區塊 …… PNG資料區塊

PNG資料區塊(Chunk)

PNG定義了兩種類型的資料區塊,一種是稱為關鍵資料區塊(critical chunk),這是標準的資料區塊,另一種叫做輔助資料區塊(ancillary chunks),這是可選的資料區塊。關鍵資料區塊定義了4個標準資料區塊,每個PNG檔案都必須包含它們,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個資料區塊按以上先後順序進行儲存,並且都只出現一次。

資料區塊結構

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

下面,我們依次來瞭解一下各個關鍵資料區塊的結構吧。

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
Compression 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圖片,然而,實際上,如果一個圖片過大,會由於記憶體耗盡而無法讀取。
  • 顏色類型:所有顏色類型都有被支援,雖然這些顏色的顯示依賴於實際裝置的顯示能力。同時,MIDP也能支援alpha通道,但是,所有的alpha通道資訊都會被忽略並且當作不透明的顏色對待。
  • 色深:所有的色深都能被支援。
  • 壓縮方法:僅支援壓縮方式0(deflate壓縮方式),這和jar檔案的壓縮方式完全相同,所以,PNG圖片資料的解壓和jar檔案的解壓可以使用相同的代碼。(其實這也就是為什麼J2ME能很好的支援PNG映像的原因:))
  • 濾波器方法:儘管在PNG的白皮書中僅定義了方法0,然而所有的5種方法都被支援!
  • 隔行掃描:雖然MIDP支援0、1兩種方式,然而,當使用隔行掃描時,MIDP卻不會真正的使用隔行掃描方式來顯示。
  • PLTE chunk:支援
  • IDAT chunk:映像資訊必須使用5種過濾方式中的方式0 (None, Sub, Up, Average, Paeth)
  • IEND chunk:當IEND資料區塊被找到時,這個PNG映像才認為是合法的PNG映像。
  • 可選資料區塊:MIDP可以支援下列輔助資料區塊,然而,這卻不是必須的。

    bKGD cHRM gAMA hIST iCCP iTXt pHYs
    sBIT sPLT sRGB tEXt tIME tRNS zTXt

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

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映像不合法。

真彩色映像和帶α通道資料的真彩色映像也可以有調色盤資料區塊,目的是便於非真彩色顯示程式用它來量化映像資料,從而顯示該映像。

IDAT

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

IDAT存放著映像真正的資料資訊,因此,如果能夠瞭解IDAT的結構,我們就可以很方便的產生PNG映像。

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。

執行個體研究PNG

以下是由Fireworks產生的一幅映像,映像大小為8*8,為了方便大家觀看,我們將映像放大:



使用UltraEdit32開啟該檔案,如下:
00000000~00000007:

 

可以看到,選中的頭8個位元組即為PNG檔案的標識。

接下來的地方就是IHDR資料區塊了:

00000008~00000020:

 

  • 00 00 00 0D 說明IHDR頭塊長為13
  • 49 48 44 52 IHDR標識
  • 00 00 00 08 映像的寬,8像素
  • 00 00 00 08 映像的高,8像素
  • 04 色深,2^4=16,即這是一個16色的映像(也有可能顏色數不超過16,當然,如果顏色數不超過8,用03表示更合適)
  • 03 顏色類型,索引映像
  • 00 PNG Spec規定此處總為0(非0值為將來使用更好的壓縮方法預留),表示使壓縮方法(LZ77派生演算法)
  • 00 同上
  • 00 非隔行掃描
  • 36 21 A3 B8 CRC校正

00000021~0000002F:

 

可選資料區塊sBIT,顏色採樣率,RGB都是256(2^8=256)

00000030~00000062:

 

這裡是調色盤資訊

  • 00 00 00 27 說明調色盤資料長為39位元組,既13個顏色數
  • 50 4C 54 45 PLTE標識
  • FF FF 00 顏色0
  • FF ED 00 顏色1
  • …… ……
  • 09 00 B2 最後一個顏色,12
  • 5F F5 BB DD CRC校正

00000063~000000C5:

 

這部分包含了pHYs、tExt兩種類型的資料區塊共3塊,由於並不太重要,因此也不再詳細描述了。

000000C0~000000F8:

 

以上選中部分是IDAT資料區塊

  • 00 00 00 27 資料長為39位元組
  • 49 44 41 54 IDAT標識
  • 78 9C…… 壓縮的資料,LZ77派生壓縮方法
  • DA 12 06 A5 CRC校正

IDAT中壓縮資料部分在後面會有詳細的介紹。

000000F9~00000104:

 

IEND資料區塊,這部分正如上所說,通常都應該是

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

至此,我們已經能夠從一個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實現有興趣,可以參考以下兩個網站:

  • http://jazzlib.sourceforge.net/
  • http://www.jcraft.com/jzlib/index.html

PNG檔案結構分析(下:在手機上產生PNG檔案)

(已閱讀 次)

上面我們已經對PNG的儲存格式有了瞭解,因此,產生PNG圖片只需要按照以上的資料區塊寫入檔案即可。

(由於IHDR、PLTE的結構都非常簡單,因此,這裡我們只是重點講一講IDAT的產生方法,IHDR和PLTE的資料內容都沿用以上的資料內容)

問題確實是這樣的,我們知道,對於大多數的圖形檔案來說,我們都可以將實際的映像內容映射為一個二維的顏色數組,對於上面的PNG檔案,由於它用的是16色的調色盤(實際是13色),因此,對於圖片的映射可以如下:


(調色盤對照圖)

 

12 11 10 9 8 7 6 5
11 10 9 8 7 6 5 4
10 9 8 7 6 5 4 3
9 8 7 6 5 4 3 2
8 7 6 5 4 3 2 1
7 6 5 4 3 2 1 0
6 5 4 3 2 1 0 0
5 4 3 2 1 0 0 0

PNG Spec中指出,如果PNG檔案不是採用隔行掃描方法儲存的話,那麼,資料是按照行(ScanLine)來儲存的,為了區分第一行,PNG規定在每一行的前面加上0以示區分,因此,上面的影像地圖應該如下:

 

0 12 11 10 9 8 7 6 5
0 11 10 9 8 7 6 5 4
0 10 9 8 7 6 5 4 3
0 9 8 7 6 5 4 3 2
0 8 7 6 5 4 3 2 1
0 7 6 5 4 3 2 1 0
0 6 5 4 3 2 1 0 0
0 5 4 3 2 1 0 0 0

另外,需要注意的是,由於PNG在儲存映像時為了節省空間的,因此每一行是按照位(Bit)來儲存的,而並不是我們想象的位元組(Byte),如果你沒有忘記的話,我們的IHDR資料區塊中的色深就指明了這一點,所以,為了湊成PNG所需要的IDAT,我們的資料得改成如下:

 

0 203 169 135 101
0 186 152 118 84
0 169 135 101 67
0 152 118 84 50
0 135 101 67 33
0 118 84 50 16
0 101 67 33 0
0 84 50 16 0

最後,我們對這些資料進行LZ77壓縮就可以得到IDAT的正確內容了。

然而,事情並不是這麼簡單,因為我們研究的是手機上的PNG,如果需要在手機上完成LZ77壓縮工作,消耗的時間是可想而知的,因此,我們得再想辦法加減少壓縮時消耗的時間。

好在LZ77也提供了無壓縮的壓縮方法(奇怪吧?),因此,我們只需要簡單的使用無壓縮的方式寫入資料就可以了,這樣雖然浪費了空間,卻換回了時間!

好了,讓我們看一看怎麼樣湊成無壓縮的LZ77壓縮塊:

 

位元組 意義
0~2 壓縮資訊,固定為0x78, 0xda, 0x1
3~6 壓縮塊的LEN和NLEN資訊
壓縮的資料
最後4位元組 Adler32資訊

其中的LEN是指資料的長度,佔用兩個位元組,對於我們的映像來說,第一個Scan Line包含了5個位元組(如第一行的0, 203, 169, 135, 101),所以LEN的值為5(位元組/行) * 8(行) = 40(位元組),產生位元組為28 00(低位元組在前),NLEN是LEN的補碼,即NLEN = LEN ^ 0xFFFF,所以NLEN的為 D7 FF,Adler32資訊為24 A7 0B A4(具體演算法見來源程式),因此,按照這樣的順序,我們產生IDAT資料區塊,最後,我們將IHDR、PLTE、IDAT和IEND資料區塊寫入檔案中,就可以得到PNG檔案了,


(選中的部分為產生的“壓縮”資料)

至此,我們已經能夠採用最快的時間將數群組轉換為PNG圖片了。

 

參考資料:

PNG檔案格式白皮書:http://www.w3.org/TR/REC-png.html
為數不多的中文PNG格式說明:http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm
RFC-1950(ZLIB Compressed Data Format Specification):ftp://ds.internic.net/rfc/rfc1950.txt
RFC-1950(DEFLATE Compressed Data Format Specification):ftp://ds.internic.net/rfc/rfc1951.txt
LZ77演算法的JAVA實現:http://jazzlib.sourceforge.net/
LZ77演算法的JAVA實現,包括J2ME版本:http://www.jcraft.com/jzlib/index.html

【轉】png檔案格式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.