Introduction
CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) image is a way to prevent from bot attacks to our website's forms.
This article demonstrates how we can create our own CAPTCHA.
Using the Code
At first, we have to create a new true color image.
We can create it with imagecreatetruecolor
[^] function in PHP.
$image = imagecreatetruecolor($this -> winWidth,
$this -> winHeight) //Create a new true color image
or die("<b>" . __FILE__ . "</b><br />" . __LINE__ . " : "
."Cannot Initialize new GD image stream");
$bg = imagecolorallocate($image, 255, 255, 255);//Allocate a color for an image
imagefill($image, 10, 10, $bg);//Flood fill
.
.
.
return imagepng($image);//Outputs or saves a PNG image from the given $image
imagedestroy($image);//rees any memory associated with image $image
This image is too simple, so we can change the background with a simple algorithm:
private $Colors = array ( '0' => '145',
'1' => '204',
'2' => '177',
'3' => '184',
'4' => '199',
'5' => '255');
.
.
.
for ($x=0; $x < $this -> winWidth; $x++)
{
for ($y=0; $y < $this -> winHeight; $y++)
{
$random = mt_rand(0 , 5);
$temp_color = imagecolorallocate($image,
$this -> Colors["$random"],
$this -> Colors["$random"], $this -> Colors["$random"]);
imagesetpixel( $image, $x, $y , $temp_color );
}
}
The result of the above code:
Then we should write the characters in our image:
//e.g $this->Characters is the string that we're writing in the image
//Font
$font = "tahomabd.ttf";
$font_size = 33;
//\\
$char = $this -> Characters[0];
$random_x = mt_rand(10 , 20);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
//Writes the given text into the image using TrueType fonts.
imagettftext($image, $font_size, $random_angle, $random_x, $random_y,
$char_color, $font, $char);
We repeat it to fill our image with characters.
The result is as follows:
But I guess it is a little plain yet, so we can add an effect to our image for creating a more complex CAPTCHA.
I've added a wave effect with a pure mathematic algorithm:
private $applyWave = true;
.
.
.
private function apply_wave($image, $width, $height)
{
$x_period = 10;
$y_period = 10;
$y_amplitude = 5;
$x_amplitude = 5;
$xp = $x_period*rand(1,3);
$k = rand(0,100);
for ($a = 0; $a<$width; $a++)
imagecopy($image, $image, $a-1, sin($k+$a/$xp)*$x_amplitude,
$a, 0, 1, $height);
$yp = $y_period*rand(1,2);
$k = rand(0,100);
for ($a = 0; $a<$height; $a++)
imagecopy($image, $image, sin($k+$a/$yp)*$y_amplitude,
$a-1, 0, $a, $width, 1);
return $image;
}
You can change the intensity of waves by changing these variables:
$x_period
$y_period
$y_amplitude
$x_amplitude
Let's see the result:
I've also added some lines to the image :
private $showLine = true;
.
.
.
//draws lines
if ($this -> showLine)
{
for ($i=0; $i<$this->winWidth; $i++ )
{
if ($i%10 == 0)
{
imageline ( $image, $i, 0,
$i+10, 50, $char_color );
imageline ( $image, $i, 0,
$i-10, 50, $char_color );
}
}
}
The latest result:
That's all.
Good luck.
How To: Using Phpbb3 CAPTCHAHow to: Using PHP Fusion 7 CAPTCHA
Dayyan CAPTCHA Class
Source Code:
<?php
/*
Created by Mohammad Dayyan (C)- 1387/3/2
http://www.mds-soft.persianblog.ir/
*/
if ( !defined('MohammadDayyan') )
{
die ("Hacking attempt <br /> <b>" . __FILE__ .
"<br /> Line " . __LINE__ . "</b>" );
exit;
}
class DayyanConfirmImage
{
private $showLine = true;
private $applyWave = true;
private $winHeight = 50;
private $winWidth = 320;
private $Characters; // random characters
private $Colors = array ( '0' => '145',
'1' => '204',
'2' => '177',
'3' => '184',
'4' => '199',
'5' => '255');
////////////////////////////////////////////////////////////////////////////////
public function __construct($ConfirmCode)
{
$this -> Characters = $ConfirmCode;
}
////////////////////////////////////////////////////////////////////////////////
public function ShowImage()
{
//detect server operation system
if ( strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' )//windows detected
$this -> win();
else //linux detected
$this -> linux();
}
////////////////////////////////////////////////////////////////////////////////
private function win()
{
////////////////////////////////////
//background image
$image = imagecreatetruecolor($this -> winWidth, $this -> winHeight)
or die("<b>" . __FILE__ . "</b><br />" . __LINE__ . " :
" ."Cannot Initialize new GD image stream");
$bg = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 10, 10, $bg);
for ($x=0; $x < $this -> winWidth; $x++)
{
for ($y=0; $y < $this -> winHeight; $y++)
{
$random = mt_rand(0 , 5);
$temp_color = imagecolorallocate($image,
$this -> Colors["$random"],
$this -> Colors["$random"], $this -> Colors["$random"]);
imagesetpixel( $image, $x, $y , $temp_color );
}
}
$char_color = imagecolorallocatealpha($image, 0, 0, 0, 90);
//Font
$font = "tahomabd.ttf";
$font_size = 33;
////////////////////////////////////
//Image characters
$char = "";
$char = $this -> Characters[0];
$random_x = mt_rand(10 , 20);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
$char = $this -> Characters[1];
$random_x = mt_rand(50 , 70);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
$char = $this -> Characters[2];
$random_x = mt_rand(100 , 120);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
$char = $this -> Characters[3];
$random_x = mt_rand(150 , 170);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
$char = $this -> Characters[4];
$random_x = mt_rand(200 , 220);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
$char = $this -> Characters[5];
$random_x = mt_rand(250 , 270);
$random_y = mt_rand(35 , 45);
$random_angle = mt_rand(-20 , 20);
imagettftext($image, $font_size, $random_angle,
$random_x, $random_y, $char_color, $font, $char);
////////////////////////////////////
if ($this -> applyWave)
$image = $this -> apply_wave($image, $this -> winWidth,
$this -> winHeight);
////////////////////////////////////
//lines
if ($this -> showLine)
{
for ($i=0; $i<$this->winWidth; $i++ )
{
if ($i%10 == 0)
{
imageline ( $image, $i, 0,
$i+10, 50, $char_color );
imageline ( $image, $i, 0,
$i-10, 50, $char_color );
}
}
}
////////////////////////////////////
return imagepng($image);
imagedestroy($image);
}
/////////////////////////////////////////////////////////////
private function linux()
{
////////////////////////////////////
//Background image
$image = imagecreatetruecolor(150, 50) or
die("<b>" . __FILE__ . "</b><br />" . __LINE__ . " : "
."Cannot Initialize new GD image stream");
$bg = imagecolorallocate($image, 255, 255, 255);
imagefill($image, 10, 10, $bg);
for ($x=0; $x < 150; $x++)
{
for ($y=0; $y < 50; $y++)
{
$random = mt_rand(0 , 5);
$temp_color = imagecolorallocate($image, $this ->
Colors["$random"], $this -> Colors["$random"], $this ->
Colors["$random"]);
imagesetpixel( $image, $x, $y , $temp_color );
}
}
$char_color = imagecolorallocatealpha($image, 0, 0, 0, 60);
////////////////////////////////////
//Image Info
$font = 5;
////////////////////////////////////
//Image characters
$char = $this -> Characters[0];
$random_x = mt_rand(10 , 20);
$random_y = mt_rand(15,25);
imagestring($image, $font, $random_x, $random_y, $char, $char_color);
$char = $this -> Characters[1];
$random_x = mt_rand(30 , 40);
$random_y = mt_rand(15,25);
imagestring($image, $font, $random_x, $random_y, $char, $char_color);
$char = $this -> Characters[2];
$random_x = mt_rand(50 , 60);
$random_y = mt_rand(15,25);
imagestring($image, $font, $random_x, $random_y, $char, $char_color);
$char = $this -> Characters[3];
$random_x = mt_rand(70 , 80);
$random_y = mt_rand(15,25);
imagestring($image, $font, $random_x, $random_y, $char, $char_color);
$char = $this -> Characters[4];
$random_x = mt_rand(90 , 100);
$random_y = mt_rand(15,25);
imagestring($image, $font, $random_x, $random_y, $char, $char_color);
$char = $this -> Characters[5];
$random_x = mt_rand(110 , 120);
$random_y = mt_rand(15,25);
imagestring($image, $font, $random_x, $random_y, $char, $char_color);
///////////////////////
return imagepng($image);
imagedestroy($image);
}
///////////////////////////////////////////////////////////
private function apply_wave($image, $width, $height)
{
$x_period = 10;
$y_period = 10;
$y_amplitude = 5;
$x_amplitude = 5;
$xp = $x_period*rand(1,3);
$k = rand(0,100);
for ($a = 0; $a<$width; $a++)
imagecopy($image, $image, $a-1, sin($k+$a/$xp)*$x_amplitude,
$a, 0, 1, $height);
$yp = $y_period*rand(1,2);
$k = rand(0,100);
for ($a = 0; $a<$height; $a++)
imagecopy($image, $image, sin($k+$a/$yp)*$y_amplitude,
$a-1, 0, $a, $width, 1);
return $image;
}
}
?>
History
- 3rd January, 2008: First post
- 23rd February, 2009: Last update