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 相关文章推荐
PHP中使用CURL伪造来路抓取页面或文件
May 04 PHP
file_get_contents获取不到网页内容的解决方法
Mar 07 PHP
php实现自动获取生成文章主题关键词功能的深入分析
Jun 03 PHP
php的array数组和使用实例简明教程(容易理解)
Mar 20 PHP
PHP关于htmlspecialchars、strip_tags、addslashes的解释
Jul 04 PHP
CodeIgniter实现更改view文件夹路径的方法
Jul 04 PHP
php中将一个对象保存到Session中的方法
Mar 13 PHP
PHP记录搜索引擎蜘蛛访问网站足迹的方法
Apr 15 PHP
CentOS下搭建PHP环境与WordPress博客程序的全流程总结
May 07 PHP
swoole和websocket简单聊天室开发
Nov 18 PHP
PHP+mysql实现的三级联动菜单功能示例
Feb 15 PHP
RSA实现JS前端加密与PHP后端解密功能示例
Aug 05 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 curl模拟浏览器抓取网站信息
2013/10/28 PHP
js从10种颜色中随机取色实现每次取出不同的颜色
2013/10/23 Javascript
js中Math之random,round,ceil,floor的用法总结
2013/12/26 Javascript
javascript正则表达式之search()用法实例
2015/01/19 Javascript
常用的JavaScript WEB操作方法分享
2015/02/28 Javascript
JavaScript的类型、值和变量小结
2015/07/09 Javascript
自动化测试读写64位操作系统的注册表
2016/08/15 Javascript
微信小程序 页面跳转及数据传递详解
2017/03/14 Javascript
Vue异步组件使用详解
2017/04/08 Javascript
利用require.js与angular搭建spa应用的方法实例
2017/07/19 Javascript
详解Node全局变量global模块
2017/09/28 Javascript
vue watch自动检测数据变化实时渲染的方法
2018/01/16 Javascript
基于vue2.0动态组件及render详解
2018/03/17 Javascript
微信小程序分享海报生成的实现方法
2018/12/10 Javascript
koa2 用户注册、登录校验与加盐加密的实现方法
2019/07/22 Javascript
微信小程序的授权实现过程解析
2019/08/02 Javascript
关于vue 项目中浏览器跨域的配置问题
2020/11/10 Javascript
[42:25]EG vs Spirit Supermajor 败者组 BO3 第二场 6.4
2018/06/05 DOTA
python Django连接MySQL数据库做增删改查
2013/11/07 Python
Python中使用 Selenium 实现网页截图实例
2014/07/18 Python
python制作websocket服务器实例分享
2016/11/20 Python
python定间隔取点(np.linspace)的实现
2019/11/27 Python
基于python 等频分箱qcut问题的解决
2020/03/03 Python
Python生成并下载文件后端代码实例
2020/08/31 Python
python 实现简单的计算器(gui界面)
2020/11/11 Python
data:image data url 文件转为Blob上传后端的方法
2019/07/16 HTML / CSS
Lands’ End英国官方网站:高质量男女服装
2017/10/07 全球购物
ALDO英国官网:加拿大女鞋品牌
2018/02/19 全球购物
整个世界的设计师家具在哈恩:Designathome
2019/03/25 全球购物
启动一个线程是用run()还是start()
2016/12/25 面试题
电子商务专业毕业生工作推荐信
2013/11/17 职场文书
如何填写个人简历自我评价
2013/12/10 职场文书
学生会宣传部部长竞选演讲稿
2014/04/25 职场文书
共产党员公开承诺践诺书
2014/05/28 职场文书
2015年毕业实习工作总结
2014/12/12 职场文书
护士求职自荐信范文
2015/03/04 职场文书