Click here to Skip to main content
15,867,594 members
Articles / Web Development / Apache

CAPTCHA Image in PHP

Rate me:
Please Sign up or sign in to vote.
4.94/5 (21 votes)
23 Feb 2009GPL31 min read 119.3K   4K   35   22
This article demonstrates how we can create a CAPTCHA image with PHP
CAPTCHA.png

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:

BG1.png

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:

CAPTCHA-2.png

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:

CAPTCHA.png

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:

CAPTCHA-lines.png

That's all.
Good luck.

How To: Using Phpbb3 CAPTCHA
How 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

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Iran (Islamic Republic of) Iran (Islamic Republic of)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionCreate CAPTCHA Code in PHP Pin
Member 1363180316-Feb-18 21:54
Member 1363180316-Feb-18 21:54 
GeneralThanks.. Pin
Member 135669679-Dec-17 14:36
Member 135669679-Dec-17 14:36 
Questionhelp me Pin
Member 1034396417-Oct-13 23:07
Member 1034396417-Oct-13 23:07 
QuestionNeed some Help Pin
Member 961824821-Nov-12 1:29
Member 961824821-Nov-12 1:29 
Questiongood Pin
ajjaj16-May-12 20:01
ajjaj16-May-12 20:01 
QuestionWindows <--> Linux and further improving security Pin
TerraD2-Apr-12 1:05
TerraD2-Apr-12 1:05 
AnswerRe: Windows Linux and further improving security Pin
Mohammad Dayyan2-Apr-12 1:26
Mohammad Dayyan2-Apr-12 1:26 
QuestionHow does the code against hacking attempts work? Pin
TerraD1-Apr-12 22:15
TerraD1-Apr-12 22:15 
AnswerRe: How does the code against hacking attempts work? Pin
Mohammad Dayyan1-Apr-12 22:22
Mohammad Dayyan1-Apr-12 22:22 
QuestionIs not working Pin
BrandonSkyPimenta1-Apr-12 8:23
BrandonSkyPimenta1-Apr-12 8:23 
AnswerRe: Is not working Pin
Mohammad Dayyan1-Apr-12 9:52
Mohammad Dayyan1-Apr-12 9:52 
GeneralNice. Pin
CalvinHartwell20-Oct-09 13:13
CalvinHartwell20-Oct-09 13:13 
GeneralNo reCaptcha for me Pin
TerraD1-Apr-12 21:32
TerraD1-Apr-12 21:32 
GeneralGreat Article/Protected IP Pin
Curtis Schlak.26-Feb-09 10:49
Curtis Schlak.26-Feb-09 10:49 
GeneralRe: Great Article/Protected IP Pin
Mohammad Dayyan26-Feb-09 23:09
Mohammad Dayyan26-Feb-09 23:09 
GeneralVery useful Pin
Perspx6-Aug-08 13:46
Perspx6-Aug-08 13:46 
GeneralRe: Very useful Pin
Mohammad Dayyan6-Aug-08 14:24
Mohammad Dayyan6-Aug-08 14:24 
Generalbut... [modified] Pin
signuperror12-Jun-08 3:20
signuperror12-Jun-08 3:20 
GeneralRe: but... Pin
Mohammad Dayyan12-Jun-08 10:10
Mohammad Dayyan12-Jun-08 10:10 
GeneralRe: but... [modified] Pin
Mohammad Dayyan12-Jun-08 13:25
Mohammad Dayyan12-Jun-08 13:25 
I fixed it, you can try it. Big Grin | :-D
Thanks for your notice.

Sorry for my English. I'm a freshman .

modified on Saturday, June 14, 2008 3:42 AM

GeneralThanks Dayyan Pin
Hari Om Prakash Sharma6-Jun-08 0:30
Hari Om Prakash Sharma6-Jun-08 0:30 
GeneralRe: Thanks Dayyan Pin
Mohammad Dayyan6-Jun-08 1:22
Mohammad Dayyan6-Jun-08 1:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.