5

i have a cronjob that generate captcha for my online forms (registration, contact and newsletter).

i generate over 5000 images per day so when i display the form, i randomly choose one and then simply display the image and set the session.

my table is very simple:

captcha (id mediumint(5) unsigned PK, phrase varchar(10));

and then i run the cronjob that generate images and insert into the DB. this process takes a while to run and I would like to know if there's a better way to do this, to maximize the performance and generation since i have other cronjob that runs all day and i want to make sure i can take this away from cronjob so my cronjob jobs can breath a little.

Owan
  • 205
  • 1
  • 7
  • 1
    If you have in total more than 5000 contact or newsletter, you are pretty popular :) This seems rather inefficient and waste of resources. Generate image only when needed. – Bakudan Feb 11 '12 at 02:21
  • well i generate 5000 to make sure when i randomize i dont get the same twice. – Owan Feb 11 '12 at 02:23
  • @Owan Bakudan is right, you should generate them on the fly using GD. I don't think you need a cronjob to do this – Book Of Zeus Feb 11 '12 at 02:31
  • @BookOfZeus i read i need to use imagecreate but it's kinda complex have something i can play with? – Owan Feb 11 '12 at 03:22
  • @Owan first you will have to check if GD is enable, you can check using php info and search for GD. – Book Of Zeus Feb 11 '12 at 03:23
  • Hi @Owan, What technology are you using?. PHP or ROR or ?. The following link is help to create the Captcha using ROR technology. http://stackoverflow.com/questions/1859139/recommendations-for-a-captcha-on-ruby-on-rails - Please point out that what technology are you using and some extra details if needed. So, It's help to give very accurate solution for you. – Mr. Black Feb 11 '12 at 03:45

1 Answers1

8

Create a file call Captcha.class.php and put this:

class Captcha {
    private $font = '/path/to/font/yourfont.ttf'; // get any font you like and dont forget to update this.

    private function generateCode($characters) {
        $possible = '23456789bcdfghjkmnpqrstvwxyz'; // why not 1 and i, because they look similar and its hard to read sometimes
        $code = '';
        $i = 0;
        while ($i < $characters) {
            $code .= substr($possible, mt_rand(0, strlen($possible)-1), 1);
            $i++;
        }
        return $code;
    }

    function getImage($width, $height, $characters) {
        $code = $this->generateCode($characters);
        $fontSize = $height * 0.75;
        $image = imagecreate($width, $height);
        if(!$image) {
            return FALSE;
        }
        $background_color = imagecolorallocate($image, 255, 255, 255);
        $text_color = imagecolorallocate($image, 66, 42, 32);
        $noiseColor = imagecolorallocate($image, 150, 150, 150);
        for( $i=0; $i<($width*$height)/3; $i++ ) {
            imagefilledellipse($image, mt_rand(0,$width), mt_rand(0,$height), 1, 1, $noiseColor);
        }
        for( $i=0; $i<($width*$height)/150; $i++ ) {
            imageline($image, mt_rand(0,$width), mt_rand(0,$height), mt_rand(0,$width), mt_rand(0,$height), $noiseColor);
        }
        $textbox = imagettfbbox($fontSize, 0, $this->font, $code);
        if(!$textbox) {
            return FALSE;
        }
        $x = ($width - $textbox[4])/2;
        $y = ($height - $textbox[5])/2;
        imagettftext($image, $fontSize, 0, $x, $y, $text_color, $this->font , $code) or die('Error in imagettftext function');
        header('Content-Type: image/jpeg');
        imagejpeg($image);
        imagedestroy($image);
        $_SESSION['captcha'] = $code;
    }
}

Then in your page you can do:

<img src="/captcha.php" />

Then in the /captcha.php you will put:

session_start();
require('Captcha.class.php');
$Captcha = new Captcha();
$Captcha->getImage(120,40,6);

You can change the params as you wish to show different captcha too.

This way you will generate on the fly. You can always save the image on the disk if you want as well.

Book Of Zeus
  • 49,509
  • 18
  • 174
  • 171