move .config from filesystem to gallery/folder/image, rename degal_dir to app_dir
"""
Per-image gallery state
"""
import filesystem, format, thumbnail, exif, utils
from utils import lazy_load
import PIL.Image
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__(*args, **kwargs)
# use config from our folder
self.config = self.parent.config
# links
self.prev = None
self.next = None
# the .html file for this image
# XXX: keep .jpg/etc file extension?
self.html = self.parent.subfile(self.basename + '.html')
# our preview/thumbnail
self.preview = thumbnail.Thumbnail(self, self.parent.preview_dir, self.config.preview_size)
self.thumb = thumbnail.Thumbnail(self, self.parent.thumb_dir, self.config.thumb_size)
# info
self.title = self.name
self.description = None
@lazy_load
def img (self) :
"""
Loads the image as a PIL.Image
"""
# open it up
return PIL.Image.open(self.path)
@property
def img_size (self) :
"""
Returns the pixel (width, height) resolution tuple of this image.
"""
return self.img.size
@lazy_load
def exif (self) :
"""
Loads the ExifHandler object for this image.
Returns None if no exif data was found
"""
# look up using exif
return exif.load(self.config, self)
@lazy_load
def orientation (self) :
"""
Loads the orientation of this image as a (mirroring, rotation) tuple, or None, if the information is not available.
"""
if self.config.with_exif and self.exif :
# try and find it
return self.exif.get_orientation()
else :
# no exif data
return None
@lazy_load
def metadata (self) :
"""
Load and return the metadata for the image as a dictionary
"""
# load stuff
stat = self.stat()
# XXX: avoid having to open the image?
size = self.img_size
# build
metadata = [
("File name", self.name),
("Resolution", "%dx%d" % size),
("File size", format.filesize(stat.st_size)),
("Last modified", format.filetime(stat.st_mtime)),
]
# optionally load Exif metadata
if self.config.with_exif and self.exif :
exif_tag_name = dict(self.config.exif_tags)
exif_tags = (tag for tag, name in self.config.exif_tags)
# merge the wanted tags
metadata.extend((
(exif_tag_name[tag], value) for tag, value in self.exif.image_tags(exif_tags)
))
return metadata
def stale (self) :
"""
Tests if this Image is stale, based on preview/thumb.
"""
return self.preview.stale() or self.thumb.stale()
def update (self) :
"""
Updates this Image's thumb/preview
"""
self.preview.update()
self.thumb.update()
def cleanup (self) :
"""
Drop some memory-intensive cached values
"""
utils.unload(self, 'img', 'exif', 'metadata')