User:Antonio/Captcha

This is some code to generate a captcha-like image in PHP. It draws some text, then rotates and distorts it using an arbitrary number of random sine waves. This is just the image-generating part; maybe someone else can do the rest of the captcha interface?

Demo
You can see a demo here: http://q0.org/captcha?q=sahana

Try reloading to see it change. You can change the text it draws by editing the parameter in the url.

Update: if you leave out the 'q' paramater, the demo will pick a random word from the english dictionary (/usr/share/dict/words on my machine). see here

Code
<?php /** * @author Antonio Alcorn * @date 4/2/2007 * @description Generate a captcha-like image */ //font size $fontSize = 30; //path to a TrueType font $font = 'OldSansBlack.ttf'; //parameters for the distortion define(max_amplitude, 20); define(min_period, 30); define(max_period, 50); define(num_waves, 3); define(max_angle, 20); define(padding, 20); //returns a random float in range (-1, 1) function randF { return (rand(0,2000)/1000)-1; } //randomly generate sine waves to mutate image $amplitude = $period = array; for($n = 0; $n < num_waves; $n++) { $amplitude[] = randF * max_amplitude; $period[] = abs(randF) * (max_period - min_period) + min_period; } //change the location of a pixel depending on the sine waves function mutate($x, $y) { global $amplitude, $period; $newX = $x; $newY = $y; foreach($amplitude as $k => $a) //waves distort on alternate axes if($k % 2) $newX += $a * sin($y / $period[$k]); else $newY += $a * sin($x / $period[$k]); return array($newX, $newY); } $code = $_GET['q']; $angle = abs(randF) * max_angle; $fontSize *= 2; $box = imagettfbbox($fontSize, $angle, $font, $code); $width = abs($box[4] - $box[0]) + $fontSize; $height = abs($box[5] - $box[1]) + $fontSize; $i = imagecreatetruecolor($width + padding * 2, $height + padding * 2); $white = imagecolorallocate($i, 255, 255, 255); //pick a random color $c = imagecolorallocate($i, rand(0,128), rand(0,128), rand(0,128)); imagefilledrectangle($i, 0, 0, $width, $height, $white); imagettftext($i, $fontSize, $angle, abs($box[0]), $height + abs($box[1]) - $fontSize, $c, $font, $code); $captcha = imagecreatetruecolor($width/2 + padding * 2, $height/2 + padding * 2); imagefilledrectangle($captcha, 0, 0, $width*2, $height*2, $white); for($y = 0; $y < $height; $y++) for($x = 1; $x < $width; $x++) { $p = imagecolorat($i, $x, $y); list($newX, $newY) = mutate($x, $y); imagesetpixel($captcha, $newX/2 + padding, $newY/2 + padding, $p); } header('Content-Type: image/png'); imagepng($captcha); ?>