Pull to refresh

Каптча 3d

Reading time 7 min
Views 6.2K
Прочитав топик «RapidShare — новые каптчи», я вспомнил как слушал доклад создателя каптчи на UaВебе.



Зайдя на сайт, желая посмотреть код, я увидел:
Q: Is it opensource?
A: No, sorry. Maybe later.

Я удивился! Мне казалось что любой маломальски образованный хороший программист сделает такую каптчу.
Погуглив и нашел пару интересных линков: 1, 2 и не получил кода, решил написать сам.

:00 С чего начать? Вспоминая времена университета, линейный анализ (ее у меня вел класный препод) и подумав что както нежно сделать с 3D -> 2D, а это как я помню называется «проекция», я набрал это слово в строку поиска
:03 Пройдя по цепочке ссылок в Википедии и прочитав подходящую статью я решил что мне подойдет изометрическая проекция
:05 Ну вот главная формула есть
изометрическая проекция
:15 пару строк кода и вот первая 3D картинка
Piccy.info - Free Image Hosting
:16 два цикла и
Piccy.info - Free Image Hosting
:20 выведу текст и используя его как патерн для z оси получаем
Piccy.info - Free Image Hosting
:30 добавим шума и синусоид получим
Piccy.info - Free Image Hosting

Скорость частота отрисовки 31.42 [#/sec] на Intel Core 2 Duo 2.2 GGz php 5.2.6 Apache 2.2.4 on Win Vista Sp1

/**
*
* @author Andrii Kasian <to.kandy@gmail.com>
*/

<?php 


$capthca 
= new Capthca3d();

$capthca->render();



class 
Capthca3d{


    const 
CHARS 'WEafRTYIPAGHJKXBNM3479j';

    
protected $hypot 8;

    
protected $image null;

    

    
protected $text '';


    

    
public function __construct()

    {

        
$this->time microtime(true);

        
$this->generateCode();


    

    }

    
protected function generateCode()

    {

        
$chars self::CHARS;

        for(
$i =0$i<3$i++){


            
$this->text .= $charsmt_rand(0,22)};

        }

    }

    

    
public function getText()


    {

        return 
$this->text;

    }

    
protected function getProection($x1,$y1,$z1)


    {

        
$x $x1 $this->hypot

        
$y $z1 $this->hypot;


        
$z = -$y1 $this->hypot;

        

        
$xx 0.707106781187

        
$xy 0;


        
$xz = -0.707106781187

        

        
$yx 0.408248290464

        
$yy 0.816496580928


        
$yz 0.408248290464;

        

        
$cx $xx*$x $xy*$y $xz*$z;


        
$cy $yx*$x $yy*$y $yz*$z20 $this->hypot;


        return array(

            
'x' => $cx,

            
'y' => $cy

            
); 

    }

    

    function 
zFunction($x,$y){


        
$z imagecolorat($this->image,$y/2,$x/2)>0?2.6:0;


        if( 
$z != ){

            
$z += mt_rand(0,60)/100;

        }

        
$z += 1.4 sin(($x+$this->startX)*3.141592654/15)*sin(($y+$this->startY)*3.141592654/15);


        return 
$z;

    }

    
public function render()    

    {

        
$xx =30;

         
$yy =60;


        

         
$this->image imageCreateTrueColor($yy $this->hypot  $xx $this->hypot);


        

        
$whiteColor imageColorAllocate($this->image,255,255,255);

        
imageFilledRectangle($this->image,0,0,$yy $this->hypot  $xx $this->hypot,$whiteColor);


        

        
$textColor imageColorAllocate($this->image,0,0,0);

        
imageString($this->image530$this->text$textColor);


        

        

         
$this->startX mt_rand(0,$xx);    

         
$this->startY mt_rand(0,$yy);


        

         
$coordinates = array();

         

        for(
$x 0$x $xx 1$x++){


            for(
$y 0$y $yy 1$y++){

                
$coordinates[$x][$y] = $this->getProection($x,$y,$this->zFunction($x,$y));


             }

         }

         

        for(
$x 0$x $xx$x++){

            for(
$y 0$y $yy$y++){


                 
$coord = array();

                 
$coord[] = $coordinates[$x][$y]['x'];

                 
$coord[] = $coordinates[$x][$y]['y'];


                 

                 
$coord[] = $coordinates[$x+1][$y]['x'];

                 
$coord[] = $coordinates[$x+1][$y]['y'];


                 

                 
$coord[] = $coordinates[$x+1][$y+1]['x'];

                 
$coord[] = $coordinates[$x+1][$y+1]['y'];


                 

                 
$coord[] = $coordinates[$x][$y+1]['x'];

                 
$coord[] = $coordinates[$x][$y+1]['y'];


                

                
$c = (int) ($this->zFunction($x,$y)*32);

                
$linesColor imageColorAllocate($this->image$c$c$c);


                
imageFilledPolygon($this->image$coord4$whiteColor);

                
imagePolygon($this->image$coord4$linesColor);


             }

         }

        

        
$textColor imageColorAllocate($this->image,0,0,0);


        
imageString($this->image530$this->text$whiteColor);


        
imageString($this->image130, (microtime(true)-$this->time), $textColor);


        
header('Content-Type: image/png');

        

        
imagepng($this->image);

        
imagedestroy($this->image);


    }

}





П.С.: GPL
Tags:
Hubs:
+132
Comments 102
Comments Comments 102

Articles