Skip to content

Instantly share code, notes, and snippets.

@jeremyjbowers
Created January 24, 2011 03:41
Show Gist options
  • Save jeremyjbowers/792799 to your computer and use it in GitHub Desktop.
Save jeremyjbowers/792799 to your computer and use it in GitHub Desktop.
A forked/fixed thumbs.py to solve a problem with syntax
# -*- encoding: utf-8 -*-
"""
django-thumbs by Antonio Melé
http://django.es
"""
from django.db.models import ImageField
from django.db.models.fields.files import ImageFieldFile
from PIL import Image
from django.core.files.base import ContentFile
import cStringIO
def generate_thumb(img, thumb_size, format):
"""
Generates a thumbnail image and returns a ContentFile object with the thumbnail
Parameters:
===========
img File object
thumb_size desired thumbnail size, ie: (200,120)
format format of the original image ('jpeg','gif','png',...)
(this format will be used for the generated thumbnail, too)
"""
img.seek(0) # see http://code.djangoproject.com/ticket/8222 for details
image = Image.open(img)
# Convert to RGB if necessary
if image.mode not in ('L', 'RGB', 'RGBA'):
image = image.convert('RGB')
# get size
thumb_w, thumb_h = thumb_size
# If you want to generate a square thumbnail
# if thumb_w == thumb_h:
# quad
xsize, ysize = image.size
# get minimum size
minsize = min(xsize,ysize)
# largest square possible in the image
dim = xsize/ysize
# xnewsize = (xsize-minsize)/2
# ynewsize = (ysize-minsize)/2
if(xsize > ysize):
xnewsize = thumb_w
ynewsize = xnewsize/xsize*ysize
else:
ynewsize = thumb_h
xnewsize = ynewsize/ysize*xsize
# crop it
# image2 = image.crop((xnewsize, ynewsize, xsize-xnewsize, ysize-ynewsize))
# load is necessary after crop
# image2.load()
# thumbnail of the cropped image (with ANTIALIAS to make it look better)
# image2.thumbnail(thumb_size, Image.ANTIALIAS)
# else:
# not quad
image2 = image
image2.thumbnail(thumb_size, Image.ANTIALIAS)
io = cStringIO.StringIO()
# PNG and GIF are the same, JPG is JPEG
if format.upper()=='JPG':
format = 'JPEG'
image2.save(io, format)
return ContentFile(io.getvalue())
class ImageWithThumbsFieldFile(ImageFieldFile):
"""
See ImageWithThumbsField for usage example
"""
def __init__(self, *args, **kwargs):
super(ImageWithThumbsFieldFile, self).__init__(*args, **kwargs)
if self.field.sizes:
def get_size(self, size):
if not self:
return ''
else:
split = self.url.rsplit('.',1)
thumb_url = '%s.%sx%s.%s' % (split[0],w,h,split[1])
return thumb_url
for size in self.field.sizes:
(w,h) = size
setattr(self, 'url_%sx%s' % (w,h), get_size(self, size))
def save(self, name, content, save=True):
super(ImageWithThumbsFieldFile, self).save(name, content, save)
if self.field.sizes:
for size in self.field.sizes:
(w,h) = size
split = self.name.rsplit('.',1)
thumb_name = '%s.%sx%s.%s' % (split[0],w,h,split[1])
# you can use another thumbnailing function if you like
thumb_content = generate_thumb(content, size, split[1])
thumb_name_ = self.storage.save(thumb_name, thumb_content)
if not thumb_name == thumb_name_:
raise ValueError('There is already a file named %s' % thumb_name)
def delete(self, save=True):
name=self.name
super(ImageWithThumbsFieldFile, self).delete(save)
if self.field.sizes:
for size in self.field.sizes:
(w,h) = size
split = name.rsplit('.',1)
thumb_name = '%s.%sx%s.%s' % (split[0],w,h,split[1])
try:
self.storage.delete(thumb_name)
except:
pass
class ImageWithThumbsField(ImageField):
attr_class = ImageWithThumbsFieldFile
"""
Usage example:
==============
photo = ImageWithThumbsField(upload_to='images', sizes=((125,125),(300,200),)
To retrieve image URL, exactly the same way as with ImageField:
my_object.photo.url
To retrieve thumbnails URL's just add the size to it:
my_object.photo.url_125x125
my_object.photo.url_300x200
Note: The 'sizes' attribute is not required. If you don't provide it,
ImageWithThumbsField will act as a normal ImageField
How it works:
=============
For each size in the 'sizes' atribute of the field it generates a
thumbnail with that size and stores it following this format:
available_filename.[width]x[height].extension
Where 'available_filename' is the available filename returned by the storage
backend for saving the original file.
Following the usage example above: For storing a file called "photo.jpg" it saves:
photo.jpg (original file)
photo.125x125.jpg (first thumbnail)
photo.300x200.jpg (second thumbnail)
With the default storage backend if photo.jpg already exists it will use these filenames:
photo_.jpg
photo_.125x125.jpg
photo_.300x200.jpg
Note: django-thumbs assumes that if filename "any_filename.jpg" is available
filenames with this format "any_filename.[widht]x[height].jpg" will be available, too.
To do:
======
Add method to regenerate thubmnails
"""
def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, sizes=None, **kwargs):
self.verbose_name=verbose_name
self.name=name
self.width_field=width_field
self.height_field=height_field
self.sizes = sizes
super(ImageField, self).__init__(**kwargs)
# # -*- encoding: utf-8 -*-
# """
# django-thumbs by Antonio Melé
# http://django.es
# """
# from django.db.models import ImageField
# from django.db.models.fields.files import ImageFieldFile
# from PIL import Image
# from django.core.files.base import ContentFile
# import cStringIO
#
# def generate_thumb(img, thumb_size, format):
# """
# Generates a thumbnail image and returns a ContentFile object with the thumbnail
#
# Parameters:
# ===========
# img File object
#
# thumb_size desired thumbnail size, ie: (200,120)
#
# format format of the original image ('jpeg','gif','png',...)
# (this format will be used for the generated thumbnail, too)
# """
#
# img.seek(0) # see http://code.djangoproject.com/ticket/8222 for details
# image = Image.open(img)
#
# # Convert to RGB if necessary
# if image.mode not in ('L', 'RGB', 'RGBA'):
# image = image.convert('RGB')
#
# # get size
# thumb_w, thumb_h = thumb_size
# # If you want to generate a square thumbnail
# if thumb_w == thumb_h:
# # quad
# xsize, ysize = image.size
# # get minimum size
# minsize = min(xsize,ysize)
# # largest square possible in the image
# xnewsize = (xsize-minsize)/2
# ynewsize = (ysize-minsize)/2
# # crop it
# image2 = image.crop((xnewsize, ynewsize, xsize-xnewsize, ysize-ynewsize))
# # load is necessary after crop
# image2.load()
# # thumbnail of the cropped image (with ANTIALIAS to make it look better)
# image2.thumbnail(thumb_size, Image.ANTIALIAS)
# else:
# # not quad
# image2 = image
# image2.thumbnail(thumb_size, Image.ANTIALIAS)
#
# io = cStringIO.StringIO()
# # PNG and GIF are the same, JPG is JPEG
# if format.upper()=='JPG':
# format = 'JPEG'
#
# image2.save(io, format)
# return ContentFile(io.getvalue())
#
# class ImageWithThumbsFieldFile(ImageFieldFile):
# """
# See ImageWithThumbsField for usage example
# """
# def __init__(self, *args, **kwargs):
# super(ImageWithThumbsFieldFile, self).__init__(*args, **kwargs)
#
# if self.field.sizes:
# def get_size(self, size):
# if not self:
# return ''
# else:
# split = self.url.rsplit('.',1)
# thumb_url = '%s.%sx%s.%s' % (split[0],w,h,split[1])
# return thumb_url
#
# for size in self.field.sizes:
# (w,h) = size
# setattr(self, 'url_%sx%s' % (w,h), get_size(self, size))
#
# def save(self, name, content, save=True):
# super(ImageWithThumbsFieldFile, self).save(name, content, save)
#
# if self.field.sizes:
# for size in self.field.sizes:
# (w,h) = size
# split = self.name.rsplit('.',1)
# thumb_name = '%s.%sx%s.%s' % (split[0],w,h,split[1])
#
# # you can use another thumbnailing function if you like
# thumb_content = generate_thumb(content, size, split[1])
#
# thumb_name_ = self.storage.save(thumb_name, thumb_content)
#
# if not thumb_name == thumb_name_:
# raise ValueError('There is already a file named %s' % thumb_name)
#
# def delete(self, save=True):
# name=self.name
# super(ImageWithThumbsFieldFile, self).delete(save)
# if self.field.sizes:
# for size in self.field.sizes:
# (w,h) = size
# split = name.rsplit('.',1)
# thumb_name = '%s.%sx%s.%s' % (split[0],w,h,split[1])
# try:
# self.storage.delete(thumb_name)
# except:
# pass
#
# class ImageWithThumbsField(ImageField):
# attr_class = ImageWithThumbsFieldFile
# """
# Usage example:
# ==============
# photo = ImageWithThumbsField(upload_to='images', sizes=((125,125),(300,200),)
#
# To retrieve image URL, exactly the same way as with ImageField:
# my_object.photo.url
# To retrieve thumbnails URL's just add the size to it:
# my_object.photo.url_125x125
# my_object.photo.url_300x200
#
# Note: The 'sizes' attribute is not required. If you don't provide it,
# ImageWithThumbsField will act as a normal ImageField
#
# How it works:
# =============
# For each size in the 'sizes' atribute of the field it generates a
# thumbnail with that size and stores it following this format:
#
# available_filename.[width]x[height].extension
#
# Where 'available_filename' is the available filename returned by the storage
# backend for saving the original file.
#
# Following the usage example above: For storing a file called "photo.jpg" it saves:
# photo.jpg (original file)
# photo.125x125.jpg (first thumbnail)
# photo.300x200.jpg (second thumbnail)
#
# With the default storage backend if photo.jpg already exists it will use these filenames:
# photo_.jpg
# photo_.125x125.jpg
# photo_.300x200.jpg
#
# Note: django-thumbs assumes that if filename "any_filename.jpg" is available
# filenames with this format "any_filename.[widht]x[height].jpg" will be available, too.
#
# To do:
# ======
# Add method to regenerate thubmnails
#
# """
# def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, sizes=None, **kwargs):
# self.verbose_name=verbose_name
# self.name=name
# self.width_field=width_field
# self.height_field=height_field
# self.sizes = sizes
# super(ImageField, self).__init__(**kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment