php开发验证码(生成验证码)
通过上一节,我们已经很好的掌握了图像处理的精髓。
通过我们所掌握的知识。进行一些简单的扩展,我们就可以写出:网上最常用的一个小东西——验证码。
验证码是为了防止机器自动注册、机器自动刷票最常用的手段之一。
我们来看一下验证码的效果:
我们根据上面的效果来推理实现的过程。
实现过程:
1.生成指定宽高的画布
2.准备好字好需要生成的字符串
3.每次执行,让背景填充随机的颜色(浅色系)
4.在画布上画上随机的干扰元素(随机点、随机线、随机弧形等均可,但不可过份影响用户的视觉)
5.写上4个文字
6.输出header头,告知浏览器按照某类型显示
7.输出图像
8.销毁图像资源
上面的步骤把实现验证码的每一步都讲清楚了。下面我们来根据这个过程来推理实现。
第一步、创建画布
$img = imagecreate($width, $height);
我们可以定义一个自定义的宽和高。做一个函数将,可以通过函数传入宽和高。这样,可以修改验证码图像的大小。
function check_code($width = 100, $height = 50) { $img = imagecreate($width, $height); }
第二步、生成验证码显示的文字
验证码的文字通常有数字、字母。而为了区别验证码字符。我们可以用0-9A-Za-Z。但是0和o,l和I有的时候区分不清楚。我们如果不需要处理,可以想办法去除掉:
方案一:
循环4个ascii码,而ascii码,而chr或者sprintf('%c',第二个参数传ascii码) 将对应的字符转为指定的字符。
for ($i = 0; $i < $num; $i++) { $rand = mt_rand(0, 2); switch ($rand) { case 0: $ascii = mt_rand(48, 57); //0-9 break; case 1: $ascii = mt_rand(65, 90); //A-Z break; case 2: $ascii = mt_rand(97, 122); //a-z break; } //chr() $string .= sprintf('%c', $ascii); }
方案二:
方案一对很多人来说有点复杂,很多人理解不了ascci码。有没有更简单的方案呢。单然有。我可以准备好字符,然后用str_shuffle打乱字符后使用substr进行截取。
//没有0,i,l,o $str = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789'; $str = str_shuffle($str); $string = substr($str,0 ,3);
三、 每次执行,让背景填充随机的颜色(浅色系)
文字是深色的看得清楚,而背景是潜色的。
背景的RGB颜色表示通常是这样的,RGB颜色是三个色值,这三个色值都是从0-255。
而:
0-120 低数值是深色系。
130 - 255 通常为浅色系。
使用到图片颜色的地方挺多的。因此,我可以定义分配颜色的功能:
//浅色的背景函数 function randBg($img) { return imagecolorallocate($img, mt_rand(130, 255), mt_rand(130, 255), mt_rand(130, 255)); } //深色函数,深色的字或者点这些干 扰元素 function randPix($img) { return imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); }
四、在画布上画上随机的干扰元素
我们可以随机的在图片中画上50个像素点。最小的位置为0,0。最大的位置为最大的宽或者最大的高。
然后使用mt_rand(0,最大宽)、mt_rand(0,最大高)。再使用randPix针对我们创建的画布来分配颜色。
//画干扰元素 for ($i = 0; $i < 50; $i++) { imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), randPix($img)); }
五、写上4个文字
$string是一个字符串,字符串$string[0]为字符的第一个字符,依此类类推。
因此,我可在使用imagechar函数在图像中写入文字。
而写入文字的x,y的坐标我们可以用一个公式推倒出来。
X位置 = 图像宽/字符个数(4) * 循环次数。 得到的结果取整后再乘以每次循环的次数。假设图像为100个宽度,那么:第一次写在0的位置,第二次为 25,第三次为50,第四次为75。
Y位置 = mt_rand(0,图像高- 15)。
我们可以推导出下面的代码,就可以写出对应的文字了:
for ($i = 0; $i < $num; $i++) { $x = floor($width / $num) * $i; $y = mt_rand(0, $height - 15); imagechar($img, 5, $x, $y, $string[$i], randPix($img)); }
六、输出header头,告知浏览器按照某类型显示
我们知道图像类型的输出函数都有:imagejpeg,imagepng,imagegif等特点。
而图像的mime类型为image/jpeg,image/png,image/gif等。
因此,我们可以声明一个变量:
$imagetype = 'jpeg';
$imagetype = 'png';
$imagetype = 'gif';
输出header类型的时候执行:
$header = 'Content-type:image/' . $imagetype;
执行函数输出的可以拼接出一个变量函数:
$func = 'image' . $type;
如果我们的系统支持个类型,则使用function_exists检测函数是否存在。存在则系统支持该类型,不存在则不支持该类型。
所以代码可以写成这样:
$func = 'image' . $type; $header = 'Content-type:image/' . $type; if (function_exists($func)) { header($header); //变为了imagejpeg等 $func($img); } else { echo '图片类型不支持'; }
八、销毁资源,返回字符
以后在验证的时候,大家需要把验证码显示出来。并且,用户输出的验证字符还需要与图像中的验证字符匹配。
所以要将验证字符返回回来,供以后保存使用。
imagedestroy($img); return $string;
我们来看一下全部的准备完成的PHP函数文件,我们将上面的代码封装成一个统一的函数供大家来学习使用:
<?php check_code(); function check_code($width = 100, $height = 50, $num = 4, $type = 'jpeg') { $img = imagecreate($width, $height); $string = ''; for ($i = 0; $i < $num; $i++) { $rand = mt_rand(0, 2); switch ($rand) { case 0: $ascii = mt_rand(48, 57); //0-9 break; case 1: $ascii = mt_rand(65, 90); //A-Z break; case 2: $ascii = mt_rand(97, 122); //a-z break; } //chr() $string .= sprintf('%c', $ascii); } //背景颜色 imagefilledrectangle($img, 0, 0, $width, $height, randBg($img)); //画干扰元素 for ($i = 0; $i < 50; $i++) { imagesetpixel($img, mt_rand(0, $width), mt_rand(0, $height), randPix($img)); } //写字 for ($i = 0; $i < $num; $i++) { $x = floor($width / $num) * $i + 2; $y = mt_rand(0, $height - 15); imagechar($img, 5, $x, $y, $string[$i], randPix($img)); } //imagejpeg $func = 'image' . $type; $header = 'Content-type:image/' . $type; if (function_exists($func)) { header($header); $func($img); } else { echo '图片类型不支持'; } imagedestroy($img); return $string; } //浅色的背景 function randBg($img) { return imagecolorallocate($img, mt_rand(130, 255), mt_rand(130, 255), mt_rand(130, 255)); } //深色的字或者点这些干 扰元素 function randPix($img) { return imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); } ?>