misc. fixes
"""
Per-image gallery state
"""
from __future__ import with_statement
import filesystem, render, html
from utils import lazy_load
import PIL.Image
from lib import EXIF
class Image (filesystem.File) :
"""
An Image is a filesystem File that represents an image that can be thumbnailed, and handled.
"""
def __init__ (self, *args, **kwargs) :
"""
Initialize as an Image based on the given Node, linked with the given previous node
"""
super(Image, self).__init__(node)
# links
self.prev = None
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
@lazy_load
def thumb (self) :
"""
Load and update the thumbnail if needed
"""
# renderer to use
# XXX: get from elsewhere
render_machine = self.config.get_renderer()
# render if needed
return render_machine.render_lazy(self,
self.config.thumb_size, self.parent.load_thumb_dir.subnode(self.name)
)
@lazy_load
def preview (self) :
"""
Load and update the preview if needed
"""
# renderer to use
# XXX: get from elsewhere
render_machine = self.config.get_renderer()
return render_machine.render_lazy(self,
self.config.preview_size, self.parent.load_preview_dir.subnode(self.name)
)