PHP使用GIFEncoder类生成gif动态滚动字幕
今天在公司,经理让做一个滚动字幕。但是,不许生成gif图片。所以上网找了GIFEncoder这个类库。确实很好用,但是,应用过程中也出现了一些问题,现在写在这里,以供后来人参考,少走弯路。
文字滚动分为两种情况。第一种为水平滚动:
<?php require_once("GIFEncoder.class.php"); $count=0; //设置默认计数器 while(true){ $str=$_REQUEST['str']?$_REQUEST['str']:"暂无输入"; $length=strlen($str)*9; //计算行长度,这个计算的比较简单,就是每个字数*9个像素 $im=imagecreatefromgif("hudongbg.gif"); //根据图片创建图像 $white=ImageColorAllocate($im,255,255,255); //设置一个白色 $str=iconv("GB2312","UTF-8",$str); //特别注意的是转换编码,因为之后用到的imagettftext只能用utf-8编码 $now=220-$count*5; //当前运行的水平位置 imagettftext($im,13,0,$now,20,$white,"ziti.ttf",$str); //根据字体在图片上写文字,参数意思(图像源,文字大小,倾斜角度,水平位置,垂直位置,颜色,使用的字体文件,要写的内容 imagegif($im); imagedestroy($im); $imagedata[]=ob_get_contents(); //创建这一帧的图像数据 ob_clean(); $count++; if($now+$length<0){ //如果最后一个文字移动到头,那么结束 break; } } $diy[]=0;//开始延迟时间 $gif=newGIFEncoder($imagedata,$diy,0,2,0,0,0,"bin"); ob_start(); Header('Content-type:image/gif'); echo$gif->GetAnimation(); ?>
然后是垂直的:
<?php /* 从url获得"str=第一行;第二行;第三行"的数据 */ require_once("GIFEncoder.class.php"); $array_str=array(); $str=$_GET['str']; /* 将$str转化成数组 */ if($str!=''){ $array_str=explode(";",$str); }else{ $array_str=array("欢迎您光临本店!"); } /* 如果数组元素没有值,清除最后一个“;” */ foreach($array_stras$k=>$v){ if(!$v) unset($array_str[$k]); } for($i=0,$length=count($array_str);$i<$length;$i++){ for($k=0;$k<20;$k++){ $im=imagecreatefromgif("hudongbg.gif"); //根据图片创建图像 $white=ImageColorAllocate($im,255,255,255); //设置一个白色 $test=iconv("GB2312","UTF-8",$array_str[$i]); //特别注意的是转换编码,因为之后用到的imagettftext只能用utf-8编码,注意,一定要用字符串接收,不能用数组,否则会乱码 $heigth=40-$k; //当前文字高度 imagettftext($im,13,0,0,$heigth,$white,"ziti.ttf",$test); //将文字写入图片 imagegif($im); $imagedata[]=ob_get_contents(); ob_clean(); } } /* 这里是设置每一张图片的延迟时间,到第20帧的时候,延迟2秒。这样才能出现文字走到顶,停顿一会的效果 */ $delay=array(); for($i=1,$length=count($array_str)*20;$i<=$length;$i++){ if($i%20==0){ $delay[$i-1]="200"; }else{ $delay[$i-1]="1"; } } $transparent=array(0); $gif=newGIFEncoder($imagedata,$delay,0,2,0,0,$transparent,"bin"); ob_start(); Header('Content-type:image/gif'); echo$gif->GetAnimation(); ?>
GIFEncoder类源码:
<?php ClassGIFEncoder{ var$GIF="GIF89a"; /*GIFheader6bytes */ var$VER="GIFEncoderV2.06"; /*Encoderversion */ var$BUF=Array(); var$LOP= 0; var$DIS= 2; var$COL=-1; var$IMG=-1; var$ERR=Array( 'ERR00'=>"Doesnotsupportedfunctionforonlyoneimage!", 'ERR01'=>"SourceisnotaGIFimage!", 'ERR02'=>"Unintelligibleflag", 'ERR03'=>"CouldnotmakeanimationfromanimatedGIFsource", ); /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GIFEncoder... :: */ functionGIFEncoder ( $GIF_src,$GIF_dly,$GIF_lop,$GIF_dis, $GIF_red,$GIF_grn,$GIF_blu,$GIF_mod ){ if(!is_array($GIF_src)&&!is_array($GIF_tim)){ printf ("%s:%s",$this->VER,$this->ERR['ERR00']); exit (0); } $this->LOP=($GIF_lop>-1)?$GIF_lop:0; $this->DIS=($GIF_dis>-1)?(($GIF_dis<3)?$GIF_dis:3):2; $this->COL=($GIF_red>-1&&$GIF_grn>-1&&$GIF_blu>-1)? ($GIF_red|($GIF_grn<<8)|($GIF_blu<<16)):-1; for($i=0;$i<count($GIF_src);$i++){ if(strToLower($GIF_mod)=="url"){ $this->BUF[]=fread(fopen($GIF_src[$i],"rb"),filesize($GIF_src[$i])); } elseif(strToLower($GIF_mod)=="bin"){ $this->BUF[]=$GIF_src[$i]; } else{ printf ("%s:%s(%s)!",$this->VER,$this->ERR['ERR02'],$GIF_mod); exit (0); } if(substr($this->BUF[$i],0,6)!="GIF87a"&&substr($this->BUF[$i],0,6)!="GIF89a"){ printf ("%s:%d%s",$this->VER,$i,$this->ERR['ERR01']); exit (0); } for($j=(13+3*(2<<(ord($this->BUF[$i]{10})&0x07))),$k=TRUE;$k;$j++){ switch($this->BUF[$i]{$j}){ case"!": if((substr($this->BUF[$i],($j+3),8))=="NETSCAPE"){ printf ("%s:%s(%ssource)!",$this->VER,$this->ERR['ERR03'],($i+1)); exit (0); } break; case";": $k=FALSE; break; } } } GIFEncoder::GIFAddHeader(); for($i=0;$i<count($this->BUF);$i++){ GIFEncoder::GIFAddFrames($i,$GIF_dly[$i]); } GIFEncoder::GIFAddFooter(); } /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GIFAddHeader... :: */ functionGIFAddHeader(){ $cmap=0; if(ord($this->BUF[0]{10})&0x80){ $cmap=3*(2<<(ord($this->BUF[0]{10})&0x07)); $this->GIF.=substr($this->BUF[0],6,7 ); $this->GIF.=substr($this->BUF[0],13,$cmap ); $this->GIF.="!/377/13NETSCAPE2.0/3/1".GIFEncoder::GIFWord($this->LOP)."/0"; } } /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GIFAddFrames... :: */ functionGIFAddFrames($i,$d){ $Locals_str=13+3*(2<<(ord($this->BUF[$i]{10})&0x07)); $Locals_end=strlen($this->BUF[$i])-$Locals_str-1; $Locals_tmp=substr($this->BUF[$i],$Locals_str,$Locals_end); $Global_len=2<<(ord($this->BUF[0 ]{10})&0x07); $Locals_len=2<<(ord($this->BUF[$i]{10})&0x07); $Global_rgb=substr($this->BUF[0 ],13, 3*(2<<(ord($this->BUF[0 ]{10})&0x07))); $Locals_rgb=substr($this->BUF[$i],13, 3*(2<<(ord($this->BUF[$i]{10})&0x07))); $Locals_ext="!/xF9/x04".chr(($this->DIS<<2)+0). chr(($d>>0)&0xFF).chr(($d>>8)&0xFF)."/x0/x0"; if($this->COL>-1&&ord($this->BUF[$i]{10})&0x80){ for($j=0;$j<(2<<(ord($this->BUF[$i]{10})&0x07));$j++){ if ( ord($Locals_rgb{3*$j+0})==($this->COL>> 0)&0xFF& ord($Locals_rgb{3*$j+1})==($this->COL>> 8)&0xFF& ord($Locals_rgb{3*$j+2})==($this->COL>>16)&0xFF ){ $Locals_ext="!/xF9/x04".chr(($this->DIS<<2)+1). chr(($d>>0)&0xFF).chr(($d>>8)&0xFF).chr($j)."/x0"; break; } } } switch($Locals_tmp{0}){ case"!": $Locals_img=substr($Locals_tmp,8,10); $Locals_tmp=substr($Locals_tmp,18,strlen($Locals_tmp)-18); break; case",": $Locals_img=substr($Locals_tmp,0,10); $Locals_tmp=substr($Locals_tmp,10,strlen($Locals_tmp)-10); break; } if(ord($this->BUF[$i]{10})&0x80&&$this->IMG>-1){ if($Global_len==$Locals_len){ if(GIFEncoder::GIFBlockCompare($Global_rgb,$Locals_rgb,$Global_len)){ $this->GIF.=($Locals_ext.$Locals_img.$Locals_tmp); } else{ $byte =ord($Locals_img{9}); $byte|=0x80; $byte&=0xF8; $byte|=(ord($this->BUF[0]{10})&0x07); $Locals_img{9}=chr($byte); $this->GIF.=($Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp); } } else{ $byte =ord($Locals_img{9}); $byte|=0x80; $byte&=0xF8; $byte|=(ord($this->BUF[$i]{10})&0x07); $Locals_img{9}=chr($byte); $this->GIF.=($Locals_ext.$Locals_img.$Locals_rgb.$Locals_tmp); } } else{ $this->GIF.=($Locals_ext.$Locals_img.$Locals_tmp); } $this->IMG =1; } /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GIFAddFooter... :: */ functionGIFAddFooter(){ $this->GIF.=";"; } /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GIFBlockCompare... :: */ functionGIFBlockCompare($GlobalBlock,$LocalBlock,$Len){ for($i=0;$i<$Len;$i++){ if ( $GlobalBlock{3*$i+0}!=$LocalBlock{3*$i+0}|| $GlobalBlock{3*$i+1}!=$LocalBlock{3*$i+1}|| $GlobalBlock{3*$i+2}!=$LocalBlock{3*$i+2} ){ return(0); } } return(1); } /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GIFWord... :: */ functionGIFWord($int){ return(chr($int&0xFF).chr(($int>>8)&0xFF)); } /* ::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: GetAnimation... :: */ functionGetAnimation(){ return($this->GIF); } } ?>