最近查一个“验证码不显示”的问题,解决的过程中学到了一些东西,这里做个记录。先贴两个验证码的代码吧。
第一个:
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
//验证码
error_reporting(E_ERROR | E_WARNING | E_PARSE);
$verify=new verifyCode;
for($i=0;$i<=3;$i++){
$zz=rand(1,9);
$code.=$zz;
}
setCookie("CODEIMG",md5($code),time()+360000,"/");
$verify->vCode($code);
$code = $verify->Output();
class verifyCode{
var $Noisy = 5; // 干扰点出现的概率
var $Count = 4; // 字符数量
var $Width = 60; // 图片宽度
var $Height = 18; // 图片高度
var $Angle = 5; // 角度随机变化量
var $Offset = 3; // 偏移随机变化量
var $Border = 2; // 边框大小
var $imgData = "";
var $Graph=array();
var $code = "";
function vCode($code){
global $code;
$this->code = $code;
for($i=0;$i<strlen($code);$i++){
$this->SetDraw(substr($code,$i,1), $i);
}
}
function SetDot($pX, $pY){
if($pX * ($this->Width-$pX-1) >= 0 && $pY * ($this->Height-$pY-1) >= 0){
$this->Graph[$pX][$pY] = 1;
}
}
function Rnd(){
mt_srand((double)microtime() * 1000000);
return mt_rand(1, 999)/1000;
}
function Sgn($v){
if($v>0) return 1;
if($v==0) return 0;
if($v<0) return -1;
}
function SetDraw($pIndex, $pNumber){
// 字符数据
$DotData[0] = array(10, 1, 80, 1, 80, 100,10,100,10,1);
$DotData[1] = array(30, 15, 50, 1, 50, 100);
$DotData[2] = array(1 ,34 ,30 ,1 ,71, 1, 100, 34, 1, 100, 93, 100, 100, 86);
$DotData[3] = array(1, 1, 100, 1, 42, 42, 100, 70, 50, 100, 1, 70);
$DotData[4] = array(100, 73, 6, 73, 75, 6, 75, 100);
$DotData[5] = array(100, 1, 1, 1, 1, 50, 50, 35, 100, 55, 100, 80, 50, 100, 1, 95);
$DotData[6] = array(100, 20, 70, 1, 20, 1, 1, 30, 1, 80, 30, 100, 70, 100, 100, 80, 100, 60, 70, 50, 30, 50, 1, 60);
$DotData[7] = array(6, 26, 6, 6, 100, 6, 53, 100);
$DotData[8] = array(100, 30, 100, 20, 70, 1, 30, 1, 1, 20, 1, 30, 100, 70, 100, 80, 70, 100, 30, 100, 1, 80, 1, 70, 100, 30);
$DotData[9] = array(1, 80, 30, 100, 80, 100, 100, 70, 100, 20, 70, 1, 30, 1, 1, 20, 1, 40, 30, 50, 70, 50, 100, 40);
$vExtent = $this->Width / strlen($this->code);
$Margin[0] = $this->Border +$vExtent *$pNumber+ $vExtent * ($this->Rnd() * $this->Offset) / 100;
$Margin[1] = $vExtent * ($pNumber + 1) - $this->Border - $vExtent * ($this->Rnd() * $this->Offset) / 100;
$Margin[2] = $this->Border + $this->Height * ($this->Rnd() * $this->Offset) / 100;
$Margin[3] = $this->Height - $this->Border - $this->Height * ($this->Rnd() * $this->Offset) / 100;
$vWidth = intval($Margin[1] - $Margin[0]);
$vHeight = intval($Margin[3] - $Margin[2]);
//起始坐标
$vStartX = intval(($DotData[$pIndex][0]-1) * $vWidth / 100);
$vStartY = intval(($DotData[$pIndex][1]-1) * $vHeight / 100);
for ($i = 1 ;$i<=count($DotData[$pIndex])/2;$i++){
If($DotData[$pIndex][2*$i-2] <> 0 && $DotData[$pIndex][2*$i] <> 0){
// 终点坐标
$vEndX = ($DotData[$pIndex][2*$i]-1) * $vWidth / 100;
$vEndY = ($DotData[$pIndex][2*$i+1]-1) * $vHeight / 100;
// 横向差距
$vDX = $vEndX - $vStartX;
// 纵向差距
$vDY = $vEndY - $vStartY;
// 倾斜角度
if($vDX == 0)
$vAngle = $this->Sgn($vDY) * 3.14/2;
else
$vAngle = atan($vDY /$vDX);
//两坐标距离
if(sin($vAngle) == 0)
$vLength = $vDX;
else
$vLength = $vDY / sin($vAngle);
// 随机转动角度
$vAngle = $vAngle + ($this->Rnd() - 0.5) * 2 * $this->Angle * 3.14 * 2 / 100;
$vDX = intval(cos($vAngle) * $vLength);
$vDY = intval(sin($vAngle) * $vLength);
if(abs($vDX) > abs($vDY))
$vDeltaT = abs($vDX) ;
else
$vDeltaT = abs($vDY);
for($j = 1;$j<=$vDeltaT;$j++)
$this->SetDot($Margin[0] + $vStartX + $j * $vDX / $vDeltaT, $Margin[2] + $vStartY + $j * $vDY / $vDeltaT);
$vStartX = $vStartX + $vDX;
$vStartY = $vStartY + $vDY;
}
}
}
function Output(){
$out = "";
// 文件类型
$out .= "GIF";
// 版本信息
$out .= "89a";
// 逻辑屏幕宽度
$out .= chr($this->Width % 256).chr(($this->Width/256) % 256);
// 逻辑屏幕高度
$out .= chr($this->Height % 256).chr(($this->Height / 256) % 256);
$out .= chr(128) . chr(0) . chr(0);
// 全局颜色列表
$out .= chr(0xEE).chr(0xEE).chr(0xEE);
$out .= chr(0x00).chr(0x00).chr(0x00);
// 图象标识符
$out .= ",";
$out .= chr(0).chr(0).chr(0).chr(0);
// 图象宽度
$out .= chr($this->Width % 256).chr(($this->Width/256) % 256);
// 图象高度
$out .= chr($this->Height % 256).chr(($this->Height / 256) % 256);
$out .= chr(0).chr(7).chr(255);
for($y = 0;$y<$this->Height;$y++)
{
for($x = 0;$x<$this->Width;$x++)
{
if($this->Rnd() < $this->Noisy / 100)
$out .= chr(1-$this->Graph[$x][$y]);
else
{
if($x * ($x-$this->Width) == 0 || $y * ($y-$this->Height) == 0)
$out .= chr($this->Graph[$x][$y]);
else
{
if($this->Graph[$x-1][$y]== 1 || $this->Graph[$x][$y] || $this->Graph[$x][$y-1] == 1)
$out .= chr(1);
else
$out .= chr(0);
}
}
if(($y * $this->Width + $x + 1) % 126 == 0)
{
$out .= chr(128);
$i++;
}
if(($y * $this->Width + $x + $i + 1) % 255 == 0)
{
if(($this->Width*$this->Height - $y * $this->Width - $x - 1) > 255)
$out .= chr(255);
else
$out .= chr($this->Width * $this->Height %255);
}
}
}
$out .= chr(128).chr(0).chr(129).chr(0).chr(59);
ob_clean();
header("Expires: -9999");
header("Pragma: no-cache");
header("cache-ctrol: no-cache");
header("Content-Type:image/gif");
echo $out;
}
}
?>
这个文件直接引入到img的src下就能用,大小是:60*18。
遇到的问题是:验证码图片不显示,也不报错,最后的解决是在Output()方法中添加了ob_clean()。
第二个:
这个是在网上看到的,转载链接如下:http://blog.csdn.net/tenghu8888/article/details/39499925
vcode.class.php:
<?php
/**
*验证码类
*/
class Vcode{
private $width;//图片宽度
private $height;//图片高度
private $num;//验证码个数
private $img;//图片资源
private $code;//验证码
private $pointNum;//干扰点个数
private $lineNum;//干扰线个数
private $fontFile;//字体文件
//构造函数初始化相关数据
function __construct($width=85,$height=34,$num=4){
$this->width=$width;
$this->height=$height;
$this->num=$num;
$this->code=$this->createCode();
$this->pointNum=100;
$this->lineNum=10;
$this->fontFile="STLITI.TTF";
}
/**
*用于设置成员属性
*@param string $key 成员属性名
*@param mixed $value 成员属性值
*@return object 返回自己对象$this,可用于连贯操作
*/
public function set($key,$val){
//get_class_vars() 获取类中的属性组成的数组
//get_class() 返回对象的类名
if(array_key_exists($key,get_class_vars(get_class($this)))){
$this->setOption($key,$val);
}
return $this;
}
//设置参数
private function setOption($key,$value){
$this->$key=$value;
}
//获取验证码
public function getCode(){
return $this->code;
}
//输出图像
public function outImg(){
//创建图像
$this->createImage();
//画验证码
$this->drawCode();
//画干扰元素
$this->drawDisturbColor();
//输出图像
$this->printImg();
}
//画验证码
private function drawCode(){
$this->fontFile="./font/".$this->fontFile;
for($i=0;$i<$this->num;$i++){
//设置随机颜色
$randColor=imagecolorallocate($this->img,rand(0,128),rand(0,128),rand(0,128));
//字体大小
$fontSize=rand(20,23);
//字体水平位置
$x=($this->width/$this->num)*$i;
//水平方向的位置
$y=rand($fontSize,imagefontheight($fontSize)+3);
//画字体
imagettftext($this->img,$fontSize,0,$x,$y,$randColor,$this->fontFile,$this->code{$i});
}
}
//画干扰元素
private function drawDisturbColor(){
//画干扰点
for($i=0;$i<$this->pointNum;$i++){
//设置随机颜色
$randColor=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),$randColor);
}
//画干扰线
for($i=0;$i<$this->lineNum;$i++){
//设置随机颜色
$randColor=imagecolorallocate($this->img,rand(0,200),rand(0,200),rand(0,200));
//画线
imageline($this->img,rand(1,$this->width-2),rand(1,$this->height-2),rand(1,$this->height-2),rand(1,$this->width-2),$randColor);
}
}
//创建图像
private function createImage(){
//创建一个真彩色图像
$this->img=imagecreatetruecolor($this->width,$this->height);
//设置背景色
$bgColor=imagecolorallocate($this->img,rand(200,255),rand(200,255),rand(200,255));
//填充背景色
imagefill($this->img,0,0,$bgColor);
//设置边框颜色
$borderColor=imagecolorallocate($this->img,0,0,0);
//画一个边框
imagerectangle($this->img,0,0,$this->width-1,$this->height-1,$borderColor);
}
//输出图像
private function printImg(){
ob_clean();
if(imagetypes() & IMG_PNG){
//针对png
header("Content-Type:image/png");
imagepng($this->img);
}else if(imagetypes() & IMG_JPG){
//针对jpg
header("Content-Type:image/jpeg");
imagejpeg($this->img,null,100);
}else if(imagetypes() & IMG_GIF){
//针对Gif
header("Content-Type:image/gif");
imagegif($this->img);
}else if(imagetypes() & IMG_WBMP){
// 针对 WBMP
header('Content-Type: image/vnd.wap.wbmp');
imagewbmp($this->img);
}else{
die('No image support in this PHP server');
}
}
//创建验证码
private function createCode(){
//默认字符串
$codes="123456789abcdefghijkmnpqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXY";
//生成验证码
$code="";
for($i=0;$i<$this->num;$i++){
$code.=$codes{rand(0,strlen($codes)-1)};
}
return $code;
}
//析构函数用于销毁图像资源
function __destruct(){
imagedestroy($this->img);
}
}
请求信息如下(image_002.php):
<?php
//开启Session
session_start();
//引入验证码类
include("vcode.class.php");
//创建验证码类
$vcode=new Vcode();
//将获取的验证码存入到session中
$_SESSION['code']=$vcode->getCode();
//$vcode->set("pointNum",10);//自定义干扰点个数
//$vcode->set("lineNum",10);//自定义干扰线个数
//$vcode->set("fontFile","wawa.ttf");//自定义字体文件
//输出图像
$vcode->outImg();
?>
页面上只用img标签直接调用就好:
<img src="image_002.php" οnclick="this.src='image_002.php?Math.random()'"/>
使用这个验证码时遇到了一个问题:图片因存在错误而无法显示
主要通过两步解决了:
第一步:
原因:vcode.class.php中imagettftext调用font生成验证码时找不到字体导致出错。
解决办法:很简单,在项目里新建一个font(drawCode方法中指定的目录为font),将指定的字体SIMYOU.TTF从Windows下拷贝过来,就能解决这个问题
第二步:在printImg()函数的第一行添加一句ob_clean()。
以上两步之后,验证码就出来了。
上面贴的第一个验证码显示不出来就是因为没有添加ob_clean(),这个问题是在解决第二个验证码的问题时顺带解决的,所以讲其粘在第一了。