展会信息港展会大全

php 验证码(倾斜,正弦干扰线,黏贴,旋转)
来源:互联网   发布日期:2016-03-02 15:28:39   浏览:2231次  

导读:1、字体变型 (一般通过算法,进行扭曲,比较有代表性就是:http://code.google.com/p/cool-php-captcha/2、字体黏贴 (这里面以qq验证码为代表了,目...

1、字体变型 (一般通过算法,进行扭曲,比较有代表性就是:http://code.google.com/p/cool-php-captcha/

2、字体黏贴 (这里面以qq验证码为代表了,目前网上还是很难找到,破解qq验证码的)

3、干扰线,噪点 (这种识别起来相当容易,很容易被程序自动化识别)

对于上面提到,第1,2 二种方法,在识别时候,是比较困难的。个人比较喜欢第二种方法,感觉看起来不是很费力。而扭曲的文字,总觉得怪怪的。 哈哈,纯粹个人喜好了。

实现代码:

<?php

/***带文字旋转,倾斜,黏贴,加正弦干扰线验证码**@version0.1*@author http://www.cnblogs.com/chengmo*@copyright 程默 QQ:8292669*/

class Utils_Caption

{

var $Width= 60;//图片宽

var $Height= 30;//图片高

var $Length= 4;//验证码位数

var $BgColor= "#FFFFFF";//背景色

var $TFonts = array("font.ttf");

var $TFontSize=array(17,20); //字体大小范围

var $TFontAngle=array(-20,20); //旋转角度

var $Chars= "0123456789";//验证码范围(字母数字)

var $Code= array();//验证码

var $Image= "";//图形对象

var $FontColors=array('#f36161','#6bc146','#5368bd');//字体颜色,红绿蓝

var $TPadden = 0.75;///字符间距,多少个字符

var $Txbase = 5;///x轴两边距离

var $Tybase =5 ;///y轴两边距离

var $TLine =true; ///画干扰线

publicfunction RandRSI() ///生成验证码

{

$this->TFontAngle=range($this->TFontAngle[0],$this->TFontAngle[1]);

$this->TFontSize=range($this->TFontSize[0],$this->TFontSize[1]);

$arr=array();

$Chars=$this->Chars;

$TFontAngle=$this->TFontAngle;

$TFontSize=$this->TFontSize;

$FontColors=$this->FontColors;

$code="";

$font=dirname(__FILE__)."/font/".$this->TFonts[0];

$charlen=strlen($Chars)-1;

$anglelen=count($TFontAngle)-1; // 角度范围

$fontsizelen=count($TFontSize)-1; // 角度范围

$fontcolorlen=count($FontColors)-1; // 角度范围

for($i=0;$i<$this->Length;$i++) ///得到字符与颜色

{

$char=$Chars[rand(0,$charlen)]; ///得到字符

$angle=$TFontAngle[rand(0,$anglelen)]; ///旋转角度

$fontsize=$TFontSize[rand(0,$fontsizelen)]; ///字体大小

$fontcolor=$FontColors[rand(0,$fontcolorlen)]; ///字体大小

$bound=$this->_calculateTextBox($fontsize,$angle,$font,$char); ///得到范围

$arr[]=array($fontsize,$angle,$fontcolor,$char,$font,$bound);///得到矩形框

$code.=$char;

}

$this->Code=$arr; //验证码

return $code;

}

public function Draw() ///画图

{

if(empty($this->Code)) $this->RandRSI();

$codes=$this->Code; ///用户验证码

$wh=$this->_getImageWH($codes);

$width=$wh[0];

$height=$wh[1]; ///高度

$this->Width=$width;

$this->Height=$height;

$this->Image = imageCreate( $width, $height );

$image=$this->Image;

$back = $this->_getColor2($this->_getColor( $this->BgColor)); ///背景颜色

imageFilledRectangle($image, 0, 0, $width, $height, $back); ///填充背景

$TPadden=$this->TPadden;

$basex=$this->Txbase;

$color=null;

foreach ($codes as $v) ///逐个画字符

{

$bound=$v[5];

$color=$this->_getColor2($this->_getColor($v[2]));

imagettftext($image, $v[0], $v[1], $basex, $bound['height'],$color , $v[4], $v[3]);

$basex=$basex+$bound['width']*$TPadden-$bound['left'];///计算下一个左边距

}

$this->TLine?$this->_wirteSinLine($color,$basex):null; ///画干扰线

header("Content-type: image/png");

imagepng( $image);

imagedestroy($image);

}

/***通过字体角度得到字体矩形宽度*** @param int $font_size 字体尺寸* @param float $font_angle 旋转角度* @param string $font_file 字体文件路径* @param string $text 写入字符* @return array 返回长宽高*/

private function _calculateTextBox($font_size, $font_angle, $font_file, $text) {

$box = imagettfbbox($font_size, $font_angle, $font_file, $text);

$min_x = min(array($box[0], $box[2], $box[4], $box[6]));

$max_x = max(array($box[0], $box[2], $box[4], $box[6]));

$min_y = min(array($box[1], $box[3], $box[5], $box[7]));

$max_y = max(array($box[1], $box[3], $box[5], $box[7]));

return array(

'left' => ($min_x >= -1) ? -abs($min_x + 1) : abs($min_x + 2),

'top' => abs($min_y),

'width' => $max_x - $min_x,

'height' => $max_y - $min_y,

'box' => $box

);

}

private function_getColor( $color ) //#ffffff

{

return array(hexdec($color[1].$color[2]),hexdec($color[3].$color[4]),hexdec($color[5].$color[6]));

}

private function_getColor2( $color ) //#ffffff

{

return imagecolorallocate ($this->Image, $color[0], $color[1], $color[2]);

}

private function _getImageWH($data)

{

$TPadden=$this->TPadden;

$w=$this->Txbase;

$h=0;

foreach ($data as $v)

{

$w=$w+$v[5]['width']*$TPadden-$v[5]['left'];

$h=$h>$v[5]['height']?$h:$v[5]['height'];

}

return array(max($w,$this->Width),max($h,$this->Height));

}

//画正弦干扰线

private function _wirteSinLine($color,$w)

{

$img=$this->Image;

$h=$this->Height;

$h1=rand(-5,5);

$h2=rand(-1,1);

$w2=rand(10,15);

$h3=rand(4,6);

for($i=-$w/2;$i<$w/2;$i=$i+0.1)

{

$y=$h/$h3*sin($i/$w2)+$h/2+$h1;

imagesetpixel($img,$i+$w/2,$y,$color);

$h2!=0?imagesetpixel($img,$i+$w/2,$y+$h2,$color):null;

}

}

}

外带字体:

font.ttf ,一个简单粗体文件。

说明:

先看下运行效果吧,大家也不要忙着复制运行了。

……

主要特点是:旋转,然后黏贴,干扰线是线粗细可以变,然后正弦波形可以变化。

比较复杂是:calculateTextBox 这个函数,这个是得到字符旋转后的宽度高度。

demo:

$rsi = new Utils_Caption();

$rsi->TFontSize=array(15,17);

$rsi->Width=50;

$rsi->Height=25;

$code = $rsi->RandRSI();

session_start();

$_SESSION["CHECKCODE"] = $code;

$rsi->Draw();

好了,就写这么些了,代码还有很多不足之处。欢迎朋友提出好的建议。

赞助本站

人工智能实验室

相关热词: 开发 编程 android

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港