<?php
        //验证码类
       class ValidateCode {
              private $charset = 'abcdefhjkmnprstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ2345678'; //随机因子
              private $code;       //验证码
              private $codelen = 4;     //验证码长度
              private $width = 300;     //宽度
              private $height = 114;     //高度
              private $img;        //图形资源句柄
              private $font;        //指定的字体
              private $fontsize = 50;    //指定字体大小
              private $fontcolor;      //指定字体颜色  
 
              //构造方法初始化
              public function __construct() {
                  $_rnd = mt_rand(1, 9);
                  $this->font = "./$_rnd.ttf";
              }  
 
            //生成随机码
              private function createCode() {
                 $_len = strlen($this->charset)-1;
                 for ($i=0;$i<$this->codelen;$i++) {
                        $this->code .= $this->charset[mt_rand(0,$_len)];
                 }
              }  
 
              //生成背景
              private function createBg() {
                 $this->img = imagecreatetruecolor($this->width, $this->height);
                 $color = imagecolorallocate($this->img, mt_rand(157,255), mt_rand(157,255), mt_rand(157,255));
                 imagefilledrectangle($this->img,0,$this->height,$this->width,0,$color);
              }  
 
              //生成文字
              private function createFont() {
                 $_x = $this->width / $this->codelen;
                 for ($i=0;$i<$this->codelen;$i++) {
						$_rnd = mt_rand(1, 9);
						$this->font = "./$_rnd.ttf";
                        $this->fontcolor = imagecolorallocate($this->img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
                        imagettftext($this->img,$this->fontsize,mt_rand(-40,40),$_x*$i+mt_rand(5,20),$this->height / 1.4,$this->fontcolor,$this->font,$this->code[$i]);
                 }
              }  
 
              //生成线条、雪花
              private function createLine() {
                 for ($i=0;$i<5;$i++) {
                        $color = imagecolorallocate($this->img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
                        imageline($this->img,mt_rand(0,$this->width),mt_rand(0,$this->height),mt_rand(0,$this->width),mt_rand(0,$this->height),$color);
                 }
                 /*
                 $_len = strlen($this->charset)-1;
                 for ($i=0;$i<60;$i++) {
                        $_str = $this->charset[mt_rand(0,$_len)];
                        $color = imagecolorallocate($this->img,mt_rand(156,200),mt_rand(156,200),mt_rand(156,200));
                        imagestring($this->img,mt_rand(1,5),mt_rand(0,$this->width),mt_rand(0,$this->height),$_str,$color);
                 }
                 */
                 for ($i=0;$i<30;$i++) {
                        $color = imagecolorallocate($this->img,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255));
                        imagestring($this->img,mt_rand(1,5),mt_rand(0,$this->width),mt_rand(0,$this->height),'*',$color);
                 }
              }  
 
 
 
            /**
             * 画杂点
             * 往图片上写不同颜色的字母或数字
             */
             
            private function writeNoise()
            {
                $codeSet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                for ($i = 0; $i < 10; $i++) {
                    //杂点颜色
                    $noiseColor = imagecolorallocate($this->img, mt_rand(150, 225), mt_rand(150, 225), mt_rand(150, 225));
                    for ($j = 0; $j < 5; $j++) {
                        // 绘杂点
                        imagestring($this->img, 5, mt_rand(-10, $this->width), mt_rand(-10, $this->height), $codeSet[mt_rand(0, 61)], $noiseColor);
                    }
                }
            }
    
 
            /**
             * 画一条由两条连在一起构成的随机正弦函数曲线作干扰线(你可以改成更帅的曲线函数)
             *
             *      高中的数学公式咋都忘了涅，写出来
             *        正弦型函数解析式：y=Asin(ωx+φ)+b
             *      各常数值对函数图像的影响：
             *        A：决定峰值（即纵向拉伸压缩的倍数）
             *        b：表示波形在Y轴的位置关系或纵向移动距离（上加下减）
             *        φ：决定波形与X轴位置关系或横向移动距离（左加右减）
             *        ω：决定周期（最小正周期T=2π/∣ω∣）
             *
             */
            private function writeCurve()
            {
                $this->fontcolor = imagecolorallocate($this->img,mt_rand(0,156),mt_rand(0,156),mt_rand(0,156));
                $px = $py = 0;
        
                // 曲线前部分
                $A = mt_rand(1, $this->height / 2); // 振幅
                $b = mt_rand(-$this->height / 4, $this->height / 4); // Y轴方向偏移量
                $f = mt_rand(-$this->height / 4, $this->height / 4); // X轴方向偏移量
                $T = mt_rand($this->height, $this->width * 2); // 周期
                $w = (2 * M_PI) / $T;
        
                $px1 = 0; // 曲线横坐标起始位置
                $px2 = mt_rand($this->width / 2, $this->width * 0.8); // 曲线横坐标结束位置
        
                for ($px = $px1; $px <= $px2; $px = $px + 1) {
                    if (0 != $w) {
                        $py = $A * sin($w * $px + $f) + $b + $this->height / 2; // y = Asin(ωx+φ) + b
                        $i  = (int) ($this->fontsize / 5);
                        while ($i > 0) {
                            imagesetpixel($this->img, $px + $i, $py + $i, $this->fontcolor); // 这里(while)循环画像素点比imagettftext和imagestring用字体大小一次画出（不用这while循环）性能要好很多
                            $i--;
                        }
                    }
                }
        
                // 曲线后部分
                $A   = mt_rand(1, $this->height / 2); // 振幅
                $f   = mt_rand(-$this->height / 4, $this->height / 4); // X轴方向偏移量
                $T   = mt_rand($this->height, $this->width * 2); // 周期
                $w   = (2 * M_PI) / $T;
                $b   = $py - $A * sin($w * $px + $f) - $this->height / 2;
                $px1 = $px2;
                $px2 = $this->width;
        
                for ($px = $px1; $px <= $px2; $px = $px + 1) {
                    if (0 != $w) {
                        $py = $A * sin($w * $px + $f) + $b + $this->height / 2; // y = Asin(ωx+φ) + b
                        $i  = (int) ($this->fontsize / 5);
                        while ($i > 0) {
                            imagesetpixel($this->img, $px + $i, $py + $i, $this->fontcolor);
                            $i--;
                        }
                    }
                }
            }
 
 
 
 
 
              //输出
              private function outPut() {
                 header('Content-type:image/png');
                 imagepng($this->img);
                 imagedestroy($this->img);
              }  
 
              //对外生成
              public function doimg() {
                 $this->createBg();
                 $this->createCode();
                 //$this->writeCurve();
                 $this->createFont();
                 $this->createLine();
                 $this->writeNoise();
                 $this->outPut();
              }  
 
              //获取验证码
              public function getCode() {
                 return strtolower($this->code);
              }  
 
     }
?>