The Python Imaging Library (PIL) makes many tasks easy in digital photography. This recipe shows how to make a "contact sheet" of images, a single image with thumbnails of many different pictures. It's limited in that it will only work with pictures of the same shape, but you can make some really fun images.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
def make_contact_sheet(fnames,(ncols,nrows),(photow,photoh), (marl,mart,marr,marb), padding): """\ Make a contact sheet from a group of filenames: fnames A list of names of the image files ncols Number of columns in the contact sheet nrows Number of rows in the contact sheet photow The width of the photo thumbs in pixels photoh The height of the photo thumbs in pixels marl The left margin in pixels mart The top margin in pixels marr The right margin in pixels marb The bottom margin in pixels padding The padding between images in pixels returns a PIL image object. """ # Calculate the size of the output image, based on the # photo thumb sizes, margins, and padding marw = marl+marr marh = mart+ marb padw = (ncols-1)*padding padh = (nrows-1)*padding isize = (ncols*photow+marw+padw,nrows*photoh+marh+padh) # Create the new image. The background doesn't have to be white white = (255,255,255) inew = Image.new('RGB',isize,white) count = 0 # Insert each thumb: for irow in range(nrows): for icol in range(ncols): left = marl + icol*(photow+padding) right = left + photow upper = mart + irow*(photoh+padding) lower = upper + photoh bbox = (left,upper,right,lower) try: # Read in an image and resize appropriately img = Image.open(fnames[count]).resize((photow,photoh)) except: break inew.paste(img,bbox) count += 1 return inew
This fork improves the memory performance: rather than loading in all the images at the start, only load each image when required. Original description follows.
I recently used the blog entry at the URL: http://www.mikematas.com/blog/2005/01/how-to-make-life-poster.html to make a Life Poster with rather striking results. I started thinking about how to do this in Python (being that kind of person), and it turns out that PIL makes this very easy indeed.
The original recipe requires IPhoto, and uses it to crop a set of pictures to the same aspect ratio, and then build a contact sheet. That sheet is then printed as a PDF, and then converted to a TIFF by Photoshop, then imported back to IPhoto for printing as a poster.
This program assumes you have a set of pictures already cropped appropriately, and then uses PIL to assemble thumbnails into a single picture. The fun part is that since you own the code, you are free to play around with lots of different settings.
I haven't actually printed out a picture this way, so I can't guarantee that the results are in any way comparable to the IPhoto/Photoshop recipe, but the images certainly look nice on my computer.
I've been testing the code with something like the following:
import glob from PIL import Image ncols,nrows = 7,14 files = glob.glob('*.TIFF') # Don't bother reading in files we aren't going to use if len(files) > ncols*nrows: files = files[:ncols*nrows] # These are all in terms of pixels: photow,photoh = 200,150 photo = (photow,photoh) margins = [5,5,5,5] padding = 1 inew = make_contact_sheet(files,(ncols,nrows),photo,margins,padding) inew.save('bs.png') #os.system('display bs.png') #os.system('open bs.png') inew.show()
I guess "marb" must be the bottom margin... ;o)
just a clerical error I noticed on the docstring...
Thanks Bazza, fixed!
Here's my variation on your fork that actually scales the image proportionally to fit the thumbnail box...
count = 0 # Insert each thumb: for irow in range(nrows): for icol in range(ncols):