How to create a Captcha with PHP GD library.

The “Captcha” idea is brilliant. While they are not totally foolproof (certain Universities have successfully been able to create software that are able to hack captchas), they provide a decent bit of protection from spam activity. The recaptha tool that many of us have seen on various sites on the web is a particular favourite of mine because apart from the added protection it also allows the crowd-sourcing of data via this small action. Currently I’ve seen two variations of this crowd sourcing. One to digitize books, so you’ll be shown a word that the Google OCR engine was probably not able to recognize and then you help them know what the word is, and the other one I’ve seen is the house numbers of Google Maps Streetview, which would probably give them more the ability to more accurately pinpoint addresses in their Maps. Below I’ve included two files that I’ve used to create a very basic captha module using PHP’s GD library. I’m just posting it for now and will include explanations later on. The first file is the captcha image creator (captha_inage.php):

<?php
	session_start();
	//set up header for PNG image file
	header( "Content-type: image/png" );

	//load a font
	$font = "fonts/abite.ttf";
	$fontSize = 32;

	//number of characters in the CAPTCHA
	$stringLength = 6;
	$string = "";

	while( strlen( $string ) < $stringLength )
	{
		//set up string to render
		$string .= chr( rand( 97, 122 ) );
	}

	$_SESSION[ "CAPTCHA" ] = $string;

	$dimensions = imagettfbbox  ( $fontSize, 0, $font , $string );

	$height = $dimensions[3] - $dimensions[5];
	$width = $dimensions[2] - $dimensions[0];

	//Create image in memory to draw font onto
	$image = imagecreatetruecolor( $width, $height );

	//Set up colour of font
	$textColour = imagecolorallocate( $image, 0, 0, 0 );
	$backgroundColour = imagecolorallocate( $image, 255, 255, 255 );

	imagefilledrectangle( $image, 0, 0, $width, $height, $backgroundColour );

	//Generate the image
	imagettftext( $image, $fontSize, 0, 0, $height - 12, $textColour, $font, $string );

	//Output image to browser
	imagepng( $image );

	//Destroy image in memory
	imagedestroy( $image );
?>

The second file is the captcha submission and verification file (check_captcha.php)

<?php
	session_start();

	if( isset( $_POST["captcha_guess"] ) )
	{
		if( strcmp( $_POST["captcha_guess"], $_SESSION[ "CAPTCHA" ] ) == 0 )
		{
			$message = "You are human.";
			$_SESSION[ "human" ] = TRUE;
		}
		else
		{
			$message = "You might not be human.";
			$_SESSION[ "human" ] = FALSE;
		}
	}
?>
<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>Captcha Guess</title>
		<script type="text/javascript">
			function newImage()
			{
				var image = document.getElementById("captcha");
				image.src="captcha_image.php?" + Math.random();
			}
		</script>
	</head>
	<body>
		<h3><?php echo $message; ?></h3>
		<img id="captcha" src="captcha_image.php" />
		<form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="POST">
			<input type="text" name="captcha_guess" size="6" maxlength="6" />
			<input type="submit" value="Guess" />
			<a href="javascript:newImage()">Generate new image.</a>
		</form>
	</body>
</html>

So the use of SESSION variables is the key here. I’ll later on explain each and every line of code to say what they actually do. For now just remember that in the first file you need to give the exact location of the font file that you want to use.