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();

这里使用了字体文件,如果需要测试,还请包含这个文件.

最终效果图:

posted @ 2011-03-12 21:41  Eslizn  阅读(205)  评论(0编辑  收藏  举报