欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

PHP生成Gif图片验证码

程序员文章站 2023-11-12 09:10:10
先看效果图  字体及字体文件的路径需要在类中$fontfilepath及$fontfilename中设置。如:复制代码 代码如下:private static...

先看效果图
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);
    }

}


用法在类开头的注释里。