Login

Filter to resize a ImageField on demand

Author:
michelts
Posted:
April 19, 2007
Language:
Python
Version:
.96
Tags:
filter models thumbnail resize imagefield
Score:
12 (after 12 ratings)

A filter to resize a ImageField on demand, a use case could be:

<img src="object.get_image_url" alt="original image"> <img src="object.image|thumbnail" alt="image resized to default 200x200 format"> <img src="object.image|thumbnail:"200x300" alt="image resized to 200x300">

The filter is applied to a image field (not the image url get from get_image_url method of the model), supposing the image filename is "image.jpg", it checks if there is a file called "image_200x200.jpg" or "image_200x300.jpg" on the second case, if the file isn't there, it resizes the original image, finally it returns the proper url to the resized image.

There is a TODO: the filter isn't checking if the original filename is newer than the cached resized image, it should check it and resize the image again in this case.

 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
import os
import Image
from django.template import Library


register = Library()


def thumbnail(file, size='200x200'):
    # defining the size
    x, y = [int(x) for x in size.split('x')]
    # defining the filename and the miniature filename
    basename, format = file.rsplit('.', 1)
    miniature = basename + '_' + size + '.' +  format
    miniature_filename = os.path.join(settings.MEDIA_ROOT, miniature)
    miniature_url = os.path.join(settings.MEDIA_URL, miniature)
    # if the image wasn't already resized, resize it
    if not os.path.exists(miniature_filename):
        print '>>> debug: resizing the image to the format %s!' % size
        filename = os.path.join(settings.MEDIA_ROOT, file)
        image = Image.open(filename)
        image.thumbnail([x, y]) # generate a 200x200 thumbnail
        image.save(miniature_filename, image.format)
    return miniature_url


register.filter(thumbnail)

More like this

Comments

Archatas (on April 19, 2007):
<p>Shouldn't there be something like</p> <pre>thumbnail = register.filter(thumbnail) </pre> <p>at the end of the snippet?</p>

#

alexkoval (on July 9, 2007):
<p>the first thing which I've noticed is that thumbnail was not regenerated when I replaced main image. I suggest fix so thumbnail is removed (and then regenerated) when its outdated. I also had to move up filename= line. </p> <pre>miniature = basename + '_' + size + '.' + format filename = os.path.join(settings.MEDIA_ROOT, file) miniature_filename = os.path.join(settings.MEDIA_ROOT, miniature) miniature_url = os.path.join(settings.MEDIA_URL, miniature) if os.path.exists(miniature_filename) and \ os.path.getmtime(filename)>os.path.getmtime(miniature_filename): os.unlink(miniature_filename) </pre>

#

alexkoval (on July 9, 2007):
<p>also... Thumbnails are bad quality, I recommend adding anti aliasing when resizing:</p> <pre> image.thumbnail([x, y],Image.ANTIALIAS) # generate a 200x200 thumbnail </pre>

#

rafacdb (on August 9, 2008):
<p>Correction to version 1.0 alpha 2</p> <pre>import os import Image from django.template import Library from django.conf import settings register = Library() def thumbnail(file, size='104x104'): # defining the size x, y = [int(x) for x in size.split('x')] # defining the filename and the miniature filename filehead, filetail = os.path.split(file.path) basename, format = os.path.splitext(filetail) miniature = basename + '_' + size + format filename = file.path miniature_filename = os.path.join(filehead, miniature) filehead, filetail = os.path.split(file.url) miniature_url = filehead + '/' + miniature if os.path.exists(miniature_filename) and os.path.getmtime(filename)>os.path.getmtime(miniature_filename): os.unlink(miniature_filename) # if the image wasn't already resized, resize it if not os.path.exists(miniature_filename): image = Image.open(filename) image.thumbnail([x, y], Image.ANTIALIAS) try: image.save(miniature_filename, image.format, quality=90, optimize=1) except: image.save(miniature_filename, image.format, quality=90) return miniature_url register.filter(thumbnail) </pre>

#

Please login first before commenting.