degal/thumbnail.py
author Tero Marttila <terom@fixme.fi>
Mon, 15 Jun 2009 00:23:55 +0300
changeset 122 292aaba6d6ec
parent 116 2d3721b9ffd0
child 123 31c4a328ef96
permissions -rw-r--r--
auto-orientation, although no mirroring support yet
"""
    State for thumbnails; derivates of Images
"""

import filesystem

import PIL.Image

class Thumbnail (filesystem.File) :
    """
        A Thumbnail is a derivate of an Image, usually resized to some other size.
    """

    def __init__ (self, image, subdir, target_size) :
        """
            Initialize to link against the given `image`.
            
            `subdir` specifies the directory to store this thumbnail in.
            `target_size` determines the target resolution of the output thumbnail.
        """

        # our file path, image name inside of the given subdir
        super(Thumbnail, self).__init__(subdir, image.fsname)

        # store
        self.image = image
        self.target_size = target_size

    def stale (self) :
        """
            Tests if this thumbnail is stale
        """
        
        if self.image.older_than(self) :
            # both exist and this is newer
            return False
        
        else :
            # this thumb doesn't exist or is older
            return True
    
    @property
    def size (self) :
        """
            Compute the *real* size of this thumbnail, from the image's actual size and our target size.

            Preserves the aspect ratio etc.
        """
        
        # real image size
        img_width, img_height = self.image.img_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)
            width = thumb_width
        
        elif img_height > thumb_height :
            width = max(img_width * thumb_height / img_height, 1)
            height = thumb_height
        
        return width, height 
    
    def resize (self, img) :
        """
            Resize the give image as needed.
        """

        return img.resize(self.size, resample=PIL.Image.ANTIALIAS)
    
    def auto_orient (self, img, orient_info) :
        """
            Automatically orient the image using the given orientation info.
        """
        
        # unpack
        mirroring, rotation = orient_info

        if mirroring :
            # XXX
            pass

        if rotation :
            # 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) :
        """
            Render new output thumbnail.
        """

        # start with origional image
        img = self.image.img

        # create resized copy of main image, using our size
        img = self.resize(img)

        # got orientation info?
        if self.image.orientation :
            img = self.auto_orient(img, self.image.orientation)

        # write it out
        img.save(self.path)