目录
0x00 图片验证码的组成
背景图片
验证码
干扰元素:线 点
0x01 图片验证码的步骤:
- 创建背景图片
- 生成验证码
- 画干扰元素
- 输出图片
注意需要GD库
0x02 GD库的相关函数
1.resource imagecreate(int $x_size,int $y_size)
@$x_size:宽
@$y_size:高
新建一个基于调色板的图片,返回值为图片句柄
2.imgpng(图片句柄) 以png的格式输出图片
imgjpeg(图片句柄) 以jpeg的格式输出图片
注意:在输出图片前需要加上
header("Content-type:image/jpeg");
表示以image/jpeg的格式解析图片
3.int imagecolorallocate(resource $image,int red,int$green,int blue);
@为一幅图像分配颜色;
@返回值为对应颜色的int值;可以用于imagettftext()的参数
4.imagettftext(resource $image,float $size,float $angle,int $x,int $y,int $color,string $frontfile,string $text)
用truetype字体向图像写入文本
$angle 字体倾斜度
$x $y 字体的位置
$fontfile 是字体文件(字体文件的路径) 准备好ttf文件,建议放在同源文件夹内
$text 要绘制的字。
注意:
mt_rand()和rand()效果相同,但是mt_rand()的效率更高一些
5.bool imageline(resource $image,int $x1,int $y1,int $x2,int $y2,int color);
@画线
@x1,y1:起点坐标
@x2,y2:终点坐标
6.bool imagesetpixel(resource $image,int $x,int $y,int $color)
@画点
7.bool imagedestroy(resource $image)
@销毁图片资源
@销毁图像资源
0x03 实现验证码
<?php
class Color{
public $red;
public $green;
public $blue;
public function __construct($r,$g,$b){
$this->red = $r;
$this->green = $g;
$this->blue = $b;
}
};
$color_array = [];
array_push($color_array,new Color(0,0,139));
array_push($color_array,new Color(139,0,139));
array_push($color_array,new Color(139,0,0));
array_push($color_array,new Color(205,0,0));
$width = 200;
$height = 50;
$img = imagecreate($width,$height);
imagecolorallocate($img,100,149,237);
$str = 'abcdefghjklmnpqrstuvwxyz23456789ABCDEFGHJKMNPQRSTUVWXYZ';
$check_str = '';
$len = 4;
for($i=0;$i<$len;$i++){
$key =mt_rand(0,strlen($str)-1);
$check_str.=$str[$key];
}
for($i=0;$i<$len;$i++){
$font_size = mt_rand(15,17);
$x =$i * ($width/$len) + $font_size/2;
$y =mt_rand($font_size,$height-$font_size);
$angle = mt_rand(-50,50);
$color = $color_array[mt_rand(0,3)];
$font_color = imagecolorallocate($img,$color->red,$color->green,$color->blue);
imagettftext($img,$font_size,$angle,$x,$y,$font_color,'code2.ttf',$check_str[$i]);
}
for($i=0;$i<100;$i++){
$x_pix = mt_rand(0,$width);
$y_pix = mt_rand(0,$height);
$dot_color = imagecolorallocate($img,mt_rand(100,255),mt_rand(100,255),mt_rand(100,255));
imagesetpixel($img,$x_pix,$y_pix,$dot_color);
}
$times =5;
for($i=0;$i<$times;$i++){
$x_beg_line = mt_rand(0,$width/$len);
$x_end_line = mt_rand($width - $width/$len ,$width);
$y_beg_line = mt_rand(0,$height);
$y_end_line = mt_rand(0,$height);
$line_color = imagecolorallocate($img,mt_rand(100,255),mt_rand(100,255),mt_rand(100,255));
imageline($img,$x_beg_line,$y_beg_line,$x_end_line,$y_end_line,$line_color);
}
header('Content-type:image/jpeg');
imagejpeg($img);
imagedestroy($img);
?>
0x04 实现验证码类
<?php
class CheckCode{
private $width;
private $height;
private $hImg;
private $str;
private $code;
private $code_len;
public function __construct($width,$height,$str,$code_len){
$this->width = $width;
$this->height = $height;
$this->hImg = imagecreate($this->width,$this->height);
$this->str = $str;
$this->code_len = $code_len;
}
public function draw(){
$this->draw_bk();
$this->set_code();
$this->set_session();
$this->draw_code();
$this->draw_salt();
ob_end_clean();
header("Content-type:image/jpeg");
imagejpeg($this->hImg);
imagedestroy($this->hImg);
}
private function draw_bk(){
imagecolorallocate($this->hImg,0,0,0);
}
private function set_code(){
for($i=0;$i<$this->code_len;$i++){
$this->code .= $this->str[mt_rand(0,strlen($this->str)-1)];
}
}
private function set_session(){
session_start();
$_SESSION['code'] = strtolower($this->code);
}
private function draw_code(){
for($i=0;$i<$this->code_len;$i++){
$size = 18;
$x = $i * ($this->width / $this->code_len) + $size;
$y = mt_rand($size,$this->height-$size);
$color = imagecolorallocate($this->hImg,0,255,0);
$angle = mt_rand(-25,25);
imagettftext($this->hImg,$size,$angle,$x,$y,$color,'code2.ttf',$this->code[$i]);
}
}
private function draw_salt(){
for($i=0;$i<5;$i++){
$bx = 0;
$by = mt_rand(0,$this->height);
$ex = $this->width;
$ey = mt_rand(0,$this->height);
$lcolor = imagecolorallocate($this->hImg,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imageline($this->hImg,$bx,$by,$ex,$ey,$lcolor);
}
for($i=0;$i<100;$i++){
$x = mt_rand(0,$this->width);
$y = mt_rand(0,$this->height);
$pcolor = imagecolorallocate($this->hImg,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imagesetpixel($this->hImg,$x,$y,$pcolor);
}
}
}
$str = 'abcdefghjkmnpqrstuvwxyz23456789ABCDEFGHJKMNPQRSTUVWXYZ';
$cc = new CheckCode(200,50,$str,4);
$cc->draw();
?>
0x05 验证码图片不显示的几种情况
1.你的验证码之前显示正常,突然不显示了 >>> 可能是GD库有问题。在php.ini中打开GD库
2.文件编码格式不对,文件编码格式最好是utf-8,不要是utf-8 BOM 或者是其他编码
3.图片输出前可能有输出内容
例如:
<?php
echo 'hello world';
header('Content-type:image/jpeg');
imagejpeg($hImg);
?>
这样做其实相当于在图片的二进制文件的开头加上了hello world。
解决方案
加上ob_end_clean();清空缓存区
<?php
echo 'hello world';
ob_end_clean();
header('Content-type:image/jpeg');
imagejpeg($hImg);
?>