29 June 2008

Каптча 3d

PHP
Прочитав топик «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 .= $chars{ mt_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*$z+ 20 * $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 != 0 ){

$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->image, 5, 3, 0, $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, $coord, 4, $whiteColor);

imagePolygon($this->image, $coord, 4, $linesColor);


}

}



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


imageString($this->image, 5, 3, 0, $this->text, $whiteColor);


imageString($this->image, 1, 3, 0, (microtime(true)-$this->time), $textColor);


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



imagepng($this->image);

imagedestroy($this->image);


}

}





П.С.: GPL
Tags:каптчаphpаукцион
Hubs: PHP
+132
5.5k 138
Comments 102