Login

Filter to resize a ImageField on demand

Author:
michelts
Posted:
April 19, 2007
Language:
Python
Version:
.96
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

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

Archatas (on April 19, 2007):

Shouldn't there be something like

thumbnail = register.filter(thumbnail)

at the end of the snippet?

#

alexkoval (on July 9, 2007):

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.

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)

#

alexkoval (on July 9, 2007):

also... Thumbnails are bad quality, I recommend adding anti aliasing when resizing:

    image.thumbnail([x, y],Image.ANTIALIAS) # generate a 200x200 thumbnail

#

rafacdb (on August 9, 2008):

Correction to version 1.0 alpha 2

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)

#

Please login first before commenting.