We already know how to upload the image file in Django, store it and use it in Django templates. Sometimes images are of large size and we want to compress them to save some space and to reduce the page load time where those images are being used. In this article, we will see how to compress and image before storing it.
Getting file in view
from blog.models import ImageModel
def upload_image(request):
data = dict()
if "GET" == request.method:
return render(request, 'blog/upload_image.html', data)
# process POST request
files = request.FILES # multivalued dict
image = files.get("image") # compress the image here and then save it
instance = ImageModel()
instance.image = image
instance.save()
return render(request, 'blog/upload_image.html', data)
Installing dependencies
We strongly recommend using a virtual environment to run your Django application. Once the virtual environment is active, install the pillow python package in it.
pip install pillow
I am using version 5.2.0.
Compressing image
First import the dependencies then open the image and then save it back with the desired quality level.
from io import BytesIO
from PIL import Image
from django.core.files.uploadedfile import InMemoryUploadedFile
i = Image.open(image)
thumb_io = BytesIO()
i.save(thumb_io, format='JPEG', quality=80)
inmemory_uploaded_file = InMemoryUploadedFile(thumb_io, None, 'foo.jpeg',
'image/jpeg', thumb_io.tell(), None)
In the last line, we are converting the processed image back to the InMemoryUploadedFile type image. Read more about the InMemoryUploadedFile class and its parameters here.
Now save this compressed image to model. Complete view code will look like below.
from blog.models import ImageModel from io import BytesIO from PIL import Image from django.core.files.uploadedfile import InMemoryUploadedFile
def upload_image(request):
data = dict()
if "GET" == request.method:
return render(request, 'blog/upload_image.html', data)
# process POST request
files = request.FILES # multivalued dict
image = files.get("image") # compress the image here and then save it i = Image.open(image) thumb_io = BytesIO() i.save(thumb_io, format='JPEG', quality=80) inmemory_uploaded_file = InMemoryUploadedFile(thumb_io, None, 'foo.jpeg', 'image/jpeg', thumb_io.tell(), None)
instance = ImageModel()
instance.image = inmemory_uploaded_file
instance.save()
return render(request, 'blog/upload_image.html', data)
Possible errors
If you are getting an error something like "cannot write mode RGBA as JPEG", then convert the image to RGB before trying to compress it.
i = Image.open(image) i = i.convert('RGB') thumb_io = BytesIO() i.save(thumb_io, format='JPEG', quality=80)
More about this error can be found in this GitHub ticket link.
Once the image is uploaded and saved on the server, compare the sizes. You will find up to a 30% reduction in size.
Host your Django Application for free on PythonAnyWhere. If you want full control of your application and server, you should consider DigitalOcean. Create an account with this link and get $100 credits.