degal/image.py
changeset 70 67dd32adf159
parent 57 8d06e0283b88
child 76 e22d9f699081
equal deleted inserted replaced
69:5b53fe294034 70:67dd32adf159
   102                 (name, exif[tag]) for tag, name in self.config.exif_tags if exif and tag in exif
   102                 (name, exif[tag]) for tag, name in self.config.exif_tags if exif and tag in exif
   103             ))
   103             ))
   104 
   104 
   105         return self.metadata
   105         return self.metadata
   106     
   106     
   107     def render_image (self) :
   107     @lazy_load
       
   108     def thumb (self) :
   108         """
   109         """
   109             Renders new thumbnails/previews for this image.
   110             Load and update the thumbnail if needed
   110             
       
   111             Note: this does not check for the existance of the thumbs/previews subdirs!
       
   112         """
   111         """
   113 
       
   114         # load origional image
       
   115         img = self.load_image()
       
   116 
   112 
   117         # renderer to use
   113         # renderer to use
   118         # XXX: get from elsewhere
   114         # XXX: get from elsewhere
   119         render_machine = self.config.get_renderer()
   115         render_machine = self.config.get_renderer()
   120 
   116 
   121         # lazy-render both thumb and preview
   117         # render if needed
   122         self.thumb = render_machine.render_lazy(self
   118         return render_machine.render_lazy(self
   123             self.config.thumb_size, self.parent.load_thumb_dir.subnode(self.name)
   119             self.config.thumb_size, self.parent.load_thumb_dir.subnode(self.name)
   124         )
   120         )
       
   121     
       
   122     @lazy_load
       
   123     def preview (self) :
       
   124         """
       
   125             Load and update the preview if needed
       
   126         """
   125 
   127 
   126         self.preview = render_machine.render_lazy(self, 
   128         # renderer to use
       
   129         # XXX: get from elsewhere
       
   130         render_machine = self.config.get_renderer()
       
   131 
       
   132         return render_machine.render_lazy(self, 
   127             self.config.preview_size, self.parent.load_preview_dir.subnode(self.name)
   133             self.config.preview_size, self.parent.load_preview_dir.subnode(self.name)
   128         )
   134         )
   129 
   135 
   130 class Image (object) :
       
   131     def __init__ (self, dir, name) :
       
   132         # the image filename, e.g. DSC3948.JPG
       
   133         self.name = unicode(name)
       
   134 
       
   135         # the Folder object that we are in
       
   136         self.dir = dir
       
   137         
       
   138         # the relative path from the root to us
       
   139         self.path = dir.pathFor(self.name)
       
   140 
       
   141         # the basename+ext, e.g. DSCR3948, .JPG
       
   142         self.base_name, self.ext = os.path.splitext(self.name)
       
   143         
       
   144         # our user-friendly title
       
   145         self.title = self.name
       
   146 
       
   147         # our long-winded description
       
   148         self.descr = ''
       
   149 
       
   150         # the image before and after us, both may be None
       
   151         self.prev = self.next = None
       
   152         
       
   153         # the image-relative names for the html page, thumb and preview images
       
   154         self.html_name = self.name + ".html"
       
   155         self.thumb_name = utils.url_join(settings.THUMB_DIR, self.name)
       
   156         self.preview_name = utils.url_join(settings.PREVIEW_DIR, self.name)
       
   157 
       
   158         # the root-relative paths to the html page, thumb and preview images
       
   159         self.html_path = self.dir.pathFor(self.html_name)
       
   160         self.thumb_path = self.dir.pathFor(settings.THUMB_DIR, self.name)
       
   161         self.preview_path = self.dir.pathFor(settings.PREVIEW_DIR, self.name)        
       
   162         
       
   163         #
       
   164         # Figured out after prepare
       
   165         #
       
   166 
       
   167         # (w, h) tuple
       
   168         self.img_size = None
       
   169         
       
   170         # the ShortURL code for this image
       
   171         self.shorturl_code = None
       
   172 
       
   173         # EXIF data
       
   174         self.exif_data = {}
       
   175 
       
   176         # what to use in the rendered templates, intended to be overridden by subclasses
       
   177         self.series_act = "add"
       
   178         self.series_verb = "Add to"
       
   179     
       
   180     def getObjInfo (self) :
       
   181         """
       
   182             Metadata for shorturl2.db
       
   183         """
       
   184         return 'img', self.dir.path, self.name
       
   185 
       
   186     def breadcrumb (self) :
       
   187         """
       
   188             Returns a [(fname, title)] list of this image's parents
       
   189        """
       
   190         
       
   191         return self.dir.breadcrumb(forImg=self) + [(self.html_name, self.title)]
       
   192 
       
   193     def render (self) :
       
   194         """
       
   195             Write out the .html file
       
   196         """
       
   197         
       
   198         # stat the image file to get the filesize and mtime
       
   199         st = os.stat(self.path)
       
   200 
       
   201         self.filesize = st.st_size
       
   202         self.timestamp = st.st_mtime
       
   203         
       
   204         # open the image in PIL to get image attributes + generate thumbnails
       
   205         img = PIL.Image.open(self.path)
       
   206 
       
   207         self.img_size = img.size
       
   208 
       
   209         for out_path, geom in ((self.thumb_path, settings.THUMB_GEOM), (self.preview_path, settings.PREVIEW_GEOM)) :
       
   210             # if it doesn't exist, or it's older than the image itself, generate
       
   211             if utils.mtime(out_path) < self.timestamp :
       
   212                 log.info("render [%sx%s]", geom[0], geom[1], wait=True)
       
   213                 
       
   214                 # XXX: is this the most efficient way to do this? It seems slow
       
   215                 out_img = img.copy()
       
   216                 out_img.thumbnail(geom, resample=True)
       
   217                 out_img.save(out_path)
       
   218 
       
   219                 log.done()
       
   220         
       
   221         # look for the metadata file
       
   222         title_path = self.dir.pathFor(self.base_name + '.txt')
       
   223         
       
   224         self.title, self.descr = utils.readTitleDescr(title_path)
       
   225         
       
   226         if not self.title :
       
   227             self.title = self.name
       
   228         
       
   229         if utils.mtime(self.html_path) < self.timestamp :
       
   230             log.info("render %s.html", self.name)
       
   231 
       
   232             # parse the exif data from the file
       
   233             try :
       
   234                     self.exif_data = dexif.parse_exif(self.path)
       
   235             except dexif.ExifError, message:
       
   236                     log.warning("Reading EXIF data for %s failed: %s" % (self.filename, message))
       
   237                     self.exif_data = {}
       
   238 
       
   239 
       
   240             image_tpl.render_to(self.html_path,
       
   241                 stylesheet_url              = self.dir.inRoot('style.css'),
       
   242                 title                       = self.title,
       
   243                 breadcrumb                  = self.breadcrumb(),
       
   244                 
       
   245                 prev                        = self.prev,
       
   246                 next                        = self.next,
       
   247                 img                         = self,
       
   248                 
       
   249                 description                 = self.descr,
       
   250                 
       
   251                 filename                    = self.name,
       
   252                 img_size                    = self.img_size,
       
   253                 file_size                   = self.filesize,
       
   254                 timestamp                   = self.timestamp,
       
   255                 exif_data                   = self.exif_data,
       
   256                 
       
   257                 shorturl                    = self.dir.inRoot('s', self.shorturl_code),
       
   258                 shorturl_code               = self.shorturl_code,
       
   259                 
       
   260                 series_url                  = self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
       
   261                 series_verb                 = self.series_verb,
       
   262             )   
       
   263     
       
   264     def __str__ (self) :
       
   265         return "Image `%s' in `%s'" % (self.name, self.dir.path)
       
   266