php生成验证码
由于最近一个项目需要,需要做验证码,本想偷懒直接用TP框架里面的,但是感觉很丑陋,而且调整大小后字符串在图片中的位置不是很美观.所以自己写了一个验证码.考虑到让以后也能用到, 所以要保证不同字符,不同高宽的情况下字符显示均匀.
由于使用imagesting写入字符串调整字体大小有点问题,而且字体过于单一,这里我采用了GD库中的imagettftext函数,此函数用法不再赘述,但是有一个参数一开始没有理解,造成了很大的困扰.
imagettftext ( resource image, float size, float angle,
int x, int y, int color, string fontfile, string text )
第五个参数Y,一开始认为是字体与顶部的距离.但是测试之后发现是字体底部与图片顶部之间的距离,所以在这里要使图片中的字符串垂直居中就必须满足Y=(图片高度 +字体高度)/2.另外图片验证码中,对字符串位置起重要作用的属性包括:图片高度, 图片宽度,字符串个数,字体大小,绘制字体起始坐标.
实现代码:
class CAPTCHA { public $width;//图片宽度 public $height;//图片高度 public $size = 14;//字体大小 public $ttf;//字体文件 public $img_res;//图片资源 public $string = "0,1,2,3,4,5,6,7,8,9,q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m";//验证码中允许出现的字符 public $angel = array(-45,45);//偏转角度范围 public $bgcolor = array(0,255);//背景RGB单色范围 public $fzcolor = array(0,255);//文字RGB单色范围 public $CaptchaStr;//验证码字符串 public $space;//字符间距 public $linenum;//干扰线条数 public $Pointnum;//干扰点数 public function PrintImg($num) { //检查,初始化各项属性 if(!isset($this->space))//字符串间距 { if(!isset($this->width))//图片宽度 { $this->width = $this->size * ( 2 * $num + 1 ); $this->space = $this->size; } } else { if(!isset($this->width)) { $this->width = $this->size * $num + $this->space * ($num + 1); } } if(!isset($this->height))//图片高度 { $this->height = $this->size * 2; } if(!isset($this->ttf))//字体 { return false; } $this->string = explode(",",$this->string);//将字符串集合转为数组 //生成图片 $this->CreateImg(); $this->PrintStr($num); $this->PrintLine(); $this->PrintPoint(); } public function display()//输出图像 { header("Content-type: image/png"); imagepng($this->img_res); imagedestroy($this->img_res); } /***********************************/ private function CreateImg()//创建图像 { if(function_exists("imagecreate")) { $this->img_res = imagecreate($this->width,$this->height); } else { return false; } } private function PrintStr($len)//输出字符串 { $x = $this->space; $y = (int)(($this->height + $this->size) / 2); while($len > 0) { $char = $this->string[rand(0,count($this->string) - 1)]; $this->CaptchaStr .= $char; imagettftext($this->img_res,$this->size,$this->getRand($this->angel),$x,$y,$this->getRandColor(),$this->ttf,$char); $x += ($this->size + $this->space); $len--; } } private function PrintLine()//输出干扰线条 { if(isset($this->linenum)) { while($this->linenum > 0) { if(rand(0,1) == 1) { imageline($this->img_res,rand(0,$this->width),rand(0,$this->height),rand(0,$this->width),rand(0,$this->height),$this->getRandColor()); } else { imagedashedline($this->img_res,rand(0,$this->width),rand(0,$this->height),rand(0,$this->width),rand(0,$this->height),$this->getRandColor()); } $this->linenum--; } } } private function PrintPoint()//输出干扰点 { if(isset($this->Pointnum)) { while($this->Pointnum> 0) { $x = rand(0,$this->width); $y = rand(0,$this->height); imageline($this->img_res,$x,$y,$x,$y,$this->getRandColor()); $this->Pointnum--; } } } private function getRandColor()//取随机颜色 { imagecolorallocate($this->img_res,$this->getRand($this->bgcolor),$this->getRand($this->bgcolor),$this->getRand($this->bgcolor));//设置背景色 return imagecolorallocate($this->img_res,$this->getRand($this->fzcolor),$this->getRand($this->fzcolor),$this->getRand($this->fzcolor)); } private function getRand($arr)//取随机数 { return rand($arr[0],$arr[1]); } }
调用代码:
$a = new CAPTCHA(); $a->ttf = "comic.ttf"; $a->linenum = 10; $a->Pointnum = 50; $a->PrintImg(4); $a->display();
这里使用了字体文件,如果需要测试,还请包含这个文件.
最终效果图: