fix rotated size of auto-oriented thumbnails, and throw some code at mirroring - untested
authorTero Marttila <terom@fixme.fi>
Mon, 15 Jun 2009 01:36:58 +0300
changeset 125 74f135774567
parent 124 cac613118e75
child 126 2c0b427e5bfd
fix rotated size of auto-oriented thumbnails, and throw some code at mirroring - untested
degal/image.py
degal/thumbnail.py
--- a/degal/image.py	Mon Jun 15 01:36:15 2009 +0300
+++ b/degal/image.py	Mon Jun 15 01:36:58 2009 +0300
@@ -125,7 +125,7 @@
     
     def cleanup (self) :
         """
-            Drop some cached heavy values
+            Drop some memory-intensive cached values
         """
 
         del self.img
--- a/degal/thumbnail.py	Mon Jun 15 01:36:15 2009 +0300
+++ b/degal/thumbnail.py	Mon Jun 15 01:36:58 2009 +0300
@@ -2,7 +2,7 @@
     State for thumbnails; derivates of Images
 """
 
-import filesystem
+import filesystem, exif
 
 import PIL.Image
 
@@ -39,27 +39,27 @@
             # this thumb doesn't exist or is older
             return True
     
-    @property
-    def size (self) :
+    def calcsize (self, size) :
         """
-            Compute the *real* size of this thumbnail, from the image's actual size and our target size.
+            Compute the *real* size of this thumbnail, from the give actual size and our target size.
 
             Preserves the aspect ratio etc.
         """
         
-        # real image size
-        img_width, img_height = self.image.img_size
+        # initial image size
+        width, height = size
 
         # target size
         thumb_width, thumb_height = self.target_size
 
         # calc new size, preserving aspect ratio
-        if img_width > thumb_width : 
-            height = max(img_height * thumb_width / img_width, 1)
+        # calculations ripped from PIL.Image.thumbnail :)
+        if width > thumb_width : 
+            height = max(height * thumb_width / width, 1)
             width = thumb_width
-        
-        elif img_height > thumb_height :
-            width = max(img_width * thumb_height / img_height, 1)
+ 
+        if height > thumb_height :
+            width = max(width * thumb_height / height, 1)
             height = thumb_height
         
         return width, height 
@@ -67,29 +67,55 @@
     ## operations
     def resize (self, img) :
         """
-            Resize the give image as needed.
+            Resize the given image as needed.
         """
 
-        return img.resize(self.size, resample=PIL.Image.ANTIALIAS)
+        return img.resize(self.calcsize(img.size), resample=PIL.Image.ANTIALIAS)
     
-    def auto_orient (self, img, orient_info) :
+    def transform (self, img, orient_info) :
         """
-            Automatically orient the image using the given orientation info.
+            Transform this image into the output version, resizing, rotating and mirroring in a single step.
         """
         
+        # get sizes
+        img_width, img_height = img_size = img.size
+        
         # unpack
         mirroring, rotation = orient_info
-
+ 
         if mirroring :
-            # XXX: does anyone actually use this?
-            pass
+            # XXX: does anyone actually use this? Untested
+            # interaction with rotate is probably wrong
+            p0, p1 = {
+                exif.MIRROR_HORIZONTAL: ((0, img_height), (img_width, 0)),
+                exif.MIRROR_VERTICAL:   ((img_width, 0), (0, img_height)),
+            }
+
+        if rotation in (exif.ROTATE_90, exif.ROTATE_270) :
+            # flip the dimensions to take rotate into account
+            img_size = img_height, img_width
+
+        # calc new size
+        thumb_size = self.calcsize(img_size)
+ 
+        if rotation in (exif.ROTATE_90, exif.ROTATE_270) :
+            # flip the dimensions back before rotate
+            thumb_size = thumb_size[1], thumb_size[0]
+       
+        if mirroring :
+            # perform the transform, can't use ANTIALIAS here :/
+            img = img.transform(thumb_size, PIL.Image.EXTENT, p0 + p1, PIL.Image.NEAREST)
+
+        else :
+            # resize with ANTIALIAS
+            img = img.resize(thumb_size, resample=PIL.Image.ANTIALIAS)
 
         if rotation :
+            # transform can't rotate
             # since these are in steps of 90 degrees, it should keep the right size
             # but gah, PIL wants these as counter-clockwise!
             img = img.rotate(360 - rotation)
         
-        # ok
         return img
 
     def update (self) :
@@ -100,12 +126,13 @@
         # start with origional image
         img = self.image.img
 
-        # create resized copy of main image, using our size
-        img = self.resize(img)
+        if self.image.orientation and (self.image.orientation[0] or self.image.orientation[1]) :
+            # rotate
+            img = self.transform(img, self.image.orientation)
 
-        # got orientation info?
-        if self.image.orientation :
-            img = self.auto_orient(img, self.image.orientation)
+        else :
+            # just create resized copy of main image, using our size
+            img = self.resize(img)
 
         # write it out
         img.save(self.path)