Depado
Depado

Reputation: 4929

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 :

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 ?

Upvotes: 13

Views: 11783

Answers (4)

Oliver Zendel
Oliver Zendel

Reputation: 2901

pexif is not working for py3+ I found this work-around with piexif 1.1.3 to read/write exif with python (note: this alters the image data as it re-encodes with jpg!):

import piexif #pip install piexif
from PIL import Image
img = Image.open(f)
exif_dict = piexif.load(img.info['exif']) if 'exif' in img.info else {'0th':{274:0}}
exif_dict['0th'][274] = 0 # must be int
exif_bytes = piexif.dump(exif_dict)
img.save(f, exif=exif_bytes)

Upvotes: 0

Simon Steinberger
Simon Steinberger

Reputation: 6825

Take a look at EXIF and Pyxif in this Git repository: https://github.com/hMatoba

Both offer simple and pure Python methods for reading and modifying EXIF tags. In combination with PIL or Pillow, these libs are fantastic and they don't come with the overhead of other huge packages, such as pyexif2.

Upvotes: 1

Wesley
Wesley

Reputation: 1264

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

Upvotes: 16

user3171689
user3171689

Reputation: 303

You can use Pillow save Exif data

img.save(output, img_format, quality, exif=img_info.get('exif'))

Upvotes: -2

Related Questions