php使用gd庫輸出中文內容的圖片

  正如標題所說那樣,本文只討論輸出內容所有爲中文或者包含中文的狀況。若是內容全是字母或者其餘字符的話,能夠參考這篇博客:生成驗證碼php

問題

  此處要注意,標題中爲何要區別windows和linux分別實現?由於我在網上搜了不少的博客,幾乎全部的博客都是同樣的,全是使用的windows系統,源代碼在linux上跑不通,會提示一個函數imagettftext()不存在,這個函數在windows下是可使用的,可是在linux上面確實不行的。這是爲何呢?html

  有人說是linux的gd庫版本過低了,應該升級爲高版本的gd庫????linux

  且不說是否是真麼gd庫太老了,另一個問題就是,使用imagettftext()函數的時候,須要傳遞一個參數,參數就是字體的文件的路徑及名稱。這個該怎麼整?canvas

  因此下面就按照上面的問題來敘述。windows

  

imagettftext()

  先看下面這個phpinfo()中對gd庫的描述:安全

 

  再看下面一個系統中phpinfo()的輸出:session

 

  仔細注意上面兩個gd庫的區別,就會發現,第二個gd庫相對於第一個gd庫要多一些「功能」,這個功能就是關係到能不能使用imagettftext()函數。app

  在一些linux上使用imagettftext()函數時,會提示函數不存在,可是,在windows上就行,其實就是這個緣由。dom

  若是你的php上面沒有這個FreeType,能夠在網上找一下相關的博客。函數

 

多字節字符串操做

  多字節字符串的截斷、求長度的問題,可使用mb_擴展,不然會出現亂碼。

  

字體

  中文驗證碼的內容是中文,因此,要使用中文的字體,能夠上網下載便可。在imagettftext()指定字體文件的路徑以及文件名和擴展名便可。

 

下面就是一個簡單的中文驗證碼例子:

  產生的驗證碼內容存儲在session中(在captcha.php完成),提交驗證碼(在index.php中完成)以後,在validate.php中將提交的驗證碼和session中的驗證碼做對比便可。

  若是要安全一點的話,能夠將驗證碼加密後再存session。

 

captcha.php  專門建立中文驗證碼

<?php
    class Captcha{
        private $width;//驗證碼的寬
        private $height;//驗證碼的高
        private $num;//驗證碼字符的個數
        private $code;//驗證碼的字符串
        private $img;//驗證碼source

        //初始化
        function __construct($width=80,$height=20,$num=4){
            mb_internal_encoding("UTF-8");
            $this->width=$width;
            $this->height=$height;
            $this->num=$num;
            $this->code=$this->create_code();
        }

        //建立畫布
        private function create_canvas(){
            $this->img=imagecreatetruecolor($this->width,$this->height);
            $background_color=imagecolorallocate($this->img,0xFF,0xFF,0xFF);
            imagefill($this->img,0,0,$background_color);
            $border_color=imagecolorallocate($this->img,0xAA,0xAA,0xAA);
            imagerectangle($this->img,0,0,$this->width-1,$this->height-1,$border_color);
        }

        //生成驗證碼的字符串
        private function create_code(){
            $src="這是字典XXXXX";
            $code="";
            for($i=0;$i<$this->num;$i++){
                $index=mt_rand(0,mb_strlen($src)-1);
                $code.= mb_substr($src,$index,1); //注意求多字節內容的長度時使用mb_擴展
            }
            return $code;
        }

        //將生成的字符串畫在畫布上
        private function paint_char(){
            for($i=0;$i<$this->num;$i++){
                $char_color=imagecolorallocate($this->img,0xFF,0,0xFF);
                $font_size=24;
                $x=5+($this->width/$this->num)*$i;
                $y=($this->height-imagefontheight($font_size));
                imagettftext($this->img,$font_size,mt_rand(2, 20),$x,$y,$char_color,"STXINGKA.TTF",mb_substr($this->code,$i,1,"UTF-8"));
                //注意截取多字節的內容使用mb_擴展
            }
        }
        
        //添加干擾標記 
        private function add_disturbance(){
            for($i=0;$i<20;$i++){
                $color=imagecolorallocate($this->img,rand(0,255),rand(0,255),rand(0,255));
                imagesetpixel($this->img,rand(1,$this->width-2),rand(1,$this->height-2),$color);
            }
        }

        //輸出圖片
        private function print_code() {
            if (imagetypes() & IMG_PNG) {
                header("Content-type: image/png");
                imagepng($this->img);
            } elseif (imagetypes() & IMG_JPG) {
                header("Content-type: image/jpeg");
                imagejpeg($this->img);
            }  else {
                  die("No image support in this PHP server");
            }
        }

        //獲取驗證碼字符串的值
        public function get_code(){
            return $this->code;
        }

        //釋放資源
        private function destroy_code(){
            imagedestroy($this->img);
        }

        //搞定全部驗證碼的工做
        public function show_image_code(){
            $this->create_canvas();
            $this->paint_char();
            $this->add_disturbance();
            $this->print_code();
            $this->destroy_code();
            
        }
    }

    session_start();
    $captcha = new Captcha(200, 60, 4);
    $captcha->show_image_code();
    $_SESSION['cap_v'] = $captcha->get_code();
 ?>

  

index.html   首頁顯示

<!DOCTYPE html>
<html>
    <head>
        <title>中文驗證碼</title>
        <meta charset='utf-8'>
    </head>

    <body>
        <img id="captcha_img" border='1' src='./captcha.php' style="width: 100px; height: 30px"><br>
        <a href='' id="change_img">換一個?</a><br><br>
        <input type='text' id='cap_v'>
        <button id="btn">submit</button>
    </body>

    <script>
        var captcha_img = document.getElementById("captcha_img"); 
        var change_img  = document.getElementById("change_img");
        var btn         = document.getElementById("btn");
        change_img = captcha_img.onclick = function(){
            captcha_img.src='./captcha.php?r='+Math.random();
            return false;
        }
    
        btn.onclick = function(){ 
            var xhr = new XMLHttpRequest();
            var cap_v = document.getElementById("cap_v").value; 
            if( cap_v.trim().length == 0){
                alert("驗證碼不能爲空");
                return;
            }
            xhr.open("post","validate.php",true);
            xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
            xhr.send("cap_v=" + cap_v);
            xhr.onreadystatechange = function(){
                if(xhr.readyState==4){
                    if((xhr.status==200 && xhr.status<300) || xhr.status==304){
                        if(xhr.responseText == 'right'){
                            alert("歡迎");
                        } else {
                            alert("驗證碼輸入錯誤");
                        }
                    } 
                }
            }
        }
    </script>
</html>

  

validate.php 用於檢測驗證碼是否正確

<?php
    session_start();
    if(isset($_POST['cap_v'])){
        if($_SESSION['cap_v'] == trim($_POST['cap_v'])){
            echo 'right';
        } else {
            echo 'wrong';
        } 
    }
?>

  

運行截圖:

 

 

相關文章
相關標籤/搜索