[工作筆記] 產生圖型認證碼

PHP 5 with GD,筆記一下,最近很容易不小心砍掉一些東西,還是記錄一下比較保險。這是在 PHP 5 才能運作的東西,因為我改寫成靜態的類,所以,就這樣吧(無責)。

update, 為了怕扭曲圖形識別上的困難,所以加了是不是要扭曲圖形的設定。

參考來源:http://blog.wu-boy.com/2009/01/05/701/

呼叫方式:

<?php
session_start();
VerifyCodeImage::SetImage(3,6,120,40);

靜態類別 VerifyCodeImage,至於怎麼改寫 session 就留給大家啦。

<?php
define ('ROOT', '../');
class VerifyCodeImage {
    static $vc;

    public static function SetImage($mode, $v_num, $img_w, $img_h, $distortion = true, $int_pixel_num = 70, $int_line_num = 1, $border=true, $borderColor='0,0,0', $font_dir='library/fonts') {
        
        if(!isset($_SESSION['authCode'])){
            $_SESSION['authCode'] = '';
        }
        self::$vc->mode = $mode;                    // 1.文字模式, 2.字母模式, 3.文字字母混合模式
        self::$vc->v_num = $v_num;                    // 驗證碼個數
        self::$vc->img_w = $img_w;                    // 圖像寬度
        self::$vc->img_h = $img_h;                    // 圖像高度
        self::$vc->distortion = $distortion;        // 扭曲圖形
        self::$vc->int_pixel_num = $int_pixel_num;    // 干擾像數個數
        self::$vc->int_line_num = $int_line_num;    // 干擾線條數量
        self::$vc->border = $border;                // 圖像邊框
        self::$vc->borderColor = $borderColor;        // 圖像邊框顏色
        self::$vc->font_dir = ROOT . $font_dir;        // 字型文件路徑

        self::GenerateImage();
    }

    private static function GetChar($mode)
    {
        switch($mode) {
            case 1:
                $ychar = '0,1,2,3,4,5,6,7,8,9';
            break;
            case 2:
                $ychar = 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z';
            break;
            case 3:
            default:
                $ychar = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
        }
        return $ychar;
    }
 
    private static function RandColor($rs, $re, $gs, $ge, $bs, $be)
    {
        $r = mt_rand($rs, $re);
        $g = mt_rand($gs, $ge);
        $b = mt_rand($bs, $be);
        return array($r, $g, $b);
    }
 
    private static function GenerateImage()
    {
        $ychar = self::GetChar(self::$vc->mode);
        $list = explode(",", $ychar);
        $cmax = count($list) - 1;
        $fonts = scandir(self::$vc->font_dir);
        $fmax = count($fonts) - 2;
        $fontrand = mt_rand(2, $fmax);
        $font = self::$vc->font_dir.'/'.$fonts[$fontrand];
        
        // 驗證碼
        $v_code = "";
        for($i = 0; $i < self::$vc->v_num; $i++){ 
            $randnum = mt_rand(0, $cmax);
            $this_char = $list[$randnum];
            $v_code .= $this_char;
        }

        // 填入驗證碼
        $textX = self::$vc->img_w * 0.02;
        $textY = self::$vc->img_h * 0.75;
        $im = imagecreatetruecolor (self::$vc->img_w + 50, self::$vc->img_h);
        $color = imagecolorallocate($im, 32, 81, 183);
        $ranum = mt_rand(0, 2);
        if($ranum == 0){
            $color = imagecolorallocate($im, 32, 81, 183);
        }else if($ranum == 1){
            $color = imagecolorallocate($im, 17, 158, 20);
        }else{
            $color = imagecolorallocate($im, 196, 31, 11);
        }
        imagefill($im, 0, 0, imagecolorallocate($im, 255, 255, 255) );
        imagettftext ($im, 22, mt_rand(-6, 6), $textX, $textY, $color, $font, $v_code);

        // 干擾線條
        for($i = 0; $i < self::$vc->int_line_num; $i++){
            $rand_color_line = $color;
            imageline($im, mt_rand(2,intval(self::$vc->img_w/3)), mt_rand(10,self::$vc->img_h - 10), mt_rand(intval(self::$vc->img_w - (self::$vc->img_w/3) + $textX),self::$vc->img_w - 10), mt_rand(0,self::$vc->img_h), $rand_color_line);
        }
        
        // 扭曲圖形
        if(self::$vc->distortion==true) {
            $ranum = mt_rand(0, 1);
            $dis_range = mt_rand(8, 12);
            $distortion_im = imagecreatetruecolor (self::$vc->img_w * 1.5 ,self::$vc->img_h);
            imagefill($distortion_im, 0, 0, imagecolorallocate($distortion_im, 255, 255, 255));
            for ($i = 0; $i < self::$vc->img_w + 50; $i++) {
                for ($j = 0; $j < self::$vc->img_h; $j++) {
                    $rgb = imagecolorat($im, $i, $j);
                    if($ranum == 0){
                        if( (int)($i+40+cos($j/self::$vc->img_h * 2 * M_PI) * 10) <= imagesx($distortion_im) && (int)($i+20+cos($j/self::$vc->img_h * 2 * M_PI) * 10) >=0 ) {
                            imagesetpixel ($distortion_im, (int)($i+10+cos($j/self::$vc->img_h * 2 * M_PI - M_PI * 0.4) * $dis_range), $j, $rgb);
                        }
                    }else{
                        if( (int)($i+40+sin($j/self::$vc->img_h * 2 * M_PI) * 10) <= imagesx($distortion_im) && (int)($i+20+sin($j/self::$vc->img_h * 2 * M_PI) * 10) >=0 ) {
                            imagesetpixel ($distortion_im, (int)($i+10+sin($j/self::$vc->img_h * 2 * M_PI - M_PI * 0.4) * $dis_range), $j, $rgb);
                        }
                    }
                }
            }
        }
        
        // 干擾像素
        for($i = 0; $i < self::$vc->int_pixel_num; $i++){
            $rand_color_pixel = $color;
            if(self::$vc->distortion) {
                imagesetpixel($distortion_im, mt_rand() % self::$vc->img_w + $textX, mt_rand() % self::$vc->img_h, $rand_color_pixel);
            } else {
                imagesetpixel($im, mt_rand() % self::$vc->img_w + $textX, mt_rand() % self::$vc->img_h, $rand_color_pixel);
            }
        }

        // 繪製邊框
        if(self::$vc->border){
            $border_color_line = self::$vc->borderColor;
            if(self::$vc->distortion) {
                imageline($distortion_im, 0, 0, self::$vc->img_w + $textX, 0, $border_color_line); // 上橫
                imageline($distortion_im, 0, self::$vc->img_h-1, self::$vc->img_w + $textX, self::$vc->img_h-1, $border_color_line); // 下橫
                imageline($distortion_im, 0, 0, 0, self::$vc->img_h, $border_color_line); // 左豎
                imageline($distortion_im, self::$vc->img_w + $textX, 0, self::$vc->img_w + $textX, self::$vc->img_h, $border_color_line); // 右豎
            } else {
                imageline($im, 0, 0, self::$vc->img_w + $textX, 0, $border_color_line); // 上橫
                imageline($im, 0, self::$vc->img_h-1, self::$vc->img_w + $textX, self::$vc->img_h-1, $border_color_line); // 下橫
                imageline($im, 0, 0, 0, self::$vc->img_h, $border_color_line); // 左豎
                imageline($im, self::$vc->img_w + $textX, 0, self::$vc->img_w + $textX, self::$vc->img_h, $border_color_line); // 右豎
            }
        }

        if(self::$vc->distortion) {
            imageantialias($distortion_im, true); // 消除鋸齒
        } else {
            imageantialias($im, true); // 消除鋸齒
        }
            
        $_SESSION['authCode'] = $v_code;

        // 生成圖像給瀏覽器
        header('Content-Transfer-Encoding: binary');
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', $_SERVER['REQUEST_TIME']));
        header('Cache-Control: private');
        header('Pragma: no-cache');
        
        if (function_exists("imagegif")) {
            header ("Content-type: image/gif");
            if(self::$vc->distortion) { imagegif($distortion_im); } else { imagegif($im); }
        }else if (function_exists("imagepng")) {
            header ("Content-type: image/png");
            if(self::$vc->distortion) { imagepng($distortion_im); } else { imagepng($im); }
        }else if (function_exists("imagejpeg")) {
            header ("Content-type: image/jpeg");
            if(self::$vc->distortion) { imagejpeg($distortion_im, '', 80); } else { imagejpeg($im, '', 80); }
        }else if (function_exists("imagewbmp")) {
            header ("Content-type: image/vnd.wap.wbmp");
            if(self::$vc->distortion) { imagewbmp($distortion_im); } else { imagewbmp($im); }
        }else{
          die("No Image Support On This Server !");
        }

        imagedestroy($im);
        if(self::$vc->distortion) imagedestroy($distortion_im);
    }
}
Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei