--- 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)