现在的位置: 首页 > 综合 > 正文

Zend_Captcha 验证码研究

2018年05月19日 ⁄ 综合 ⁄ 共 6324字 ⁄ 字号 评论关闭
 
复制PHP内容到剪贴板

PHP代码:

private $codeSession//定义一个全局 Zend_Session_Namespace

$this->codeSession = new Zend_Session_Namespace('code'); //在默认构造函数里实例化
$captcha = new Zend_Captcha_Image(array('font'=>'/images/Faktos.ttf',

//字体文件路径
              'fontsize'=>24,
              
'imgdir'=>'images/captcha',
//验证码图片存放位置
              'session'=>$this->codeSession,
              
'width'=>200,
              
'height'=>50,
              
'wordlen'=>));
//字母数
  $captcha->setGcFreq(3);//设置删除生成的旧的验证码图片的随机几率
  $captcha->generate();//生成图片
  
  
$this->codeSession->code=$captcha->getWord();
//获取当前生成的验证字符串

echo $this->codeSession->code;

Faktos.ttf 这是字体文件. 换成你的也可以.注意路径.
出来的结果如下

 

并且实现了  验证码字符 存放在了  session 中.
现在问题, 怎么 降噪,  上面的 黑色斑点太多了...

(1)编辑 Zend/Captcha/Image.php
两个地方同时改动红色数字 降低躁点,查找 imagefilledellipse
// generate noise
       for ($i=0; $i<100; $i++) {
          imagefilledellipse($img, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color);
       }
或者
(2)

PHP代码:

class ImgCode extends Zend_Captcha_Image 
{
protected function 
_generateImage($id$word
    { 
        if (!
extension_loaded("gd")) {
            require_once 
'Zend/Form/Exception.php';
            throw new 
Zend_Form_Exception("Image CAPTCHA requires GD extension");
        }
        if (!
function_exists("imagepng")) {
            require_once 
'Zend/Form/Exception.php';
            throw new 
Zend_Form_Exception("Image CAPTCHA requires PNG support");
        }
        if (!
function_exists("imageftbbox")) {
            require_once 
'Zend/Form/Exception.php';
            throw new 
Zend_Form_Exception("Image CAPTCHA requires FT fonts support");
        }
        
$font $this->getFont();
        if (empty(
$font)) {
            require_once 
'Zend/Form/Exception.php';
            throw new 
Zend_Form_Exception("Image CAPTCHA requires font");
        }
       @
header("Content-Type:image/png"); //这是我添加的
        
$w     $this->getWidth();
        
$h     $this->getHeight();
        
$fsize $this->getFontSize();
        
        
$img_file   $this->getImgDir() . $id $this->getSuffix();
        
$img        imagecreatetruecolor($w$h);
        
$text_color imagecolorallocate($img000);
        
$bg_color   imagecolorallocate($img255255255);
        
imagefilledrectangle($img00$w-1$h-1$bg_color);
        
$textbox imageftbbox($fsize0$font$word);
        
$x = ($w - ($textbox[2] - $textbox[0])) / 2;
        
$y = ($h - ($textbox[7] - $textbox[1])) / 2;
        
imagefttext($img$fsize0$x$y$text_color$font$word);
        
       
// generate noise
//        for ($i=0; $i<100; $i++) {
//           imagefilledellipse($img, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color);
//        }
        
for($i=0$i<5$i++) {
           
imageline($imgmt_rand(0,$w), mt_rand(0,$h), mt_rand(0,$w), mt_rand(0,$h), $text_color);
        }
        
        
// transformed image
        
$img2     imagecreatetruecolor($w$h);
        
$bg_color imagecolorallocate($img2255255255);
        
imagefilledrectangle($img200$w-1$h-1$bg_color);
        
// apply wave transforms
        
$freq1 $this->_randomFreq();
        
$freq2 $this->_randomFreq();
     
$freq3 $this->_randomFreq();
     
$freq4 $this->_randomFreq();
        
$ph1 $this->_randomPhase();
        
$ph2 $this->_randomPhase();
        
$ph3 $this->_randomPhase();
        
$ph4 $this->_randomPhase();
        
$szx $this->_randomSize();
        
$szy $this->_randomSize();

        for ($x 0$x $w$x++) {
            for (
$y 0$y $h$y++) {
                
$sx $x + (sin($x*$freq1 $ph1) + sin($y*$freq3 $ph3)) * $szx;
                
$sy $y + (sin($x*$freq2 $ph2) + sin($y*$freq4 $ph4)) * $szy;
    
                if (
$sx || $sy || $sx >= $w || $sy >= $h 1) { 
                    continue;
                } else {
                    
$color    = (imagecolorat($img$sx$sy) >> 16)         & 0xFF;
                    
$color_x  = (imagecolorat($img$sx 1$sy) >> 16)     & 0xFF;
                    
$color_y  = (imagecolorat($img$sx$sy 1) >> 16)     & 0xFF;
                    
$color_xy = (imagecolorat($img$sx 1$sy 1) >> 16) & 0xFF;
                }
                if (
$color == 255 && $color_x == 255 && $color_y == 255 && $color_xy == 255) {
                    
// ignore background
                    
continue;
                } elseif (
$color == && $color_x == && $color_y == && $color_xy == 0) {
                    
// transfer inside of the image as-is
                    
$newcolor 0;
                } else {
                    
// do antialiasing for border items
                    
$frac_x  $sx-floor($sx);
                    
$frac_y  $sy-floor($sy);
                    
$frac_x1 1-$frac_x;
                    
$frac_y1 1-$frac_y;
                    
$newcolor $color    $frac_x1 $frac_y1
                              
$color_x  $frac_x  $frac_y1
                              
$color_y  $frac_x1 $frac_y
                              
$color_xy $frac_x  $frac_y;
                }
                
imagesetpixel($img2$x$yimagecolorallocate($img2$newcolor$newcolor$newcolor));
            }
        }
       
        
// generate noise
//        for ($i=0; $i<100; $i++) {
//            imagefilledellipse($img2, mt_rand(0,$w), mt_rand(0,$h), 2, 2, $text_color);
//        }
//        for ($i=0; $i<5; $i++) {
//           imageline($img2, mt_rand(0,$w), mt_rand(0,$h), mt_rand(0,$w), mt_rand(0,$h), $text_color);
//        }
        
      
imagepng($img2); //这里我去掉了 $img_file 这个参数
        
imagedestroy($img);
        
imagedestroy($img2);
    }
}

只是继承了 Zend_Captcha_Image  并 重写了里面的方法, 只是把他的方法复制过来.然后 注释了几行.加了 header
把 ImgCode 这个类放在 modules 目录里就可以了

Zend居然每刷新一次 就生成一张图片 并且存放到 $imgdir 下面
在这里设定一个图片数量 超过限制就自动删除。 如上代码所示 $captcha->setGcFreq(3)

另外需要修改 protected function _gc() 函数为:

protected function _gc()
    {
        //$expire = time() - $this->getExpiration();
        $expire = time();
        echo $this->getExpiration();
        foreach (new DirectoryIterator($this->getImgDir()) as $file) {
            if (!$file->isDot() && !$file->isDir()) {
                if ($file->getMTime() < $expire) {
                    unlink($file->getPathname());
                }
            }
        }
    }

PHP代码:
$captcha = new ImgCode(array('font'=>'/images/Faktos.ttf',//字体路径
         
'fontsize'=>字体大小,
         
'session'=>$this->codeSession,//存放的 session 对象
         
'width'=>,
         
'height'=>,
         
'wordlen'=>字符数));
         $id=$captcha->generate();

抱歉!评论已关闭.