degal/image.py
author Tero Marttila <terom@fixme.fi>
Wed, 10 Jun 2009 23:33:28 +0300
changeset 84 891545a38a2b
parent 77 2a53c5ade434
child 85 7da934333469
permissions -rw-r--r--
change utils.LazyProperty to store the cached value using obj.__dict__
"""
    Per-image gallery state
"""

from __future__ import with_statement

import filesystem, render, html, format
from utils import lazy_load

import PIL.Image
from lib import EXIF

class Image (filesystem.File) :
    """
        An Image is a filesystem File that represents an image that can be thumbnailed, and handled.
    """

    def __init__ (self, *args, **kwargs) :
        """
            Initialize as an Image based on the given Node, linked with the given previous node
        """

        super(Image, self).__init__(*args, **kwargs)

        # links
        self.prev = None
        self.next = None

        # the .html file for this image
        self.html = self.parent.subfile(self.basename + '.html')

        # info
        self.title = self.name
        self.description = None

    @lazy_load
    def stat (self) :
        """
            Load and return the os.stat info for this file
        """

        return super(Image, self).stat()
    
    @lazy_load
    def image (self) :
        """
            Loads the image as a PIL.Image
        """
        
        # open it up
        return PIL.Image.open(self.path)

    @lazy_load
    def exif (self) :
        """
            Loads the EXIF data for the image and returns as a dict of EXIF tag names -> values.

            Returns None if no exif data was found
        """

        # load
        with self.open('rb') as fh :
            # XXX: details=False?
            exif = EXIF.process_file(fh)
            
        # empty dict -> no exif data
        if exif :
            return exif

        else :
            return None
    
    @lazy_load
    def metadata (self) :
        """
            Load and return the metadata for the image as a dictionary
        """

        # load stuff
        stat = self.stat
        exif = self.exif

        # XXX: avoid having to open the image?
        size = self.image.size
        
        # build
        return dict({
            "File name":        self.name,
            "Resolution":       "%dx%d" % size,
            "File size":        format.filesize(stat.st_size),
            "Last modified":    format.filetime(stat.st_mtime),
        }, **dict(
            (name, exif[tag]) for tag, name in self.config.exif_tags if exif and tag in exif
        ))
    
    @lazy_load
    def thumb (self) :
        """
            Load and update the thumbnail if needed
        """

        # renderer to use
        # XXX: get from elsewhere
        render_machine = self.config.get_renderer()

        # render if needed
        return render_machine.render_lazy(self,
            self.config.thumb_size, self.parent.thumb_dir.subnode(self.name)
        )
    
    @lazy_load
    def preview (self) :
        """
            Load and update the preview if needed
        """

        # renderer to use
        # XXX: get from elsewhere
        render_machine = self.config.get_renderer()

        return render_machine.render_lazy(self, 
            self.config.preview_size, self.parent.preview_dir.subnode(self.name)
        )