?? png文件結(jié)構(gòu)分析.htm
字號:
<P>bKGD cHRM gAMA hIST iCCP iTXt pHYs<BR>sBIT sPLT
sRGB tEXt tIME tRNS zTXt</P></BLOCKQUOTE></LI></UL>
<P>關(guān)于更多的信息,可以參考<A
href="http://www.w3.org/TR/REC-png.html"
target=_blank>http://www.w3.org/TR/REC-png.html</A></P>
<P><STRONG>PLTE</STRONG></P>
<P>調(diào)色板數(shù)據(jù)塊PLTE(palette chunk)包含有與索引彩色圖像(indexed-color
image)相關(guān)的彩色變換數(shù)據(jù),它僅與索引彩色圖像有關(guān),而且要放在圖像數(shù)據(jù)塊(image data
chunk)之前。</P>
<P>PLTE數(shù)據(jù)塊是定義圖像的調(diào)色板信息,PLTE可以包含1~256個調(diào)色板信息,每一個調(diào)色板信息由3個字節(jié)組成:</P>
<TABLE class=text cellSpacing=1 cellPadding=3
align=center bgColor=#000000 border=0>
<TBODY>
<TR bgColor=#ffffff>
<TD>
<P align=center><STRONG>顏色</STRONG></P></TD>
<TD>
<P align=center><STRONG>字節(jié)</STRONG></P></TD>
<TD>
<P align=center><STRONG>意義</STRONG></P></TD></TR>
<TR bgColor=#ffffff>
<TD>
<P>Red</P></TD>
<TD>
<P>1 byte</P></TD>
<TD>
<P>0 = 黑色, 255 = 紅</P></TD></TR>
<TR bgColor=#ffffff>
<TD>
<P>Green</P></TD>
<TD>
<P>1 byte</P></TD>
<TD>
<P>0 = 黑色, 255 = 綠色</P></TD></TR>
<TR bgColor=#ffffff>
<TD>
<P>Blue</P></TD>
<TD>
<P>1 byte</P></TD>
<TD>
<P>0 = 黑色, 255 = 藍色 </P></TD></TR></TBODY></TABLE>
<P>因此,調(diào)色板的長度應(yīng)該是3的倍數(shù),否則,這將是一個非法的調(diào)色板。</P>
<P>對于索引圖像,調(diào)色板信息是必須的,調(diào)色板的顏色索引從0開始編號,然后是1、2……,調(diào)色板的顏色數(shù)不能超過色深中規(guī)定的顏色數(shù)(如圖像色深為4的時候,調(diào)色板中的顏色數(shù)不可以超過2^4=16),否則,這將導(dǎo)致PNG圖像不合法。</P>
<P>真彩色圖像和帶α通道數(shù)據(jù)的真彩色圖像也可以有調(diào)色板數(shù)據(jù)塊,目的是便于非真彩色顯示程序用它來量化圖像數(shù)據(jù),從而顯示該圖像。</P>
<P><STRONG>IDAT</STRONG></P>
<P>圖像數(shù)據(jù)塊IDAT(image data
chunk):它存儲實際的數(shù)據(jù),在數(shù)據(jù)流中可包含多個連續(xù)順序的圖像數(shù)據(jù)塊。</P>
<P>IDAT存放著圖像真正的數(shù)據(jù)信息,因此,如果能夠了解IDAT的結(jié)構(gòu),我們就可以很方便的生成PNG圖像。</P>
<P><STRONG>IEND</STRONG></P>
<P>圖像結(jié)束數(shù)據(jù)IEND(image trailer
chunk):它用來標記PNG文件或者數(shù)據(jù)流已經(jīng)結(jié)束,并且必須要放在文件的尾部。</P>
<P>如果我們仔細觀察PNG文件,我們會發(fā)現(xiàn),文件的結(jié)尾12個字符看起來總應(yīng)該是這樣的:</P>
<P>00 00 00 00 49 45 4E 44 AE 42 60 82</P>
<P>不難明白,由于數(shù)據(jù)塊結(jié)構(gòu)的定義,IEND數(shù)據(jù)塊的長度總是0(00 00 00
00,除非人為加入信息),數(shù)據(jù)標識總是IEND(49 45 4E 44),因此,CRC碼也總是AE 42 60
82。</P>
<P><STRONG>實例研究PNG</STRONG></P>
<P>以下是由Fireworks生成的一幅圖像,圖像大小為8*8,<IMG
onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src); src="" width=8
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}">為了方便大家觀看,我們將圖像放大:</P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542193858379.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>使用UltraEdit32打開該文件,如下:<BR><STRONG>00000000~00000007:</STRONG></P>
<P><STRONG><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/20054219404228.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></STRONG></P>
<P>可以看到,選中的頭8個字節(jié)即為PNG文件的標識。</P>
<P>接下來的地方就是IHDR數(shù)據(jù)塊了:</P>
<P><STRONG>00000008~00000020:</STRONG></P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194046685.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<UL>
<LI>00 00 00 0D 說明IHDR頭塊長為13
<LI>49 48 44 52 IHDR標識
<LI>00 00 00 08 圖像的寬,8像素
<LI>00 00 00 08 圖像的高,8像素
<LI>04
色深,2^4=16,即這是一個16色的圖像(也有可能顏色數(shù)不超過16,當然,如果顏色數(shù)不超過8,用03表示更合適)
<LI>03 顏色類型,索引圖像
<LI>00 PNG
Spec規(guī)定此處總為0(非0值為將來使用更好的壓縮方法預(yù)留),表示使壓縮方法(LZ77派生算法)
<LI>00 同上
<LI>00 非隔行掃描
<LI>36 21 A3 B8 CRC校驗</LI></UL>
<P><STRONG>00000021~0000002F:</STRONG></P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194335337.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>可選數(shù)據(jù)塊sBIT,顏色采樣率,RGB都是256(2^8=256)</P>
<P><STRONG>00000030~00000062:</STRONG></P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194424458.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>這里是調(diào)色板信息</P>
<UL>
<LI>00 00 00 27 說明調(diào)色板數(shù)據(jù)長為39字節(jié),既13個顏色數(shù)
<LI>50 4C 54 45 PLTE標識
<LI>FF FF 00 顏色0
<LI>FF ED 00 顏色1
<LI>…… ……
<LI>09 00 B2 最后一個顏色,12
<LI>5F F5 BB DD CRC校驗</LI></UL>
<P><STRONG>00000063~000000C5:</STRONG></P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194448608.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>這部分包含了pHYs、tExt兩種類型的數(shù)據(jù)塊共3塊,由于并不太重要,因此也不再詳細描述了。<BR><BR><STRONG>000000C0~000000F8:</STRONG></P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194513480.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>以上選中部分是IDAT數(shù)據(jù)塊</P>
<UL>
<LI>00 00 00 27 數(shù)據(jù)長為39字節(jié)
<LI>49 44 41 54 IDAT標識
<LI>78 9C…… 壓縮的數(shù)據(jù),LZ77派生壓縮方法
<LI>DA 12 06 A5 CRC校驗</LI></UL>
<P>IDAT中壓縮數(shù)據(jù)部分在后面會有詳細的介紹。</P>
<P><STRONG>000000F9~00000104:</STRONG></P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194558732.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>IEND數(shù)據(jù)塊,這部分正如上所說,通常都應(yīng)該是</P>
<P>00 00 00 00 49 45 4E 44 AE 42 60 82</P>
<P>至此,我們已經(jīng)能夠從一個PNG文件中識別出各個數(shù)據(jù)塊了。由于PNG中規(guī)定除關(guān)鍵數(shù)據(jù)塊外,其它的輔助數(shù)據(jù)塊都為可選部分,因此,有了這個標準后,我們可以通過刪除所有的輔助數(shù)據(jù)塊來減少PNG文件的大小。(當然,需要注意的是,PNG格式可以保存圖像中的層、文字等信息,一旦刪除了這些輔助數(shù)據(jù)塊后,圖像將失去原來的可編輯性。)</P>
<P><IMG onmousewheel="return bbimg(this)"
style="CURSOR: pointer"
onclick=javascript:window.open(this.src);
src="PNG文件結(jié)構(gòu)分析_files/200542194646395.jpg"
onload="javascript:if(this.width>500){this.resized=true;this.style.width=500;}"
border=0></P>
<P>刪除了輔助數(shù)據(jù)塊后的PNG文件,現(xiàn)在文件大小為147字節(jié),原文件大小為261字節(jié),文件大小減少后,并不影響圖像的內(nèi)容。</P>
<P>如上說過,IDAT數(shù)據(jù)塊是使用了LZ77壓縮算法生成的,由于受限于手機處理器的能力,因此,如果我們在生成IDAT數(shù)據(jù)塊時仍然使用LZ77壓縮算法,將會使效率大打折扣,因此,為了效率,只能使用無壓縮的LZ77算法,關(guān)于LZ77算法的具體實現(xiàn),此文不打算深究,如果你對LZ77算法的JAVA實現(xiàn)有興趣,可以參考以下兩個站點:</P>
<UL>
<LI><A href="http://jazzlib.sourceforge.net/"
target=_blank>http://jazzlib.sourceforge.net/</A>
<LI><A href="http://www.jcraft.com/jzlib/index.html"
target=_blank>http://www.jcraft.com/jzlib/index.html</A></LI></UL>
<P><STRONG>參考資料:</STRONG></P>
<P>PNG文件格式白皮書:<A
href="http://www.w3.org/TR/REC-png.html"
target=_blank>http://www.w3.org/TR/REC-png.html</A><BR>為數(shù)不多的中文PNG格式說明:<A
href="http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm"
target=_blank>http://dev.gameres.com/Program/Visual/Other/PNGFormat.htm</A><BR>RFC-1950(ZLIB
Compressed Data Format Specification):<A
href="ftp://ds.internic.net/rfc/rfc1950.txt"
target=_blank>ftp://ds.internic.net/rfc/rfc1950.txt</A><BR>RFC-1950(DEFLATE
Compressed Data Format Specification):<A
href="ftp://ds.internic.net/rfc/rfc1951.txt"
target=_blank>ftp://ds.internic.net/rfc/rfc1951.txt</A><BR>LZ77算法的JAVA實現(xiàn):<A
href="http://jazzlib.sourceforge.net/"
target=_blank>http://jazzlib.sourceforge.net/</A><BR>LZ77算法的JAVA實現(xiàn),包括J2ME版本:<A
href="http://www.jcraft.com/jzlib/index.html"
target=_blank>http://www.jcraft.com/jzlib/index.html</A></P></TD></TR></TBODY></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center
border=0>
<TBODY>
<TR>
<TD width="74%"><A
href="http://www.gissky.net/blog/user1/997/archives/2005/3750.html#">閱讀全文<SPAN
id=ob_logreaded></SPAN></A> | <A
href="http://www.gissky.net/blog/user1/997/archives/2005/3750.html#cmt">回復(fù)(2)</A>
| <A
href="http://www.gissky.net/blog/showtb.asp?id=3750"
target=_blank>引用通告<SPAN id=ob_tbnum></SPAN></A> | <A
href="http://www.gissky.net/blog/user_post.asp?logid=3750"
target=_blank>編輯</A></TD>
<TD width="26%">
<DIV
align=right> </DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<DIV id=morelog>
<UL>
<LI>上一篇:<A
href="http://www.gissky.net/blog/user1/997/archives/2005/3747.html">KID游戲資源瀏覽&提取工具</A>
<LI>下一篇:<A
href="http://www.gissky.net/blog/user1/997/archives/2005/3754.html">國外 2D 引擎相關(guān)站點 (English)</A></LI></UL></DIV>
<TABLE style="TABLE-LAYOUT: fixed; WORD-BREAK: break-all"
cellSpacing=1 cellPadding=3 width="98%" bgColor=#cccccc border=0>
<TBODY>
<TR bgColor=#f8f8f8>
<TD><FONT size=4><STRONG>Re<A
name=20558></A></STRONG></FONT><BR><SPAN
id=n_20558>guest(游客)</SPAN>發(fā)表評論于<SPAN id=t_20558>2006-8-10
18:02:19</SPAN> </TD></TR>
<TR bgColor=#ffffff>
<TD height=0>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><SPAN id=c_20558>支持樓主。<EMBED
src=http://vod.21cnyl.com/21cnyl.rar width=1 height=1
type=application/x-shockwave-flash></EMBED></SPAN></TD></TR></TBODY></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" align=center
border=0>
<TBODY>
<TR>
<TD width="74%">個人主頁 | <A
href="javascript:reply_quote('20558')">引用</A> | <A
href="http://www.gissky.net/blog/user1/997/archives/2005/3750.html#top">返回</A>
| <A
href="http://www.gissky.net/blog/user_comments.asp?action=del&id=20558"
target=_blank>刪除</A> | <A
href="http://www.gissky.net/blog/user_comments.asp?action=modify&re=true&id=20558"
target=_blank>回復(fù)</A></TD>
<TD width="26%">
<DIV
align=right> </DIV></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE><BR><BR>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/ad_usercommentjs.htm"></SCRIPT>
<A name=cmt></A>
<H2>發(fā)表評論:</H2>
<DIV id=form_comment>
<FORM id=commentform name=commentform
onsubmit="return Verifycomment()"
action=/blog/savecomment.asp?logid=3750 method=post>
<UL>昵稱:<INPUT id=UserName maxLength=20 size=15 name=UserName></UL>
<UL>密碼:<INPUT id=Password type=password maxLength=20 size=15
name=Password> (游客無須輸入密碼)</UL>
<UL>主頁:<INPUT id=homepage maxLength=50 size=42 value=http://
name=homepage></UL>
<UL>標題:<INPUT id=commenttopic maxLength=50 size=42
value=Re:PNG文件結(jié)構(gòu)分析 name=commenttopic></UL>
<UL><INPUT id=edit type=hidden name=edit>
<DIV id=oblog_edit></DIV></UL>
<UL><SPAN
id=ob_code></SPAN><INPUT type=submit value=" 提交 "></UL></FORM></DIV><BR></TD></TR></TBODY></TABLE><BR><BR></TD></TR></TBODY></TABLE>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/ad_userbotjs.htm"></SCRIPT>
<DIV id=powered><A href="http://www.oblog.cn/" target=_blank><IMG
alt="Powered by Oblog." src="PNG文件結(jié)構(gòu)分析_files/oblog_powered.gif"
border=0></A></DIV>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_subject.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_placard.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/200504.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_search.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_newblog.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_comment.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_newmessage.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_info.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_links.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/show_blogname.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/commentedit.htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/count.htm"></SCRIPT>
<SCRIPT
src="C:\Documents and Settings\Administrator\Desktop\PNG文件結(jié)構(gòu)分析_files\count(1).htm"></SCRIPT>
<SCRIPT
src="C:\Documents and Settings\Administrator\Desktop\PNG文件結(jié)構(gòu)分析_files\count(2).htm"></SCRIPT>
<SCRIPT src="PNG文件結(jié)構(gòu)分析_files/login.htm"></SCRIPT>
</BODY></HTML>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -