--- /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
+