In making this website and in my 4th year honours project I implemented a captcha (which you can see if you try and make a comment). I thought this would be a bit of a nightmare to do, but with Steven’s help and the awesomeness of Python, it was quite easy. The code originally comes from here, but I have made a few edits such as keeping the image in memory.
You will need a .ttf font file to generate the image. You can specify the font size of the text, and the image generated will automatically adjust to fit in the word.
# python imports import random import Image import ImageFont import ImageDraw import ImageFilter from cStringIO import StringIO from os import path # local imports from lowmanio.utils.utils import ROOT_DIR """ This code is taken from and is copyright to: http://code.activestate.com/recipes/440588/ """ FONT_FILE = path.join(ROOT_DIR, 'lowmanio', 'utils', 'arialbd.ttf') def gen_captcha(text, fnt, fnt_sz, f, fmt='JPEG'): """Generate a captcha image""" # randomly select the foreground color fgcolor = random.randint(0,0xffff00) # make the background color the opposite of fgcolor bgcolor = fgcolor ^ 0xffffff # create a font object font = ImageFont.truetype(fnt,fnt_sz) # determine dimensions of the text dim = font.getsize(text) # create a new image slightly larger that the text im = Image.new('RGB', (dim+5,dim+5), bgcolor) d = ImageDraw.Draw(im) x, y = im.size r = random.randint # draw 100 random colored boxes on the background for num in range(100): d.rectangle((r(0,x),r(0,y),r(0,x),r(0,y)),fill=r(0,0xffffff)) # add the text to the image d.text((3,3), text, font=font, fill=fgcolor) im = im.filter(ImageFilter.EDGE_ENHANCE_MORE) # save the image to a file im.save(f, format=fmt) def gen_random_word(wordLen=6): """Generate a random word of length wordLen. Some characters have been removed to avoid ambiguity such as i,l,o,I,L,0, and 1""" allowedChars = "abcdefghjkmnpqrstuvwzyzABCDEFGHJKMNPQRSTUVWZYZ23456789" word = "" for i in range(0, wordLen): word = word + allowedChars[random.randint(0,0xffffff) % len(allowedChars)] return word def generateCaptcha(): """Generate a captcha image in memory using a randomly generated word and a font file on the system. Returns the word and the image""" word = gen_random_word() buf = StringIO() gen_captcha(word.strip(), FONT_FILE, 50, buf) s = buf.getvalue() buf.close() return word, s
When the page with the captcha is loaded, the captcha image URL controller method saves the word in the session, and returns the image to be displayed. This makes sure the images aren’t cached.