degal/image.py
changeset 57 8d06e0283b88
parent 44 533b7e8b5d3b
child 70 67dd32adf159
--- a/degal/image.py	Fri Jun 05 19:29:04 2009 +0300
+++ b/degal/image.py	Fri Jun 05 19:30:15 2009 +0300
@@ -1,15 +1,131 @@
-import os, os.path
+"""
+    Per-image gallery state
+"""
+
+from __future__ import with_statement
+
+import filesystem, render, html
 
 import PIL.Image
-
-import dexif
+from lib import EXIF
 
-import settings, utils, log
-from template import image as image_tpl
+class Image (filesystem.File) :
+    """
+        An Image is a filesystem File that represents an image that can be thumbnailed, and handled.
+    """
 
-"""
-    Handling induvidual Images
-"""
+    def __init__ (self, node, prev) :
+        """
+            Initialize as an Image based on the given Node, linked with the given previous node
+        """
+
+        super(Image, self).__init__(node)
+
+        # links
+        self.prev = prev
+        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-loading
+        self.img = None
+        self.exif = None
+        self.metadata = None
+        self.stat_data = None
+
+    def load_stat (self) :
+        """
+            Load and return the os.stat info for this file
+        """
+
+        if not self.stat_data :
+            self.stat_data = self.stat()
+
+        return self.stat_data
+
+    def load_image (self) :
+        """
+            Loads the image as a PIL.Image
+        """
+        
+        if not self.img :
+            # open it up
+            self.img = PIL.Image.open(self.path)
+
+        return self.img
+
+    def load_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
+        """
+
+        if self.exif is None :
+            # load
+            with self.open('rb') as fh :
+                # XXX: details=False?
+                self.exif = EXIF.process_file(fh)
+            
+        # empty dict -> no exif data
+        if self.exif :
+            return self.exif
+
+        else :
+            return None
+
+    def load_metadata (self) :
+        """
+            Load and return the metadata for the image as a dictionary
+        """
+
+        if not self.metadata :
+            # load stuff
+            stat = self.load_stat()
+            exif = self.load_exif()
+
+            # XXX: avoid having to open the image?
+            size = self.load_image().size
+            
+            # build
+            self.metadata = 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
+            ))
+
+        return self.metadata
+    
+    def render_image (self) :
+        """
+            Renders new thumbnails/previews for this image.
+            
+            Note: this does not check for the existance of the thumbs/previews subdirs!
+        """
+
+        # load origional image
+        img = self.load_image()
+
+        # renderer to use
+        # XXX: get from elsewhere
+        render_machine = self.config.get_renderer()
+
+        # lazy-render both thumb and preview
+        self.thumb = render_machine.render_lazy(self
+            self.config.thumb_size, self.parent.load_thumb_dir.subnode(self.name)
+        )
+
+        self.preview = render_machine.render_lazy(self, 
+            self.config.preview_size, self.parent.load_preview_dir.subnode(self.name)
+        )
 
 class Image (object) :
     def __init__ (self, dir, name) :
@@ -54,8 +170,8 @@
         # the ShortURL code for this image
         self.shorturl_code = None
 
-	# EXIF data
-	self.exif_data = {}
+        # EXIF data
+        self.exif_data = {}
 
         # what to use in the rendered templates, intended to be overridden by subclasses
         self.series_act = "add"
@@ -122,27 +238,27 @@
 
 
             image_tpl.render_to(self.html_path,
-                stylesheet_url             = self.dir.inRoot('style.css'),
-                title                      = self.title,
-                breadcrumb                 = self.breadcrumb(),
-                
-                prev                       = self.prev,
-                next                       = self.next,
-                img                        = self,
-                
-                description                = self.descr,
+                stylesheet_url              = self.dir.inRoot('style.css'),
+                title                       = self.title,
+                breadcrumb                  = self.breadcrumb(),
                 
-                filename                   = self.name,
-                img_size                   = self.img_size,
-                file_size                  = self.filesize,
-                timestamp                  = self.timestamp,
-		exif_data		   = self.exif_data,
+                prev                        = self.prev,
+                next                        = self.next,
+                img                         = self,
                 
-                shorturl                   = self.dir.inRoot('s', self.shorturl_code),
-                shorturl_code              = self.shorturl_code,
+                description                 = self.descr,
                 
-                series_url                 = self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
-                series_verb                = self.series_verb,
+                filename                    = self.name,
+                img_size                    = self.img_size,
+                file_size                   = self.filesize,
+                timestamp                   = self.timestamp,
+                exif_data                   = self.exif_data,
+                
+                shorturl                    = self.dir.inRoot('s', self.shorturl_code),
+                shorturl_code               = self.shorturl_code,
+                
+                series_url                  = self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
+                series_verb                 = self.series_verb,
             )   
     
     def __str__ (self) :