Posted by T800 on December 13, 2010
An example of using the Python Imaging Library or PIL to produce Captcha style pictures from a given text.
It is a contrived acronym for "Completely Automated Public Turing test to tell Computers and Humans Apart".
This snippet of code has been left in its simplistic state as so you can follow the PIL side of the process. For reference you may like to check out the PIL site to follow this article. This code could easily rewritten as class to Incorporated into other programs were anti-spam or human verification is needed.

There is a download link at the bottom of the page if you with play with this example.
- #! /usr/bin/env python
- #
- # Human.py is a Captcha type generator for Linux / Win32 systems with PIL
- # Version 1.0.1 - 30 March 2010 - T800
-
- import sys
- import Image
- import ImageFile
- import random
- import ImageFilter
- import ImageChops
- import ImageFont
- import ImageDraw
-
- # User definable variables
- #
- random_fonts = True # True or False
- random_rotate = True # True or False
- random_fonts_colour = True # True or False
- sizer = 48 # Set font size
- text = 'Google' # Test test to created in a CAPTCHA style
-
-
- def chr_bitmap( txts, sze, typn, ang):
- textlen = len(text)
- if random_fonts == True: # Selects a randon font to use
- typn = random.randint(0, len(fonts)-1)
- else:
- typn = 0
- if random_rotate == True: # Choose a random slant on chr
- ang = random.choice([-25, 0, 25, 45, 0])
- else:
- ang = 0
-
- # Please note that the colours will be inverted as the merge is image.subtract
- #
- if random_fonts_colour == True:
- fcol = random.choice( ['#ff0000', '#00ff00', '#0000ff', '#00ffff', '#ff00ff', '#ffff00', '#7f7f7f'])
- else:
- fcol = '#ffffff'
- font = ImageFont.truetype( fonts[typn], sze )
-
- # Returns the width and height of the given text, as a 2-tuple.
- #
- sizer = font.getsize(txts)
-
- im = Image.new('RGBA', sizer, (0, 0, 0, 0)) # Create a blank image with the given size
- draw = ImageDraw.Draw(im)
- draw.text((0, 0), txts, font=font, fill = fcol ) #Draw text
- im = im.rotate(ang, expand=True)
- return im, im.size
-
- def make_phrase():
- maxy = 0 # Default x, y to assemble chr on canvas
- maxx = 0
- textlen = len(text)
- img = []
- for txt in range(textlen):
- typen = 0
- angle = 0
- im, (dimx, dimy) = chr_bitmap( text[txt], sizer, typen, angle)
- img.append(im)
- if dimy > maxy:
- maxy=dimy
- maxx = maxx + dimx
-
- spacer = 0
- imgf = Image.open("zat.jpg").convert("RGBA") # Background image
- sz2 = ( maxx, maxy+2*spacer)
- imgc = imgf.resize( sz2 )
- posx = 0
- posy = 0
-
- for tile in range(len(text)):
- (tx, ty) = img[tile].size # get dimentions of chr
- rect = (0, 0, tx, ty) # calc rectangle to cut
- clip = img[tile].crop(rect) # Cut chr
- sz = ( posx, posy, posx + tx, posy + ty) # calc canvas paste
- imc = imgc.crop(sz) # cut chr sized lump out of canvas
- imd = ImageChops.subtract( imc, clip ) # Merge clip and chr by subtraction
- imgc.paste(imd, sz) # Paste it
- posx = posx + tx +1
- return imgc
-
- if __name__=='__main__':
-
- br, bg, bb = 255, 255, 255 # Canvas colour
-
- fonts = ['fonts/1942.ttf', 'fonts/01 DigiGraphics.ttf', 'fonts/AARDC___.TTF',
- 'fonts/abaddon.TTF', 'fonts/Acens.ttf', 'fonts/advent_bold.ttf', 'fonts/BOGSTAND.TTF' ]
-
- imgc = make_phrase() # Main Call
-
- imgc.save("human.jpg", "JPEG")
| human.zip | 168.87 kB | 13-12-2010 21:57 | ![]() |
| © 2012 Man-Machine. | Powered by concrete5 | Sign In to Edit this Site |