# $Id$ # a minimalist CCITT G3/G4 libtiff loader for PIL # you need the 'ctypes' python extension, and the appropriate libtiff # DLL files ('libtiff3.dll', 'jpeg62.dll', and 'zlib1.dll'). copies # of the latter are included under ./DLLs. # this loader has only been tested on a small number of CCITT G4 com- # pressed bilevel (mode 1) samples, and definitely needs more work to # handle more TIFF file flavours. # TODO: add proper function signatures # TODO: test with more modes and samples # TODO: handle tiled images # TODO: test on unix import Image import ctypes import os, sys if sys.platform == "win32": dllroot = os.path.join(os.path.dirname(__file__), "DLLs") if os.path.isdir(dllroot): os.environ["PATH"] = dllroot + os.pathsep + os.environ["PATH"] libtiff = ctypes.cdll.libtiff3 ## # Loads a PIL image, using the libtiff library to read CCITT G3/G4 # files. # # @param im A PIL Image instance. def libtiff_load(im): if im.format != "TIFF" or not im.tile: raise IOError("cannot load this image using libtiff") if im.tile[0][0] not in ("group3", "group4"): return im tif = libtiff.TIFFOpen(im.filename, "r") if not tif: raise IOError("libtiff failed to open the file") out = Image.new(im.mode, im.size, None) # allocate transfer buffer bufsize = libtiff.TIFFStripSize(tif) buf = ctypes.create_string_buffer(bufsize) # make sure that PIL and libtiff agrees on the layout if libtiff.TIFFNumberOfStrips(tif) != len(im.tile): raise IOError("wrong number of strips") # check polarity photometric_interpretation = im.tag.getscalar(262, 0) if photometric_interpretation: rawmode = "1" # min is black else: rawmode = "1;I" # min is white # copy strips to the PIL image for strip, tile in enumerate(im.tile): compression, bbox, offset, info = tile result = libtiff.TIFFReadEncodedStrip(tif, strip, buf, -1) if result < 0: raise IOError("libtiff failed to read strip") size = bbox[2]-bbox[0], bbox[3]-bbox[1] tile = Image.frombuffer(im.mode, size, buf, "raw", rawmode) out.paste(tile, bbox) libtiff.TIFFClose(tif) # update source image object im.tile = [] im.im = out.im return im # -------------------------------------------------------------------- # demo code if __name__ == "__main__": import sys im = Image.open(sys.argv[1]) print "mode", im.mode print "size", im.size print "tile", im.tile if im.format == "TIFF": libtiff_load(im) im.show()