I have the following scenario:
I am sending an image from iPhone along with the EXIF information to my Pyhon socket server.
I need the image to be properly oriented based on the actual orientation when the image was taken. I know IOS always saves the image as Landscape Left and adds the actual orientation as EXIF field (EXIF.Image.Orientation).
I am reading the EXIF field to see the actual orientation. Then I am rotating the image using wxpython to the proper orientation.
I am using pyexiv2 for EXIF manipulation.
Issue: The EXIF information incluiding the thumbnails lost while rotating the image using wxpython.
What I did: I am reading the EXIF before rotating the image. I reset the orientation field in the EXIF. Then I am putting it back after rotation.
The problem:
The thumbnail inside the EXIF is not rotated. So, the image and thumbnail have different orientations.
Questions?
Is there any module other than PIL to rotate an image keeping its EXIF info?
Is there a separate EXIF field for thumbnail orientation?
Is there a way I can just rotate the Thumbnail alone?
Thanks for your help...
解决方案'''
Rotate Image
'''
import pyexiv2
import wx
import cStringIO
import os
def rotateImage(infile, device):
try:
# Read Metadata from the image
metadata = pyexiv2.metadata.ImageMetadata(infile)
metadata.read();
# Let's get the orientation
orientation = metadata.__getitem__("Exif.Image.Orientation")
orientation = int(str(orientation).split("=")[1][1:-1])
# Extract thumbnail
thumb = metadata.exif_thumbnail
angle = 0
# Check the orientation field in EXIF and rotate image accordingly
if device == "iPhone" or device == "iPad":
# Landscape Left : Do nothing
if orientation == ORIENTATION_NORMAL:
angle = 0
# Portrait Normal : Rotate Right
elif orientation == ORIENTATION_LEFT:
angle = -90
# Landscape Right : Rotate Right Twice
elif orientation == ORIENTATION_DOWN:
angle = 180
# Portrait Upside Down : Rotate Left
elif orientation == ORIENTATION_RIGHT:
angle = 90
# Resetting Exif field to normal
print "Resetting exif..."
orientation = 1
metadata.__setitem__("Exif.Image.Orientation", orientation)
# Rotate
if angle != 0:
# Just rotating the image based on the angle
print "Rotating image..."
angle = math.radians(angle)
img = wx.Image(infile, wx.BITMAP_TYPE_ANY)
img_centre = wx.Point( img.GetWidth()/2, img.GetHeight()/2 )
img = img.Rotate( angle, img_centre, True )
img.SaveFile(infile, wx.BITMAP_TYPE_JPEG)
# Create a stream out of the thumbnail and rotate it using wx
# Save the rotated image to a temporary file
print "Rotating thumbnail..."
t = wx.EmptyImage(100, 100)
thumbStream = cStringIO.StringIO(thumb.data)
t.LoadStream(thumbStream, wx.BITMAP_TYPE_ANY)
t_centre = wx.Point( t.GetWidth()/2, t.GetHeight()/2 )
t = t.Rotate( angle, t_centre, True )
t.SaveFile(infile + ".jpg", wx.BITMAP_TYPE_JPEG)
thumbStream.close()
# Read the rotated thumbnail and put it back in the rotated image
thumb.data = open(infile + ".jpg", "rb").read();
# Remove temporary file
os.remove(infile + ".jpg")
# Write back metadata
metadata.write();
except Exception, e:
print "Error rotating image... : " + str(e)