Monday, August 17, 2009

Captcha

Here's a custom image captcha I just made. What's cool about it is that it's transparent (PNG), so it 'blends' into the background. To suit different backgrounds, it has two settings - dark and light - which you set according to the background color of the page you want to put it on. Here's a picture that demonstrates this; you can see that the captcha is completely unreadable when put on the wrong background, but completely readable when it's right: Captcha Demo Here's the code: <?php $W = 160; // width $H = 60; // height $L = 6; // length of the key $BG = 'light'; // can be 'light' or 'dark', accorting to the background color of // the page it will be on $F = './DejaVuSans.ttf'; // path to true-type font file function makeKey($length) { // generate a random sequence of characters $a = 'abcdefghijklmnopqrstuvwxyz'; $s = ''; for ($i=0; $i < $length; $i++) { $s .= $a[mt_rand(0, strlen($a) - 1)]; } return $s; } $img = imagecreatetruecolor($W, $H); // make the image alpha-aware imagesavealpha($img, true); // make colors 'blend', not overwrite imagealphablending($img, true); // make the image transparent imagefill($img, 1, 1, imagecolorallocatealpha($img, 0, 0, 0, 127)); // generate two random colors and decide which one goes where $dark = Array (mt_rand(0, 126), mt_rand(0, 126), mt_rand(0, 126)); $light = Array (mt_rand(127, 255), mt_rand(127, 255), mt_rand(127, 255)); if ($BG == 'dark') { $bg_color = imagecolorallocatealpha($img, $dark[0], $dark[1], $dark[2], mt_rand(64, 96)); $fg_color = imagecolorallocatealpha($img, $light[0], $light[1], $light[2], mt_rand(32, 64)); } else { $bg_color = imagecolorallocatealpha($img, $light[0], $light[1], $light[2], mt_rand(64, 96)); $fg_color = imagecolorallocatealpha($img, $dark[0], $dark[1], $dark[2], mt_rand(32, 64)); } // write background static $angle = mt_rand(20, 35); for ($i=0; $i < 15; $i++) { imagettftext($img, 12, $angle, 0, $i*15, $bg_color, $F, makeKey(30)); } $key = makeKey($L); // you should store this in the user session to check it later // write the actual key, in two parts imagettftext($img, mt_rand(16, 22), mt_rand(10, 30), mt_rand(5, 30), mt_rand($H-16, $H-22), $fg_color, $F, substr($key, 0, 3)); imagettftext($img, mt_rand(16, 22), mt_rand(-30, -10), mt_rand($W/2+5, $W/2+30), mt_rand(16, 22), $fg_color, $F, substr($key, 3, 3)); // output the image header("Content-Type: image/png"); imagepng($img); ?> On my machine (Pentium DualCore @ 2.80Ghz) it generates images in 70-75ms. I think that's pretty fair. Also, it works with non-bundled GD versions, too, so you don't have to worry about that. Enjoy.

2 comments:

  1. This is kind of a waste to have here, nothing else explained. I spent 10 minutes on it and went with a different route. Easy code those...

    You should put directions on how to use this, I created a captcha.php and added it to my page via img src pointing to the php file but there is no way to transfer the session variables from the page that I can see but I am not a pro on php.

    Just a word of advice, have a good one!

    ReplyDelete
  2. You're supposed to modify the code. Right after the $key = makeKey($L) call, you can store $key wherever you want -- like a session, and use it afterwards for checking.

    ReplyDelete