terom@57: """ terom@57: Per-image gallery state terom@57: """ terom@57: terom@57: from __future__ import with_statement terom@57: terom@57: import filesystem, render, html terom@12: terom@12: import PIL.Image terom@57: from lib import EXIF terom@33: terom@57: class Image (filesystem.File) : terom@57: """ terom@57: An Image is a filesystem File that represents an image that can be thumbnailed, and handled. terom@57: """ terom@44: terom@57: def __init__ (self, node, prev) : terom@57: """ terom@57: Initialize as an Image based on the given Node, linked with the given previous node terom@57: """ terom@57: terom@57: super(Image, self).__init__(node) terom@57: terom@57: # links terom@57: self.prev = prev terom@57: self.next = None terom@57: terom@57: # the .html file for this image terom@57: self.html = self.parent.subfile(self.basename + '.html') terom@57: terom@57: # info terom@57: self.title = self.name terom@57: self.description = None terom@57: terom@57: # lazy-loading terom@57: self.img = None terom@57: self.exif = None terom@57: self.metadata = None terom@57: self.stat_data = None terom@57: terom@57: def load_stat (self) : terom@57: """ terom@57: Load and return the os.stat info for this file terom@57: """ terom@57: terom@57: if not self.stat_data : terom@57: self.stat_data = self.stat() terom@57: terom@57: return self.stat_data terom@57: terom@57: def load_image (self) : terom@57: """ terom@57: Loads the image as a PIL.Image terom@57: """ terom@57: terom@57: if not self.img : terom@57: # open it up terom@57: self.img = PIL.Image.open(self.path) terom@57: terom@57: return self.img terom@57: terom@57: def load_exif (self) : terom@57: """ terom@57: Loads the EXIF data for the image and returns as a dict of EXIF tag names -> values. terom@57: terom@57: Returns None if no exif data was found terom@57: """ terom@57: terom@57: if self.exif is None : terom@57: # load terom@57: with self.open('rb') as fh : terom@57: # XXX: details=False? terom@57: self.exif = EXIF.process_file(fh) terom@57: terom@57: # empty dict -> no exif data terom@57: if self.exif : terom@57: return self.exif terom@57: terom@57: else : terom@57: return None terom@57: terom@57: def load_metadata (self) : terom@57: """ terom@57: Load and return the metadata for the image as a dictionary terom@57: """ terom@57: terom@57: if not self.metadata : terom@57: # load stuff terom@57: stat = self.load_stat() terom@57: exif = self.load_exif() terom@57: terom@57: # XXX: avoid having to open the image? terom@57: size = self.load_image().size terom@57: terom@57: # build terom@57: self.metadata = dict({ terom@57: "File name": self.name, terom@57: "Resolution": "%dx%d" % size, terom@57: "File size": format.filesize(stat.st_size), terom@57: "Last modified": format.filetime(stat.st_mtime), terom@57: }, **dict( terom@57: (name, exif[tag]) for tag, name in self.config.exif_tags if exif and tag in exif terom@57: )) terom@57: terom@57: return self.metadata terom@57: terom@70: @lazy_load terom@70: def thumb (self) : terom@57: """ terom@70: Load and update the thumbnail if needed terom@57: """ terom@57: terom@57: # renderer to use terom@57: # XXX: get from elsewhere terom@57: render_machine = self.config.get_renderer() terom@57: terom@70: # render if needed terom@70: return render_machine.render_lazy(self terom@57: self.config.thumb_size, self.parent.load_thumb_dir.subnode(self.name) terom@57: ) terom@70: terom@70: @lazy_load terom@70: def preview (self) : terom@70: """ terom@70: Load and update the preview if needed terom@70: """ terom@57: terom@70: # renderer to use terom@70: # XXX: get from elsewhere terom@70: render_machine = self.config.get_renderer() terom@70: terom@70: return render_machine.render_lazy(self, terom@57: self.config.preview_size, self.parent.load_preview_dir.subnode(self.name) terom@57: ) terom@44: