degal/image.py
branchuse-distutils
changeset 41 3b1579a7bffb
parent 33 4943047bfcb5
child 44 533b7e8b5d3b
equal deleted inserted replaced
40:373392025533 41:3b1579a7bffb
       
     1 # DeGAL - A pretty simple web image gallery
       
     2 # Copyright (C) 2007 Tero Marttila
       
     3 # http://marttila.de/~terom/degal/
       
     4 #
       
     5 # This program is free software; you can redistribute it and/or modify
       
     6 # it under the terms of the GNU General Public License as published by
       
     7 # the Free Software Foundation; either version 2 of the License, or
       
     8 # (at your option) any later version.
       
     9 #
       
    10 # This program is distributed in the hope that it will be useful,
       
    11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13 # GNU General Public License for more details.
       
    14 #
       
    15 # You should have received a copy of the GNU General Public License
       
    16 # along with this program; if not, write to the
       
    17 # Free Software Foundation, Inc.,
       
    18 # 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
       
    19 #
       
    20 
       
    21 import os, os.path
       
    22 
       
    23 import PIL.Image
       
    24 
       
    25 import dexif
       
    26 
       
    27 import settings, utils, log
       
    28 from template import image as image_tpl
       
    29     
       
    30 class Image (object) :
       
    31     def __init__ (self, dir, name) :
       
    32         # the image filename, e.g. DSC3948.JPG
       
    33         self.name = unicode(name)
       
    34 
       
    35         # the Folder object that we are in
       
    36         self.dir = dir
       
    37         
       
    38         # the relative path from the root to us
       
    39         self.path = dir.pathFor(self.name)
       
    40 
       
    41         # the basename+ext, e.g. DSCR3948, .JPG
       
    42         self.base_name, self.ext = os.path.splitext(self.name)
       
    43         
       
    44         # our user-friendly title
       
    45         self.title = self.name
       
    46 
       
    47         # our long-winded description
       
    48         self.descr = ''
       
    49 
       
    50         # the image before and after us, both may be None
       
    51         self.prev = self.next = None
       
    52         
       
    53         # the image-relative names for the html page, thumb and preview images
       
    54         self.html_name = self.name + ".html"
       
    55         self.thumb_name = utils.url_join(settings.THUMB_DIR, self.name)
       
    56         self.preview_name = utils.url_join(settings.PREVIEW_DIR, self.name)
       
    57 
       
    58         # the root-relative paths to the html page, thumb and preview images
       
    59         self.html_path = self.dir.pathFor(self.html_name)
       
    60         self.thumb_path = self.dir.pathFor(settings.THUMB_DIR, self.name)
       
    61         self.preview_path = self.dir.pathFor(settings.PREVIEW_DIR, self.name)        
       
    62         
       
    63         #
       
    64         # Figured out after prepare
       
    65         #
       
    66 
       
    67         # (w, h) tuple
       
    68         self.img_size = None
       
    69         
       
    70         # the ShortURL code for this image
       
    71         self.shorturl_code = None
       
    72 
       
    73 	# EXIF data
       
    74 	self.exif_data = {}
       
    75 
       
    76         # what to use in the rendered templates, intended to be overridden by subclasses
       
    77         self.series_act = "add"
       
    78         self.series_verb = "Add to"
       
    79     
       
    80     def getObjInfo (self) :
       
    81         """
       
    82             Metadata for shorturl2.db
       
    83         """
       
    84         return 'img', self.dir.path, self.name
       
    85 
       
    86     def breadcrumb (self) :
       
    87         """
       
    88             Returns a [(fname, title)] list of this image's parents
       
    89        """
       
    90         
       
    91         return self.dir.breadcrumb(forImg=self) + [(self.html_name, self.title)]
       
    92 
       
    93     def render (self) :
       
    94         """
       
    95             Write out the .html file
       
    96         """
       
    97         
       
    98         # stat the image file to get the filesize and mtime
       
    99         st = os.stat(self.path)
       
   100 
       
   101         self.filesize = st.st_size
       
   102         self.timestamp = st.st_mtime
       
   103         
       
   104         # open the image in PIL to get image attributes + generate thumbnails
       
   105         img = PIL.Image.open(self.path)
       
   106 
       
   107         self.img_size = img.size
       
   108 
       
   109         for out_path, geom in ((self.thumb_path, settings.THUMB_GEOM), (self.preview_path, settings.PREVIEW_GEOM)) :
       
   110             # if it doesn't exist, or it's older than the image itself, generate
       
   111             if utils.mtime(out_path) < self.timestamp :
       
   112                 log.info("render [%sx%s]", geom[0], geom[1], wait=True)
       
   113                 
       
   114                 # XXX: is this the most efficient way to do this? It seems slow
       
   115                 out_img = img.copy()
       
   116                 out_img.thumbnail(geom, resample=True)
       
   117                 out_img.save(out_path)
       
   118 
       
   119                 log.done()
       
   120         
       
   121         # look for the metadata file
       
   122         title_path = self.dir.pathFor(self.base_name + '.txt')
       
   123         
       
   124         self.title, self.descr = utils.readTitleDescr(title_path)
       
   125         
       
   126         if not self.title :
       
   127             self.title = self.name
       
   128         
       
   129         if utils.mtime(self.html_path) < self.timestamp :
       
   130             log.info("render %s.html", self.name)
       
   131 
       
   132             # parse the exif data from the file
       
   133             try :
       
   134                     self.exif_data = dexif.parse_exif(self.path)
       
   135             except dexif.ExifError, message:
       
   136                     log.warning("Reading EXIF data for %s failed: %s" % (self.filename, message))
       
   137                     self.exif_data = {}
       
   138 
       
   139 
       
   140             image_tpl.render_to(self.html_path,
       
   141                 stylesheet_url             = self.dir.inRoot('style.css'),
       
   142                 title                      = self.title,
       
   143                 breadcrumb                 = self.breadcrumb(),
       
   144                 
       
   145                 prev                       = self.prev,
       
   146                 next                       = self.next,
       
   147                 img                        = self,
       
   148                 
       
   149                 description                = self.descr,
       
   150                 
       
   151                 filename                   = self.name,
       
   152                 img_size                   = self.img_size,
       
   153                 file_size                  = self.filesize,
       
   154                 timestamp                  = self.timestamp,
       
   155 		exif_data		   = self.exif_data,
       
   156                 
       
   157                 shorturl                   = self.dir.inRoot('s', self.shorturl_code),
       
   158                 shorturl_code              = self.shorturl_code,
       
   159                 
       
   160                 series_url                 = self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
       
   161                 series_verb                = self.series_verb,
       
   162             )   
       
   163     
       
   164     def __str__ (self) :
       
   165         return "Image `%s' in `%s'" % (self.name, self.dir.path)
       
   166