PHP使用GIFEncoder类生成gif动态滚动字幕


Posted in PHP onJuly 01, 2014

今天在公司,经理让做一个滚动字幕。但是,不许生成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 = new GIFEncoder($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_str as $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 = new GIFEncoder($imagedata,$delay,0,2,0,0,$transparent,"bin");

ob_start();

Header ('Content-type:image/gif');

echo $gif->GetAnimation();

?>

 GIFEncoder类源码:
 

 <?php

Class GIFEncoder {

    var $GIF = "GIF89a";                /* GIF header 6 bytes        */

    var $VER = "GIFEncoder V2.06";        /* Encoder version                */

    var $BUF = Array ( );

    var $LOP =  0;

    var $DIS =  2;

    var $COL = -1;

    var $IMG = -1;

    var $ERR = Array (

    'ERR00' =>"Does not supported function for only one image!",

    'ERR01' =>"Source is not a GIF image!",

    'ERR02' =>"Unintelligible flag ",

    'ERR03' =>"Could not make animation from animated GIF source",

    );

    /*

    :::::::::::::::::::::::::::::::::::::::::::::::::::

    ::

    ::        GIFEncoder...

    ::

    */

    function GIFEncoder        (

    $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 ] ) );

            }

            else if ( 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 ( %s source )!", $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...

    ::

    */

    function GIFAddHeader ( ) {

        $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...

    ::

    */

    function GIFAddFrames ( $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...

    ::

    */

    function GIFAddFooter ( ) {

        $this->GIF .= ";";

    }

    /*

    :::::::::::::::::::::::::::::::::::::::::::::::::::

    ::

    ::        GIFBlockCompare...

    ::

    */

    function GIFBlockCompare ( $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...

    ::

    */

    function GIFWord ( $int ) {

        return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) );

    }

    /*

    :::::::::::::::::::::::::::::::::::::::::::::::::::

    ::

    ::        GetAnimation...

    ::

    */

    function GetAnimation ( ) {

        return ( $this->GIF );

    }

}

?>

 
PHP 相关文章推荐
PHP4实际应用经验篇(7)
Oct 09 PHP
简单的PHP图片上传程序
Mar 27 PHP
PHP开发不能违背的安全规则 过滤用户输入
May 01 PHP
php中获取远程客户端的真实ip地址的方法
Aug 03 PHP
无JS,完全php面向过程数据分页实现代码
Aug 27 PHP
PHP中函数rand和mt_rand的区别比较
Dec 26 PHP
深入PHP与浏览器缓存的分析
Jun 03 PHP
php设置允许大文件上传示例代码
Mar 10 PHP
PHP中大于2038年时间戳的问题处理方案
Mar 03 PHP
PHP的文件操作与算法实现的面试题示例
Aug 10 PHP
php正则表达式验证(邮件地址、Url地址、电话号码、邮政编码)
Mar 14 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
Nov 17 PHP
PHP使用GIFEncoder类生成的GIF动态图片验证码
Jul 01 #PHP
ThinkPHP模板范围判断输出In标签与Range标签用法详解
Jun 30 #PHP
ThinkPHP模板判断输出Empty标签用法详解
Jun 30 #PHP
ThinkPHP模板判断输出Defined标签用法详解
Jun 30 #PHP
ThinkPHP模板判断输出Present标签用法详解
Jun 30 #PHP
ThinkPHP模板比较标签用法详解
Jun 30 #PHP
ThinkPHP模板Switch标签用法示例
Jun 30 #PHP
You might like
php array_walk() 数组函数
2011/07/12 PHP
PHP中的替代语法介绍
2015/01/09 PHP
php制作动态随机验证码
2015/02/12 PHP
PHP中获取文件创建日期、修改日期、访问时间的方法
2016/11/05 PHP
javascript 通用简单的table选项卡实现
2010/05/07 Javascript
Jquery中对数组的操作代码
2011/08/12 Javascript
jQuery最佳实践完整篇
2011/08/20 Javascript
回车直接实现点击某按钮的效果即触发单击事件
2014/02/27 Javascript
JavaScript编程的10个实用小技巧
2014/04/18 Javascript
浅谈Javascript中匀速运动的停止条件
2014/12/19 Javascript
Angularjs注入拦截器实现Loading效果
2015/12/28 Javascript
vue模板语法-插值详解
2017/03/06 Javascript
移动设备手势事件库Touch.js使用详解
2017/08/18 Javascript
微信小程序实现打卡日历功能
2020/09/21 Javascript
vue组件数据传递、父子组件数据获取,slot,router路由功能示例
2019/03/19 Javascript
一文读懂ES7中的javascript修饰器
2019/05/06 Javascript
jquery弹窗时禁止body滚动条滚动的例子
2019/09/21 jQuery
利用layer实现表单完美验证的方法
2019/09/26 Javascript
javascript实现摄像头拍照预览
2019/09/30 Javascript
vue 解除鼠标的监听事件的方法
2019/11/13 Javascript
js实现小时钟效果
2020/03/25 Javascript
使用 UniApp 实现小程序的微信登录功能
2020/06/09 Javascript
python scatter散点图用循环分类法加图例
2019/03/19 Python
Django Sitemap 站点地图的实现方法
2019/04/29 Python
python对象转字典的两种实现方式示例
2019/11/07 Python
css3 利用transform打造走动的2D时钟
2020/10/20 HTML / CSS
Jacadi Paris美国官方网站:法国童装品牌
2017/10/15 全球购物
加拿大床上用品、家居装饰、厨房和浴室产品购物网站:Linen Chest
2018/06/05 全球购物
基督教卡片、励志礼品、家居装饰等:DaySpring
2018/10/12 全球购物
如何删除一个表里面的重复行
2013/07/13 面试题
《鸿门宴》教学反思
2014/04/22 职场文书
2014小学语文教师个人工作总结
2014/12/03 职场文书
银行求职自荐信范文
2015/03/04 职场文书
工资证明格式模板
2015/06/12 职场文书
Python读取文件夹下的所有文件实例代码
2021/04/02 Python
Python卷积神经网络图片分类框架详解分析
2021/11/07 Python