degal/lib/EXIF.py
changeset 98 d7d98c4479ab
parent 54 cc007b6ab972
--- a/degal/lib/EXIF.py	Thu Jun 11 22:50:44 2009 +0300
+++ b/degal/lib/EXIF.py	Thu Jun 11 23:24:48 2009 +0300
@@ -81,7 +81,7 @@
 #
 # ----- See 'changes.txt' file for all contributors and changes ----- #
 #
-
+import mmap
 
 # Don't throw an exception when given an out of range character.
 def make_string(seq):
@@ -1240,20 +1240,27 @@
 class EXIF_header:
     def __init__(self, file, endian, offset, fake_exif, strict, debug=0):
         self.file = file
+        self.mmap = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
         self.endian = endian
         self.offset = offset
         self.fake_exif = fake_exif
         self.strict = strict
         self.debug = debug
         self.tags = {}
+    
+    def pread(self, reloffset, length):
+        """Read <length> bytes from self.file at relative offset <offset>"""
+        
+        offset = self.offset + reloffset
+
+        return self.mmap[offset:offset + length]
 
     # convert slice to integer, based on sign and endian flags
     # usually this offset is assumed to be relative to the beginning of the
     # start of the EXIF information.  For some cameras that use relative tags,
     # this offset may be relative to some other starting point.
     def s2n(self, offset, length, signed=0):
-        self.file.seek(self.offset+offset)
-        slice=self.file.read(length)
+        slice=self.pread(offset, length)
         if self.endian == 'I':
             val=s2n_intel(slice)
         else:
@@ -1349,8 +1356,7 @@
                     # XXX investigate
                     # sometimes gets too big to fit in int value
                     if count != 0 and count < (2**31):
-                        self.file.seek(self.offset + offset)
-                        values = self.file.read(count)
+                        values = self.pread(offset, count)
                         #print values
                         # Drop any garbage after a null.
                         values = values.split('\x00', 1)[0]
@@ -1426,8 +1432,7 @@
         else:
             tiff = 'II*\x00\x08\x00\x00\x00'
         # ... plus thumbnail IFD data plus a null "next IFD" pointer
-        self.file.seek(self.offset+thumb_ifd)
-        tiff += self.file.read(entries*12+2)+'\x00\x00\x00\x00'
+        tiff += self.pread(thumb_ifd, entries*12+2)+'\x00\x00\x00\x00'
 
         # fix up large value offset pointers into data area
         for i in range(entries):
@@ -1454,8 +1459,7 @@
                     strip_off = newoff
                     strip_len = 4
                 # get original data and store it
-                self.file.seek(self.offset + oldoff)
-                tiff += self.file.read(count * typelen)
+                tiff += self.pread(oldoff, count * typelen)
 
         # add pixel strips and update strip offset info
         old_offsets = self.tags['Thumbnail StripOffsets'].values
@@ -1466,8 +1470,7 @@
             tiff = tiff[:strip_off] + offset + tiff[strip_off + strip_len:]
             strip_off += strip_len
             # add pixel strip to end
-            self.file.seek(self.offset + old_offsets[i])
-            tiff += self.file.read(old_counts[i])
+            tiff += self.pread(old_offsets[i], old_counts[i])
 
         self.tags['TIFFThumbnail'] = tiff