Am trying to create a thumbnail in django, am trying to build a custom class specifically to be used for generating thumbnails. As following
from StringIO import StringIO
from PIL import Image
class Thumbnail(object):
source = ''
size = (50, 50)
output = ''
def __init__(self):
pass
@staticmethod
def load(src):
self = Thumbnail()
self.source = src
return self
def generate(self, size=(50, 50)):
if not isinstance(size, tuple):
raise Exception('Thumbnail class: The size parameter must be an instance of a tuple.')
self.size = size
# resize properties
box = self.size
factor = 1
fit = True
image = Image.open(self.source)
# Convert to RGB if necessary
if image.mode not in ('L', 'RGB'): image = image.convert('RGB')
while image.size[0]/factor > 2*box[0] and image.size[1]*2/factor > 2*box[1]:
factor *=2
if factor > 1:
image.thumbnail((image.size[0]/factor, image.size[1]/factor), Image.NEAREST)
#calculate the cropping box and get the cropped part
if fit:
x1 = y1 = 0
x2, y2 = image.size
wRatio = 1.0 * x2/box[0]
hRatio = 1.0 * y2/box[1]
if hRatio > wRatio:
y1 = int(y2/2-box[1]*wRatio/2)
y2 = int(y2/2+box[1]*wRatio/2)
else:
x1 = int(x2/2-box[0]*hRatio/2)
x2 = int(x2/2+box[0]*hRatio/2)
image = image.crop((x1,y1,x2,y2))
#Resize the image with best quality algorithm ANTI-ALIAS
image.thumbnail(box, Image.ANTIALIAS)
# save image to memory
temp_handle = StringIO()
image.save(temp_handle, 'png')
temp_handle.seek(0)
self.output = temp_handle
return self
def get_output(self):
return self.output.read()
the purpose of the class is so i can use it inside different locations to generate thumbnails on the fly. The class works perfectly, I've tested it directly under a view.. I've implemented the thumbnail class inside the save method of the forms to resize the original images on saving.
in my design, I have two fields for thumbnails. I was able to generate one thumbnail, if I try to generate two it crashes and I've been stuck for hours not sure whats the problem.
Here is my model
class Image(models.Model):
article = models.ForeignKey(Article)
title = models.CharField(max_length=100, null=True, blank=True)
src = models.ImageField(upload_to='publication/image/')
r128 = models.ImageField(upload_to='publication/image/128/', blank=True, null=True)
r200 = models.ImageField(upload_to='publication/image/200/', blank=True, null=True)
uploaded_at = models.DateTimeField(auto_now=True)
Here is my forms
class ImageForm(models.ModelForm):
"""
"""
class Meta:
model = Image
fields = ('src',)
def save(self, commit=True):
instance = super(ImageForm, self).save(commit=True)
file = Thumbnail.load(instance.src)
instance.r128 = SimpleUploadedFile(
instance.src.name,
file.generate((128, 128)).get_output(),
content_type='image/png'
)
instance.r200 = SimpleUploadedFile(
instance.src.name,
file.generate((200, 200)).get_output(),
content_type='image/png'
)
if commit:
instance.save()
return instance
the strange part is, when i remove the line which contains instance.r200 in the form save. It works fine, and it does the thumbnail and stores it successfully. Once I add the second thumbnail it fails..
Any ideas what am doing wrong here?
Thanks
Update:
I tried earlier doing the following but I still got the same error
class ImageForm(models.ModelForm):
"""
"""
class Meta:
model = Image
fields = ('src',)
def save(self, commit=True):
instance = super(ImageForm, self).save(commit=True)
instance.r128 = SimpleUploadedFile(
instance.src.name,
Thumbnail.load(instance.src).generate((128, 128)).get_output(),
content_type='image/png'
)
instance.r200 = SimpleUploadedFile(
instance.src.name,
Thumbnail.load(instance.src).generate((200, 200)).get_output(),
content_type='image/png'
)
if commit:
instance.save()
return instance