mattura
Member
- Messages
- 570
- Reaction score
- 2
- Points
- 18
I haven't seen a tutorial for this yet, so why not make one myself!
First of all, you will need at least the intermediate version of x10's php, so upgrade your account if you haven't already.
It also helps to have a reasonable knowledge of php (or you won't be able to customise this code!)
What is a CAPTCHA?
A CAPTCHA is a Completely Automated Public Turing test to tell Computers and Humans Apart. It gives you something that only a human can read, thereby helping to prevent spam. See here for more details: http://en.wikipedia.org/wiki/Captcha
How do I make one?
Simple! I'll take you through the steps. In the example I'll be creating a png, but it is possible to generate jpg, bmp etc as well.
Step 1 - Create an empty image
For other background colours, change the '0x99ccff' to the hex value for your favourite colour.
Step 2 - Generate random characters
You may want to skip this step if you know how to get your random characters. There are many ways to do so, but one simple method follows:
Step 3 - Make some random lines etc to confuse Optical Character Recognition
Here we will be using the imageline function. Go look it up if you want to understand it.
First, we will make an array of potential colour to choose from (we'll use this later for the letters as well). Choose them from here, but don't make any similar to the background colour.
Then, using a loop to draw about 10 lines (you don't want to overcrowd things), pick random colour values from your array, and also random co-ordinates for each line. I complicated matters by using mostly horizontal-ish and vertical-ish lines, which are most likely to confuse an OCR. Don't worry too much if you don't understand, just copy and paste.
Step 4 - Write your letters on the image
This makes use of the imagestring function. Again, go look it up if you want to understand it.
Step 5 - Outputting your image
Ok, finally you are ready to send your image and see what you have produced.
That's it! Test your code now and enjoy the result!
But wait - it's really quite small! This is because php's built-in font only has five sizes (1-5), which is what the '5' is in the imagestring line. It doesn't get any bigger!
What can we do about it?
Well, we can use a true type font.
First, you need to find a nice font and save it in the same directory as your php file. If you use windows, you might find them in c:/windows/fonts. Make sure it is *.ttf
Now instead of imagestring, use imagettftext.
I used the following (with the Arial Black font ariblk.ttf saved in my web directory):
You will have to change your $x and $y ($imgheight/2) values to reflect the font size
Sample output, using above code:
Sample output, using close together letters and angles between -10 and 20 (not too negative or 7 looks like 1):
If additional distortion is required, you can use imagefilter to apply filters to your image after the letters have been written. The output below is generated by using the following code:
Here's one with a different font (TempusITC.ttf). A little harder to read, but a lot harder to detect:
Bear in mind
The point is to make the image unreadable to a computer, not almost illegible for humans! Many people have great difficulty reading text which is a similar colour to the background, so try to make sure your colour array only contains light colours if your background is dark, or vice versa.
If you eliminate the gap between letters (make them touch each other), clever OCR software has great difficulty in separating the individual letters, this is a huge problem for computers, yet is still pretty readable for humans. Do this if you are worried clever software will try to unleash spam on you. It's unlikely though!
You should offer an alternative for accessibility purposes. Many sites offer an audible CAPTCHA.
Have fun kiddies!
First of all, you will need at least the intermediate version of x10's php, so upgrade your account if you haven't already.
It also helps to have a reasonable knowledge of php (or you won't be able to customise this code!)
What is a CAPTCHA?
A CAPTCHA is a Completely Automated Public Turing test to tell Computers and Humans Apart. It gives you something that only a human can read, thereby helping to prevent spam. See here for more details: http://en.wikipedia.org/wiki/Captcha
How do I make one?
Simple! I'll take you through the steps. In the example I'll be creating a png, but it is possible to generate jpg, bmp etc as well.
Step 1 - Create an empty image
PHP:
$imgheight=60;
$imgwidth=400; //whatever dimensions you need
$img=imagecreatetruecolor($imgwidth,$imgheight);
imagefill($img, 0, 0, 0x99ccff); //fill with light blue
Step 2 - Generate random characters
You may want to skip this step if you know how to get your random characters. There are many ways to do so, but one simple method follows:
PHP:
$str=substr(md5(uniqid(rand(), true)),0,6); //create random token of length 6
Step 3 - Make some random lines etc to confuse Optical Character Recognition
Here we will be using the imageline function. Go look it up if you want to understand it.
First, we will make an array of potential colour to choose from (we'll use this later for the letters as well). Choose them from here, but don't make any similar to the background colour.
PHP:
$colours=array(0x000055,0xff0000,0x009900,0xffcc99,0xff00ff,0x6b8e00);
$cl=count($colours); //makes processing faster
PHP:
for($i=0;$i<10;$i++) {
$col=$colours[rand(0,$cl)]; //using your array of colour values
$typ=rand(0,1); //draw either h/v line to confuse OCR
if ($typ==1) { //horizontal line:
$x1=rand(0,$imgwidth/2);$x2=rand($imgwidth/2,$imgwidth);
$y1=rand(0,$imgheight);$y2=rand($y1-$imgheight/5,$y1+$imgheight/5);
} else { //vertical line:
$x1=rand(0,$imgwidth);$x2=rand($x2-$imgwidth/5,$x2+$imgwidth/5);
$y1=rand(0,$imgheight/2);$y2=rand($imgheight/2,$imgheight);
}
imageline($img,$x1,$y1,$x2,$y2,$col); //draw the actual line
}
Step 4 - Write your letters on the image
This makes use of the imagestring function. Again, go look it up if you want to understand it.
PHP:
$let=str_split($str); //convert your string to an array for convenience
$strl=count($let); //count length for later
foreach($let as $key=>$char) {
$x=$imgwidth/2-$strl*8+$key*16;//*$siz*3+10+rand(1,5);
$colour=$colours[rand(0,$cl)];
imagestring($img,5,$x,$imgheight/2-6,$char,$colour);
}
Step 5 - Outputting your image
Ok, finally you are ready to send your image and see what you have produced.
PHP:
header("Content-type: image/png"); //send the appropriate header
return imagepng($img);
But wait - it's really quite small! This is because php's built-in font only has five sizes (1-5), which is what the '5' is in the imagestring line. It doesn't get any bigger!
What can we do about it?
Well, we can use a true type font.
First, you need to find a nice font and save it in the same directory as your php file. If you use windows, you might find them in c:/windows/fonts. Make sure it is *.ttf
Now instead of imagestring, use imagettftext.
I used the following (with the Arial Black font ariblk.ttf saved in my web directory):
PHP:
$siz=16; //font size, in pt
$ang=0; //angle of rotation - randomize this for even more fun!
imagettftext($img, $siz, $ang, $x, $imgheight/2, $colour, "ariblk.ttf", $char);
Sample output, using above code:
Sample output, using close together letters and angles between -10 and 20 (not too negative or 7 looks like 1):
If additional distortion is required, you can use imagefilter to apply filters to your image after the letters have been written. The output below is generated by using the following code:
PHP:
imagefilter($img,IMG_FILTER_MEAN_REMOVAL);
Here's one with a different font (TempusITC.ttf). A little harder to read, but a lot harder to detect:
Bear in mind
The point is to make the image unreadable to a computer, not almost illegible for humans! Many people have great difficulty reading text which is a similar colour to the background, so try to make sure your colour array only contains light colours if your background is dark, or vice versa.
If you eliminate the gap between letters (make them touch each other), clever OCR software has great difficulty in separating the individual letters, this is a huge problem for computers, yet is still pretty readable for humans. Do this if you are worried clever software will try to unleash spam on you. It's unlikely though!
You should offer an alternative for accessibility purposes. Many sites offer an audible CAPTCHA.
Have fun kiddies!
Last edited: