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操作xml代码
Jun 17 PHP
利用PHP实现智能文件类型检测的实现代码
Aug 02 PHP
php ci框架验证码实例分析
Jun 26 PHP
PHP实现绘制3D扇形统计图及图片缩放实例
Oct 01 PHP
Laravel 5.3 学习笔记之 配置
Aug 28 PHP
PHP7标量类型declare用法实例分析
Sep 26 PHP
php json_encode与json_decode详解及实例
Dec 13 PHP
php7基于递归实现删除空文件夹的方法示例
Jun 15 PHP
Laravel框架实现的记录SQL日志功能示例
Jun 19 PHP
ThinkPHP中图片按比例切割的代码实例
Mar 08 PHP
使用Zookeeper分布式部署PHP应用程序
Mar 15 PHP
php和vue配合使用技巧和方法
May 09 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
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
php 获取mysql数据库信息代码
2009/03/12 PHP
snoopy 强大的PHP采集类使用实例代码
2010/12/09 PHP
使ecshop模板中可引用常量的实现方法
2011/06/02 PHP
实例分析基于PHP微信网页获取用户信息
2017/11/24 PHP
前端必备神器 Snap.svg 弹动效果
2014/11/10 Javascript
WEB前端设计师常用工具集锦
2014/12/09 Javascript
javascript中的3种继承实现方法
2016/01/27 Javascript
jQuery解决浏览器兼容性问题案例分析
2016/04/15 Javascript
JavaScript中数组的22种方法必学(推荐)
2016/07/20 Javascript
js select下拉联动 更具级联性!
2020/04/17 Javascript
微信小程序 两种为对象属性赋值的方式详解
2017/02/23 Javascript
jQuery ajax读取本地json文件的实例
2017/10/31 jQuery
javascript 易错知识点实例小结
2020/04/25 Javascript
[44:30]完美世界DOTA2联赛PWL S2 GXR vs Magma 第一场 11.25
2020/11/26 DOTA
Python环境搭建之OpenCV的步骤方法
2017/10/20 Python
Numpy array数据的增、删、改、查实例
2018/06/04 Python
解决Pycharm出现的部分快捷键无效问题
2018/10/22 Python
Python3监控疫情的完整代码
2020/02/20 Python
法国珠宝店:CLEOR
2017/01/29 全球购物
苏格兰在线威士忌商店:The Whisky Barrel
2019/05/07 全球购物
写一个方法1000的阶乘
2012/11/21 面试题
什么是组件架构
2016/05/15 面试题
移动通信专业自荐信范文
2013/11/12 职场文书
家庭教育先进个人事迹材料
2014/01/24 职场文书
商务英语广告词大全
2014/03/18 职场文书
公司担保书格式范文
2014/05/12 职场文书
基层党员干部四风问题整改方向和措施
2014/09/25 职场文书
2014年教师德育工作总结
2014/11/10 职场文书
新郎接新娘保证书
2015/05/08 职场文书
项目备案申请报告
2015/05/15 职场文书
法制工作总结2015
2015/07/23 职场文书
三八节祝酒词
2015/08/11 职场文书
三好学生竞选稿
2015/11/21 职场文书
本地通过nginx配置反向代理的全过程记录
2021/03/31 Servers
gtx1650怎么样 gtx1650显卡相当于什么级别
2022/04/08 数码科技