I've had success with PIL to thumbnail uploaded images.
In upload form handling:
if form.accepts(request.vars,session):
if not form.vars.get("delete_this_record",False):
response.flash = "image accepted"
makeThumbnail(
form.vars.id)
else:
response.flash = "image deleted"
then the function to make the thumbnail. This might have less error
handling than you'd like. My images are in the db, the main image is
field 'image_blob' and the thumbnail, also a blob, 'thumbnail_data'.
If yours are in a file then the changes you'd need would actually make
the code simpler.
THUMBNAILSIZE = 120
def makeThumbnail(id):
import Image
import StringIO
imgRecord = db.images[id]
if not imgRecord:
return None
imgData = Image.open(StringIO.StringIO
(imgRecord.image_blob)).convert("RGB")
imgData.thumbnail((THUMBNAILSIZE,THUMBNAILSIZE),Image.ANTIALIAS)
thumbFile = StringIO.StringIO()
imgData.save(thumbFile,"JPEG")
thumbFile.seek(0)
imgRecord.update_record(thumbnail_data=thumbFile.read())
db.commit()
return True
From memory, the above will shrink the picture so the largest
dimension is THUMBNAILSIZE, and the aspect ratio is maintained - the
shorter dimension may be less than THUMBNAILSIZE if the image wasn't
square.
From a different iteration of my code, the following will always give
you a square of dimensions xy by xy, without distorting the image, but
will crop the image if it wasn't already square.
def makeThumbnail(blob, xy):
imgData = Image.open(StringIO.StringIO(blob)).convert("RGB")
# make sure thumbnails are square by cropping original to a
# square.
# Find the longest side
w,h = imgData.size
if w >= h:
voffset=0
hoffset=(w-h)/2
ex = h
else:
hoffset=0
voffset=(h-w)/2
ex = w
imgData = imgData.transform((xy,xy),Image.EXTENT,
(hoffset,voffset,hoffset+ex,voffset+ex),Image.BICUBIC)
thumbFile = StringIO.StringIO()
imgData.save(thumbFile,"JPEG")
thumbFile.seek(0)
return thumbFile
Sorry if the speed I'm writing my reply, or the inelegance of my
implementation makes this post less than helpful.
Chris