I normally like to write code myself instead of installing some large script just to do one task for me. There were a few scripts out there that could create thumbnails, but I wanted something simple and wouldn’t use most of those features. Plus, I wanted to know how to use the Python Image Library with Django 1.0 and learn on my own how to take an uploaded picture and create a few thumbnails of them.

After searching for a while I was able to piece some things together to get something working. In my model I added these two functions.

def thumbnailed ( self , file , width, height ) : from django. core . files . base import ContentFile from StringIO import StringIO import Image try : size = width, height tmp_file = StringIO ( ) im = Image. open ( StringIO ( file . read ( ) ) ) format = im. format # since new im won't have format if format == "gif" or format == "GIF" : im = im. convert ( "RGB" ) im. thumbnail ( size, Image. ANTIALIAS ) if format == "gif" or format == "GIF" : im = im. convert ( "P" , dither=Image. NONE , palette=Image. ADAPTIVE ) im. save ( tmp_file, format, quality= 95 ) except IOError : return None return ContentFile ( tmp_file. getvalue ( ) )

Using StringIO I was able to create a temporary file in memory to hold the thumbnail data and return it where it would later be passed to django. I was trying to create 3 thumbnails which presented another problem: django was obliterating the uploaded file and the data in my temp files when I was saving. So I figured out how to get around that, but there may be better ways.

def create_thumbnails ( self , file ) : pic = self . thumbnailed ( file , 160 , 400 ) if pic is not None : self . picture . save ( file . name , pic, save= False ) # Django's InMemoryUploadedFile uses StringIO # This will reset it to be ready to use again file . seek ( 0 ) thumb = self . thumbnailed ( file , 288 , 96 ) if thumb is not None : self . thumbnail . save ( file . name , thumb, save= False ) # Django's InMemoryUploadedFile uses StringIO # This will reset it to be ready to use again file . seek ( 0 ) tiny = self . thumbnailed ( file , 144 , 48 ) if tiny is not None : self . tiny_image . save ( file . name , tiny, save= False )

The model has picture, thumbnail, and tiny_image as ImageFields and create_thumbnails was originally called from the view and passed the uploaded file from request.FILES.

There was a lot of trial and error trying to get this together, so I hope it helps someone get past that.

Updated July 10, 2009

I added a condition to check if the image is a gif. If it is, it is converted so that the thumnails will look much better than they would without converting them. I also set the quality to 95 so that all images will have the best possible thumbnails.

I use webfaction to host a lot of my django projects. It has an easy setup that will get you developing quickly and a great community of talented programmers. There is also a quick setup for rails, wordpress, and a lot more.

Related posts: