Bläddra i källkod

Read Exif from image to rotate image correctly

Kentaro Wada 6 år sedan
förälder
incheckning
f1600ce40e
1 ändrade filer med 56 tillägg och 14 borttagningar
  1. 56 14
      labelme/app.py

+ 56 - 14
labelme/app.py

@@ -5,8 +5,9 @@ import os.path as osp
 import re
 import webbrowser
 
+import PIL.ExifTags
 import PIL.Image
-
+import PIL.ImageOps
 from qtpy import QtCore
 from qtpy.QtCore import Qt
 from qtpy import QtGui
@@ -1131,16 +1132,12 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
             self.fillColor = QtGui.QColor(*self.labelFile.fillColor)
             self.otherData = self.labelFile.otherData
         else:
-            # Load image:
-            # read data first and store for saving into label file.
-            self.imageData = read(filename, None)
-            if self.imageData is not None:
-                # the filename is image not JSON
+            self.imageData = self.loadImageFile(filename)
+            if self.imageData:
                 self.imagePath = filename
-                if QtGui.QImage.fromData(self.imageData).isNull():
-                    self.imageData = self.convertImageDataToPng(self.imageData)
             self.labelFile = None
         image = QtGui.QImage.fromData(self.imageData)
+
         if image.isNull():
             formats = ['*.{}'.format(fmt.data().decode())
                        for fmt in QtGui.QImageReader.supportedImageFormats()]
@@ -1173,6 +1170,20 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
         self.status("Loaded %s" % osp.basename(str(filename)))
         return True
 
+    def loadImageFile(self, filename):
+        try:
+            image_pil = PIL.Image.open(filename)
+        except IOError:
+            return
+
+        # apply orientation to image according to exif
+        image_pil = apply_exif_orientation(image_pil)
+
+        with io.BytesIO() as f:
+            image_pil.save(f, format='PNG')
+            f.seek(0)
+            return f.read()
+
     def resizeEvent(self, event):
         if self.canvas and not self.image.isNull()\
            and self.zoomMode != self.MANUAL_ZOOM:
@@ -1549,9 +1560,40 @@ class MainWindow(QtWidgets.QMainWindow, WindowMixin):
         return images
 
 
-def read(filename, default=None):
-    try:
-        with open(filename, 'rb') as f:
-            return f.read()
-    except Exception:
-        return default
+def apply_exif_orientation(image):
+    exif = image._getexif()
+    if exif is None:
+        return image
+
+    exif = {
+        PIL.ExifTags.TAGS[k]: v
+        for k, v in exif.items()
+        if k in PIL.ExifTags.TAGS
+    }
+
+    orientation = exif['Orientation']
+
+    if orientation == 1:
+        # do nothing
+        return image
+    elif orientation == 2:
+        # left-to-right mirror
+        return PIL.ImageOps.mirror(image)
+    elif orientation == 3:
+        # rotate 180
+        return image.transpose(PIL.Image.ROTATE_180)
+    elif orientation == 4:
+        # top-to-bottom mirror
+        return PIL.ImageOps.flip(image)
+    elif orientation == 5:
+        # top-to-left mirror
+        return PIL.ImageOps.mirror(image.transpose(PIL.Image.ROTATE_270))
+    elif orientation == 6:
+        # rotate 270
+        return image.transpose(PIL.Image.ROTATE_270)
+    elif orientation == 7:
+        # top-to-right mirror
+        return PIL.ImageOps.mirror(image.transpose(PIL.Image.ROTATE_90))
+    elif orientation == 8:
+        # rotate 90
+        return image.transpose(PIL.Image.ROTATE_90)