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);
}
}
?>