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
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
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)
#
Ah - good point. I'm too hard-wired into thinking of filesystem paths! I'll update the sample. Thanks.
#
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.