terom@85: """ terom@85: State for thumbnails; derivates of Images terom@85: """ terom@85: terom@85: import filesystem terom@85: terom@85: import PIL.Image terom@85: terom@85: class Thumbnail (filesystem.File) : terom@85: """ terom@85: A Thumbnail is a derivate of an Image, usually resized to some other size. terom@85: """ terom@85: terom@115: def __init__ (self, image, subdir, target_size) : terom@85: """ terom@85: Initialize to link against the given `image`. terom@85: terom@85: `subdir` specifies the directory to store this thumbnail in. terom@115: `target_size` determines the target resolution of the output thumbnail. terom@85: """ terom@85: terom@95: # our file path, image name inside of the given subdir terom@95: super(Thumbnail, self).__init__(subdir, image.fsname) terom@85: terom@85: # store terom@85: self.image = image terom@115: self.target_size = target_size terom@85: terom@85: def stale (self) : terom@85: """ terom@85: Tests if this thumbnail is stale terom@85: """ terom@85: terom@95: if self.image.older_than(self) : terom@95: # both exist and this is newer terom@95: return False terom@95: terom@95: else : terom@95: # this thumb doesn't exist or is older terom@95: return True terom@115: terom@115: @property terom@115: def size (self) : terom@115: """ terom@115: Compute the *real* size of this thumbnail, from the image's actual size and our target size. terom@115: terom@115: Preserves the aspect ratio etc. terom@115: """ terom@115: terom@115: # real image size terom@115: img_width, img_height = self.image.img_size terom@115: terom@115: # target size terom@115: thumb_width, thumb_height = self.target_size terom@115: terom@115: # calc new size, preserving aspect ratio terom@115: if img_width > thumb_width : terom@115: height = max(img_height * thumb_width / img_width, 1) terom@115: width = thumb_width terom@115: terom@116: elif img_height > thumb_height : terom@115: width = max(img_width * thumb_height / img_height, 1) terom@115: height = thumb_height terom@115: terom@115: return width, height terom@122: terom@122: def resize (self, img) : terom@122: """ terom@122: Resize the give image as needed. terom@122: """ terom@122: terom@122: return img.resize(self.size, resample=PIL.Image.ANTIALIAS) terom@122: terom@122: def auto_orient (self, img, orient_info) : terom@122: """ terom@122: Automatically orient the image using the given orientation info. terom@122: """ terom@122: terom@122: # unpack terom@122: mirroring, rotation = orient_info terom@122: terom@122: if mirroring : terom@122: # XXX terom@122: pass terom@122: terom@122: if rotation : terom@122: # since these are in steps of 90 degrees, it should keep the right size terom@122: # but gah, PIL wants these as counter-clockwise! terom@122: img = img.rotate(360 - rotation) terom@122: terom@122: # ok terom@122: return img terom@85: terom@85: def update (self) : terom@85: """ terom@115: Render new output thumbnail. terom@85: """ terom@85: terom@122: # start with origional image terom@122: img = self.image.img terom@122: terom@115: # create resized copy of main image, using our size terom@122: img = self.resize(img) terom@122: terom@122: # got orientation info? terom@122: if self.image.orientation : terom@122: img = self.auto_orient(img, self.image.orientation) terom@85: terom@115: # write it out terom@122: img.save(self.path) terom@95: