php使用gd库输出中文内容的图片
正如标题所说那样,本文只讨论输出内容全部为中文或者包含中文的情况。如果内容全是字母或者其他字符的话,可以参考这篇博客:生成验证码
问题
此处要注意,标题中为什么要区别windows和linux分别实现?因为我在网上搜了很多的博客,几乎所有的博客都是一样的,全是使用的windows系统,源代码在linux上跑不通,会提示一个函数imagettftext()不存在,这个函数在windows下是可以使用的,但是在linux上面确实不行的。这是为什么呢?
有人说是linux的gd库版本太低了,应该升级为高版本的gd库????
且不说是不是真么gd库太老了,另外一个问题就是,使用imagettftext()函数的时候,需要传递一个参数,参数就是字体的文件的路径及名称。这个该怎么整?
所以下面就按照上面的问题来叙述。
imagettftext()
先看下面这个phpinfo()中对gd库的描述:
再看下面一个系统中phpinfo()的输出:
仔细注意上面两个gd库的区别,就会发现,第二个gd库相对于第一个gd库要多一些“功能”,这个功能就是关系到能不能使用imagettftext()函数。
在一些linux上使用imagettftext()函数时,会提示函数不存在,但是,在windows上就行,其实就是这个原因。
如果你的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'; } } ?>
运行截图: