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...
See yer...
Bazza...
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):