Developing a Captcha Application with an Image Generator Class with PHP 5

PHP is a powerful server-side scripting language that is recognized for its flexibility for developing a huge variety of web applications with relative ease. Speaking more specifically, its robust set of graphic processing functions, which has been packaged into the popular GD extension, makes it perfectly suitable for building image generating classes with minor hassles.

Introduction

This series, which is made up of three instructive tutorials, walks you through the creation of a highly-extensible image generator class, which can be easily adapted to work with other classes that require the interaction of image processing modules, such as dynamic banner mechanisms and noisy image applications.

You’ll probably recall that over the course of the previous article, I demonstrated how to build a PHP 5-based image generator class that was provided initially with the capacity for displaying different dynamic image streams on the browser.

Of course, the feature to highlight here concerning the development of the aforementioned class was its ability to embed several input strings into the image stream in question. This feature makes this class ideal to use in conjunction with other web applications that require some kind of graphic processing, including the examples that I referenced a few lines above, that is dynamic banner systems and noisy graphics.

In this last article of the series I’m going to show you how to couple this class with a simple randomizer mechanism to implement a basic yet effective application that will be capable of outputting on the browser different random strings, which  will be previously embedded into a predefined image stream.

As you might have guessed at this point, I’m talking about building the popular "captchas" (or noisy images), which can be really useful when you want to implement a simple mechanism for preventing automated submissions by robot scripts of the forms included in your web sites.

The experience can be instructive and — why not? — also fun. So now that I have introduced the topic that I plan to cover in this final article of the series, let’s move forward and learn together how to build a pluggable noisy image system with PHP 5. Let’s get started!

{mospagebreak title=The complete definition of the image generator class}

Before building the noisy image application that I mentioned in the beginning of this article, I will list the complete signature corresponding to the image generator class that I created in the preceding article of the series. Doing so should give you a much better idea of how this class can be easily "plugged" to a string randomizer system to create a noisy image generation mechanism.

All right, having said that, here’s the full definition of the aforementioned image generator class, as it was originally built in the previous article of the series. Have a look at it, please:

// define ‘ImageGenerator’ class

class ImageGenerator{

  private $width;

  private $height;

  private $bgColor;

  private $textColor;

  private $inputString;

  private $img;

// initialize input arguments

public function __construct($inputString=’Default Input
String’,$width=400,$height=300,$bgColor=’0,0,0′,
$textColor=’255,255,255′){

  if(strlen($inputString>255)){

   throw new Exception(‘Invalid length for input string.’);

}

  if(!is_int($width)&&$width>800){

   throw new Exception(‘Invalid width for image stream.’);

}

  if(!is_int($width)&&$height>600){

   throw new Exception(‘Invalid height for image stream.’);

}

if(!preg_match("/^d{1,3},d{1,3},d{1,3}$/",$bgColor)||!preg_match
("/^d{1,3},d{1,3},d{1,3}$/",$textColor)){

throw new Exception(‘Invalid format for background or text
color.’);

}

  $this->inputString=$inputString;

  $this->width=$width;

  $this->height=$height;

  $this->bgColor=explode(‘,’,$bgColor);

  $this->textColor=explode(‘,’,$textColor);

  $this->buildImageStream();

}

// create image stream

  private function buildImageStream(){

   if(!$this->img=imagecreate($this->width,$this->height)){

    throw new Exception(‘Error creating image stream’);

}

// allocate background color on image stream

imagecolorallocate($this->img,$this->bgColor[0],$this->bgColor
[1],$this->bgColor[2]);

// allocate text color on image stream

$textColor=imagecolorallocate($this->img,$this->textColor
[0],$this->textColor[1],$this->textColor[2]);

  $font=imageloadfont($this->font);

if(!imagestring($this->img,$this->font,$this->width/2-strlen
($this->inputString)*5,$this->height/2-5,$this-
>inputString,$textColor)){

  throw new Exception(‘Error creating image text’);

}

}

// display image stream on the browser

  public function displayImage(){

   header("Content-type: image/png");

// display image

  imagepng($this->img);

// free up memory

  imagedestroy($this->img);

 }

}

As you can see, the logic that drives the above image generator class is very simple to follow. The class takes up a few input parameters, including the foreground and background colors of the image stream being generated, and the text string that will be embedded into the stream.

These basic tasks are carried out by the two primary methods of the class, called "buildImageStream()" and "displayImage()" respectively.

However, if you study in detail the signature of the previous class, you’ll probably see that it seems pretty inflexible, since it actually builds the corresponding image stream whenever the class is instantiated. This prohibits the creation of other, different streams during the execution of given script.

Therefore, in the section to come I’ll introduce some important modifications to the original structure of the image generator class to solve this issue. I’ll also build a simple text randomizer, which will be extremely useful for creating an efficient noisy image application.

To see how all of these interesting tasks will be carried out, please jump forward and read the next few lines. They’re just one click away.

{mospagebreak title=Defining the core structure of a noisy image application}

As I expressed in the previous section, the next step involves improving the structure of the original image generator class, so it can be called repeatedly, without having to create different instances of it.

Here’s the modified signature of the image generator class that you learned in the previous article:

// define ‘ImageGenerator’ class (final version)

class ImageGenerator{

  private $width=400;

  private $height=300;

  private $bgColor=’0,0,0′;

  private $textColor=’255,255,255′;

  private $inputString=’Default Input String’;

  private $bgImage=NULL;

  private $img;

// initialize input arguments

public function __construct($inputString=’Default Input String’){

  if(strlen($inputString>255)){

   throw new Exception(‘Invalid length for input string.’);

}

  $this->inputString=$inputString;

}

  public function setImageWidth($width=400){

   if(!is_int($width)&&$width>800){

    throw new Exception(‘Invalid width for image stream.’);

}

  $this->width=$width;

}

  public function setImageHeight($height=300){

   if(!is_int($width)&&$height>600){

    throw new Exception(‘Invalid height for image stream.’);

}

}

  public function setImageBgColor($bgColor=’0,0,0′){

   if(!preg_match("/^d{1,3},d{1,3},d{1,3}$/",$bgColor)){

    throw new Exception(‘Invalid format for background color.’);

}

  $this->bgColor=$bgColor;

}

  public function setImageTextColor($textColor=’255,255,255′){

   if(!preg_match("/^d{1,3},d{1,3},d{1,3}$/",$textColor)){

    throw new Exception(‘Invalid format for text color.’);

}

  $this->textColor=$textColor;

}

  public function setBgImage($bgImage=’default.gif’){

   if(!file_exists($bgImage)){

    throw new Exception(‘Invalid background image.’);

}

  $this->bgImage=$bgImage;

}

  public function setImageFont($font){

   if(!file_exists($font)){

    throw new Exception(‘Invalid image font.’);

}

  $this->font=$font;

}

// create image stream

  public function displayImageStream(){

$this->img=$this->bgImage!=NULL?imagecreatefromgif($this-
>bgImage):imagecreate($this->width,$this->height);

  $bgColor=explode(‘,’,$this->bgColor);

  $textColor=explode(‘,’,$this->textColor);

// allocate background color on image stream

imagecolorallocate($this->img,$bgColor[0],$bgColor[1],$bgColor
[2]);

// allocate text color on image stream

$textColor=imagecolorallocate($this->img,$textColor[0],$textColor
[1],$textColor[2]);

// load font

if(!imagestring($this->img,5,$this->width/2-strlen($this-
>inputString)*5,$this->height/2-5,$this->inputString,$textColor)){

  throw new Exception(‘Error creating image text’);

}

  header("Content-type: image/gif");

// display image

  imagegif($this->img);

// free up memory

  imagedestroy($this->img);

 }

}

As illustrated above, the definition of the image generator class now looks slightly more robust and efficient. It incorporates some important improvements, such as the declaration and implementation of some handy setting methods for assigning different values for its respective properties. In addition to these modifications, the class also allows you to specify a background image for the dynamic graphic stream to be created via its "setBgImage()" method, which is handy for including pre-built graphics into the image stream.

So far, so good, right? At this stage hopefully you realized how simple it was to improve the definition of the previous image generator class to make it slightly more flexible and efficient. So what’s the next step?

Well, since my intention here is to demonstrate how to use the prior image generator class to implement a simple noisy image system, below I included the complete signature of a brand new class, called "RandomGenerator," for creating random strings.

The definition of this class is as follows:

class RandomGenerator{

  private $length;

  private $chars="ABCDEFGHIJKLMNPQRSTUVWXYZ123456789";

  public function __construct($length=4){

   if(!is_int($length)||$length<1){

    throw new Exception(‘Invalid length for random string.’);

}

  $this->length=$length;

}

  public function getRandomValue(){

   $rndstr=”;

    $maxvalue=strlen($this->chars)-1;

   for($i=0;$i<$this->length;$i++){

    $rndstr.=substr($this->chars,rand(0,$maxvalue),1);

}

  return $rndstr;

 }

}

As you can see, the logic implemented by the above "RandomGenerator" class is indeed very simple. Basically, all that this class does is return to client code a randomized string, which has a predefined length (four characters is its default size).

Discussing how this class works doesn’t make much sense here, so now it’s time to demonstrate by the mean of a hands-n example how to couple the two classes defined earlier to implement an efficient noisy image generation system.

Want to learn more on how this will be achieved? Click on the link that appears below and keep reading.

{mospagebreak title=Developing a basic noisy image generation system}

As I stated in the section that you just read, the best way to demonstrate how the two previously defined classes can be put to work together to implement a simple noisy image system is by developing an example where you can see how they function in tandem.

So first I will list the complete source code corresponding to the two classes. Here it is:

// define ‘ImageGenerator’ class

class ImageGenerator{

  private $width=400;

  private $height=300;

  private $bgColor=’0,0,0′;

  private $textColor=’255,255,255′;

  private $inputString=’Default Input String’;

  private $bgImage=NULL;

  private $img;

// initialize input arguments

public function __construct($inputString=’Default Input String’){

  if(strlen($inputString>255)){

   throw new Exception(‘Invalid length for input string.’);

}

  $this->inputString=$inputString;

}

  public function setImageWidth($width=400){

   if(!is_int($width)&&$width>800){

    throw new Exception(‘Invalid width for image stream.’);

}

  $this->width=$width;

}

  public function setImageHeight($height=300){

   if(!is_int($width)&&$height>600){

    throw new Exception(‘Invalid height for image stream.’);

 }

}

  public function setImageBgColor($bgColor=’0,0,0′){

   if(!preg_match("/^d{1,3},d{1,3},d{1,3}$/",$bgColor)){

    throw new Exception(‘Invalid format for background color.’);

}

  $this->bgColor=$bgColor;

}

  public function setImageTextColor($textColor=’255,255,255′){

   if(!preg_match("/^d{1,3},d{1,3},d{1,3}$/",$textColor)){

    throw new Exception(‘Invalid format for text color.’);

}

  $this->textColor=$textColor;

}

  public function setBgImage($bgImage=’default.gif’){

   if(!file_exists($bgImage)){

    throw new Exception(‘Invalid background image.’);

}

  $this->bgImage=$bgImage;

}

  public function setImageFont($font){

   if(!file_exists($font)){

    throw new Exception(‘Invalid image font.’);

}

  $this->font=$font;

}

// create image stream

  public function displayImageStream(){

$this->img=$this->bgImage!=NULL?imagecreatefromgif($this-
>bgImage):imagecreate($this->width,$this->height);

  $bgColor=explode(‘,’,$this->bgColor);

  $textColor=explode(‘,’,$this->textColor);

// allocate background color on image stream

imagecolorallocate($this->img,$bgColor[0],$bgColor[1],$bgColor
[2]);

// allocate text color on image stream

$textColor=imagecolorallocate($this->img,$textColor[0],$textColor
[1],$textColor[2]);

// load font

if(!imagestring($this->img,5,$this->width/2-strlen($this-
>inputString)*5,$this->height/2-5,$this->inputString,$textColor)){

  throw new Exception(‘Error creating image text’);

}

  header("Content-type: image/gif");

// display image

  imagegif($this->img);

// free up memory

  imagedestroy($this->img);

 }

}

class RandomGenerator{

  private $length;

  private $chars="ABCDEFGHIJKLMNPQRSTUVWXYZ123456789";

  public function __construct($length=4){

   if(!is_int($length)||$length<1){

    throw new Exception(‘Invalid length for random string.’);

}

  $this->length=$length;

}

  public function getRandomValue(){

   $rndstr=”;

    $maxvalue=strlen($this->chars)-1;

   for($i=0;$i<$this->length;$i++){

    $rndstr.=substr($this->chars,rand(0,$maxvalue),1);

}

  return $rndstr;

 }

}

Now, take a look at the following code sample, which shows how to embed dynamically several four-digit random strings into a predefined image stream:

  try{

// create new instance of ‘RandomGenerator’ class

  $rnd=new RandomGenerator();

// create new instance of ‘ImageGenerator’ class

  $imgGen=new ImageGenerator($rnd->getRandomValue());

// display image stream on the browser

  $imgGen->displayImageStream();

}

  catch(Exception $e){

   echo $e->getMessage();

  exit();

}

 

There you have it! By using the pair of PHP 5 classes that I built previously, it was feasible to develop a fully-functional noisy image application, which can be easily incorporated into any existing web site to prevent (at least partially) automated submissions of its web forms.

Final thoughts

Unfortunately, this series has come to and end. Hopefully the whole learning experience has been positive, since you learned how to utilize the functionality provided by some of the most important functions packaged with the GD extension to build an image generator class. As you have seen, such a class can be really handy for creating, among other useful things, a simple and efficient noisy image system.

See you in the next PHP development tutorial!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan