resize image on save
I use this code to handle uploaded images, resize them on memory(whithout saving them permanently on disk), and then saving the thumb on a Django ImageField. Hope can help.
def handle_uploaded_image(i):
import StringIO
from PIL import Image, ImageOps
import os
from django.core.files import File
# read image from InMemoryUploadedFile
image_str = “”
for c in i.chunks():
image_str += c
# create PIL Image instance
imagefile = StringIO.StringIO(image_str)
image = Image.open(imagefile)
# if not RGB, convert
if image.mode not in (“L”, “RGB”):
image = image.convert(“RGB”)
#define file output dimensions (ex 60x60)
x = 130
y = 130
#get orginal image ratio
img_ratio = float(image.size[0]) / image.size[1]
# resize but constrain proportions?
if x==0.0:
x = y * img_ratio
elif y==0.0:
y = x / img_ratio
# output file ratio
resize_ratio = float(x) / y
x = int(x); y = int(y)
# get output with and height to do the first crop
if(img_ratio > resize_ratio):
output_width = x * image.size[1] / y
output_height = image.size[1]
originX = image.size[0] / 2 - output_width / 2
originY = 0
else:
output_width = image.size[0]
output_height = y * image.size[0] / x
originX = 0
originY = image.size[1] / 2 - output_height / 2
#crop
cropBox = (originX, originY, originX + output_width, originY + output_height)
image = image.crop(cropBox)
# resize (doing a thumb)
image.thumbnail([x, y], Image.ANTIALIAS)
# re-initialize imageFile and set a hash (unique filename)
imagefile = StringIO.StringIO()
filename = hashlib.md5(imagefile.getvalue()).hexdigest()+’.jpg’
#save to disk
imagefile = open(os.path.join(‘/tmp’,filename), ‘w’)
image.save(imagefile,’JPEG’, quality=90)
imagefile = open(os.path.join(‘/tmp’,filename), ‘r’)
content = File(imagefile)
return (filename, content)
#views.py
form = YourModelForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
ob = form.save(commit=False)
try:
t = handle_uploaded_image(request.FILES[‘icon’])
ob.image.save(t[0],t[1])
except KeyError:
ob.save()
You should use a method to handle the uploaded file, as demonstrated in the Django documentation.
In this method, you could concatenate the chunks in a variable (rather than writing them to disk directly), create a PIL Image from that variable, resize the image and save it to disk.
In PIL, you should look at Image.fromstring
and Image.resize
.
I highly recommend the sorl-thumbnail app for handling image resizing easily and transparently. It goes in every single Django project I start.
I recommend using StdImageField from django-stdimage, it should handle all the dirty work for you. It's easy to use, you just specify the dimensions of the resized image in the field definition:
class MyModel(models.Model):
image = StdImageField(upload_to='path/to/img', size=(640, 480))
Check out the docs — it can do thumbnails also.