home *** CD-ROM | disk | FTP | other *** search
/ Freelog 116 / FreelogNo116-JuilletSeptembre2013.iso / Bureautique / gImageReader / gimagereader_0.9-1_win32.exe / bin / TiffImagePlugin.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2011-03-24  |  22KB  |  732 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. __version__ = '1.3.5'
  5. import Image
  6. import ImageFile
  7. import ImagePalette
  8. import array
  9. import string
  10. import sys
  11. II = 'II'
  12. MM = 'MM'
  13.  
  14. try:
  15.     if sys.byteorder == 'little':
  16.         native_prefix = II
  17.     else:
  18.         native_prefix = MM
  19. except AttributeError:
  20.     if ord(array.array('i', [
  21.         1]).tostring()[0]):
  22.         native_prefix = II
  23.     else:
  24.         native_prefix = MM
  25.  
  26.  
  27. def il16(c, o = 0):
  28.     return ord(c[o]) + (ord(c[o + 1]) << 8)
  29.  
  30.  
  31. def il32(c, o = 0):
  32.     return ord(c[o]) + (ord(c[o + 1]) << 8) + (ord(c[o + 2]) << 16) + (ord(c[o + 3]) << 24)
  33.  
  34.  
  35. def ol16(i):
  36.     return chr(i & 255) + chr(i >> 8 & 255)
  37.  
  38.  
  39. def ol32(i):
  40.     return chr(i & 255) + chr(i >> 8 & 255) + chr(i >> 16 & 255) + chr(i >> 24 & 255)
  41.  
  42.  
  43. def ib16(c, o = 0):
  44.     return ord(c[o + 1]) + (ord(c[o]) << 8)
  45.  
  46.  
  47. def ib32(c, o = 0):
  48.     return ord(c[o + 3]) + (ord(c[o + 2]) << 8) + (ord(c[o + 1]) << 16) + (ord(c[o]) << 24)
  49.  
  50.  
  51. def ob16(i):
  52.     return chr(i >> 8 & 255) + chr(i & 255)
  53.  
  54.  
  55. def ob32(i):
  56.     return chr(i >> 24 & 255) + chr(i >> 16 & 255) + chr(i >> 8 & 255) + chr(i & 255)
  57.  
  58. IMAGEWIDTH = 256
  59. IMAGELENGTH = 257
  60. BITSPERSAMPLE = 258
  61. COMPRESSION = 259
  62. PHOTOMETRIC_INTERPRETATION = 262
  63. FILLORDER = 266
  64. IMAGEDESCRIPTION = 270
  65. STRIPOFFSETS = 273
  66. SAMPLESPERPIXEL = 277
  67. ROWSPERSTRIP = 278
  68. STRIPBYTECOUNTS = 279
  69. X_RESOLUTION = 282
  70. Y_RESOLUTION = 283
  71. PLANAR_CONFIGURATION = 284
  72. RESOLUTION_UNIT = 296
  73. SOFTWARE = 305
  74. DATE_TIME = 306
  75. ARTIST = 315
  76. PREDICTOR = 317
  77. COLORMAP = 320
  78. TILEOFFSETS = 324
  79. EXTRASAMPLES = 338
  80. SAMPLEFORMAT = 339
  81. JPEGTABLES = 347
  82. COPYRIGHT = 33432
  83. IPTC_NAA_CHUNK = 33723
  84. PHOTOSHOP_CHUNK = 34377
  85. ICCPROFILE = 34675
  86. EXIFIFD = 34665
  87. XMP = 700
  88. COMPRESSION_INFO = {
  89.     1: 'raw',
  90.     2: 'tiff_ccitt',
  91.     3: 'group3',
  92.     4: 'group4',
  93.     5: 'tiff_lzw',
  94.     6: 'tiff_jpeg',
  95.     7: 'jpeg',
  96.     32771: 'tiff_raw_16',
  97.     32773: 'packbits' }
  98. OPEN_INFO = {
  99.     (II, 0, 1, 1, (1,), ()): ('1', '1;I'),
  100.     (II, 0, 1, 2, (1,), ()): ('1', '1;IR'),
  101.     (II, 0, 1, 1, (8,), ()): ('L', 'L;I'),
  102.     (II, 0, 1, 2, (8,), ()): ('L', 'L;IR'),
  103.     (II, 1, 1, 1, (1,), ()): ('1', '1'),
  104.     (II, 1, 1, 2, (1,), ()): ('1', '1;R'),
  105.     (II, 1, 1, 1, (8,), ()): ('L', 'L'),
  106.     (II, 1, 1, 1, (8, 8), (2,)): ('LA', 'LA'),
  107.     (II, 1, 1, 2, (8,), ()): ('L', 'L;R'),
  108.     (II, 1, 1, 1, (16,), ()): ('I;16', 'I;16'),
  109.     (II, 1, 2, 1, (16,), ()): ('I;16S', 'I;16S'),
  110.     (II, 1, 2, 1, (32,), ()): ('I', 'I;32S'),
  111.     (II, 1, 3, 1, (32,), ()): ('F', 'F;32F'),
  112.     (II, 2, 1, 1, (8, 8, 8), ()): ('RGB', 'RGB'),
  113.     (II, 2, 1, 2, (8, 8, 8), ()): ('RGB', 'RGB;R'),
  114.     (II, 2, 1, 1, (8, 8, 8, 8), (0,)): ('RGBX', 'RGBX'),
  115.     (II, 2, 1, 1, (8, 8, 8, 8), (1,)): ('RGBA', 'RGBa'),
  116.     (II, 2, 1, 1, (8, 8, 8, 8), (2,)): ('RGBA', 'RGBA'),
  117.     (II, 2, 1, 1, (8, 8, 8, 8), (999,)): ('RGBA', 'RGBA'),
  118.     (II, 3, 1, 1, (1,), ()): ('P', 'P;1'),
  119.     (II, 3, 1, 2, (1,), ()): ('P', 'P;1R'),
  120.     (II, 3, 1, 1, (2,), ()): ('P', 'P;2'),
  121.     (II, 3, 1, 2, (2,), ()): ('P', 'P;2R'),
  122.     (II, 3, 1, 1, (4,), ()): ('P', 'P;4'),
  123.     (II, 3, 1, 2, (4,), ()): ('P', 'P;4R'),
  124.     (II, 3, 1, 1, (8,), ()): ('P', 'P'),
  125.     (II, 3, 1, 1, (8, 8), (2,)): ('PA', 'PA'),
  126.     (II, 3, 1, 2, (8,), ()): ('P', 'P;R'),
  127.     (II, 5, 1, 1, (8, 8, 8, 8), ()): ('CMYK', 'CMYK'),
  128.     (II, 6, 1, 1, (8, 8, 8), ()): ('YCbCr', 'YCbCr'),
  129.     (II, 8, 1, 1, (8, 8, 8), ()): ('LAB', 'LAB'),
  130.     (MM, 0, 1, 1, (1,), ()): ('1', '1;I'),
  131.     (MM, 0, 1, 2, (1,), ()): ('1', '1;IR'),
  132.     (MM, 0, 1, 1, (8,), ()): ('L', 'L;I'),
  133.     (MM, 0, 1, 2, (8,), ()): ('L', 'L;IR'),
  134.     (MM, 1, 1, 1, (1,), ()): ('1', '1'),
  135.     (MM, 1, 1, 2, (1,), ()): ('1', '1;R'),
  136.     (MM, 1, 1, 1, (8,), ()): ('L', 'L'),
  137.     (MM, 1, 1, 1, (8, 8), (2,)): ('LA', 'LA'),
  138.     (MM, 1, 1, 2, (8,), ()): ('L', 'L;R'),
  139.     (MM, 1, 1, 1, (16,), ()): ('I;16B', 'I;16B'),
  140.     (MM, 1, 2, 1, (16,), ()): ('I;16BS', 'I;16BS'),
  141.     (MM, 1, 2, 1, (32,), ()): ('I;32BS', 'I;32BS'),
  142.     (MM, 1, 3, 1, (32,), ()): ('F;32BF', 'F;32BF'),
  143.     (MM, 2, 1, 1, (8, 8, 8), ()): ('RGB', 'RGB'),
  144.     (MM, 2, 1, 2, (8, 8, 8), ()): ('RGB', 'RGB;R'),
  145.     (MM, 2, 1, 1, (8, 8, 8, 8), (0,)): ('RGBX', 'RGBX'),
  146.     (MM, 2, 1, 1, (8, 8, 8, 8), (1,)): ('RGBA', 'RGBa'),
  147.     (MM, 2, 1, 1, (8, 8, 8, 8), (2,)): ('RGBA', 'RGBA'),
  148.     (MM, 2, 1, 1, (8, 8, 8, 8), (999,)): ('RGBA', 'RGBA'),
  149.     (MM, 3, 1, 1, (1,), ()): ('P', 'P;1'),
  150.     (MM, 3, 1, 2, (1,), ()): ('P', 'P;1R'),
  151.     (MM, 3, 1, 1, (2,), ()): ('P', 'P;2'),
  152.     (MM, 3, 1, 2, (2,), ()): ('P', 'P;2R'),
  153.     (MM, 3, 1, 1, (4,), ()): ('P', 'P;4'),
  154.     (MM, 3, 1, 2, (4,), ()): ('P', 'P;4R'),
  155.     (MM, 3, 1, 1, (8,), ()): ('P', 'P'),
  156.     (MM, 3, 1, 1, (8, 8), (2,)): ('PA', 'PA'),
  157.     (MM, 3, 1, 2, (8,), ()): ('P', 'P;R'),
  158.     (MM, 5, 1, 1, (8, 8, 8, 8), ()): ('CMYK', 'CMYK'),
  159.     (MM, 6, 1, 1, (8, 8, 8), ()): ('YCbCr', 'YCbCr'),
  160.     (MM, 8, 1, 1, (8, 8, 8), ()): ('LAB', 'LAB') }
  161. PREFIXES = [
  162.     'MM\x00*',
  163.     'II*\x00',
  164.     'II\xbc\x00']
  165.  
  166. def _accept(prefix):
  167.     return prefix[:4] in PREFIXES
  168.  
  169.  
  170. class ImageFileDirectory:
  171.     
  172.     def __init__(self, prefix):
  173.         self.prefix = prefix[:2]
  174.         if self.prefix == MM:
  175.             self.i16 = ib16
  176.             self.i32 = ib32
  177.             self.o16 = ob16
  178.             self.o32 = ob32
  179.         elif self.prefix == II:
  180.             self.i16 = il16
  181.             self.i32 = il32
  182.             self.o16 = ol16
  183.             self.o32 = ol32
  184.         else:
  185.             raise SyntaxError('not a TIFF IFD')
  186.         None.reset()
  187.  
  188.     
  189.     def reset(self):
  190.         self.tags = { }
  191.         self.tagdata = { }
  192.         self.tagtype = { }
  193.         self.next = None
  194.  
  195.     
  196.     def keys(self):
  197.         return self.tagdata.keys() + self.tags.keys()
  198.  
  199.     
  200.     def items(self):
  201.         items = self.tags.items()
  202.         for tag in self.tagdata.keys():
  203.             items.append((tag, self[tag]))
  204.         
  205.         return items
  206.  
  207.     
  208.     def __len__(self):
  209.         return len(self.tagdata) + len(self.tags)
  210.  
  211.     
  212.     def __getitem__(self, tag):
  213.         
  214.         try:
  215.             return self.tags[tag]
  216.         except KeyError:
  217.             (type, data) = self.tagdata[tag]
  218.             (size, handler) = self.load_dispatch[type]
  219.             self.tags[tag] = data = handler(self, data)
  220.             del self.tagdata[tag]
  221.             return data
  222.  
  223.  
  224.     
  225.     def get(self, tag, default = None):
  226.         
  227.         try:
  228.             return self[tag]
  229.         except KeyError:
  230.             return default
  231.  
  232.  
  233.     
  234.     def getscalar(self, tag, default = None):
  235.         
  236.         try:
  237.             value = self[tag]
  238.             if len(value) != 1:
  239.                 if tag == SAMPLEFORMAT:
  240.                     raise KeyError
  241.                 raise ValueError, 'not a scalar'
  242.             return value[0]
  243.         except KeyError:
  244.             if default is None:
  245.                 raise 
  246.             return default
  247.  
  248.  
  249.     
  250.     def has_key(self, tag):
  251.         if not self.tags.has_key(tag):
  252.             pass
  253.         return self.tagdata.has_key(tag)
  254.  
  255.     
  256.     def __setitem__(self, tag, value):
  257.         if type(value) is not type(()):
  258.             value = (value,)
  259.         self.tags[tag] = value
  260.  
  261.     load_dispatch = { }
  262.     
  263.     def load_byte(self, data):
  264.         l = []
  265.         for i in range(len(data)):
  266.             l.append(ord(data[i]))
  267.         
  268.         return tuple(l)
  269.  
  270.     load_dispatch[1] = (1, load_byte)
  271.     
  272.     def load_string(self, data):
  273.         if data[-1:] == '\x00':
  274.             data = data[:-1]
  275.         return data
  276.  
  277.     load_dispatch[2] = (1, load_string)
  278.     
  279.     def load_short(self, data):
  280.         l = []
  281.         for i in range(0, len(data), 2):
  282.             l.append(self.i16(data, i))
  283.         
  284.         return tuple(l)
  285.  
  286.     load_dispatch[3] = (2, load_short)
  287.     
  288.     def load_long(self, data):
  289.         l = []
  290.         for i in range(0, len(data), 4):
  291.             l.append(self.i32(data, i))
  292.         
  293.         return tuple(l)
  294.  
  295.     load_dispatch[4] = (4, load_long)
  296.     
  297.     def load_rational(self, data):
  298.         l = []
  299.         for i in range(0, len(data), 8):
  300.             l.append((self.i32(data, i), self.i32(data, i + 4)))
  301.         
  302.         return tuple(l)
  303.  
  304.     load_dispatch[5] = (8, load_rational)
  305.     
  306.     def load_float(self, data):
  307.         a = array.array('f', data)
  308.         if self.prefix != native_prefix:
  309.             a.byteswap()
  310.         return tuple(a)
  311.  
  312.     load_dispatch[11] = (4, load_float)
  313.     
  314.     def load_double(self, data):
  315.         a = array.array('d', data)
  316.         if self.prefix != native_prefix:
  317.             a.byteswap()
  318.         return tuple(a)
  319.  
  320.     load_dispatch[12] = (8, load_double)
  321.     
  322.     def load_undefined(self, data):
  323.         return data
  324.  
  325.     load_dispatch[7] = (1, load_undefined)
  326.     
  327.     def load(self, fp):
  328.         self.reset()
  329.         i16 = self.i16
  330.         i32 = self.i32
  331.         for i in range(i16(fp.read(2))):
  332.             ifd = fp.read(12)
  333.             tag = i16(ifd)
  334.             typ = i16(ifd, 2)
  335.             if Image.DEBUG:
  336.                 import TiffTags as TiffTags
  337.                 tagname = TiffTags.TAGS.get(tag, 'unknown')
  338.                 typname = TiffTags.TYPES.get(typ, 'unknown')
  339.                 print 'tag: %s (%d)' % (tagname, tag), '- type: %s (%d)' % (typname, typ),
  340.             
  341.             try:
  342.                 dispatch = self.load_dispatch[typ]
  343.             except KeyError:
  344.                 if Image.DEBUG:
  345.                     print '- unsupported type', typ
  346.                     continue
  347.                     continue
  348.                 
  349.  
  350.             (size, handler) = dispatch
  351.             size = size * i32(ifd, 4)
  352.             if size > 4:
  353.                 here = fp.tell()
  354.                 fp.seek(i32(ifd, 8))
  355.                 data = ImageFile._safe_read(fp, size)
  356.                 fp.seek(here)
  357.             else:
  358.                 data = ifd[8:8 + size]
  359.             if len(data) != size:
  360.                 raise IOError, 'not enough data'
  361.             self.tagdata[tag] = (typ, data)
  362.             self.tagtype[tag] = typ
  363.             if Image.DEBUG or tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
  364.                 print '- value: <table: %d bytes>' % size
  365.             else:
  366.                 print '- value:', self[tag]
  367.         
  368.         self.next = i32(fp.read(4))
  369.  
  370.     
  371.     def save(self, fp):
  372.         o16 = self.o16
  373.         o32 = self.o32
  374.         fp.write(o16(len(self.tags)))
  375.         tags = self.tags.items()
  376.         tags.sort()
  377.         directory = []
  378.         append = directory.append
  379.         offset = fp.tell() + len(self.tags) * 12 + 4
  380.         stripoffsets = None
  381.         for tag, value in tags:
  382.             typ = None
  383.             if self.tagtype.has_key(tag):
  384.                 typ = self.tagtype[tag]
  385.             if typ == 1:
  386.                 data = value = string.join(map(chr, value), '')
  387.             elif typ == 7:
  388.                 data = value = string.join(value, '')
  389.             elif type(value[0]) is type(''):
  390.                 typ = 2
  391.                 data = value = string.join(value, '\x00') + '\x00'
  392.             elif tag == STRIPOFFSETS:
  393.                 stripoffsets = len(directory)
  394.                 typ = 4
  395.             elif tag in (X_RESOLUTION, Y_RESOLUTION):
  396.                 typ = 5
  397.             elif not typ:
  398.                 typ = 3
  399.                 for v in value:
  400.                     if v >= 65536:
  401.                         typ = 4
  402.                         continue
  403.             if typ == 3:
  404.                 data = string.join(map(o16, value), '')
  405.             else:
  406.                 data = string.join(map(o32, value), '')
  407.             if Image.DEBUG:
  408.                 import TiffTags
  409.                 tagname = TiffTags.TAGS.get(tag, 'unknown')
  410.                 typname = TiffTags.TYPES.get(typ, 'unknown')
  411.                 print 'save: %s (%d)' % (tagname, tag), '- type: %s (%d)' % (typname, typ),
  412.                 if tag in (COLORMAP, IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, ICCPROFILE, XMP):
  413.                     size = len(data)
  414.                     print '- value: <table: %d bytes>' % size
  415.                 else:
  416.                     print '- value:', value
  417.             if len(data) == 4:
  418.                 append((tag, typ, len(value), data, ''))
  419.                 continue
  420.             if len(data) < 4:
  421.                 append((tag, typ, len(value), data + (4 - len(data)) * '\x00', ''))
  422.                 continue
  423.             count = len(value)
  424.             if typ == 5:
  425.                 count = count / 2
  426.             append((tag, typ, count, o32(offset), data))
  427.             offset = offset + len(data)
  428.             if offset & 1:
  429.                 offset = offset + 1
  430.                 continue
  431.         if stripoffsets is not None:
  432.             (tag, typ, count, value, data) = directory[stripoffsets]
  433.             if not not data:
  434.                 raise AssertionError, 'multistrip support not yet implemented'
  435.             value = None(self.i32(value) + offset)
  436.             directory[stripoffsets] = (tag, typ, count, value, data)
  437.         for tag, typ, count, value, data in directory:
  438.             if Image.DEBUG > 1:
  439.                 print tag, typ, count, repr(value), repr(data)
  440.             fp.write(o16(tag) + o16(typ) + o32(count) + value)
  441.         
  442.         fp.write('\x00\x00\x00\x00')
  443.         for tag, typ, count, value, data in directory:
  444.             fp.write(data)
  445.             if len(data) & 1:
  446.                 fp.write('\x00')
  447.                 continue
  448.         return offset
  449.  
  450.  
  451.  
  452. class TiffImageFile(ImageFile.ImageFile):
  453.     format = 'TIFF'
  454.     format_description = 'Adobe TIFF'
  455.     
  456.     def _open(self):
  457.         '''Open the first image in a TIFF file'''
  458.         ifh = self.fp.read(8)
  459.         if ifh[:4] not in PREFIXES:
  460.             raise SyntaxError, 'not a TIFF file'
  461.         self.tag = self.ifd = ImageFileDirectory(ifh[:2])
  462.         self._TiffImageFile__first = self._TiffImageFile__next = self.ifd.i32(ifh, 4)
  463.         self._TiffImageFile__frame = -1
  464.         self._TiffImageFile__fp = self.fp
  465.         self._seek(0)
  466.  
  467.     
  468.     def seek(self, frame):
  469.         '''Select a given frame as current image'''
  470.         if frame < 0:
  471.             frame = 0
  472.         self._seek(frame)
  473.  
  474.     
  475.     def tell(self):
  476.         '''Return the current frame number'''
  477.         return self._tell()
  478.  
  479.     
  480.     def _seek(self, frame):
  481.         self.fp = self._TiffImageFile__fp
  482.         if frame < self._TiffImageFile__frame:
  483.             self._TiffImageFile__frame = -1
  484.             self._TiffImageFile__next = self._TiffImageFile__first
  485.         while self._TiffImageFile__frame < frame:
  486.             if not self._TiffImageFile__next:
  487.                 raise EOFError, 'no more images in TIFF file'
  488.             self.fp.seek(self._TiffImageFile__next)
  489.             self.tag.load(self.fp)
  490.             self._TiffImageFile__next = self.tag.next
  491.             self._TiffImageFile__frame = self._TiffImageFile__frame + 1
  492.         self._setup()
  493.  
  494.     
  495.     def _tell(self):
  496.         return self._TiffImageFile__frame
  497.  
  498.     
  499.     def _decoder(self, rawmode, layer):
  500.         '''Setup decoder contexts'''
  501.         args = None
  502.         if rawmode == 'RGB' and self._planar_configuration == 2:
  503.             rawmode = rawmode[layer]
  504.         compression = self._compression
  505.         if compression == 'raw':
  506.             args = (rawmode, 0, 1)
  507.         elif compression == 'jpeg':
  508.             args = (rawmode, '')
  509.             if self.tag.has_key(JPEGTABLES):
  510.                 self.tile_prefix = self.tag[JPEGTABLES]
  511.             
  512.         elif compression == 'packbits':
  513.             args = rawmode
  514.         elif compression == 'tiff_lzw':
  515.             args = rawmode
  516.             if self.tag.has_key(317):
  517.                 self.decoderconfig = (self.tag[PREDICTOR][0],)
  518.             
  519.         if self.tag.has_key(ICCPROFILE):
  520.             self.info['icc_profile'] = self.tag[ICCPROFILE]
  521.         return args
  522.  
  523.     
  524.     def _setup(self):
  525.         '''Setup this image object based on current tags'''
  526.         if self.tag.has_key(48129):
  527.             raise IOError, 'Windows Media Photo files not yet supported'
  528.         getscalar = self.tag.getscalar
  529.         self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)]
  530.         self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1)
  531.         photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0)
  532.         fillorder = getscalar(FILLORDER, 1)
  533.         if Image.DEBUG:
  534.             print '*** Summary ***'
  535.             print '- compression:', self._compression
  536.             print '- photometric_interpretation:', photo
  537.             print '- planar_configuration:', self._planar_configuration
  538.             print '- fill_order:', fillorder
  539.         xsize = getscalar(IMAGEWIDTH)
  540.         ysize = getscalar(IMAGELENGTH)
  541.         self.size = (xsize, ysize)
  542.         if Image.DEBUG:
  543.             print '- size:', self.size
  544.         format = getscalar(SAMPLEFORMAT, 1)
  545.         key = (self.tag.prefix, photo, format, fillorder, self.tag.get(BITSPERSAMPLE, (1,)), self.tag.get(EXTRASAMPLES, ()))
  546.         if Image.DEBUG:
  547.             print 'format key:', key
  548.         
  549.         try:
  550.             (self.mode, rawmode) = OPEN_INFO[key]
  551.         except KeyError:
  552.             if Image.DEBUG:
  553.                 print '- unsupported format'
  554.             raise SyntaxError, 'unknown pixel mode'
  555.  
  556.         if Image.DEBUG:
  557.             print '- raw mode:', rawmode
  558.             print '- pil mode:', self.mode
  559.         self.info['compression'] = self._compression
  560.         xres = getscalar(X_RESOLUTION, (1, 1))
  561.         yres = getscalar(Y_RESOLUTION, (1, 1))
  562.         if xres and yres:
  563.             if not xres[1]:
  564.                 pass
  565.             xres = xres[0] / 1
  566.             if not yres[1]:
  567.                 pass
  568.             yres = yres[0] / 1
  569.             resunit = getscalar(RESOLUTION_UNIT, 1)
  570.             if resunit == 2:
  571.                 self.info['dpi'] = (xres, yres)
  572.             elif resunit == 3:
  573.                 self.info['dpi'] = (xres * 2.54, yres * 2.54)
  574.             else:
  575.                 self.info['resolution'] = (xres, yres)
  576.         x = y = l = 0
  577.         self.tile = []
  578.         if self.tag.has_key(STRIPOFFSETS):
  579.             h = getscalar(ROWSPERSTRIP, ysize)
  580.             w = self.size[0]
  581.             a = None
  582.             for o in self.tag[STRIPOFFSETS]:
  583.                 if not a:
  584.                     a = self._decoder(rawmode, l)
  585.                 self.tile.append((self._compression, (0, min(y, ysize), w, min(y + h, ysize)), o, a))
  586.                 y = y + h
  587.                 if y >= self.size[1]:
  588.                     x = y = 0
  589.                     l = l + 1
  590.                     a = None
  591.                     continue
  592.         if self.tag.has_key(TILEOFFSETS):
  593.             w = getscalar(322)
  594.             h = getscalar(323)
  595.             a = None
  596.             for o in self.tag[TILEOFFSETS]:
  597.                 if not a:
  598.                     a = self._decoder(rawmode, l)
  599.                 self.tile.append((self._compression, (x, y, x + w, y + h), o, a))
  600.                 x = x + w
  601.                 if x >= self.size[0]:
  602.                     x = 0
  603.                     y = y + h
  604.                     if y >= self.size[1]:
  605.                         x = y = 0
  606.                         l = l + 1
  607.                         a = None
  608.                     
  609.         if Image.DEBUG:
  610.             print '- unsupported data organization'
  611.         raise SyntaxError('unknown data organization')
  612.         if self.mode == 'P':
  613.             palette = map((lambda a: chr(a / 256)), self.tag[COLORMAP])
  614.             self.palette = ImagePalette.raw('RGB;L', string.join(palette, ''))
  615.  
  616.  
  617. SAVE_INFO = {
  618.     '1': ('1', II, 1, 1, (1,), None),
  619.     'L': ('L', II, 1, 1, (8,), None),
  620.     'LA': ('LA', II, 1, 1, (8, 8), 2),
  621.     'P': ('P', II, 3, 1, (8,), None),
  622.     'PA': ('PA', II, 3, 1, (8, 8), 2),
  623.     'I': ('I;32S', II, 1, 2, (32,), None),
  624.     'I;16': ('I;16', II, 1, 1, (16,), None),
  625.     'I;16S': ('I;16S', II, 1, 2, (16,), None),
  626.     'F': ('F;32F', II, 1, 3, (32,), None),
  627.     'RGB': ('RGB', II, 2, 1, (8, 8, 8), None),
  628.     'RGBX': ('RGBX', II, 2, 1, (8, 8, 8, 8), 0),
  629.     'RGBA': ('RGBA', II, 2, 1, (8, 8, 8, 8), 2),
  630.     'CMYK': ('CMYK', II, 5, 1, (8, 8, 8, 8), None),
  631.     'YCbCr': ('YCbCr', II, 6, 1, (8, 8, 8), None),
  632.     'LAB': ('LAB', II, 8, 1, (8, 8, 8), None),
  633.     'I;32BS': ('I;32BS', MM, 1, 2, (32,), None),
  634.     'I;16B': ('I;16B', MM, 1, 1, (16,), None),
  635.     'I;16BS': ('I;16BS', MM, 1, 2, (16,), None),
  636.     'F;32BF': ('F;32BF', MM, 1, 3, (32,), None) }
  637.  
  638. def _cvt_res(value):
  639.     if type(value) in (type([]), type(())):
  640.         if not len(value) % 2 == 0:
  641.             raise AssertionError
  642.         return None
  643.     if None(value) == type(1):
  644.         return (value, 1)
  645.     value = None(value)
  646.     return (int(value * 65536), 65536)
  647.  
  648.  
  649. def _save(im, fp, filename):
  650.     
  651.     try:
  652.         (rawmode, prefix, photo, format, bits, extra) = SAVE_INFO[im.mode]
  653.     except KeyError:
  654.         raise IOError, 'cannot write mode %s as TIFF' % im.mode
  655.  
  656.     ifd = ImageFileDirectory(prefix)
  657.     if fp.tell() == 0:
  658.         fp.write(ifd.prefix + ifd.o16(42) + ifd.o32(8))
  659.     ifd[IMAGEWIDTH] = im.size[0]
  660.     ifd[IMAGELENGTH] = im.size[1]
  661.     if hasattr(im, 'tag'):
  662.         for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION):
  663.             if im.tag.tagdata.has_key(key):
  664.                 ifd[key] = im.tag.tagdata.get(key)
  665.                 continue
  666.         ifd.tagtype = im.tag.tagtype
  667.         for key in (IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
  668.             if im.tag.has_key(key):
  669.                 ifd[key] = im.tag[key]
  670.                 continue
  671.         if im.info.has_key('icc_profile'):
  672.             ifd[ICCPROFILE] = im.info['icc_profile']
  673.         
  674.     if im.encoderinfo.has_key('description'):
  675.         ifd[IMAGEDESCRIPTION] = im.encoderinfo['description']
  676.     if im.encoderinfo.has_key('resolution'):
  677.         ifd[X_RESOLUTION] = ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo['resolution'])
  678.     if im.encoderinfo.has_key('x resolution'):
  679.         ifd[X_RESOLUTION] = _cvt_res(im.encoderinfo['x resolution'])
  680.     if im.encoderinfo.has_key('y resolution'):
  681.         ifd[Y_RESOLUTION] = _cvt_res(im.encoderinfo['y resolution'])
  682.     if im.encoderinfo.has_key('resolution unit'):
  683.         unit = im.encoderinfo['resolution unit']
  684.         if unit == 'inch':
  685.             ifd[RESOLUTION_UNIT] = 2
  686.         elif unit == 'cm' or unit == 'centimeter':
  687.             ifd[RESOLUTION_UNIT] = 3
  688.         else:
  689.             ifd[RESOLUTION_UNIT] = 1
  690.     if im.encoderinfo.has_key('software'):
  691.         ifd[SOFTWARE] = im.encoderinfo['software']
  692.     if im.encoderinfo.has_key('date time'):
  693.         ifd[DATE_TIME] = im.encoderinfo['date time']
  694.     if im.encoderinfo.has_key('artist'):
  695.         ifd[ARTIST] = im.encoderinfo['artist']
  696.     if im.encoderinfo.has_key('copyright'):
  697.         ifd[COPYRIGHT] = im.encoderinfo['copyright']
  698.     dpi = im.encoderinfo.get('dpi')
  699.     if dpi:
  700.         ifd[RESOLUTION_UNIT] = 2
  701.         ifd[X_RESOLUTION] = _cvt_res(dpi[0])
  702.         ifd[Y_RESOLUTION] = _cvt_res(dpi[1])
  703.     if bits != (1,):
  704.         ifd[BITSPERSAMPLE] = bits
  705.         if len(bits) != 1:
  706.             ifd[SAMPLESPERPIXEL] = len(bits)
  707.         
  708.     if extra is not None:
  709.         ifd[EXTRASAMPLES] = extra
  710.     if format != 1:
  711.         ifd[SAMPLEFORMAT] = format
  712.     ifd[PHOTOMETRIC_INTERPRETATION] = photo
  713.     if im.mode == 'P':
  714.         lut = im.im.getpalette('RGB', 'RGB;L')
  715.         ifd[COLORMAP] = tuple(map((lambda v: ord(v) * 256), lut))
  716.     stride = len(bits) * ((im.size[0] * bits[0] + 7) / 8)
  717.     ifd[ROWSPERSTRIP] = im.size[1]
  718.     ifd[STRIPBYTECOUNTS] = stride * im.size[1]
  719.     ifd[STRIPOFFSETS] = 0
  720.     ifd[COMPRESSION] = 1
  721.     offset = ifd.save(fp)
  722.     ImageFile._save(im, fp, [
  723.         ('raw', (0, 0) + im.size, offset, (rawmode, stride, 1))])
  724.     if im.encoderinfo.has_key('_debug_multipage'):
  725.         im._debug_multipage = ifd
  726.  
  727. Image.register_open('TIFF', TiffImageFile, _accept)
  728. Image.register_save('TIFF', _save)
  729. Image.register_extension('TIFF', '.tif')
  730. Image.register_extension('TIFF', '.tiff')
  731. Image.register_mime('TIFF', 'image/tiff')
  732.