diff -r e7855eefb4c7 -r 55cb7fc9c8fb degal/exif.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/degal/exif.py Sun Jun 14 23:43:40 2009 +0300 @@ -0,0 +1,137 @@ +""" + The various Exif backends that we have +""" + +from __future__ import with_statement + +import utils + +class ExifHandler (object) : + """ + Our generic interface for Exif data + """ + + def __init__ (self, file) : + """ + Load Exif data from the given File. + """ + + self.file = file + + def image_tag (self, tag, default=None) : + """ + Load and return the human-readable unicode-safe value for the given main image tag. + """ + + abstract + + def image_tags (self, tags) : + """ + Load and return the given tags for the main image as a sequence of (tag, value) tuples , following the same + rules as image_tag, except there should mainly be only one call to this function, encompassing all the + relevant tags. + + The returned list should omit those values which were not found. + """ + + for tag in tags : + # try and fetch value + value = self.image_tag(tag) + + # filter out default not-found + if value is not None : + yield tag, value + +try : + import pyexiv2 + +except ImportError : + PyExiv2_Handler = None + +else : + class PyExiv2_Handler (ExifHandler) : + NAME = 'pyexiv2' + + def __init__ (self, file) : + """ + Load as pyexiv2.Image + """ + + # create + self.image = pyexiv2.Image(file.path) + + # load + self.image.readMetadata() + + def image_tag (self, tag, default=None) : + try : + # XXX: this is wrong + return self.image.interpretedExifValue("Exif.Photo.%s" % tag) + + except (IndexError, KeyError) : + return default + +try : + from lib import EXIF + +except ImportError : + EXIF_Handler = None + +else : + class EXIF_Handler (ExifHandler) : + NAME = 'EXIFpy' + + def __init__ (self, file) : + """ + Load using EXIF.process_file + """ + + with file.open('rb') as fh : + self.tags = EXIF.process_file(fh) + + def image_tag (self, tag, default=None) : + # XXX: this is wrong + return self.tags.get('Image %s' % (tag, ), default) + +# ExifHandler implementations to use, in preference order +EXIF_HANDLERS = [ + # reasonably fast, but requires the native library and extension module + PyExiv2_Handler, + + # pure-python, but very, very slow + EXIF_Handler, +] + +# default ExifHandler to use +EXIF_HANDLER = utils.first(EXIF_HANDLERS) + +# ExifHandler implementations by name +EXIF_HANDLERS_BY_NAME = dict((h.NAME, h) for h in EXIF_HANDLERS) + +def load (config, file) : + """ + Load Exif data using the configured Exif handler, and return the instance. + + Returns None if there wasn't any Exif handler available for use. + """ + + if config.exif_handler : + # explicit + exif_handler = config.exif_handler + + elif config.exif_handler_name : + # by name + exif_handler = EXIF_HANDLERS_BY_NAME[config.exif_handler_name] + + else : + # default + exif_handler = EXIF_HANDLER + + if exif_handler : + # found one, use it + return exif_handler(file) + + else : + # nothing :( + return None +