Click here to Skip to main content
Click here to Skip to main content

CAPTCHA Image in PHP

, 23 Feb 2009 GPL3
Rate this:
Please Sign up or sign in to vote.
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)

Share

About the Author

Mohammad Dayyan

Iran (Islamic Republic Of) Iran (Islamic Republic Of)
No Biography provided

Comments and Discussions

 
Questionhelp me PinmemberMember 1034396418-Oct-13 0:07 
QuestionNeed some Help PinmemberMember 961824821-Nov-12 2:29 
Questiongood Pinmemberajjaj16-May-12 21:01 
QuestionWindows <--> Linux and further improving security PinmemberTerraD2-Apr-12 2:05 
AnswerRe: Windows Linux and further improving security PinmemberMohammad Dayyan2-Apr-12 2:26 
QuestionHow does the code against hacking attempts work? [modified] PinmemberTerraD1-Apr-12 23:15 
AnswerRe: How does the code against hacking attempts work? PinmemberMohammad Dayyan1-Apr-12 23:22 
QuestionIs not working PinmemberBrandonSkyPimenta1-Apr-12 9:23 
AnswerRe: Is not working PinmemberMohammad Dayyan1-Apr-12 10:52 
GeneralNice. PinmemberCalvinHartwell20-Oct-09 14:13 
GeneralNo reCaptcha for me PinmemberTerraD1-Apr-12 22:32 
GeneralGreat Article/Protected IP PinmemberCurtis Schlak.26-Feb-09 11:49 
GeneralRe: Great Article/Protected IP PinmemberMohammad Dayyan27-Feb-09 0:09 
GeneralVery useful PinmemberPerspx6-Aug-08 14:46 
GeneralRe: Very useful PinmemberMohammad Dayyan6-Aug-08 15:24 
Generalbut... [modified] Pinmembersignuperror12-Jun-08 4:20 
GeneralRe: but... PinmemberM-Dayyan12-Jun-08 11:10 
GeneralRe: but... [modified] PinmemberM-Dayyan12-Jun-08 14: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 PinmemberHari Om Prakash Sharma6-Jun-08 1:30 
GeneralRe: Thanks Dayyan PinmemberM-Dayyan6-Jun-08 2:22 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 23 Feb 2009
Article Copyright 2008 by Mohammad Dayyan
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid