Based on the original http://code.google.com/p/django-thumbs/
Added South support too.
Usage:
photo = ImageWithThumbsField(upload_to='images', sizes=((125,125,True),(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`
To convert to greyscale set the third attribute of size to True
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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 | # -*- 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,bw=False):
"""
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)
bw convert to grayscale? True or False
"""
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'):
image = image.convert('RGB')
if bw:
image = image.convert('L')
# 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
x1 = y1 = 0
x2, y2 = image.size
wRatio = 1.0 * x2/thumb_size[0]
hRatio = 1.0 * y2/thumb_size[1]
if hRatio > wRatio:
y1 = int(y2/2-thumb_size[1]*wRatio/2)
y2 = int(y2/2+thumb_size[1]*wRatio/2)
else:
x1 = int(x2/2-thumb_size[0]*hRatio/2)
x2 = int(x2/2+thumb_size[0]*hRatio/2)
image2 = image
image2 = image2.crop((x1,y1,x2,y2))
print image2.size
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,quality=100)
return ContentFile(io.getvalue())
def generate_bw(img):
"""
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)
bw convert to grayscale? True or False
"""
img.seek(0) # see http://code.djangoproject.com/ticket/8222 for details
image = Image.open(img)
image = image.convert('L')
io = cStringIO.StringIO()
# PNG and GIF are the same, JPG is JPEG
if format.upper()=='JPG':
format = 'JPEG'
image2.save(io, format,quality=100)
return ContentFile(io.getvalue())
class ImageWithThumbsFieldFile(ImageFieldFile):
"""
See ImageWithThumbsField for usage example
"""
def __init__(self, *args, **kwargs):
super(ImageWithThumbsFieldFile, self).__init__(*args, **kwargs)
self.sizes = self.field.sizes
self.bw = self.field.bw
if self.field.bw:
def get_bw(self):
if not self:
return ''
else:
split = self.url.rsplit('.',1)
thumb_url = '%s.bw.%s' % (split[0],split[1])
return thumb_url
setattr(self, 'url_bw', get_bw(self))
if self.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.sizes:
if len(size)>2:
(w,h,bw,) = size
else:
(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.bw:
split = self.name.rsplit('.',1)
thumb_name = '%s.bw.%s' % (split[0],split[1])
thumb_content = generate_bw(content)
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)
if self.sizes:
for size in self.sizes:
bw = False
if len(size)>2:
(w,h,bw,) = size
else:
(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[:2], split[1],bw)
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.sizes:
for size in self.sizes:
if len(size)>2:
(w,h,bw,) = size
else:
(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,True),(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
To convert to greyscale set the third attribute of size to True
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, bw=False,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
self.bw = bw
super(ImageField, self).__init__(**kwargs)
try:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^thumbs\.ImageWithThumbsField"])
except ImportError:
pass
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 8 months ago
Comments
Please login first before commenting.