久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    PNG文件結構分析

     思考的軌跡 2011-04-28

    PNG文件結構分析(上:了解PNG文件存儲格式)

     

    前言

    我們都知道,在進行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字節組成,它的格式如下表所示。

    域的名稱
    字節數
    說明
    Width4 bytes圖像寬度,以像素為單位
    Height4 bytes圖像高度,以像素為單位
    Bit depth1 byte圖像深度:
    索引彩色圖像:1,2,4或8
    灰度圖像:1,2,4,8或16
    真彩色圖像:8或16
    ColorType1 byte顏色類型:
    0:灰度圖像, 1,2,4,8或16
    2:真彩色圖像,8或16
    3:索引彩色圖像,1,2,4或8
    4:帶α通道數據的灰度圖像,8或16
    6:帶α通道數據的真彩色圖像,8或16
    Compression method1 byte壓縮方法(LZ77派生算法)
    Filter method1 byte濾波器方法
    Interlace method1 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./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,PNG文件結構分析(上:了解PNG文件存儲格式)為了方便大家觀看,我們將圖像放大:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    使用UltraEdit32打開該文件,如下:
    00000000~00000007:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    可以看到,選中的頭8個字節即為PNG文件的標識。

    接下來的地方就是IHDR數據塊了:

    00000008~00000020:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    • 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:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    可選數據塊sBIT,顏色采樣率,RGB都是256(2^8=256)

    00000030~00000062:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    這里是調色板信息

    • 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:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    這部分包含了pHYs、tExt兩種類型的數據塊共3塊,由于并不太重要,因此也不再詳細描述了。

    000000C0~000000F8:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    以上選中部分是IDAT數據塊

    • 00 00 00 27 數據長為39字節
    • 49 44 41 54 IDAT標識
    • 78 9C…… 壓縮的數據,LZ77派生壓縮方法
    • DA 12 06 A5 CRC校驗

    IDAT中壓縮數據部分在后面會有詳細的介紹。

    000000F9~00000104:

    PNG文件結構分析(上:了解PNG文件存儲格式)

    IEND數據塊,這部分正如上所說,通常都應該是

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

    至此,我們已經能夠從一個PNG文件中識別出各個數據塊了。由于PNG中規定除關鍵數據塊外,其它的輔助數據塊都為可選部分,因此,有了這個標準 后,我們可以通過刪除所有的輔助數據塊來減少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實現有興趣,可以參考以下兩個站點:


    PNG文件結構分析(下:在手機上生成PNG文件)

    上面我們已經對PNG的存儲格式有了了解,因此,生成PNG圖片只需要按照以上的數據塊寫入文件即可。

    (由于IHDR、PLTE的結構都非常簡單,因此,這里我們只是重點講一講IDAT的生成方法,IHDR和PLTE的數據內容都沿用以上的數據內容)

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

    調色板對照圖
    (調色板對照圖)

     

    12111098765
    1110987654
    109876543
    98765432
    87654321
    76543210
    65432100
    54321000

    PNG Spec中指出,如果PNG文件不是采用隔行掃描方法存儲的話,那么,數據是按照行(ScanLine)來存儲的,為了區分第一行,PNG規定在每一行的前面加上0以示區分,因此,上面的圖像映射應該如下:

     

    012111098765
    01110987654
    0109876543
    098765432
    087654321
    076543210
    065432100
    054321000

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

     

    0203169135101
    018615211884
    016913510167
    01521188450
    01351016733
    0118845016
    010167330
    08450160

    最后,我們對這些數據進行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文件存儲格式)
    (選中的部分為生成的“壓縮”數據)

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

     

    參考資料:

    PNG文件格式白皮書:http://www./TR/REC-png.html
    為數不多的中文PNG格式說明:http://dev./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./
    LZ77算法的JAVA實現,包括J2ME版本:http://www./jzlib/index.html

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 人妻影音先锋啪啪AV资源| 国产午夜精品理论大片| 国产一区二区三区在线观看免费| 午夜福利在线观看6080| 中文字幕无码免费久久| 久久夜色精品国产嚕嚕亚洲AV| 中文字幕国产精品资源| 成年视频人免费网站动漫在线| 亚洲色欲色欲WWW成人网| 偷拍专区一区二区三区| 国产精品毛片无遮挡高清| 久久中文字幕一区二区| 精品国际久久久久999波多野| 亚洲av永久无码精品水牛影视 | 日本久久99成人网站| 亚洲AV无码成人精品区| 老司机午夜精品视频资源| 永久黄网站色视频免费直播| AV老司机色爱区综合| 欧美又粗又大XXXXBBBB疯狂| 亚洲色大成成人网站久久| 亚洲中文字幕国产综合| 国产亚洲999精品AA片在线爽| 国产精品久久蜜臀av| 国产精品无码久久久久成人影院| 无码国产偷倩在线播放| 美女裸体无遮挡免费视频网站| 久久大香伊蕉在人线免费AV| 麻豆亚洲精品一区二区| 亚州少妇无套内射激情视频 | 国产精品亚洲二区在线播放| 亚洲精品V天堂中文字幕| 菠萝菠萝蜜午夜视频在线播放观看 | 精品久久久久成人码免费动漫 | 成人国产精品一区二区网站公司| 国产精品美脚玉足脚交欧美| 中文无码乱人伦中文视频在线| 狠狠色噜噜狠狠亚洲AV| 97午夜理论电影影院| 日本福利一区二区精品| 日韩精品一区二区亚洲AV|