degal/exif.py
branchnew-exif
changeset 105 effae6f38749
parent 104 6afe59e5ffae
child 106 a4f605bd122c
--- a/degal/exif.py	Sat Jun 13 20:31:51 2009 +0300
+++ b/degal/exif.py	Sat Jun 13 20:59:53 2009 +0300
@@ -4,6 +4,8 @@
 
 import struct, mmap, os
 
+from utils import lazy_load, lazy_load_iter
+
 def read_struct (file, fmt) :
     """
         Utility function to read data from the a file using struct
@@ -107,11 +109,12 @@
         Represents a single Tag in an IFD
     """
 
-    def __init__ (self, offset, tag, type, count, data_raw) :
+    def __init__ (self, ifd, offset, tag, type, count, data_raw) :
         """
             Build a Tag with the given binary items from the IFD entry
         """
         
+        self.ifd = ifd
         self.offset = offset
         self.tag = tag
         self.type = type
@@ -126,13 +129,8 @@
             self.type_format, self.type_name, self.type_func = self.type_data
     
         # lookup the tag data for this tag
-        self.tag_data = exif_data.EXIF_TAGS.get(tag)
+        self.tag_data = self.ifd.tag_dict.get(tag)
         
-        # unpack it
-        if self.tag_data :
-            # the EXIF tag name
-            self.tag_name, self.tag_value_spec = self.tag_data
-            
     @property
     def name (self) :
         """
@@ -140,7 +138,7 @@
         """
 
         if self.tag_data :
-            return self.tag_name
+            return self.tag_data.name
 
         else :
             return None
@@ -166,14 +164,12 @@
         """
 
         if self.tag_data :
-            spec = self.tag_value_spec
+            # map it
+            return self.tag_data.map_values(values)
 
         else :
-            # fallback to default
-            spec = None
-
-        # map it
-        return exif_data.map_values(spec, values)
+            # default value-mapping
+            return ", ".join(str(value) for value in values)
 
 # size of an IFD entry in bytes
 IFD_ENTRY_SIZE = 12
@@ -183,7 +179,7 @@
         Represents an IFD (Image file directory) region in EXIF data.
     """
 
-    def __init__ (self, buffer, **buffer_opts) :
+    def __init__ (self, buffer, tag_dict, **buffer_opts) :
         """
             Access the IFD data from the given bufferable object with given buffer opts.
 
@@ -192,6 +188,9 @@
 
         # init
         super(IFD, self).__init__(buffer, **buffer_opts)
+
+        # store
+        self.tag_dict = tag_dict
         
         # read header
         self.count = self.pread_item(0, 'H')
@@ -199,7 +198,8 @@
         # read next-offset
         self.next_offset = self.pread_item(0x02 + self.count * IFD_ENTRY_SIZE, 'I')
     
-    def iter_tags (self) :
+    @lazy_load_iter
+    def tags (self) :
         """
             Iterate over all the Tag objects in this IFD
         """
@@ -210,7 +210,7 @@
             tag, type, count, data_raw = self.pread_struct(offset, 'HHI4s')
             
             # yield the new Tag
-            yield Tag(offset, tag, type, count, data_raw)
+            yield Tag(self, offset, tag, type, count, data_raw)
 
 class EXIF (Buffer) :
     """
@@ -230,7 +230,8 @@
         # store
         self.buffer = buffer
     
-    def iter_ifds (self) :
+    @lazy_load_iter
+    def ifds (self) :
         """
             Iterate over the primary IFDs in this EXIF.
         """
@@ -240,7 +241,7 @@
 
         while offset :
             # create and read the IFD, operating on the right sub-buffer
-            ifd = IFD(self.buf, offset=offset)
+            ifd = IFD(self.buf, exif_data.EXIF_TAGS, offset=offset)
 
             # yield it
             yield ifd
@@ -252,8 +253,6 @@
         """
             Iterate over all of the IFDs contained within this EXIF, or within other IFDs.
         """
-
-    __iter__ = iter_ifds
     
     def tag_data_info (self, tag) :
         """
@@ -500,7 +499,7 @@
 
     print "EXIF offset=%#08x, size=%d:" % (exif.offset, exif.size)
 
-    for i, ifd in enumerate(exif.iter_ifds()) :
+    for i, ifd in enumerate(exif.ifds) :
         print "\tIFD:%d offset=%#04x(%#08x), count=%d, next=%d:" % (
             i, 
             ifd.offset, ifd.offset + exif.offset,
@@ -508,7 +507,7 @@
             ifd.next_offset
         )
         
-        for i, tag in enumerate(ifd.iter_tags()) :
+        for i, tag in enumerate(ifd.tags) :
             data_info = exif.tag_data_info(tag)
 
             if data_info :