由于最近一个项目需要,需要做验证码,本想偷懒直接用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();
这里使用了字体文件,如果需要测试,还请包含这个文件.
最终效果图: