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 相关文章推荐
session 的生命周期是多长
Oct 09 PHP
php与paypal整合方法
Nov 28 PHP
如何在PHP中使用正则表达式进行查找替换
Jun 13 PHP
php实现的常见排序算法汇总
Sep 08 PHP
php修改文件上传限制方法汇总
Apr 07 PHP
PHP中iconv函数知识汇总
Jul 02 PHP
PHP入门教程之数学运算技巧总结
Sep 11 PHP
PHP异常类及异常处理操作实例详解
Dec 19 PHP
PHP Primary script unknown 解决方法总结
Aug 22 PHP
PHP迭代器和生成器用法实例分析
Sep 28 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 PHP
PHP如何使用array_unshift()在数组开头插入元素
Sep 01 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
在数据量大(超过10万)的情况下
2007/01/15 PHP
php Ajax乱码
2008/04/09 PHP
ThinkPHP3.2.1图片验证码实现方法
2016/08/19 PHP
php工具型代码之印章抠图
2018/07/18 PHP
再谈IE中Flash控件的自动激活 ObjectWrap
2007/03/09 Javascript
Expandable &quot;Detail&quot; Table Rows
2007/08/29 Javascript
JavaScript全局函数使用简单说明
2011/03/11 Javascript
node.js中的fs.realpath方法使用说明
2014/12/16 Javascript
javascript事件冒泡实例分析
2015/05/13 Javascript
angularJS+requireJS实现controller及directive的按需加载示例
2017/02/20 Javascript
Bootstrap 过渡效果Transition 模态框(Modal)
2017/03/17 Javascript
JavaScript之filter_动力节点Java学院整理
2017/06/28 Javascript
BootStrap Table前台和后台分页对JSON格式的要求
2017/06/28 Javascript
Nuxt.js 数据双向绑定的实现
2019/02/17 Javascript
移动端底部导航固定配合vue-router实现组件切换功能
2019/06/13 Javascript
js代码编写无缝轮播图
2020/09/13 Javascript
JavaScript实现五子棋小游戏
2020/10/26 Javascript
jQuery实现容器间的元素拖拽功能
2020/12/01 jQuery
python实现网站的模拟登录
2016/01/04 Python
Python基于更相减损术实现求解最大公约数的方法
2018/04/04 Python
python实现寻找最长回文子序列的方法
2018/06/02 Python
Python 中的range(),以及列表切片方法
2018/07/02 Python
Python中如何使用if语句处理列表实例代码
2019/02/24 Python
python 内置函数汇总详解
2019/09/16 Python
关于TensorFlow新旧版本函数接口变化详解
2020/02/10 Python
python获取天气接口给指定微信好友发天气预报
2020/12/28 Python
css3实现文字扫光渐变动画效果的示例
2017/11/07 HTML / CSS
Myprotein葡萄牙官方网站:英国优质运动营养品牌
2016/09/12 全球购物
可靠的数据流传输TCP
2016/03/15 面试题
艺术设计专业个人求职信
2013/09/21 职场文书
单位人事专员介绍信
2014/01/11 职场文书
十月份红领巾广播稿
2014/01/22 职场文书
鉴定评语大全
2014/05/05 职场文书
四十年同学聚会致辞
2015/07/28 职场文书
2016年12月份红领巾广播稿
2015/12/21 职场文书
文明和谐家庭事迹材料(2016精选版)
2016/02/29 职场文书