Python, PIL and Pretty Polaroids

(2009)

I suspect that by now everyone and their grandmother has written a script to convert photos so they look like Polaroids. Yesterday I spent a slow morning at work replacing all our slideshows (which used a super-ugly Flash control) with these:

There's plenty of other neat effects that could be done.. maybe add a bit of aging or apply some filters. But I think it looks pretty good. The following script uses Python, PIL (Python Imaging Library), and a pre-drawn "polaroid" frame.

import PIL, time, glob, random, os, sys
from PIL import Image, ImageOps, ImageEnhance, ImageDraw, ImageFont

# Generate Polaroid-looking images
def make_polaroid(infile, outfile, text=''):
    base = (300,320)    #size of polaroid background
    polaroid = Image.open('polaroid-0.png')
    polaroid = ImageOps.fit(polaroid, base, Image.ANTIALIAS, 0, (0.5,0.5))

   target = (272,248); # size of empty target area on polaroid background
    img = Image.open(infile)
    img = ImageOps.fit(img, target, Image.ANTIALIAS, 0, (0.5,0.5))

    #enhance the image a bit
    img = ImageOps.autocontrast(img, cutoff=2)
    img = ImageEnhance.Sharpness(img).enhance(2.0)

    #draw the text, if any
    font = ImageFont.truetype("arial.ttf", 16)
    text_size = ImageDraw.Draw(polaroid).textsize(text, font=font)
    fontxy = (base[0]/2 - text_size[0]/2, 278)
    ImageDraw.Draw(polaroid).text(fontxy, text, font=font, fill=(40,40,40))

    #copy the image onto the polaroid background
    imgcorner = (14,20) #paste image onto polaroid
    polaroid.paste(img, imgcorner)

    #copy the whole thing onto a larger background and rotate randomly
    angle = random.randint(-10,10)
    blank = Image.new(polaroid.mode, (400,400))
    blank.paste(polaroid, (blank.size[0]/2-polaroid.size[0]/2, blank.size[1]/2-polaroid.size[1]/2))
    blank = blank.rotate(angle, Image.BICUBIC)

    blank.save(outfile)

if __name__ == "__main__":
    # Takes 1 required argument -- the desired prefix for the output filename
    if len(sys.argv) < 2:
        print "Missing required positional argument 'prefix'"
        exit()

    # Text to appear on image, use "" if none 
    text = "Some Text, or leave blank"

    # Erase everything in Output folder
    for f in glob.glob('output/*'):
        os.remove(f)

    # Create Polaroids of each JPG in Input folder
    files = [f[6:] for f in glob.glob('input/*.jpg')]
    for f in files:
        make_polaroid('input/'+f,'output/'+sys.argv[1]+'-'+f[:-4]+'.jpg',text)

    # Write index.html so Output folder can be copied/renamed elsewhere
    files = [f[7:] for f in glob.glob('output/*')]
    outhtml = open('output/index.html','w')
    outhtml.write("<html><head></head><body style='background-color: #000;'><div align='center'><p>")

    for i in range(len(files)):
        outhtml.write("<img src='%s' />" % (files[i]))
        if (i+1) % 2 == 0:
            outhtml.write("</p>")
    outhtml.write("</div></body></html>")
    outhtml.close()

The script is a bit over-specialized to my purpose .. converting a bunch of individual folders one at a time. So you may need to hack on it a bit to suit your needs.