

I’ve got a Model with an ImageField, and i needed to resize the uploaded image (done through a modelform) before saving it to the disk: resizing the image on memory (or when it’s saved on a temp folder).
It took me a lot of time to understand how django’s InMemoryUploadedFile is done, and how to override the ImageField related file with the new resized one, so hope this can be usefull to someone.
Here is my code
def handle_uploaded_image(i):
import StringIO
from PIL import Image, ImageOps
import os
from django.core.files import File
# read image from InMemoryUploadedFile
str = “”
for c in i.chunks():
str += c
# create PIL Image instance
imagefile = StringIO.StringIO(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()
Th basic aproach is reading the uploaded image from memory, create another one image on momory, using StringIO and PIL, then resize the image (note than it also makes a crop), and finaly save it to the disk.
Then we return back the filename and content(a File instance), witch are used to override the default ImageField.
I know this code may be improved a lot, hope someone can do it, anyway it makes the job done.
I know these things can be very annoying, so if you have questions, just ask.