PHP生成Gif图片验证码


Posted in PHP onOctober 27, 2013

先看效果图
PHP生成Gif图片验证码
 PHP生成Gif图片验证码

字体及字体文件的路径需要在类中$FontFilePath及$FontFileName中设置。如:

private static $FontFilePath = "static/font/"; //相对地本代码文件的位置
private static $FontFileName = array("3.ttf");// array("1.ttf", "2.ttf", "3.ttf", "4.ttf", "5.ttf", "6.ttf", "7.ttf", "8.ttf"); //

完整代码如下:
<?PHP
/**
  说明: 验证码生成类,支持生成Gif图片验证码(带噪点,干扰线,网格,随机色背景,随机自定义字体,倾斜,Gif动画)
  服务端:
  $mod = strtolower(isset($_REQUEST["mod"]) ? $_REQUEST["mod"] : "");
  if($mod == "code"){
  echo SecurityCode::Draw(4, 1, 120, 30, 5, 10, 100, "secode");
  die();
  }
  调用: <img src="/getcode.php?mod=code" onclick="this.src='/getcode.php?mod=code&r='+Math.round(Math.random(0)*1000)">
  验证:
  $reqCode = strtolower(isset($_REQUEST["secode"]) ? $_REQUEST["secode"] : "");  //请求的验证码
  $sessionCode = strtolower(isset($_SESSION["secode"]) ? $_SESSION["secode"] : ""); //会话生成的验证码
  if($reqCode != $sessionCode){
  echo "安全验证码错误!";
  die();
  }
 */
$mod = strtolower(isset($_REQUEST["mod"]) ? $_REQUEST["mod"] : "");
if ($mod == "code") {
    echo SecurityCode::Draw(4, 15, 100, 27, 10, 2, 100, "secode");
    die();
}
//安全验证码类
class SecurityCode {
    private static $Debug = 0;
    private static $Code = '';
    private static $Chars = 'bcdefhkmnrstuvwxyABCDEFGHKMNPRSTUVWXY34568';
    //private static $Chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890';
    private static $TextGap = 20;
    private static $TextMargin = 5;
    private static $FontFilePath = "static/font/"; //相对地本代码文件的位置
    private static $FontFileName =array("3.ttf");// array("1.ttf", "2.ttf", "3.ttf", "4.ttf", "5.ttf", "6.ttf", "7.ttf", "8.ttf"); //
    private static $Img = 'GIF89a'; //GIF header 6 bytes    
    private static $BUF = Array();
    private static $LOP = 0;
    private static $DIS = 2;
    private static $COL = -1;
    private static $IMG = -1;
    /**
      生成GIF图片验证
      @param int $L 验证码长度
      @param int $F 生成Gif图的帧数
      @param int $W 宽度
      @param int $H 高度
      @param int $MixCnt 干扰线数
      @param int $lineGap 网格线间隔
      @param int $noisyCnt 澡点数
      @param int $sessionName 验证码Session名称
     */
    public static function Draw($L = 4, $F = 1, $W = 150, $H = 30, $MixCnt = 2, $lineGap = 0, $noisyCnt = 10, $sessionName = "Code") {
        ob_start();
        ob_clean();
        for ($i = 0; $i < $L; $i++) {
            self::$Code .= SubStr(self::$Chars, mt_rand(0, strlen(self::$Chars) - 1), 1);
        }
        if (!isset($_SESSION))
            session_start();
        $_SESSION[$sessionName] = strtolower(self::$Code);
        $bgRGB = array(rand(0, 255), rand(0, 255), rand(0, 255));
        //生成一个多帧的GIF动画
        for ($i = 0; $i < $F; $i++) {
            $img = ImageCreate($W, $H);
            //背景色
            $bgColor = imagecolorallocate($img, $bgRGB[0], $bgRGB[1], $bgRGB[2]);
            ImageColorTransparent($img, $bgColor);
            unset($bgColor);
            //添加噪点
            $maxNoisy = rand(0, $noisyCnt);
            $noisyColor = imagecolorallocate($img, rand(0, 255), rand(0, 255), rand(0, 255));
            for ($k = 0; $k <= $maxNoisy; $k++) {
                imagesetpixel($img, rand(0, $W), rand(0, $H), $noisyColor);
            }
            //添加网格
            if ($lineGap > 0) {
                for ($m = 0; $m < ($W / $lineGap); $m++) { //竖线
                    imageline($img, $m * $lineGap, 0, $m * $lineGap, $H, $noisyColor);
                }
                for ($n = 0; $n < ($H / $lineGap); $n++) { //横线
                    imageline($img, 0, $n * $lineGap, $W, $n * $lineGap, $noisyColor);
                }
            }
            unset($noisyColor);
            // 添加干扰线
            for ($k = 0; $k < $MixCnt; $k++) {
                $wr = mt_rand(0, $W);
                $hr = mt_rand(0, $W);
                $lineColor = imagecolorallocate($img, rand(0, 255), rand(0, 255), rand(0, 255));
                imagearc($img, $W - floor($wr / 2), floor($hr / 2), $wr, $hr, rand(90, 180), rand(180, 270), $lineColor);
                unset($lineColor);
                unset($wr, $hr);
            }
            //第一帧忽略文字
            if ($i != 0 || $F <= 1) {
                //文字            
                $foreColor = imagecolorallocate($img, rand(0, 255), rand(0, 255), rand(0, 255));
                for ($j = 0; $j < $L; $j++) {
                    $fontFile = self::$FontFilePath . self::$FontFileName[rand(0, count(self::$FontFileName) - 1)];
                    if (!file_exists($fontFile))
                        imagestring($img, 4, self::$TextMargin + $j * self::$TextGap, ($H - rand($H / 2, $H)), self::$Code[$j], $foreColor);
                    else
                        imageTTFtext($img, rand(15, 18), rand(-15, 15), self::$TextMargin + $j * self::$TextGap, ($H - rand(7, 10)), $foreColor, $fontFile, self::$Code[$j]);
                }
                unset($foreColor);
            }
            ImageGif($img);
            Imagedestroy($img);
            $Imdata[] = ob_get_contents();
            OB_clean();
        }
        unset($W, $H, $B);
        if (self::$Debug) {
            echo $_SESSION['code'];
            echo '<pre>', Var_Dump($Imdata), '</pre>';
            die();
        }
        header('Content-type:image/gif');
        return self::CreateGif($Imdata, 20);
        unset($Imdata);
    }
    private static function CreateGif($GIF_src, $GIF_dly = 10, $GIF_lop = 0, $GIF_dis = 0, $GIF_red = 0, $GIF_grn = 0, $GIF_blu = 0, $GIF_mod = 'bin') {
        if (!is_array($GIF_src) && !is_array($GIF_tim)) {
            throw New Exception('Error:' . __LINE__ . ',Does not supported function for only one image!!');
            die();
        }
        self::$LOP = ($GIF_lop > -1) ? $GIF_lop : 0;
        self::$DIS = ($GIF_dis > -1) ? (($GIF_dis < 3) ? $GIF_dis : 3) : 2;
        self::$COL = ($GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1) ? ($GIF_red | ($GIF_grn << 8) | ($GIF_blu << 16)) : -1;
        for ($i = 0, $src_count = count($GIF_src); $i < $src_count; $i++) {
            if (strToLower($GIF_mod) == 'url') {
                self::$BUF[] = fread(fopen($GIF_src[$i], 'rb'), filesize($GIF_src[$i]));
            } elseif (strToLower($GIF_mod) == 'bin') {
                self::$BUF[] = $GIF_src[$i];
            } else {
                throw New Exception('Error:' . __LINE__ . ',Unintelligible flag (' . $GIF_mod . ')!');
                die();
            }
            if (!(Substr(self::$BUF[$i], 0, 6) == 'GIF87a' Or Substr(self::$BUF[$i], 0, 6) == 'GIF89a')) {
                throw New Exception('Error:' . __LINE__ . ',Source ' . $i . ' is not a GIF image!');
                die();
            }
            for ($j = (13 + 3 * (2 << (ord(self::$BUF[$i]{10}) & 0x07))), $k = TRUE; $k; $j++) {
                switch (self::$BUF[$i]{$j}) {
                    case '!':
                        if ((substr(self::$BUF[$i], ($j + 3), 8)) == 'NETSCAPE') {
                            throw New Exception('Error:' . __LINE__ . ',Could not make animation from animated GIF source (' . ($i + 1) . ')!');
                            die();
                        }
                        break;
                    case ';':
                        $k = FALSE;
                        break;
                }
            }
        }
        self::AddHeader();
        for ($i = 0, $count_buf = count(self::$BUF); $i < $count_buf; $i++) {
            self::AddFrames($i, $GIF_dly);
        }
        self::$Img .= ';';
        return (self::$Img);
    }
    private static function AddHeader() {
        $i = 0;
        if (ord(self::$BUF[0]{10}) & 0x80) {
            $i = 3 * (2 << (ord(self::$BUF[0]{10}) & 0x07));
            self::$Img .= substr(self::$BUF[0], 6, 7);
            self::$Img .= substr(self::$BUF[0], 13, $i);
            self::$Img .= "!\377\13NETSCAPE2.0\3\1" . chr(self::$LOP & 0xFF) . chr((self::$LOP >> 8) & 0xFF) . "\0";
        }
        unset($i);
    }
    private static function AddFrames($i, $d) {
        $L_str = 13 + 3 * (2 << (ord(self::$BUF[$i]{10}) & 0x07));
        $L_end = strlen(self::$BUF[$i]) - $L_str - 1;
        $L_tmp = substr(self::$BUF[$i], $L_str, $L_end);
        $G_len = 2 << (ord(self::$BUF[0]{10}) & 0x07);
        $L_len = 2 << (ord(self::$BUF[$i]{10}) & 0x07);
        $G_rgb = substr(self::$BUF[0], 13, 3 * (2 << (ord(self::$BUF[0]{10}) & 0x07)));
        $L_rgb = substr(self::$BUF[$i], 13, 3 * (2 << (ord(self::$BUF[$i]{10}) & 0x07)));
        $L_ext = "!\xF9\x04" . chr((self::$DIS << 2) + 0) . chr(($d >> 0) & 0xFF) . chr(($d >> 8) & 0xFF) . "\x0\x0";
        if (self::$COL > -1 && ord(self::$BUF[$i]{10}) & 0x80) {
            for ($j = 0; $j < (2 << (ord(self::$BUF[$i]{10}) & 0x07)); $j++) {
                if (ord($L_rgb{3 * $j + 0}) == (self::$COL >> 0) & 0xFF && ord($L_rgb{3 * $j + 1}) == (self::$COL >> 8) & 0xFF && ord($L_rgb{3 * $j + 2}) == (self::$COL >> 16) & 0xFF) {
                    $L_ext = "!\xF9\x04" . chr((self::$DIS << 2) + 1) . chr(($d >> 0) & 0xFF) . chr(($d >> 8) & 0xFF) . chr($j) . "\x0";
                    break;
                }
            }
        }
        switch ($L_tmp{0}) {
            case '!':
                $L_img = substr($L_tmp, 8, 10);
                $L_tmp = substr($L_tmp, 18, strlen($L_tmp) - 18);
                break;
            case ',':
                $L_img = substr($L_tmp, 0, 10);
                $L_tmp = substr($L_tmp, 10, strlen($L_tmp) - 10);
                break;
        }
        if (ord(self::$BUF[$i]{10}) & 0x80 && self::$IMG > -1) {
            if ($G_len == $L_len) {
                if (self::Compare($G_rgb, $L_rgb, $G_len)) {
                    self::$Img .= ($L_ext . $L_img . $L_tmp);
                } else {
                    $byte = ord($L_img{9});
                    $byte |= 0x80;
                    $byte &= 0xF8;
                    $byte |= (ord(self::$BUF[0]{10}) & 0x07);
                    $L_img{9} = chr($byte);
                    self::$Img .= ($L_ext . $L_img . $L_rgb . $L_tmp);
                }
            } else {
                $byte = ord($L_img{9});
                $byte |= 0x80;
                $byte &= 0xF8;
                $byte |= (ord(self::$BUF[$i]{10}) & 0x07);
                $L_img{9} = chr($byte);
                self::$Img .= ($L_ext . $L_img . $L_rgb . $L_tmp);
            }
        } else {
            self::$Img .= ($L_ext . $L_img . $L_tmp);
        }
        self::$IMG = 1;
    }
    private static function Compare($G_Block, $L_Block, $Len) {
        for ($i = 0; $i < $Len; $i++) {
            if ($G_Block{3 * $i + 0} != $L_Block{3 * $i + 0} || $G_Block{3 * $i + 1} != $L_Block{3 * $i + 1} || $G_Block{3 * $i + 2} != $L_Block{3 * $i + 2}) {
                return (0);
            }
        }
        return (1);
    }
}

用法在类开头的注释里。
PHP 相关文章推荐
PHP开发框架总结收藏
Apr 24 PHP
Cannot modify header information错误解决方法
Oct 08 PHP
php编写的简单页面跳转功能实现代码
Nov 27 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
PHP借助phpmailer发送邮件
May 11 PHP
PHP合并数组函数array_merge用法分析
Feb 17 PHP
php基于数组函数实现关联表的编辑操作示例
Jul 04 PHP
php实现和c#一致的DES加密解密实例
Jul 24 PHP
使用php自动备份数据库表的实现方法
Jul 28 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
Nov 14 PHP
laravel实现一个上传图片的接口,并建立软链接,访问图片的方法
Oct 12 PHP
PHP使用QR Code生成二维码实例
Jul 07 PHP
php操作xml
Oct 27 #PHP
关于php内存不够用的快速解决方法
Oct 26 #PHP
PHP中$_SERVER的详细参数与说明介绍
Oct 26 #PHP
php数组转换js数组操作及json_encode的用法详解
Oct 26 #PHP
php while循环得到循环次数
Oct 26 #PHP
php中OR与|| AND与&amp;&amp;的区别总结
Oct 26 #PHP
php中的PHP_EOL换行符详细解析
Oct 26 #PHP
You might like
编写PHP的安全策略
2006/10/09 PHP
PHP Memcached应用实现代码
2010/02/08 PHP
ThinkPHP 防止表单重复提交的方法
2011/08/08 PHP
JQuery 1.3.2以上版本中出现pareseerror错误的解决方法
2011/01/11 Javascript
JS中setTimeout()的用法详解
2013/04/14 Javascript
js实现单行文本向上滚动效果实例代码
2013/11/28 Javascript
js获取窗口相对于屏幕左边和上边的位置坐标
2014/05/15 Javascript
js实现两点之间画线的方法
2015/05/12 Javascript
JS实现先显示大图后自动收起显示小图的广告代码
2015/09/04 Javascript
jQuery模拟物体自由落体运动(附演示与demo源码下载)
2016/01/21 Javascript
JS操作JSON方法总结(推荐)
2016/06/14 Javascript
jQuery条件分页 代替离线查询(附代码)
2017/08/17 jQuery
weex里Vuex state使用storage持久化详解
2017/09/09 Javascript
JS随机数产生代码分享
2018/02/24 Javascript
vue路由组件按需加载的几种方法小结
2018/07/12 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
微信用户访问小程序的登录过程详解
2019/09/20 Javascript
vue props对象validator自定义函数实例
2019/11/13 Javascript
小程序api实现promise封装过程解析
2019/11/21 Javascript
原生JS实现拖拽功能
2020/12/16 Javascript
Python cookbook(数据结构与算法)实现查找两个字典相同点的方法
2018/02/18 Python
Numpy之文件存取的示例代码
2018/08/03 Python
​如何愉快地迁移到 Python 3
2019/04/28 Python
selenium跳过webdriver检测并模拟登录淘宝
2019/06/12 Python
Django 反向生成url实例详解
2019/07/30 Python
python实现代码统计程序
2019/09/19 Python
.dcm格式文件软件读取及python处理详解
2020/01/16 Python
python 实现图像快速替换某种颜色
2020/06/04 Python
Alba Moda德国网上商店:意大利时尚女装销售
2016/11/14 全球购物
北美三大旅游网站之一:Travelocity
2017/08/12 全球购物
文件中有一组整数,要求排序后输出到另一个文件中
2012/01/04 面试题
年度考核自我鉴定
2013/11/09 职场文书
社区巾帼文明岗事迹材料
2014/06/03 职场文书
机关单位工作失职检讨书
2014/11/20 职场文书
使用Oracle命令进行数据库备份与还原
2021/12/06 Oracle
在ubuntu下安装go开发环境的全过程
2022/08/05 Golang