Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify or Delete Exif tag 'Orientation' in Python

I need some of my pictures to be displayed with the same orientation whether the software reads the exif data or not. One solution (the only one that could fit actually) would be to rotate the image according to the exif tag if it exists and then delete or modify this tag to '1'.

Example
Let's say an image has the Orientation exif tag set to 3. What I want to do is rotate this image according to this tag and save it this way. So that a software that doesn't interpret exif will still display it in the good orientation. Though if the exif tag Orientation is still set to 3, then a software that interprets Exif will rotate my already-rotated image. So that's why I want to set this tag to 1 (which means : no orientation) or delete it.

My final goal is that the image will always be displayed the same, whichever software I use to open it.

There are a lot of questions about that, Exif and Python, blah blah blah. Here is a list of libs that I heard about :

  • Pyexiv2 : Not suitable, I'm currently using Python 3.3 with Pillow
  • Gexiv2 : Looks like a bit platform specific
  • EXIF.py
  • Pexif : Looks like the most recent one ?

What are the best practices ? Is there a pure python solution ? (Which I could install with pip and put it in my requirements.txt) Is there some kind of new lib I could use which is specific to Python3 ?

My only problem right now is to modify and write those exif data to the image file. I have no problem to read exif data, and rotate the image according to the orientation tag. Any tips or advice on that ?

like image 563
Depado Avatar asked Feb 26 '14 15:02

Depado


People also ask

What is EXIF orientation tag?

Auto-rotation The EXIF orientation value is used by Photoshop and other photo editing software to automatically rotate photos, saving you a manual task.

How do I view EXIF orientation?

Read and Write Exif Info To view the image Exif info, open an image and click Image -> Information . If the image contains Exif info, you can then click the EXIF info button at the bottom left of the popup window to check the image Exif info.

Can we add our own EXIF parameter?

EXIF key-value pairs are called tags, and each tag can contain either a string or numeric value. There are dozens of tags in the current EXIF standard (version 2.32), and anyone — from smartphone and camera manufacturers to photographers — is free to add their own.


1 Answers

note:

This answer works for Python2.7 - you can probably just swap Pillow for PIL in Python3, but I can't speak to that from experience. Note that unlike pyexiv2 and most of the other packages that allow you to modify EXIF metadata, the pexif library is standalone and pure python, so it does not need to bind to any C libraries that may not be present on your machine.

overview:

You need to use two separate tools for the two steps:

  • pexif to modify the metadata (EXIF tag)
  • PIL to rotate the image

pexif part:

Four steps:

  • open the image
  • check orientation (needed later for rotation)
  • change orientation to 1
  • save the image

If the orientation tag isn't found, an AttributeError results, hence the try:. Also note that pexif needs the orientation tag to be a list (with one element).

import pexif
img = pexif.JpegFile.fromFile(temp_dir + filename)

try:
  #Get the orientation if it exists
  orientation = img.exif.primary.Orientation[0]
  img.exif.primary.Orientation = [1]
  img.writeFile(temp_dir + filename)

PIL part:

Now to rotate the image. A source for the meaning of the possible orientations (used to generate the lookup table for rotations) is here.

  • open the image
  • apply the necessary rotation/reflection
  • save the image
from PIL import Image

img = Image.open(temp_dir + filename)
if orientation is 6: img = img.rotate(-90)
elif orientation is 8: img = img.rotate(90)
elif orientation is 3: img = img.rotate(180)
elif orientation is 2: img = img.transpose(Image.FLIP_LEFT_RIGHT)
elif orientation is 5: img = img.rotate(-90).transpose(Image.FLIP_LEFT_RIGHT)
elif orientation is 7: img = img.rotate(90).transpose(Image.FLIP_LEFT_RIGHT)
elif orientation is 4: img = img.rotate(180).transpose(Image.FLIP_LEFT_RIGHT)

#save the result
img.save(temp_dir + filename)

put it all together:

if ctype == 'image/jpeg':
  from PIL import Image
  import pexif

  img = pexif.JpegFile.fromFile(temp_dir + filename)

  try:
    #Get the orientation if it exists
    orientation = img.exif.primary.Orientation[0]
    img.exif.primary.Orientation = [1]
    img.writeFile(temp_dir + filename)

    #now rotate the image using the Python Image Library (PIL)
    img = Image.open(temp_dir + filename)
    if orientation is 6: img = img.rotate(-90)
    elif orientation is 8: img = img.rotate(90)
    elif orientation is 3: img = img.rotate(180)
    elif orientation is 2: img = img.transpose(Image.FLIP_LEFT_RIGHT)
    elif orientation is 5: img = img.rotate(-90).transpose(Image.FLIP_LEFT_RIGHT)
    elif orientation is 7: img = img.rotate(90).transpose(Image.FLIP_LEFT_RIGHT)
    elif orientation is 4: img = img.rotate(180).transpose(Image.FLIP_LEFT_RIGHT)

    #save the result
    img.save(temp_dir + filename)
  except: pass
like image 149
Wesley Avatar answered Nov 01 '22 12:11

Wesley