php程序读取firework生成的png图片数据
生活随笔
收集整理的這篇文章主要介紹了
php程序读取firework生成的png图片数据
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前陣子花了好幾天在看png結構文檔,無奈國內文檔太少了
也沒有涉及到png數據真彩解碼問題
文檔結構可以看我前面的文檔。
這里直接貼php代碼,希望在做游戲的同學能用上。
因為有些角色一樣的,可以真接把調色板顏色修改下就可以了
像魔獸中不同單位只有顏色差別,現在android支持png文件,支持32位色
也就是真彩透明,這樣做起來界面非常漂亮
<?php /* 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 圖像結束數據 否 否 最后一個數據塊 */ class png{private $png=null;private $fp=null;var $data=null;var $seek=0;var $info=array();var $color=array();const IHEADER ='0D0A1A0A'; //文件開頭常量const IEND ='0000000049454E44AE426082';//文件結尾常量public function __construct($png=null){$this->png=$png;if($this->png!=null){$this->read($this->png);}}/**讀取1字節*/public function readBits8(){$t='';$t=unpack("C",fread($this->fp,1));return $t[1];}/**讀取雙字節*/public function readBH16(){$t='';$t=unpack("n",fread($this->fp,2));return $t[1];}/**讀取雙字節*/public function readBits16(){$t='';$t=unpack("S",fread($this->fp,2));return $t[1];}/**讀取四字節*/public function readBH32(){$t='';$t=unpack("N",fread($this->fp,4));return $t[1];}/**讀取四字節*/public function readBits32(){$t='';$t=unpack("L",fread($this->fp,4));return $t[1];}public function version(){fseek($this->fp,1);$this->info['version']=fread($this->fp,3); return $this->info['version'];}public function seek($s){fseek($this->fp,$s);return $this;}public function rBName(){return fread($this->fp,4);}public function rSize($s){return fread($this->fp,$s);}public function rCRC(){return $this->readBH32();}//讀取一個塊public function rBlock(){ $b=new ArrayObject();$b->length=$this->readBH32();$b->name=$this->rBName();if($b->length>0){$b->data=$this->rSize($b->length);}else{$b->data='';}$b->crc=$this->rCRC(); if(crc32($b->name.$b->data)==$b->crc){$b->checkcrc=true;}else{$b->checkcrc=false;}return $b;}/**IHDR開始模埠*/public function pIHDR($obj){//寬度四字節$t=unpack("N",substr($obj->data,0,4));$this->info['width']=$t[1];//高度四字節$t=unpack("N",substr($obj->data,4,4));$this->info['height']=$t[1];/** Bit depth 1 byte 圖像深度:* 索引彩色圖像:1,2,4或8* 灰度圖像:1,2,4,8或16* 真彩色圖像:8或16 */$t=unpack("C",substr($obj->data,8,1));$this->info['bitdepth']=$t[1];/** ColorType 1 byte 顏色類型:* 0:灰度圖像, 1,2,4,8或16* 2:真彩色圖像,8或16* 3:索引彩色圖像,1,2,4或8* 4:帶α通道數據的灰度圖像,8或16* 6:帶α通道數據的真彩色圖像,8或16 */$t=unpack("C",substr($obj->data,9,1));$this->info['colortype']=$t[1];//lz77的算法$t=unpack("C",substr($obj->data,10,1));$this->info['lz77']=$t[1];//濾波器方法 $t=unpack("C",substr($obj->data,11,1));$this->info['filter']=$t[1];//是否隔行掃描$t=unpack("C",substr($obj->data,12,1));$this->info['interlace']=$t[1];return $this;}/**樣本有效位數據塊 */public function psBit($obj){$this->info['sbit']=array();for($i=0;$i<$obj->length;$i++){$t=unpack("C",substr($obj->data,$i,1));$this->info['sbit'][$i]=$t[1];}return $this;}/** 調調色板讀取*/public function pPLTE($obj){$this->info['plte']=array();$j=0;for($i=0;$i<$obj->length;$i+=3){$r=unpack("C",substr($obj->data,$i,1));$this->info['plte'][$j]['r']=$r[1];$g=unpack("C",substr($obj->data,$i+1,1));$this->info['plte'][$j]['g']=$g[1];$b=unpack("C",substr($obj->data,$i+2,1));$this->info['plte'][$j]['b']=$b[1];$this->info['plte'][$j]['rgb']=$this->rgbHex($r[1]).$this->rgbHex($g[1]).$this->rgbHex($b[1]);$j++;}return $this;}/** 圖像透明數據塊 */public function ptRNS($obj){$this->info['trns']=array();for($i=0;$i<$obj->length;$i++){$t=unpack("C",substr($obj->data,$i,1));$this->info['trns'][$i]=$t[1];}return $this;}/** 物理像素尺寸數據塊 */public function ppHYs($obj){$this->info['phys']=array();$t=unpack("N",substr($obj->data,0,4));$this->info['phys']['x']=$t[1];$t=unpack("N",substr($obj->data,4,4));$this->info['phys']['y']=$t[1];$t=unpack("C",substr($obj->data,8,1));$this->info['phys']['unit']=$t[1];return $this;}/** 文本信息數據塊 * 分隔行為02的話 是用自已的值去xor上面相同位置的值* 00 1A50B8FF 000003FF 99CC33FF * 如果是01的話用后面的數據加上前邊的RGB* 用02數據RGB加上上面數據* 03 為上一行數據除以2+本行數據 RGBA分別運算* 如果不是第一列,那么本列前面的對應的字節加上一行對應的字節然后平均;** 04 左邊加上上邊減去左上角,得到的值再減去(左邊,上邊,左上邊 那個值最小就取那個。 * 02 00000000 0000FC00 00000000*/public function ptEXt($obj){$this->info['create']=$obj->data;return $this;}/** 圖像數據塊 */public function pIDAT($obj){$this->data=gzuncompress($obj->data);$this->seek=0;return $this;}/** 物理像素尺寸數據塊 */public function pcHRM($obj){$this->info['chrm']=array();$t=unpack("N",substr($obj->data,0,4));$this->info['chrm']['wx']=$t[1];$t=unpack("N",substr($obj->data,4,4));$this->info['chrm']['wy']=$t[1];$t=unpack("N",substr($obj->data,8,4));$this->info['chrm']['rx']=$t[1];$t=unpack("N",substr($obj->data,12,4));$this->info['chrm']['ry']=$t[1];$t=unpack("N",substr($obj->data,16,4));$this->info['chrm']['gx']=$t[1];$t=unpack("N",substr($obj->data,20,4));$this->info['chrm']['gy']=$t[1];$t=unpack("N",substr($obj->data,24,4));$this->info['chrm']['bx']=$t[1];$t=unpack("N",substr($obj->data,28,4));$this->info['chrm']['by']=$t[1];return $this;}/** 讀取文件信息*/public function read($png=null){if($this->png=null) $this->png=$png;$this->fp = fopen($png, 'rb'); if($this->readBits8()==0x89&&$this->version()=='PNG'&&$this->readBH32()==0x0D0A1A0A){ do{$obj=$this->rBlock();switch($obj->name){case 'IHDR':$this->pIHDR($obj);break;case 'sBIT':$this->psBit($obj);break;case 'PLTE': $this->pPLTE($obj);break;case 'tRNS':$this->ptRNS($obj);break;case 'pHYs':$this->ppHYs($obj);break;case 'cHRM':$this->pcHRM($obj);break;case 'tEXt':$this->ptEXt($obj);break;case 'IDAT':$this->pIDAT($obj);break;case 'IEND':break;}}while(!feof($this->fp)&&$obj->name!='IEND');fclose($this->fp);}else{echo "這是不是png文件";}}/**讀取一行*/function decode(){/*顏色類型:0:灰度圖像, 1,2,4,8或162:真彩色圖像,8或163:索引彩色圖像,1,2,4或84:帶α通道數據的灰度圖像,8或166:帶α通道數據的真彩色圖像,8或16 */switch($this->info['colortype']){case '0':break;case '2':$this->png24row();break;case '3':$this->indexrow(); break;case '4':break;case '6':$this->png32row();break;}}/** png24 真彩讀取*/function png32row(){$tcolor=array();$rh=array();for($ii=0;$ii<$this->info['height'];$ii++){$rh[$ii]=$this->rRowHeader();for($i=0;$i<$this->info['width'];$i++){$t=$this->rRGBA();$tcolor[$ii][$i]=$t;switch($rh[$ii]){case '0':$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$t->r;$this->color[$ii][$i]->g=$t->g;$this->color[$ii][$i]->b=$t->b;$this->color[$ii][$i]->a=$t->a;break;case '1':if($i==0){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$t->r;$this->color[$ii][$i]->g=$t->g;$this->color[$ii][$i]->b=$t->b;$this->color[$ii][$i]->a=$t->a;}else{$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt1($t->r,$this->color[$ii][$i-1]->r);$this->color[$ii][$i]->g=$this->filt1($t->g,$this->color[$ii][$i-1]->g);$this->color[$ii][$i]->b=$this->filt1($t->b,$this->color[$ii][$i-1]->b); $this->color[$ii][$i]->a=$this->filt1($t->a,$this->color[$ii][$i-1]->a); }break;case '2':$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt2($t->r,$this->color[$ii-1][$i]->r);$this->color[$ii][$i]->g=$this->filt2($t->g,$this->color[$ii-1][$i]->g);$this->color[$ii][$i]->b=$this->filt2($t->b,$this->color[$ii-1][$i]->b); $this->color[$ii][$i]->a=$this->filt2($t->a,$this->color[$ii-1][$i]->a); break;case '3':if($i==0){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt3($t->r,$this->color[$ii-1][$i]->r,0);$this->color[$ii][$i]->g=$this->filt3($t->g,$this->color[$ii-1][$i]->g,0);$this->color[$ii][$i]->b=$this->filt3($t->b,$this->color[$ii-1][$i]->b,0);$this->color[$ii][$i]->a=$this->filt3($t->a,$this->color[$ii-1][$i]->a,0);}else{$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt3($t->r,$this->color[$ii-1][$i]->r,$this->color[$ii][$i-1]->r);$this->color[$ii][$i]->g=$this->filt3($t->g,$this->color[$ii-1][$i]->g,$this->color[$ii][$i-1]->g);$this->color[$ii][$i]->b=$this->filt3($t->b,$this->color[$ii-1][$i]->b,$this->color[$ii][$i-1]->b);$this->color[$ii][$i]->a=$this->filt3($t->a,$this->color[$ii-1][$i]->a,$this->color[$ii][$i-1]->a);}break; case '4':if($i==0){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt4($t->r,$this->color[$ii-1][$i]->r,$this->color[$ii-1][$i]->r,0);$this->color[$ii][$i]->g=$this->filt4($t->g,$this->color[$ii-1][$i]->g,$this->color[$ii-1][$i]->g,0);$this->color[$ii][$i]->b=$this->filt4($t->b,$this->color[$ii-1][$i]->b,$this->color[$ii-1][$i]->b,0);$this->color[$ii][$i]->a=$this->filt4($t->a,$this->color[$ii-1][$i]->a,$this->color[$ii-1][$i]->a,0);}else{$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt4($t->r,$this->color[$ii-1][$i]->r,$this->color[$ii][$i-1]->r,$this->color[$ii-1][$i-1]->r);$this->color[$ii][$i]->g=$this->filt4($t->g,$this->color[$ii-1][$i]->g,$this->color[$ii][$i-1]->g,$this->color[$ii-1][$i-1]->g);$this->color[$ii][$i]->b=$this->filt4($t->b,$this->color[$ii-1][$i]->b,$this->color[$ii][$i-1]->b,$this->color[$ii-1][$i-1]->b);$this->color[$ii][$i]->a=$this->filt4($t->a,$this->color[$ii-1][$i]->a,$this->color[$ii][$i-1]->a,$this->color[$ii-1][$i-1]->a);}break; } }}}/** png24 真彩讀取*/function png24row(){$tcolor=array();$rh=array();for($ii=0;$ii<$this->info['height'];$ii++){$rh[$ii]=$this->rRowHeader();for($i=0;$i<$this->info['width'];$i++){$t=$this->rRGB();$tcolor[$ii][$i]=$t;switch($rh[$ii]){case '0':$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$t->r;$this->color[$ii][$i]->g=$t->g;$this->color[$ii][$i]->b=$t->b;break;case '1':if($i==0){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$t->r;$this->color[$ii][$i]->g=$t->g;$this->color[$ii][$i]->b=$t->b;}else{$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt1($t->r,$this->color[$ii][$i-1]->r);$this->color[$ii][$i]->g=$this->filt1($t->g,$this->color[$ii][$i-1]->g);$this->color[$ii][$i]->b=$this->filt1($t->b,$this->color[$ii][$i-1]->b); }break;case '2':$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt2($t->r,$this->color[$ii-1][$i]->r);$this->color[$ii][$i]->g=$this->filt2($t->g,$this->color[$ii-1][$i]->g);$this->color[$ii][$i]->b=$this->filt2($t->b,$this->color[$ii-1][$i]->b); break;case '3':if($i==0){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt3($t->r,$this->color[$ii-1][$i]->r,0);$this->color[$ii][$i]->g=$this->filt3($t->g,$this->color[$ii-1][$i]->g,0);$this->color[$ii][$i]->b=$this->filt3($t->b,$this->color[$ii-1][$i]->b,0);}else{$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt3($t->r,$this->color[$ii-1][$i]->r,$this->color[$ii][$i-1]->r);$this->color[$ii][$i]->g=$this->filt3($t->g,$this->color[$ii-1][$i]->g,$this->color[$ii][$i-1]->g);$this->color[$ii][$i]->b=$this->filt3($t->b,$this->color[$ii-1][$i]->b,$this->color[$ii][$i-1]->b);}break; case '4':if($i==0){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt4($t->r,$this->color[$ii-1][$i]->r,$this->color[$ii-1][$i]->r,0);$this->color[$ii][$i]->g=$this->filt4($t->g,$this->color[$ii-1][$i]->g,$this->color[$ii-1][$i]->g,0);$this->color[$ii][$i]->b=$this->filt4($t->b,$this->color[$ii-1][$i]->b,$this->color[$ii-1][$i]->b,0);}else{$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->filt4($t->r,$this->color[$ii-1][$i]->r,$this->color[$ii][$i-1]->r,$this->color[$ii-1][$i-1]->r);$this->color[$ii][$i]->g=$this->filt4($t->g,$this->color[$ii-1][$i]->g,$this->color[$ii][$i-1]->g,$this->color[$ii-1][$i-1]->g);$this->color[$ii][$i]->b=$this->filt4($t->b,$this->color[$ii-1][$i]->b,$this->color[$ii][$i-1]->b,$this->color[$ii-1][$i-1]->b);}break; } }}}/**索引色讀取一行*/function indexrow(){for($ii=0;$ii<$this->info['height'];$ii++){$rowchar=ceil($this->info['width']*($this->info['bitdepth'])/8);$rowheader=$this->rRowHeader();//一行的偏移$this->wseek=0;$rowdata=substr($this->data,$this->seek,$rowchar);$this->seek+=$rowchar;$cdata='';for($i=strlen($rowdata)-1;$i>=0;$i--){$t=unpack("C",$rowdata[$i]);$cdata=str_pad(decbin($t[1]),8, "0", STR_PAD_LEFT).$cdata; }for($i=0;$i<$this->info['width'];$i++){$this->color[$ii][$i]=new ArrayObject();$this->color[$ii][$i]->r=$this->info['plte'][bindec(substr($cdata,$this->wseek,$this->info['bitdepth']))]['r'];$this->color[$ii][$i]->g=$this->info['plte'][bindec(substr($cdata,$this->wseek,$this->info['bitdepth']))]['g'];$this->color[$ii][$i]->b=$this->info['plte'][bindec(substr($cdata,$this->wseek,$this->info['bitdepth']))]['b'];$this->wseek+=$this->info['bitdepth'];}}}/** 讀取每行分隔* 32 24 位png時候可能會有 01 02 03 04等目前還不知道是什么* 別的程序生成沒有,但是firework生成有,可能跟透明度有關和重復有關*/function rRowHeader(){ $t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;return $t[1];}function rBits(){$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;return $t[1];}function rBitC(){$t=unpack("n",substr($this->data,$this->seek,2));$this->seek+=2;return $t[1]; }function rRGB(){$rgb=new ArrayObject();$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->r=$t[1];$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->g=$t[1];$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->b=$t[1];return $rgb;}function rRGBA(){$rgb=new ArrayObject();$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->r=$t[1];$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->g=$t[1];$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->b=$t[1];$t=unpack("C",substr($this->data,$this->seek,1));$this->seek+=1;$rgb->a=$t[1];return $rgb;}/**第行頭為02類形*/function filt1($x,$b){$p=$x+$b;$p=substr(str_pad(strtoupper(dechex($p)), 2, "0", STR_PAD_LEFT),-2);return hexdec('0x'.$p);}/**第行頭為02類形*/function filt2($x,$b){$p=$x+$b;$p=substr(str_pad(strtoupper(dechex($p)), 2, "0", STR_PAD_LEFT),-2);return hexdec('0x'.$p);}/**第行頭為03類形*/function filt3($x,$b,$a=0){$p=($b+$a)/2;$p=$x+$p;$p=substr(str_pad(strtoupper(dechex($p)), 2, "0", STR_PAD_LEFT),-2);return hexdec('0x'.$p);}/**第行頭為04類形*/function filt4($x,$b,$a=0,$c=0){$p=$a+$b-$c;$pa=abs($p-$a);$pb=abs($p-$b);$pc=abs($p-$c);if($pa<$pb&&$pa<=$pc) $p=$a;elseif($pb<=$pc) $p=$b;else $p=$c;$p=$x+$p;$p=substr(str_pad(strtoupper(dechex($p)), 2, "0", STR_PAD_LEFT),-2);return hexdec('0x'.$p);}function rgbHex($value){$value &= 0xff; return str_pad(strtoupper(dechex($value)), 2, "0", STR_PAD_LEFT); }function tohex($value) { $value &= 0xffffffff; return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT); } } ?>調用方法 <?php include("png.class.php"); $png=new png("kkbg.png"); ?> <style> <?php if(is_array($png->info['plte'])){ foreach($png->info['plte'] as $k=>$v) { ?> .plte<?php echo $k;?>{background-color:<?php echo "#".$v['rgb'];?>;width:10px;height:5px;float:left; } <?php} } ?> PRE{ font-size:14px; font-weight:bold; } </style> <div style="width:<?php echo $png->info['width']*12; ?>px; float:left;word-break: break-all;"> <?php //print_r($png->info()); $png->decode(); if(is_array($png->color)) {foreach($png->color as $v){if(is_array($v)){foreach($v as $k){ echo "<b style='float:left;height:12px;width:12px;background-color:#".$png->rgbHex($k->r).$png->rgbHex($k->g).$png->rgbHex($k->b).";'></b>";}}} } ?> </div>
總結
以上是生活随笔為你收集整理的php程序读取firework生成的png图片数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言程序设计实践教程课,C语言程序设计
- 下一篇: IBM收购以色列应用发现公司EZSour