Login

UPDATED: Django Image Thumbnail Filter

Author:
danfairs
Posted:
October 30, 2007
Language:
Python
Version:
.96
Score:
1 (after 1 ratings)

A Django image thumbnail filter, adapted from code by Batiste Bieler.

This updated version drops support for cropping and just rescales. You should use it in your templates like this:

<img src='{{ MEDIA_URL }}{{ image.get_image_filename|thumbnail:"300w,listingimages" }}' alt="{{ image.title }}" title="{{ image.title }}" />

This will produce a 300-pixel wide thumbnail of image, with the height scaled appropriately to keep the same image aspect ratio. 'listingimages' is the path under your MEDIA_ROOT that the image lives in - it'll be whatever upload_to is set to in your ImageField.

If instead you wanted an image scaled to a maximum height of 140px, you'd use something like this:

<img src='{{ MEDIA_URL }}{{ image.get_image_filename|thumbnail:"140h,listingimages" }}' alt="{{ image.title }}" title="{{ image.title }}" />

Note the number has changed from 300 to 140, and the trailing letter from 'w' to 'h'.

Please leave feedback and bug reports on my blog, Stereoplex. I've only lightly tested this so you'll probably find something!

 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
54
55
56
57
58
59
THUMBNAILS = 'thumbnails'
SCALE_WIDTH = 'w'
SCALE_HEIGHT = 'h'

def scale(max_x, pair):
    x, y = pair
    new_y = (float(max_x) / x) * y
    return (int(max_x), int(new_y))
    
# Thumbnail filter based on code from http://batiste.dosimple.ch/blog/2007-05-13-1/
@register.filter
def thumbnail(original_image_path, arg):  
    if not original_image_path:  
        return ''  
        
    if arg.find(','):
        size, upload_path = [a.strip() for a in  arg.split(',')]
    else:
        size = arg
        upload_path = ''

    if (size.lower().endswith('h')):
        mode = 'h'
    else:
        mode = 'w'
        
    # defining the size  
    size = size[:-1]
    max_size = int(size.strip())
    
    # defining the filename and the miniature filename  
    basename, format = original_image_path.rsplit('.', 1)  
    basename, name = basename.rsplit(os.path.sep, 1)  

    miniature = name + '_' + str(max_size) + mode + '.' + format
    thumbnail_path = os.path.join(basename, THUMBNAILS)
    if not os.path.exists(thumbnail_path):  
        os.mkdir(thumbnail_path)  
    
    miniature_filename = os.path.join(thumbnail_path, miniature)  
    miniature_url = '/'.join((settings.MEDIA_URL, upload_path, THUMBNAILS, miniature))  
    
    # if the image wasn't already resized, resize it  
    if not os.path.exists(miniature_filename) \
        or os.path.getmtime(original_image_path) > os.path.getmtime(miniature_filename):
        image = Image.open(original_image_path)  
        image_x, image_y = image.size  
        
        if mode == SCALE_HEIGHT:
            image_y, image_x = scale(max_size, (image_y, image_x))
        else:
            image_x, image_y = scale(max_size, (image_x, image_y))
            
        
        image = image.resize((image_x, image_y), Image.ANTIALIAS)
              
        image.save(miniature_filename, image.format)  

    return miniature_url  

More like this

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

Comments

Eftarjin (on November 3, 2007):

miniature_url = os.path.join(settings.MEDIA_URL, upload_path, THUMBNAILS, miniature)

It may not be a good idea to use os.path.join (which is platform-specific) to build URLs.

I suggest to use '/'.join instead. (The separator for URLs is always '/', whatever platform you're on)

#

danfairs (on November 7, 2007):

Ah - good point. I'm too hard-wired into thinking of filesystem paths! I'll update the sample. Thanks.

#

vladka (on July 21, 2011):

i'd thing you're should also add: if not os.path.exists(original_image_path): return ''

because source image can be deleted, or move and etc.

thank you for you snippet.

#

Please login first before commenting.