1. pydica
  2. pydica
  3. tiffany

Commits

Christian Tismer  committed bcf5fa1

tiffany seems to be quite ready. Need to check it later, and a break now

  • Participants
  • Parent commits 1fcbd9d
  • Branches default

Comments (0)

Files changed (2)

File tool/tiff_reader/tiffany/__init__.py

View file
     __path__[1:] = []
     uninstall_mapper()
 
+start_mapper()
+from .monkeypil import open
+stop_mapper()
+
+__all__ = ['open']

File tool/tiff_reader/tiffany/monkeypil.py

View file
-import sys, os, types, new
+import sys, os, types, new, StringIO
 
 """
 Tiffany - Tiff with PIL without PIL
     
     class FakeImage:
         def pixel_access(self, readonly):
-            return 4711
+            return SyntaxError('this value should not be used')
     
     def new(self, mode, size):
         im = self.FakeImage()
             self.args = args
             
         def decode(self, block):
-            self.im.saved_data = block
+            # we ignore the read block and say 'ok'
             return -1, 0
     
     def group4_decoder(self, mode, *args):
         return self.TiffanyDecoder(mode, *args)
 
     class TiffanyEncoder:
-        def __init__(self, mode, *strips):
+        def __init__(self, mode, src_fp, strips):
             self.mode = mode
+            self.src_fp = src_fp
             self.strips = strips
             
         def setimage(self, im, *args):
             self.args = args
 
         def encode_to_file(self, fh, bufsize):
-            buf = self.im.saved_data
+            # we ignore the bufsize and just copy over
+            src = self.src_fp
             for ofs, lng in self.strips:
-                # we ignore ofs for now (only one strip)
-                # improve later
-                assert len(buf) >= lng
-                os.write(fh, buf[:lng])
-                buf = buf[lng:]
+                src.seek(ofs)
+                buf = src.read(lng)
+                os.write(fh, buf)
             return 0
         
-    def tiffany_encoder(self, mode, args):
+        def encode(self, bufsize):
+            # we ignore the bufsize and just copy over
+            src = self.src_fp
+            ret = ''
+            for ofs, lng in self.strips:
+                src.seek(ofs)
+                ret += src.read(lng)
+            return None, 1, ret
+        
+    def tiffany_encoder(self, mode, source, *strips):
         """ this encoder blindly copies what it gets from the (equally blind)
         decoder """
-        return self.TiffanyEncoder(mode, args)
+        return self.TiffanyEncoder(mode, source, strips)
 
 
 # a handy metaclass that injects a class into a different module
         offset = ifd.save(fp)
     
         ImageFile._save(im, fp, [
-            ("tiffany", (0,0)+im.size, offset, ())
+            ("tiffany", (0,0)+im.size, offset, (im._TiffImageFile__fp,))
             ])
         
         # A bigger problem with PIL was that it uses the file handle internally,
         # and therefore the fp is not updated. We do that now:
-        syncpos = os.lseek(fp.fileno(), 0, 1) # emulated tell()
-        fp.seek(syncpos, 0)
+        if hasattr(fp, 'fileno'):
+            syncpos = os.lseek(fp.fileno(), 0, 1) # emulated tell()
+            fp.seek(syncpos, 0)
     
         # -- helper for multi-page save --
         if is_multipage:
         # -- find ifd's link position --
         im.last_linkoffset = savepos + 2 + len(ifd.tags) * 12
         
+# override the already registered plugin
+Image.register_open("TIFF", TiffanyImageFile, TiffImagePlugin._accept)
 Image.register_save("TIFF", TiffanyImageFile._save_as_is)
+
+class Tiffany(object):
+    ''' the minimum interface to Tiffany:
     
+    im = tiffany.open(fp)  -- opens an image, given the file name or open file
+        a Tiffany object is returned.
+        
+    Methods of a Tiffany object:
+    
+    im.seek(frame)    -- seek the given frame in a multipage tiff
+    
+    im.tell()         -- return the current frame number
+    
+    im.save(fp)       -- write the current frame to a file
+        fp can be a file name or an open file pointer.
+        In the latter case, multiple saves to that fp create a multipage Tiff.
+    '''
+    
+    def __init__(self, im):
+        assert isinstance(im, Image.Image)
+        self.im = im
+        
+    def seek(self, pos):
+        self.im.seek(pos)
+    
+    def tell(self):
+        return self.im.tell()
+    
+    def save(self, fp):
+        self.im.save(fp, 'tiff')
+    
+def open(file_or_fp, mode='r'):
+    im = Image.open(file_or_fp)
+    return Tiffany(im)
+
+
 def inline_test():
+    
+    # reading from a file
     imfile = os.path.join(rootpath, 'test/data/test_image.tiff')
     outfile = os.path.join(os.path.dirname(imfile), 'look_page2.tiff')
-    im = Image.open(imfile)
+    im = open(imfile)
     
     with file(outfile, 'wb') as imf:
         for i in range(5):
             im.seek(1)
-            im.save(imf, 'tiff')
+            im.save(imf)
             im.seek(0)
-            im.save(imf, 'tiff')
+            im.save(imf)
             
+    # reading from a buffer
+    im = file(imfile, 'rb').read()
+    im = StringIO.StringIO(im)
+    im = open(im)
+    
+    with file(outfile, 'wb') as imf:
+        for i in range(5):
+            im.seek(1)
+            im.save(imf)
+            im.seek(0)
+            im.save(imf)
+                        
+    # writing to a buffer
+    imf = StringIO.StringIO()
+    for i in range(5):
+        im.seek(1)
+        im.save(imf)
+        im.seek(0)
+        im.save(imf)
+                
 if __name__ == '__main__':
     inline_test()