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 相关文章推荐
JS中encodeURIComponent函数用php解码的代码
Mar 01 PHP
Win下如何安装PHP的APC拓展
Aug 07 PHP
PHP迭代器实现斐波纳契数列的函数
Nov 12 PHP
javascript数组与php数组的地址传递及值传递用法实例
Jan 22 PHP
PHP的APC模块实现上传进度条
Oct 27 PHP
Yii2隐藏frontend/web和backend/web的方法
Dec 12 PHP
Laravel SQL语句记录方式(推荐)
May 26 PHP
PHP flush 函数使用注意事项
Aug 26 PHP
php识别翻转iphone拍摄的颠倒图片
May 17 PHP
PHP实现PDO操作mysql存储过程示例
Feb 13 PHP
Thinkphp5.0 框架实现控制器向视图view赋值及视图view取值操作示例
Oct 12 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 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
全国FM电台频率大全 - 31 新疆维吾尔族自治区
2020/03/11 无线电
最令PHP初学者们头痛的十四个问题
2007/01/15 PHP
无法在发生错误时创建会话,请检查 PHP 或网站服务器日志,并正确配置 PHP 安装(win+linux)
2012/05/05 PHP
yii上传文件或图片实例
2014/04/01 PHP
php调用nginx的mod_zip模块打包ZIP文件
2014/06/11 PHP
PHP框架Laravel学习心得体会
2015/10/28 PHP
php实现统计目录文件大小的函数
2015/12/25 PHP
PHP的Yii框架中YiiBase入口类的扩展写法示例
2016/03/17 PHP
ThinkPHP框架整合微信支付之Native 扫码支付模式一图文详解
2019/04/09 PHP
gearman中任务的优先级和返回状态实例分析
2020/02/27 PHP
jQuery Tips 为AJAX回调函数传递额外参数的方法
2010/12/28 Javascript
js获取系统的根路径实现介绍
2013/09/08 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
实例讲解JavaScript中call、apply、bind方法的异同
2016/09/13 Javascript
JQuery和HTML5 Canvas实现弹幕效果
2017/01/04 Javascript
遍历json获得数据的几种方法小结
2017/01/21 Javascript
为jquery的ajax请求添加超时timeout时间的操作方法
2018/09/04 jQuery
js+css3实现简单时钟特效
2020/09/13 Javascript
vue-resource 拦截器interceptors使用详解
2021/01/18 Vue.js
[03:56]DOTA2完美大师赛趣味视频之小鸽子和Mineski打台球
2017/11/24 DOTA
matplotlib设置legend图例代码示例
2017/12/19 Python
python利用openpyxl拆分多个工作表的工作簿的方法
2019/09/27 Python
python+tifffile之tiff文件读写方式
2020/01/13 Python
如何查看python关键字
2021/01/17 Python
CSS3 实现的加载动画
2020/12/07 HTML / CSS
Free People中国官网:波西米亚风格女装服饰
2016/08/30 全球购物
C#中的验证控件有几种
2014/03/08 面试题
JS原生实现轮播图的几种方法
2021/03/23 Javascript
yy婚礼主持词
2014/03/14 职场文书
公司合作协议书范本
2014/04/18 职场文书
跳蚤市场口号
2014/06/13 职场文书
合伙经营协议书范本
2014/09/13 职场文书
普通党员个人剖析材料
2014/10/08 职场文书
2014年后勤工作总结
2014/11/18 职场文书
如何使用php生成zip压缩包
2021/04/21 PHP
Java字符缓冲流BufferedWriter
2022/04/09 Java/Android