Losslessly compressing images on django

user4910881 picture user4910881 · Oct 12, 2015 · Viewed 18.3k times · Source

I'm doing optimization and Google recommends Lossless compression to images, looking for a way to implement this in Django.

Here's the images they specified, I think for it to be done effectively it needs to implemented systemwide possibly using a middleware class wondering if anyone has done this before. Here's the link to google analytics for pagespeed https://developers.google.com/speed/pagespeed/insights/?url=www.kenyabuzz.com

Optimize images Properly formatting and compressing images can save many bytes of data. Optimize the following images to reduce their size by 627.3KiB (74% reduction).

Losslessly compressing http://www.kenyabuzz.com/media/uploads/clients/kenya_buzz_2.jpg could save 594.3KiB (92% reduction).
Losslessly compressing http://www.kenyabuzz.com/media/uploads/clients/new_tribe_2.jpg could save 25KiB (44% reduction).
Losslessly compressing http://www.kenyabuzz.com/…a/uploads/clients/EthiopianAirlines2.jpg could save 3KiB (22% reduction).
Losslessly compressing http://www.kenyabuzz.com/static/kb/images/Nightlife.Homepage.jpg could save 1.3KiB (2% reduction).
Losslessly compressing http://www.kenyabuzz.com/static/kb/img/social/blog.png could save 1.1KiB (43% reduction).
Losslessly compressing http://www.kenyabuzz.com/static/kb/img/social/twitter.png could save 969B (52% reduction).
Losslessly compressing http://www.kenyabuzz.com/…der-Board---Email-Signature--Neutral.jpg could save 920B (2% reduction).
Losslessly compressing http://www.kenyabuzz.com/static/kb/img/social/youtube.png could save 757B (31% reduction).

Answer

xyres picture xyres · Nov 29, 2015

Losslessly compressing http://www.kenyabuzz.com/media/uploads/clients/kenya_buzz_2.jpg could save 594.3KiB (92% reduction).

First of all, the information in the logs is not very accurate. 92% lossless reduction is only possible when the original image is uncompressed and has very small number of colours.

Read this answer and this answer for more info. Really, do read them, both are excellent answers.

Second, you can use lossy compression formats "without losing quality" – the differences are so subtle, human eye doesn't even notice.


So, I downloaded an image from the website you're optimizing from this link: http://www.kenyabuzz.com/media/uploads/clients/kenya_buzz_2.jpg

I opened my Python console and wrote this:

>>> from PIL import Image

>>> # Open the image
>>> im = Image.open("kenya_buzz_2.jpg")
>>> # Now save it
>>> im.save("kenya_buzz_compressed.jpg", format="JPEG", quality=70)

This created a new image on my disk. Below are both the images.

Original (655.3kB)

original image


Compressed (22.4kB ~96% reduction @ quality=70)

compressed image using Python


You can play around with the quality option. Like, value of 80 will give you a better quality image but with a little larger size.


Compressing images in Django

Since this is a pretty popular question, I've decided to add a sample code to compress images in Django.

This code works for Django >= 1.7.

from io import BytesIO
from PIL import Image
from django.core.files import File


def compress(image):
    im = Image.open(image)
    # create a BytesIO object
    im_io = BytesIO() 
    # save image to BytesIO object
    im.save(im_io, 'JPEG', quality=70) 
    # create a django-friendly Files object
    new_image = File(im_io, name=image.name)
    return new_image

And this is how you can use the above compress function in your Django model (or anywhere):

# models.py

class MyModel(...):
    image = models.ImageField(...)

    def save(self, *args, **kwargs):
        # call the compress function
        new_image = compress(self.image)
        # set self.image to new_image
        self.image = new_image
        # save
        super().save(*args, **kwargs)

That is basically it. This is fairly basic code. You can improve the code by compressing the image only when the image changes, not every time the model is saved.