lib/image.py
author terom
Sun, 04 May 2008 18:23:03 +0000
changeset 33 4943047bfcb5
parent 28 70b6c13d084f
permissions -rw-r--r--
merged http://pajukanta.fi/temp/degal_exif_r33.tar.bz2 patch from Japsu
# DeGAL - A pretty simple web image gallery
# Copyright (C) 2007 Tero Marttila
# http://marttila.de/~terom/degal/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#

import os, os.path

import PIL.Image

import dexif

import settings, utils, log
from template import image as image_tpl
    
class Image (object) :
    def __init__ (self, dir, name) :
        # the image filename, e.g. DSC3948.JPG
        self.name = unicode(name)

        # the Folder object that we are in
        self.dir = dir
        
        # the relative path from the root to us
        self.path = dir.pathFor(self.name)

        # the basename+ext, e.g. DSCR3948, .JPG
        self.base_name, self.ext = os.path.splitext(self.name)
        
        # our user-friendly title
        self.title = self.name

        # our long-winded description
        self.descr = ''

        # the image before and after us, both may be None
        self.prev = self.next = None
        
        # the image-relative names for the html page, thumb and preview images
        self.html_name = self.name + ".html"
        self.thumb_name = utils.url_join(settings.THUMB_DIR, self.name)
        self.preview_name = utils.url_join(settings.PREVIEW_DIR, self.name)

        # the root-relative paths to the html page, thumb and preview images
        self.html_path = self.dir.pathFor(self.html_name)
        self.thumb_path = self.dir.pathFor(settings.THUMB_DIR, self.name)
        self.preview_path = self.dir.pathFor(settings.PREVIEW_DIR, self.name)        
        
        #
        # Figured out after prepare
        #

        # (w, h) tuple
        self.img_size = None
        
        # the ShortURL code for this image
        self.shorturl_code = None

	# EXIF data
	self.exif_data = {}

        # what to use in the rendered templates, intended to be overridden by subclasses
        self.series_act = "add"
        self.series_verb = "Add to"
    
    def getObjInfo (self) :
        """
            Metadata for shorturl2.db
        """
        return 'img', self.dir.path, self.name

    def breadcrumb (self) :
        """
            Returns a [(fname, title)] list of this image's parents
       """
        
        return self.dir.breadcrumb(forImg=self) + [(self.html_name, self.title)]

    def render (self) :
        """
            Write out the .html file
        """
        
        # stat the image file to get the filesize and mtime
        st = os.stat(self.path)

        self.filesize = st.st_size
        self.timestamp = st.st_mtime
        
        # open the image in PIL to get image attributes + generate thumbnails
        img = PIL.Image.open(self.path)

        self.img_size = img.size

        for out_path, geom in ((self.thumb_path, settings.THUMB_GEOM), (self.preview_path, settings.PREVIEW_GEOM)) :
            # if it doesn't exist, or it's older than the image itself, generate
            if utils.mtime(out_path) < self.timestamp :
                log.info("render [%sx%s]", geom[0], geom[1], wait=True)
                
                # XXX: is this the most efficient way to do this? It seems slow
                out_img = img.copy()
                out_img.thumbnail(geom, resample=True)
                out_img.save(out_path)

                log.done()
        
        # look for the metadata file
        title_path = self.dir.pathFor(self.base_name + '.txt')
        
        self.title, self.descr = utils.readTitleDescr(title_path)
        
        if not self.title :
            self.title = self.name
        
        if utils.mtime(self.html_path) < self.timestamp :
            log.info("render %s.html", self.name)

            # parse the exif data from the file
            try :
                    self.exif_data = dexif.parse_exif(self.path)
            except dexif.ExifError, message:
                    log.warning("Reading EXIF data for %s failed: %s" % (self.filename, message))
                    self.exif_data = {}


            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,
                
                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) :
        return "Image `%s' in `%s'" % (self.name, self.dir.path)