<?php
namespace imcat;
//生成验证码
class comVCode {
private $im; //图片对象
private $dis; //图片对象
private $imw = 160; //宽
private $imh = 40; //高
private $mod = ''; //模块
private $ttf = ''; //字体文件 //array
private $ttOld = '';
private $clOld = Null;
private $code = ''; //字符
private $corg = ''; //字符
private $ctab = ''; //随机颜色表
//private $cTab = "";
//private $oTab = '';
static $ctabN = [];
static $ctabA = [];
static $ctabB = [];
static function initTab(){
self::$ctabN['4'] = ['0'=>0, '5'=>85, 'A'=>170, 'F'=>255]; # gap:5 : 0-5-A-F
self::$ctabN['5'] = ['00'=>0, '40'=>64, '80'=>128, 'C0'=>192, 'F0'=>255]; # gap:8 : 00:80:C0:F0
self::$ctabN['6'] = ['0'=>0, '3'=>51, '6'=>102, '9'=>153, 'C'=>204, 'F'=>255];
//
self::$ctabA['6'] = [ # gap:6
'0'=>['6','9','C','F'],
'3'=>[ '9','C','F'],
'6'=>['0', 'C','F'],
'9'=>['0','3', 'F'],
'C'=>['0','3','6' ],
'F'=>['0','3','6','9'],
];
self::$ctabB['6'] = [ # gap:6
'0'=>['3'],
'3'=>['0','6'],
'6'=>['3','9'],
'9'=>['6','C'],
'C'=>['9','F'],
'F'=>['C'],
];
}
# 前背景颜色
static function tabrc($n=6, $rc3=0, $rx=0){
$tbcn = self::$ctabN['6']; $tbkn = array_keys($tbcn);
$tban = self::$ctabA['6']; $tbbn = self::$ctabB['6'];
# one
if(!$n){
return $rc3 ? implode('',$tb3) : [$tbcn[$tb3[0]],$tbcn[$tb3[1]],$tbcn[$tb3[2]]];
}
# RGB(n+1)
$tb3 = $ts1 = []; shuffle($tbkn); #dump($tbkn);
$xb3 = $xs1 = [];
for($i=0;$i<3;$i++){
$tb3[] = $k1 = $tbkn[$i]; $ts1[] = $tban[$k1];
$xb3[] = $k1 = $tbkn[$i]; $xs1[] = $tbbn[$k1];
} #dump($tb3); dump($ts1);
# return n + 1
$ts3[] = $rc3 ? implode('',$tb3) : [$tbcn[$tb3[0]],$tbcn[$tb3[1]],$tbcn[$tb3[2]]];
for($i=0;$i<$n;$i++){
$k1 = array_rand($ts1[0],1); $c1=$ts1[0][$k1]; $k2 = array_rand($ts1[1],1); $c2=$ts1[1][$k2]; $k3 = array_rand($ts1[2],1); $c3=$ts1[2][$k3];
$ts3[] = $rc3 ? "$c1$c2$c3" : [$tbcn[$c1],$tbcn[$c2],$tbcn[$c3]];
$k1 = array_rand($xs1[0],1); $c1=$xs1[0][$k1]; $k2 = array_rand($xs1[1],1); $c2=$xs1[1][$k2]; $k3 = array_rand($xs1[2],1); $c3=$xs1[2][$k3];
$xs3[] = $rc3 ? "$c1$c2$c3" : [$tbcn[$c1],$tbcn[$c2],$tbcn[$c3]];
}
#dump($tb3); dump($ts1); dump($ts3);
return [$ts3, $xs3];
}
function __construct($mod='(istest)', $ttf='', $corg='0'){
$this->mod = $mod;
$this->ttf = $ttf;
$this->corg = $corg;
self::initTab();
// 显示图片一般图片
if(function_exists('imagecreate')){
$this->show();
}else{ //bmp
glbError::show("NO function:imagecreate!");
}
}
function init(){
if($this->mod=='(emtel)'){
$this->code = $this->corg;
$this->imw = 20+strlen($this->corg)*20;
}else{
$this->code = self::strRand();
}
$this->im = imagecreate($this->imw, $this->imh);
// 填充
$this->ctbs = $this->tabrc(strlen($this->code), 0, 1); # n+1个颜色
$this->bgColor = $this->rndCimg($this->ctbs[0][0]);
imagefill($this->im,0,0,$this->bgColor);
}
// 输出
function output(){
$typa = array(1=>'gif', 2=>'png', 3=>'jpeg');
$type = $typa[rand(1,3)];
basEnv::obClean();
#header("Pragma:no-cache");
#header("Cache-control:no-cache");
#header("Content-type:image/$type");
$func = "image$type"; //imagejpeg
$func($this->im);
}
// 显示
function show(){
$this->init();
safComm::formCVimg($this->mod, $this->code, 'save');
// 干扰: 点,线,特殊字符,雪花
if($this->mod!='(emtel)'){
$r = rand(1,4);
if($r==1) $this->_rndPixels();
if($r==2) $this->_rndLines();
if($r==3) $this->_rndChars();
if($r==4) $this->_rndSnow();
}
$this->drawStr(); // Draw字符,划边框
//$this->distOrtion(); // 扭曲文字
$this->output();
imagedestroy($this->im);
if(is_resource($this->dis)){
imagedestroy($this->dis);
}
}
// Draw字符
function drawStr(){
for($i=0;$i<strlen($this->code);$i++) {
$chr = $this->code[$i];
if($this->mod=='(emtel)'){
$size = 20;
}elseif(ord($chr)>96){
$size = mt_rand(22,26);
}else{
$size = mt_rand(16,20);
}
$angle = $this->mod=='(emtel)' ? 0 : mt_rand(-20,20);
$x = $this->mod=='(emtel)' ? $i*20+8 : mt_rand(15,20)+$i*26;
$y = $this->mod=='(emtel)' ? mt_rand(24,30) : mt_rand(27,30);
$ffile = $this->rndFonts(); $tcolor = $this->rndCimg($this->ctbs[0][$i+1]);
if($this->mod!='(emtel)'){
// 外围描边(空心效果) ctab -> ctbs
$cb = $this->rndCimg($this->ctbs[1][$i]);
imagettftext($this->im, $size, $angle, $x+1, $y, $cb, $ffile, $chr); // x
imagettftext($this->im, $size, $angle, $x, $y+1, $cb, $ffile, $chr); // y
}
// 文字本身
imagettftext($this->im, $size, $angle, $x, $y, $tcolor, $ffile, $chr);
}
}
function rndCimg($ctab){
$cl = imagecolorallocate($this->im, $ctab[0], $ctab[1], $ctab[2]);
if($cl===false){
$cl = imagecolorclosest($this->im, $ctab[0], $ctab[1], $ctab[2]);
}
return $cl;
}
// 随机颜色
function rndColor($no=0){
$ct = [];
for($i=0;$i<3;$i++){ $ct[]=mt_rand(2,254); }
$cl = $this->rndCimg($ct);
return $cl;
}
// 随机Font
public function rndFonts(){
if(is_string($this->ttf)){
$tti = $this->ttf;
}else{
$tti = $this->ttf[mt_rand(0,count($this->ttf)-1)];
while($this->ttOld==$tti){
$tti = $this->ttf[mt_rand(0,count($this->ttf)-1)];
}
$this->ttOld = $tti;
}
$ffile = DIR_STATIC.'/media/fonts/'.$tti.'.ttf';
return $ffile;
}
// 干扰象素
function _rndPixels(){ //加入干扰象素
for($i=0;$i<200;$i++){
imagesetpixel($this->im, rand()%160 , rand()%100 , $this->rndColor());
}
}
// 干扰线
function _rndLines(){
$w = $this->imw-2;
$h = $this->imh-2;
$cnt = mt_rand(5,8);
for($j=2;$j<$cnt;$j++){
imageline($this->im, rand(2,$w),rand(2,$h),rand(2,$w),rand(2,$h), $this->rndColor()
); //18
}
imagerectangle($this->im, 0, 0, $this->imw-1, $this->imh-1, $this->rndColor()); // 边框
}
// 干扰字符
function _rndChars(){
if(empty($this->ttf)){ return; }
$cnt = mt_rand(5,10); //《!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~》// All:32 '+','-',
$chars = array('!',"'",'(',')',',','/',";","?","^","`","~");
for($i=1; $i<=$cnt; $i++){
imagestring($this->im,mt_rand(1,5),mt_rand(1,$this->imw),mt_rand(1,$this->imh),$chars[mt_rand(0,4)],$this->rndColor());
}
}
// 雪花
function _rndSnow(){
for ($i=0;$i<30;$i++) {
$color = imagecolorallocate($this->im,mt_rand(200,255),mt_rand(200,255),mt_rand(200,255));
imagestring($this->im,mt_rand(2,5),mt_rand(0,$this->imw),mt_rand(0,$this->imh),'*',$color);
}
}
// 扭曲文字
public function distOrtion(){
$rate = floor(0.08 * $this->imh); // 扭曲程度
$this->dis = imagecreatetruecolor($this->imw, $this->imh);
imagefill($this->dis, 0, 0, $this->bgColor);
for ($x = 0; $x < $this->imw; $x++) {
for ($y = 0; $y < $this->imh; $y++) {
$rgb = imagecolorat($this->im, $x, $y);
if( (int)($x + sin($y / $this->imh * 2 * M_PI) * $rate) <= $this->imw && (int)($x + sin($y / $this->imh * 2 * M_PI) * $rate) >= 0 )
{
imagesetpixel($this->dis, (int)($x + sin($y / $this->imh * 2 * M_PI - M_PI * 0.1) * $rate) , $y, $rgb);
}
}
}
$this->im = $this->dis;
}
// *** 随机码
static function strRand(){
global $_cbase;
$vimg = $_cbase['ucfg']['vimg'];
$type = in_array($vimg,array('0','H','K')) ? $vimg : 'K';
$str = basKeyid::kidRand($type,rand(4,5));
return strtoupper($str);
}
// 颜色表
/*function setCtab($xTab,$xArr,$init){}*/
//basDebug::bugLogs('vcode', $this->code, 'vcode.txt', 'file');
}