Losslessly compressing images on django

后端 未结 3 1737
执笔经年
执笔经年 2021-01-31 04:46

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 f

3条回答
  •  醉梦人生
    2021-01-31 05:17

    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 rather misleading because it is impossible to compress images by 92% using a lossless format (except for some cases like single-colour images, basic geometric shapes like squares, etc). 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)


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


    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.

提交回复
热议问题