22

In order to reduce the size of images to be used in a website, I reduced the quality to 80-85%. This decreases the image size quite a bit, up to an extent.

To reduce the size further without compromising the quality, my friend pointed out that raw images from cameras have a lot of metadata called Exif info. Since there is no need to retain this Exif info for images in a website, we can remove it. This will further reduce the size by 3-10 kB.

But I'm not able to find an appropriate library to do this in my Python code. I have browsed through related questions and tried out some of the methods:

Original image: http://mdb.ibcdn.com/8snmhp4sjd75vdr27gbadolc003i.jpg

  1. Mogrify

    /usr/local/bin/mogrify -strip filename
    

    Result: http://s23.postimg.org/aeaw5x7ez/8snmhp4sjd75vdr27gbadolc003i_mogrify.jpg This method reduces the size from 105 kB to 99.6 kB, but also changed the color quality.

  2. Exif-tool

    exiftool -all= filename
    

    Result: http://s22.postimg.org/aiq99o775/8snmhp4sjd75vdr27gbadolc003i_exiftool.jpg This method reduces the size from 105 kB to 72.7 kB, but also changed the color quality.

  3. This answer explains in detail how to manipulate the Exif info, but how do I use it to remove the info?

Can anyone please help me remove all the extra metadata without changing the colours, dimensions, and other properties of an image?

StarGeek
  • 4,948
  • 2
  • 19
  • 30
Sudipta
  • 4,773
  • 2
  • 27
  • 42
  • 3
    You are wrong about ExifTool modifying 'color quality' (changing actual pixels? color? compression?). Compare original and result with IM's **compare**: `compare -metric AE 8snmhp4sjd75vdr27gbadolc003i.jpg 8snmhp4sjd75vdr27gbadolc003i_exiftool.jpg null:` and you'll get zero difference (or use **JPEGsnoop**, etc.). You may be confused because original has icc-profile embedded and result hasn't, and you compare them in color-managed application. But you can strip all but icc-profile: `exiftool -all= --icc_profile:all 8snmhp4sjd75vdr27gbadolc003i.jpg` and get 74.1 kb with icc-profile untouched – user2846289 Nov 05 '13 at 15:32
  • Regarding method 3 (Exif-py), it looks like that tool is for extracting Exif information from images so that you have access to it in your program, not for removing it from the image files. I don't think it is designed to modify image files. – swimfar Jul 06 '18 at 15:56

5 Answers5

47
from PIL import Image

image = Image.open('image_file.jpeg')
    
# next 3 lines strip exif
data = list(image.getdata())
image_without_exif = Image.new(image.mode, image.size)
image_without_exif.putdata(data)
    
image_without_exif.save('image_file_without_exif.jpeg')

# as a good practice, close the file handler after saving the image.
image_without_exif.close()
Yaakov Bressler
  • 9,056
  • 2
  • 45
  • 69
user2141737
  • 607
  • 6
  • 5
  • In case Image.open(...) is not working for you too: https://stackoverflow.com/questions/19230991/image-open-cannot-identify-image-file-python – andrew Jun 28 '17 at 03:12
  • I just tried out this method. With the image given in the question, the file size was reduced from 106 KB to 63 KB. – Aidas Bendoraitis May 16 '18 at 20:16
  • 1
    This breaks some images, e.g. https://www.bk.com/sites/default/files/Hero_0001_Chocolate_Milk.png – Gallaecio Jul 20 '18 at 06:49
  • If this breaks certain images, such as the PNG identified above by @Gallaecio (which is no longer available) it is probably because the image has a palette which is not propagated forward to the new image, see https://stackoverflow.com/a/52307690/2836621 – Mark Setchell Mar 01 '21 at 08:17
  • This function works but is not suitable for Production code. During high load times, I've seen this function take north of 15s, which is a HUGE bottleneck. If we can optimize it in some way, that would be great! – Adhish Thite Jul 25 '22 at 20:54
12

For me, gexiv2 works fine:

#!/usr/bin/python3

from gi.repository import GExiv2

exif = GExiv2.Metadata('8snmhp4sjd75vdr27gbadolc003i.jpg')
exif.clear_exif()
exif.clear_xmp()
exif.save_file()

See also Exif manipulation library for python, which you linked, but didn't read all answers ;)

Community
  • 1
  • 1
Christoph
  • 47,569
  • 8
  • 87
  • 187
8

You can try loading the image with the Python Image Lirbary (PIL) and then save it again to a different file. That should remove the meta data.

Ber
  • 40,356
  • 16
  • 72
  • 88
6

You don't even need to do the extra steps @user2141737 suggested. Just opening it up with PIL and saving it again seems to do the trick just fine:

from PIL import Image
image = Image.open('path/to/image')
image.save('new/path/' + file_name)
Ahmad
  • 69,608
  • 17
  • 111
  • 137
2

As for pillow==9.2.0

This seems to print exif data, a mutable mapping

print(im.info)

This seems to clear exif data for PNG

def clear_exif():
with Image.open('./my_image.png', mode='r', formats=['PNG']) as im:
    fields_to_keep = ('transparency', )
    exif_fields = list(im.info.keys())
    for k in exif_fields:
        if k not in fields_to_keep:
            del im.info[k]

    im.save('./my_image.png', format='PNG')
Omony
  • 31
  • 1
  • 2