Click here to Skip to main content
11,714,719 members (78,018 online)
Click here to Skip to main content

CAPTCHA Image in PHP

, 23 Feb 2009 GPL3 54.2K 2.6K 33
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

You may also be interested in...

Comments and Discussions

 
Questionhelp me Pin
Member 1034396417-Oct-13 23:07
memberMember 1034396417-Oct-13 23:07 
QuestionNeed some Help Pin
Member 961824821-Nov-12 1:29
memberMember 961824821-Nov-12 1:29 
Questiongood Pin
ajjaj16-May-12 20:01
memberajjaj16-May-12 20:01 
QuestionWindows <--> Linux and further improving security Pin
TerraD2-Apr-12 1:05
memberTerraD2-Apr-12 1:05 
AnswerRe: Windows Linux and further improving security Pin
Mohammad Dayyan2-Apr-12 1:26
memberMohammad Dayyan2-Apr-12 1:26 
QuestionHow does the code against hacking attempts work? Pin
TerraD1-Apr-12 22:15
memberTerraD1-Apr-12 22:15 
AnswerRe: How does the code against hacking attempts work? Pin
Mohammad Dayyan1-Apr-12 22:22
memberMohammad Dayyan1-Apr-12 22:22 
QuestionIs not working Pin
BrandonSkyPimenta1-Apr-12 8:23
memberBrandonSkyPimenta1-Apr-12 8:23 
AnswerRe: Is not working Pin
Mohammad Dayyan1-Apr-12 9:52
memberMohammad Dayyan1-Apr-12 9:52 
GeneralNice. Pin
CalvinHartwell20-Oct-09 13:13
memberCalvinHartwell20-Oct-09 13:13 
GeneralNo reCaptcha for me Pin
TerraD1-Apr-12 21:32
memberTerraD1-Apr-12 21:32 
GeneralGreat Article/Protected IP Pin
Curtis Schlak.26-Feb-09 10:49
memberCurtis Schlak.26-Feb-09 10:49 
GeneralRe: Great Article/Protected IP Pin
Mohammad Dayyan26-Feb-09 23:09
memberMohammad Dayyan26-Feb-09 23:09 
Generalbut... [modified] Pin
signuperror12-Jun-08 3:20
membersignuperror12-Jun-08 3:20 
GeneralRe: but... Pin
M-Dayyan12-Jun-08 10:10
memberM-Dayyan12-Jun-08 10:10 
GeneralRe: but... [modified] Pin
M-Dayyan12-Jun-08 13:25
memberM-Dayyan12-Jun-08 13:25 
GeneralThanks Dayyan Pin
Hari Om Prakash Sharma6-Jun-08 0:30
memberHari Om Prakash Sharma6-Jun-08 0:30 
GeneralRe: Thanks Dayyan Pin
M-Dayyan6-Jun-08 1:22
memberM-Dayyan6-Jun-08 1: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
Web01 | 2.8.150819.1 | Last Updated 23 Feb 2009
Article Copyright 2008 by Mohammad Dayyan
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid