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 相关文章推荐
Gregarius中文日期格式问题解决办法
Apr 22 PHP
PHP使用PDO连接ACCESS数据库
Mar 05 PHP
PHP使用递归生成文章树
Apr 21 PHP
php cookie工作原理与实例详解
Jul 18 PHP
详谈php静态方法及普通方法的区别
Oct 04 PHP
PHP串行化与反串行化实例分析
Dec 27 PHP
php利用imagemagick实现复古老照片效果实例
Feb 16 PHP
PHP的RSA加密解密方法以及开发接口使用
Feb 11 PHP
php微信扫码支付 php公众号支付
Mar 24 PHP
laravel 多图上传及图片的存储例子
Oct 14 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
Dec 20 PHP
TP3.2框架分页相关实现方法分析
Jun 03 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
WINDOWS下php5.2.4+mysql6.0+apache2.2.4+ZendOptimizer-3.3.0配置
2008/03/28 PHP
php使用PDO下exec()函数查询执行后受影响行数的方法
2017/03/28 PHP
JQuery EasyUI 对话框的使用方法
2010/10/24 Javascript
3分钟写出来的Jquery版checkbox全选反选功能
2013/10/23 Javascript
JavaScript中的console.time()函数详细介绍
2014/12/29 Javascript
JS实现一个按钮的方法
2015/02/05 Javascript
js实现鼠标划过给div加透明度的方法
2015/05/25 Javascript
无刷新上传文件并返回自定义值
2015/06/11 Javascript
js利用正则表达式检验输入内容是否为网址
2016/07/05 Javascript
canvas实现探照灯效果
2017/02/07 Javascript
Angular2开发——组件规划篇
2017/03/28 Javascript
JS实现移动端实时监听输入框变化的实例代码
2017/04/12 Javascript
详解weex默认webpack.config.js改造
2018/01/08 Javascript
vue中实现移动端的scroll滚动方法
2018/03/03 Javascript
react中使用swiper的具体方法
2018/05/15 Javascript
Vue的click事件防抖和节流处理详解
2019/11/13 Javascript
深入了解JS之作用域和闭包
2020/06/16 Javascript
vue实现整屏滚动切换
2020/06/29 Javascript
vue+iview分页组件的封装
2020/11/17 Vue.js
[05:46]DOTA2英雄梦之声_第18期_陈
2014/06/20 DOTA
[34:39]DOTA2上海特级锦标赛主赛事日 - 4 败者组第四轮#1COL VS EG第二局
2016/03/05 DOTA
Python中非常实用的一些功能和函数分享
2015/02/14 Python
详解Python中find()方法的使用
2015/05/18 Python
Python扫描IP段查看指定端口是否开放的方法
2015/06/09 Python
利用python模拟实现POST请求提交图片的方法
2017/07/25 Python
Python实现数据可视化看如何监控你的爬虫状态【推荐】
2018/08/10 Python
Python语法分析之字符串格式化
2019/06/13 Python
Python2和3字符编码的区别知识点整理
2019/08/08 Python
python 实现目录复制的三种小结
2019/12/04 Python
tensorflow 获取所有variable或tensor的name示例
2020/01/04 Python
python实现五子棋游戏(pygame版)
2020/01/19 Python
python程序文件扩展名知识点详解
2020/02/27 Python
Python参数传递机制传值和传引用原理详解
2020/05/22 Python
英智兴达软件测试笔试题
2016/10/12 面试题
2015年教学副校长工作总结
2015/07/22 职场文书
小学二年级班主任工作经验交流材料
2015/11/02 职场文书