PHP使用GIFEncoder类生成的GIF动态图片验证码


Posted in PHP onJuly 01, 2014

相信很多人都想过如何用PHP生成GIF动画来实现动态图片验证码,以下是实现过程。
ImageCode函数通过GIFEncoder类实现的GIF动画的PHP源代码,有兴趣的朋友可以研究一下。

效果如图:PHP使用GIFEncoder类生成的GIF动态图片验证码

/**

 

* ImageCode 生成GIF图片验证

 

* @param $string 字符串

 

* @param $width 宽度

 

* @param $height 高度

 

* */

 

function ImageCode($string = '', $width = 75, $height = 25)

 

{

 

$authstr = $string ? $string : ((time() % 2 == 0) ? mt_rand(1000, 9999) : mt_rand(10000, 99999));

 

$board_width = $width;

 

$board_height = $height;

 

// 生成一个32帧的GIF动画

 

for($i = 0; $i < 32; $i++)

 

{

 

ob_start();

 

$image = imagecreate($board_width, $board_height);

 

imagecolorallocate($image, 0,0,0);

 

// 设定文字颜色数组

 

$colorList[] = ImageColorAllocate($image, 15,73,210);

 

$colorList[] = ImageColorAllocate($image, 0,64,0);

 

$colorList[] = ImageColorAllocate($image, 0,0,64);

 

$colorList[] = ImageColorAllocate($image, 0,128,128);

 

$colorList[] = ImageColorAllocate($image, 27,52,47);

 

$colorList[] = ImageColorAllocate($image, 51,0,102);

 

$colorList[] = ImageColorAllocate($image, 0,0,145);

 

$colorList[] = ImageColorAllocate($image, 0,0,113);

 

$colorList[] = ImageColorAllocate($image, 0,51,51);

 

$colorList[] = ImageColorAllocate($image, 158,180,35);

 

$colorList[] = ImageColorAllocate($image, 59,59,59);

 

$colorList[] = ImageColorAllocate($image, 0,0,0);

 

$colorList[] = ImageColorAllocate($image, 1,128,180);

 

$colorList[] = ImageColorAllocate($image, 0,153,51);

 

$colorList[] = ImageColorAllocate($image, 60,131,1);

 

$colorList[] = ImageColorAllocate($image, 0,0,0);

 

$fontcolor = ImageColorAllocate($image, 0,0,0);

 

$gray = ImageColorAllocate($image, 245,245,245);

 

$color = imagecolorallocate($image, 255,255,255);

 

$color2 = imagecolorallocate($image, 255,0,0);

 

imagefill($image, 0, 0, $gray);

 

$space = 15; // 字符间距

 

if($i > 0) // 屏蔽第一帧

 

{

 

for ($k = 0; $k < strlen($authstr); $k++)

 

{

 

$colorRandom = mt_rand(0,sizeof($colorList)-1);

 

$float_top = rand(0,4);

 

$float_left = rand(0,3);

 

imagestring($image, 6, $space * $k, $top + $float_top, substr($authstr, $k, 1), $colorList[$colorRandom]);

 

}

 

}

 

for ($k = 0; $k < 20; $k++)

 

{

 

$colorRandom = mt_rand(0,sizeof($colorList)-1);

 

imagesetpixel($image, rand()%70 , rand()%15 , $colorList[$colorRandom]);

 

}

 

// 添加干扰线

 

for($k = 0; $k < 3; $k++)

 

{

 

$colorRandom = mt_rand(0, sizeof($colorList)-1);

 

// $todrawline = rand(0,1);

 

$todrawline = 1;

 

if($todrawline)

 

{

 

imageline($image, mt_rand(0, $board_width), mt_rand(0,$board_height), mt_rand(0,$board_width), mt_rand(0,$board_height), $colorList[$colorRandom]);

 

}

 

else

 

{

 

$w = mt_rand(0,$board_width);

 

$h = mt_rand(0,$board_width);

 

imagearc($image, $board_width - floor($w / 2) , floor($h / 2), $w, $h, rand(90,180), rand(180,270), $colorList[$colorRandom]);

 

}

 

}

 

imagegif($image);

 

imagedestroy($image);

 

$imagedata[] = ob_get_contents();

 

ob_clean();

 

++$i;

 

}

 

$gif = new GIFEncoder($imagedata);

 

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 相关文章推荐
NO3第三帝国留言簿制作过程
Oct 09 PHP
PHP安装攻略:常见问题解答(一)
Oct 09 PHP
php INI配置文件的解析实现分析
Jan 04 PHP
写出高质量的PHP程序
Feb 04 PHP
PHP数据库链接类(PDO+Access)实例分享
Dec 05 PHP
函数中使用require_once问题深入探讨 优雅的配置文件定义方法推荐
Jul 02 PHP
PHP数组遍历知识汇总(包含遍历方法、数组指针操作函数、数组遍历测速)
Jul 05 PHP
ThinkPHP自动完成中使用函数与回调方法实例
Nov 29 PHP
ThinkPHP设置禁止百度等搜索引擎转码(简单实用)
Feb 15 PHP
php实现中文转数字
Feb 18 PHP
PHP的openssl加密扩展使用小结(推荐)
Jul 18 PHP
tp5(thinkPHP5框架)captcha验证码配置及验证操作示例
May 28 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
ThinkPHP之foreach标签使用概述
Jun 30 #PHP
You might like
php中simplexml_load_file函数用法实例
2014/11/12 PHP
PHP+MySQL修改记录的方法
2015/01/21 PHP
PHP传参之传值与传址的区别
2015/04/24 PHP
php结合web uploader插件实现分片上传文件
2016/05/10 PHP
Javascript中的数学函数集合
2007/05/08 Javascript
javascript删除元素节点removeChild()用法实例
2015/05/26 Javascript
JavaScript如何调试有哪些建议和技巧附五款有用的调试工具
2015/10/28 Javascript
JS显示日历和天气的方法
2016/03/01 Javascript
ES6中非常实用的新特性介绍
2016/03/10 Javascript
再谈Javascript中的异步以及如何异步
2016/08/19 Javascript
jQuery层次选择器用法示例
2016/09/09 Javascript
js实现模糊匹配功能
2017/02/15 Javascript
使用MUI框架模拟手机端的下拉刷新和上拉加载功能
2017/09/04 Javascript
基于js原生和ajax的get和post方法以及jsonp的原生写法实例
2017/10/16 Javascript
Node错误处理笔记之挖坑系列教程
2018/06/05 Javascript
Vue axios设置访问基础路径方法
2018/09/19 Javascript
vue富文本编辑器组件vue-quill-edit使用教程
2018/09/21 Javascript
js变量值传到php过程详解 将php解析成数据
2019/06/26 Javascript
javascript二维数组和对象的深拷贝与浅拷贝实例分析
2019/10/26 Javascript
小程序登录之支付宝授权的实现示例
2019/12/13 Javascript
Nodejs + sequelize 实现增删改查操作
2020/11/07 NodeJs
[01:57]DOTA2上海特锦赛小组赛解说单车采访花絮
2016/02/27 DOTA
python 生成不重复的随机数的代码
2011/05/15 Python
Python正则表达式匹配HTML页面编码
2015/04/08 Python
分享PyCharm最新激活码(真永久激活方法)不用每月找安装参数或最新激活码了
2020/12/27 Python
西铁城美国官方网站:Citizen Watch美国
2019/11/08 全球购物
NET程序员上机面试题
2015/05/23 面试题
消防安全汇报材料
2014/02/08 职场文书
办公自动化专业大学生职业规划书
2014/03/06 职场文书
工作简历自我评价
2015/03/11 职场文书
2015年社区计生工作总结
2015/04/21 职场文书
银行保安拾金不昧表扬稿
2015/05/05 职场文书
Python 如何解决稀疏矩阵运算
2021/05/26 Python
Python爬虫中urllib3与urllib的区别是什么
2021/07/21 Python
Python装饰器的练习题
2021/11/23 Python
hive数据仓库新增字段方法
2022/06/25 数据库