You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1832 lines
63 KiB

4 years ago
  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # TIFF file handling
  6. #
  7. # TIFF is a flexible, if somewhat aged, image file format originally
  8. # defined by Aldus. Although TIFF supports a wide variety of pixel
  9. # layouts and compression methods, the name doesn't really stand for
  10. # "thousands of incompatible file formats," it just feels that way.
  11. #
  12. # To read TIFF data from a stream, the stream must be seekable. For
  13. # progressive decoding, make sure to use TIFF files where the tag
  14. # directory is placed first in the file.
  15. #
  16. # History:
  17. # 1995-09-01 fl Created
  18. # 1996-05-04 fl Handle JPEGTABLES tag
  19. # 1996-05-18 fl Fixed COLORMAP support
  20. # 1997-01-05 fl Fixed PREDICTOR support
  21. # 1997-08-27 fl Added support for rational tags (from Perry Stoll)
  22. # 1998-01-10 fl Fixed seek/tell (from Jan Blom)
  23. # 1998-07-15 fl Use private names for internal variables
  24. # 1999-06-13 fl Rewritten for PIL 1.0 (1.0)
  25. # 2000-10-11 fl Additional fixes for Python 2.0 (1.1)
  26. # 2001-04-17 fl Fixed rewind support (seek to frame 0) (1.2)
  27. # 2001-05-12 fl Added write support for more tags (from Greg Couch) (1.3)
  28. # 2001-12-18 fl Added workaround for broken Matrox library
  29. # 2002-01-18 fl Don't mess up if photometric tag is missing (D. Alan Stewart)
  30. # 2003-05-19 fl Check FILLORDER tag
  31. # 2003-09-26 fl Added RGBa support
  32. # 2004-02-24 fl Added DPI support; fixed rational write support
  33. # 2005-02-07 fl Added workaround for broken Corel Draw 10 files
  34. # 2006-01-09 fl Added support for float/double tags (from Russell Nelson)
  35. #
  36. # Copyright (c) 1997-2006 by Secret Labs AB. All rights reserved.
  37. # Copyright (c) 1995-1997 by Fredrik Lundh
  38. #
  39. # See the README file for information on usage and redistribution.
  40. #
  41. from __future__ import division, print_function
  42. from . import Image, ImageFile, ImagePalette, TiffTags
  43. from ._binary import i8, o8
  44. from ._util import py3
  45. from fractions import Fraction
  46. from numbers import Number, Rational
  47. import io
  48. import itertools
  49. import os
  50. import struct
  51. import sys
  52. import warnings
  53. from .TiffTags import TYPES
  54. try:
  55. # Python 3
  56. from collections.abc import MutableMapping
  57. except ImportError:
  58. # Python 2.7
  59. from collections import MutableMapping
  60. __version__ = "1.3.5"
  61. DEBUG = False # Needs to be merged with the new logging approach.
  62. # Set these to true to force use of libtiff for reading or writing.
  63. READ_LIBTIFF = False
  64. WRITE_LIBTIFF = False
  65. IFD_LEGACY_API = True
  66. II = b"II" # little-endian (Intel style)
  67. MM = b"MM" # big-endian (Motorola style)
  68. #
  69. # --------------------------------------------------------------------
  70. # Read TIFF files
  71. # a few tag names, just to make the code below a bit more readable
  72. IMAGEWIDTH = 256
  73. IMAGELENGTH = 257
  74. BITSPERSAMPLE = 258
  75. COMPRESSION = 259
  76. PHOTOMETRIC_INTERPRETATION = 262
  77. FILLORDER = 266
  78. IMAGEDESCRIPTION = 270
  79. STRIPOFFSETS = 273
  80. SAMPLESPERPIXEL = 277
  81. ROWSPERSTRIP = 278
  82. STRIPBYTECOUNTS = 279
  83. X_RESOLUTION = 282
  84. Y_RESOLUTION = 283
  85. PLANAR_CONFIGURATION = 284
  86. RESOLUTION_UNIT = 296
  87. SOFTWARE = 305
  88. DATE_TIME = 306
  89. ARTIST = 315
  90. PREDICTOR = 317
  91. COLORMAP = 320
  92. TILEOFFSETS = 324
  93. EXTRASAMPLES = 338
  94. SAMPLEFORMAT = 339
  95. JPEGTABLES = 347
  96. COPYRIGHT = 33432
  97. IPTC_NAA_CHUNK = 33723 # newsphoto properties
  98. PHOTOSHOP_CHUNK = 34377 # photoshop properties
  99. ICCPROFILE = 34675
  100. EXIFIFD = 34665
  101. XMP = 700
  102. # https://github.com/imagej/ImageJA/blob/master/src/main/java/ij/io/TiffDecoder.java
  103. IMAGEJ_META_DATA_BYTE_COUNTS = 50838
  104. IMAGEJ_META_DATA = 50839
  105. COMPRESSION_INFO = {
  106. # Compression => pil compression name
  107. 1: "raw",
  108. 2: "tiff_ccitt",
  109. 3: "group3",
  110. 4: "group4",
  111. 5: "tiff_lzw",
  112. 6: "tiff_jpeg", # obsolete
  113. 7: "jpeg",
  114. 8: "tiff_adobe_deflate",
  115. 32771: "tiff_raw_16", # 16-bit padding
  116. 32773: "packbits",
  117. 32809: "tiff_thunderscan",
  118. 32946: "tiff_deflate",
  119. 34676: "tiff_sgilog",
  120. 34677: "tiff_sgilog24",
  121. }
  122. COMPRESSION_INFO_REV = {v: k for k, v in COMPRESSION_INFO.items()}
  123. OPEN_INFO = {
  124. # (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
  125. # ExtraSamples) => mode, rawmode
  126. (II, 0, (1,), 1, (1,), ()): ("1", "1;I"),
  127. (MM, 0, (1,), 1, (1,), ()): ("1", "1;I"),
  128. (II, 0, (1,), 2, (1,), ()): ("1", "1;IR"),
  129. (MM, 0, (1,), 2, (1,), ()): ("1", "1;IR"),
  130. (II, 1, (1,), 1, (1,), ()): ("1", "1"),
  131. (MM, 1, (1,), 1, (1,), ()): ("1", "1"),
  132. (II, 1, (1,), 2, (1,), ()): ("1", "1;R"),
  133. (MM, 1, (1,), 2, (1,), ()): ("1", "1;R"),
  134. (II, 0, (1,), 1, (2,), ()): ("L", "L;2I"),
  135. (MM, 0, (1,), 1, (2,), ()): ("L", "L;2I"),
  136. (II, 0, (1,), 2, (2,), ()): ("L", "L;2IR"),
  137. (MM, 0, (1,), 2, (2,), ()): ("L", "L;2IR"),
  138. (II, 1, (1,), 1, (2,), ()): ("L", "L;2"),
  139. (MM, 1, (1,), 1, (2,), ()): ("L", "L;2"),
  140. (II, 1, (1,), 2, (2,), ()): ("L", "L;2R"),
  141. (MM, 1, (1,), 2, (2,), ()): ("L", "L;2R"),
  142. (II, 0, (1,), 1, (4,), ()): ("L", "L;4I"),
  143. (MM, 0, (1,), 1, (4,), ()): ("L", "L;4I"),
  144. (II, 0, (1,), 2, (4,), ()): ("L", "L;4IR"),
  145. (MM, 0, (1,), 2, (4,), ()): ("L", "L;4IR"),
  146. (II, 1, (1,), 1, (4,), ()): ("L", "L;4"),
  147. (MM, 1, (1,), 1, (4,), ()): ("L", "L;4"),
  148. (II, 1, (1,), 2, (4,), ()): ("L", "L;4R"),
  149. (MM, 1, (1,), 2, (4,), ()): ("L", "L;4R"),
  150. (II, 0, (1,), 1, (8,), ()): ("L", "L;I"),
  151. (MM, 0, (1,), 1, (8,), ()): ("L", "L;I"),
  152. (II, 0, (1,), 2, (8,), ()): ("L", "L;IR"),
  153. (MM, 0, (1,), 2, (8,), ()): ("L", "L;IR"),
  154. (II, 1, (1,), 1, (8,), ()): ("L", "L"),
  155. (MM, 1, (1,), 1, (8,), ()): ("L", "L"),
  156. (II, 1, (1,), 2, (8,), ()): ("L", "L;R"),
  157. (MM, 1, (1,), 2, (8,), ()): ("L", "L;R"),
  158. (II, 1, (1,), 1, (12,), ()): ("I;16", "I;12"),
  159. (II, 1, (1,), 1, (16,), ()): ("I;16", "I;16"),
  160. (MM, 1, (1,), 1, (16,), ()): ("I;16B", "I;16B"),
  161. (II, 1, (2,), 1, (16,), ()): ("I", "I;16S"),
  162. (MM, 1, (2,), 1, (16,), ()): ("I", "I;16BS"),
  163. (II, 0, (3,), 1, (32,), ()): ("F", "F;32F"),
  164. (MM, 0, (3,), 1, (32,), ()): ("F", "F;32BF"),
  165. (II, 1, (1,), 1, (32,), ()): ("I", "I;32N"),
  166. (II, 1, (2,), 1, (32,), ()): ("I", "I;32S"),
  167. (MM, 1, (2,), 1, (32,), ()): ("I", "I;32BS"),
  168. (II, 1, (3,), 1, (32,), ()): ("F", "F;32F"),
  169. (MM, 1, (3,), 1, (32,), ()): ("F", "F;32BF"),
  170. (II, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"),
  171. (MM, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"),
  172. (II, 2, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
  173. (MM, 2, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
  174. (II, 2, (1,), 2, (8, 8, 8), ()): ("RGB", "RGB;R"),
  175. (MM, 2, (1,), 2, (8, 8, 8), ()): ("RGB", "RGB;R"),
  176. (II, 2, (1,), 1, (8, 8, 8, 8), ()): ("RGBA", "RGBA"), # missing ExtraSamples
  177. (MM, 2, (1,), 1, (8, 8, 8, 8), ()): ("RGBA", "RGBA"), # missing ExtraSamples
  178. (II, 2, (1,), 1, (8, 8, 8, 8), (0,)): ("RGBX", "RGBX"),
  179. (MM, 2, (1,), 1, (8, 8, 8, 8), (0,)): ("RGBX", "RGBX"),
  180. (II, 2, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("RGBX", "RGBXX"),
  181. (MM, 2, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("RGBX", "RGBXX"),
  182. (II, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("RGBX", "RGBXXX"),
  183. (MM, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("RGBX", "RGBXXX"),
  184. (II, 2, (1,), 1, (8, 8, 8, 8), (1,)): ("RGBA", "RGBa"),
  185. (MM, 2, (1,), 1, (8, 8, 8, 8), (1,)): ("RGBA", "RGBa"),
  186. (II, 2, (1,), 1, (8, 8, 8, 8, 8), (1, 0)): ("RGBA", "RGBaX"),
  187. (MM, 2, (1,), 1, (8, 8, 8, 8, 8), (1, 0)): ("RGBA", "RGBaX"),
  188. (II, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (1, 0, 0)): ("RGBA", "RGBaXX"),
  189. (MM, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (1, 0, 0)): ("RGBA", "RGBaXX"),
  190. (II, 2, (1,), 1, (8, 8, 8, 8), (2,)): ("RGBA", "RGBA"),
  191. (MM, 2, (1,), 1, (8, 8, 8, 8), (2,)): ("RGBA", "RGBA"),
  192. (II, 2, (1,), 1, (8, 8, 8, 8, 8), (2, 0)): ("RGBA", "RGBAX"),
  193. (MM, 2, (1,), 1, (8, 8, 8, 8, 8), (2, 0)): ("RGBA", "RGBAX"),
  194. (II, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (2, 0, 0)): ("RGBA", "RGBAXX"),
  195. (MM, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (2, 0, 0)): ("RGBA", "RGBAXX"),
  196. (II, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10
  197. (MM, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10
  198. (II, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16L"),
  199. (MM, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16B"),
  200. (II, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16L"),
  201. (MM, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16B"),
  202. (II, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGBX", "RGBX;16L"),
  203. (MM, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGBX", "RGBX;16B"),
  204. (II, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16L"),
  205. (MM, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16B"),
  206. (II, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16L"),
  207. (MM, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16B"),
  208. (II, 3, (1,), 1, (1,), ()): ("P", "P;1"),
  209. (MM, 3, (1,), 1, (1,), ()): ("P", "P;1"),
  210. (II, 3, (1,), 2, (1,), ()): ("P", "P;1R"),
  211. (MM, 3, (1,), 2, (1,), ()): ("P", "P;1R"),
  212. (II, 3, (1,), 1, (2,), ()): ("P", "P;2"),
  213. (MM, 3, (1,), 1, (2,), ()): ("P", "P;2"),
  214. (II, 3, (1,), 2, (2,), ()): ("P", "P;2R"),
  215. (MM, 3, (1,), 2, (2,), ()): ("P", "P;2R"),
  216. (II, 3, (1,), 1, (4,), ()): ("P", "P;4"),
  217. (MM, 3, (1,), 1, (4,), ()): ("P", "P;4"),
  218. (II, 3, (1,), 2, (4,), ()): ("P", "P;4R"),
  219. (MM, 3, (1,), 2, (4,), ()): ("P", "P;4R"),
  220. (II, 3, (1,), 1, (8,), ()): ("P", "P"),
  221. (MM, 3, (1,), 1, (8,), ()): ("P", "P"),
  222. (II, 3, (1,), 1, (8, 8), (2,)): ("PA", "PA"),
  223. (MM, 3, (1,), 1, (8, 8), (2,)): ("PA", "PA"),
  224. (II, 3, (1,), 2, (8,), ()): ("P", "P;R"),
  225. (MM, 3, (1,), 2, (8,), ()): ("P", "P;R"),
  226. (II, 5, (1,), 1, (8, 8, 8, 8), ()): ("CMYK", "CMYK"),
  227. (MM, 5, (1,), 1, (8, 8, 8, 8), ()): ("CMYK", "CMYK"),
  228. (II, 5, (1,), 1, (8, 8, 8, 8, 8), (0,)): ("CMYK", "CMYKX"),
  229. (MM, 5, (1,), 1, (8, 8, 8, 8, 8), (0,)): ("CMYK", "CMYKX"),
  230. (II, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
  231. (MM, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
  232. # JPEG compressed images handled by LibTiff and auto-converted to RGB
  233. # Minimal Baseline TIFF requires YCbCr images to have 3 SamplesPerPixel
  234. (II, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
  235. (MM, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
  236. (II, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
  237. (MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
  238. }
  239. PREFIXES = [
  240. b"MM\x00\x2A", # Valid TIFF header with big-endian byte order
  241. b"II\x2A\x00", # Valid TIFF header with little-endian byte order
  242. b"MM\x2A\x00", # Invalid TIFF header, assume big-endian
  243. b"II\x00\x2A", # Invalid TIFF header, assume little-endian
  244. ]
  245. def _accept(prefix):
  246. return prefix[:4] in PREFIXES
  247. def _limit_rational(val, max_val):
  248. inv = abs(val) > 1
  249. n_d = IFDRational(1 / val if inv else val).limit_rational(max_val)
  250. return n_d[::-1] if inv else n_d
  251. ##
  252. # Wrapper for TIFF IFDs.
  253. _load_dispatch = {}
  254. _write_dispatch = {}
  255. class IFDRational(Rational):
  256. """ Implements a rational class where 0/0 is a legal value to match
  257. the in the wild use of exif rationals.
  258. e.g., DigitalZoomRatio - 0.00/0.00 indicates that no digital zoom was used
  259. """
  260. """ If the denominator is 0, store this as a float('nan'), otherwise store
  261. as a fractions.Fraction(). Delegate as appropriate
  262. """
  263. __slots__ = ('_numerator', '_denominator', '_val')
  264. def __init__(self, value, denominator=1):
  265. """
  266. :param value: either an integer numerator, a
  267. float/rational/other number, or an IFDRational
  268. :param denominator: Optional integer denominator
  269. """
  270. self._denominator = denominator
  271. self._numerator = value
  272. self._val = float(1)
  273. if isinstance(value, Fraction):
  274. self._numerator = value.numerator
  275. self._denominator = value.denominator
  276. self._val = value
  277. if isinstance(value, IFDRational):
  278. self._denominator = value.denominator
  279. self._numerator = value.numerator
  280. self._val = value._val
  281. return
  282. if denominator == 0:
  283. self._val = float('nan')
  284. return
  285. elif denominator == 1:
  286. self._val = Fraction(value)
  287. else:
  288. self._val = Fraction(value, denominator)
  289. @property
  290. def numerator(a):
  291. return a._numerator
  292. @property
  293. def denominator(a):
  294. return a._denominator
  295. def limit_rational(self, max_denominator):
  296. """
  297. :param max_denominator: Integer, the maximum denominator value
  298. :returns: Tuple of (numerator, denominator)
  299. """
  300. if self.denominator == 0:
  301. return (self.numerator, self.denominator)
  302. f = self._val.limit_denominator(max_denominator)
  303. return (f.numerator, f.denominator)
  304. def __repr__(self):
  305. return str(float(self._val))
  306. def __hash__(self):
  307. return self._val.__hash__()
  308. def __eq__(self, other):
  309. return self._val == other
  310. def _delegate(op):
  311. def delegate(self, *args):
  312. return getattr(self._val, op)(*args)
  313. return delegate
  314. """ a = ['add','radd', 'sub', 'rsub','div', 'rdiv', 'mul', 'rmul',
  315. 'truediv', 'rtruediv', 'floordiv',
  316. 'rfloordiv','mod','rmod', 'pow','rpow', 'pos', 'neg',
  317. 'abs', 'trunc', 'lt', 'gt', 'le', 'ge', 'nonzero',
  318. 'ceil', 'floor', 'round']
  319. print("\n".join("__%s__ = _delegate('__%s__')" % (s,s) for s in a))
  320. """
  321. __add__ = _delegate('__add__')
  322. __radd__ = _delegate('__radd__')
  323. __sub__ = _delegate('__sub__')
  324. __rsub__ = _delegate('__rsub__')
  325. __div__ = _delegate('__div__')
  326. __rdiv__ = _delegate('__rdiv__')
  327. __mul__ = _delegate('__mul__')
  328. __rmul__ = _delegate('__rmul__')
  329. __truediv__ = _delegate('__truediv__')
  330. __rtruediv__ = _delegate('__rtruediv__')
  331. __floordiv__ = _delegate('__floordiv__')
  332. __rfloordiv__ = _delegate('__rfloordiv__')
  333. __mod__ = _delegate('__mod__')
  334. __rmod__ = _delegate('__rmod__')
  335. __pow__ = _delegate('__pow__')
  336. __rpow__ = _delegate('__rpow__')
  337. __pos__ = _delegate('__pos__')
  338. __neg__ = _delegate('__neg__')
  339. __abs__ = _delegate('__abs__')
  340. __trunc__ = _delegate('__trunc__')
  341. __lt__ = _delegate('__lt__')
  342. __gt__ = _delegate('__gt__')
  343. __le__ = _delegate('__le__')
  344. __ge__ = _delegate('__ge__')
  345. __nonzero__ = _delegate('__nonzero__')
  346. __ceil__ = _delegate('__ceil__')
  347. __floor__ = _delegate('__floor__')
  348. __round__ = _delegate('__round__')
  349. class ImageFileDirectory_v2(MutableMapping):
  350. """This class represents a TIFF tag directory. To speed things up, we
  351. don't decode tags unless they're asked for.
  352. Exposes a dictionary interface of the tags in the directory::
  353. ifd = ImageFileDirectory_v2()
  354. ifd[key] = 'Some Data'
  355. ifd.tagtype[key] = 2
  356. print(ifd[key])
  357. 'Some Data'
  358. Individual values are returned as the strings or numbers, sequences are
  359. returned as tuples of the values.
  360. The tiff metadata type of each item is stored in a dictionary of
  361. tag types in
  362. `~PIL.TiffImagePlugin.ImageFileDirectory_v2.tagtype`. The types
  363. are read from a tiff file, guessed from the type added, or added
  364. manually.
  365. Data Structures:
  366. * self.tagtype = {}
  367. * Key: numerical tiff tag number
  368. * Value: integer corresponding to the data type from
  369. ~PIL.TiffTags.TYPES`
  370. .. versionadded:: 3.0.0
  371. """
  372. """
  373. Documentation:
  374. 'internal' data structures:
  375. * self._tags_v2 = {} Key: numerical tiff tag number
  376. Value: decoded data, as tuple for multiple values
  377. * self._tagdata = {} Key: numerical tiff tag number
  378. Value: undecoded byte string from file
  379. * self._tags_v1 = {} Key: numerical tiff tag number
  380. Value: decoded data in the v1 format
  381. Tags will be found in the private attributes self._tagdata, and in
  382. self._tags_v2 once decoded.
  383. Self.legacy_api is a value for internal use, and shouldn't be
  384. changed from outside code. In cooperation with the
  385. ImageFileDirectory_v1 class, if legacy_api is true, then decoded
  386. tags will be populated into both _tags_v1 and _tags_v2. _Tags_v2
  387. will be used if this IFD is used in the TIFF save routine. Tags
  388. should be read from tags_v1 if legacy_api == true.
  389. """
  390. def __init__(self, ifh=b"II\052\0\0\0\0\0", prefix=None):
  391. """Initialize an ImageFileDirectory.
  392. To construct an ImageFileDirectory from a real file, pass the 8-byte
  393. magic header to the constructor. To only set the endianness, pass it
  394. as the 'prefix' keyword argument.
  395. :param ifh: One of the accepted magic headers (cf. PREFIXES); also sets
  396. endianness.
  397. :param prefix: Override the endianness of the file.
  398. """
  399. if ifh[:4] not in PREFIXES:
  400. raise SyntaxError("not a TIFF file (header %r not valid)" % ifh)
  401. self._prefix = prefix if prefix is not None else ifh[:2]
  402. if self._prefix == MM:
  403. self._endian = ">"
  404. elif self._prefix == II:
  405. self._endian = "<"
  406. else:
  407. raise SyntaxError("not a TIFF IFD")
  408. self.reset()
  409. self.next, = self._unpack("L", ifh[4:])
  410. self._legacy_api = False
  411. prefix = property(lambda self: self._prefix)
  412. offset = property(lambda self: self._offset)
  413. legacy_api = property(lambda self: self._legacy_api)
  414. @legacy_api.setter
  415. def legacy_api(self, value):
  416. raise Exception("Not allowing setting of legacy api")
  417. def reset(self):
  418. self._tags_v1 = {} # will remain empty if legacy_api is false
  419. self._tags_v2 = {} # main tag storage
  420. self._tagdata = {}
  421. self.tagtype = {} # added 2008-06-05 by Florian Hoech
  422. self._next = None
  423. self._offset = None
  424. def __str__(self):
  425. return str(dict(self))
  426. def named(self):
  427. """
  428. :returns: dict of name|key: value
  429. Returns the complete tag dictionary, with named tags where possible.
  430. """
  431. return dict((TiffTags.lookup(code).name, value)
  432. for code, value in self.items())
  433. def __len__(self):
  434. return len(set(self._tagdata) | set(self._tags_v2))
  435. def __getitem__(self, tag):
  436. if tag not in self._tags_v2: # unpack on the fly
  437. data = self._tagdata[tag]
  438. typ = self.tagtype[tag]
  439. size, handler = self._load_dispatch[typ]
  440. self[tag] = handler(self, data, self.legacy_api) # check type
  441. val = self._tags_v2[tag]
  442. if self.legacy_api and not isinstance(val, (tuple, bytes)):
  443. val = val,
  444. return val
  445. def __contains__(self, tag):
  446. return tag in self._tags_v2 or tag in self._tagdata
  447. if not py3:
  448. def has_key(self, tag):
  449. return tag in self
  450. def __setitem__(self, tag, value):
  451. self._setitem(tag, value, self.legacy_api)
  452. def _setitem(self, tag, value, legacy_api):
  453. basetypes = (Number, bytes, str)
  454. if not py3:
  455. basetypes += unicode,
  456. info = TiffTags.lookup(tag)
  457. values = [value] if isinstance(value, basetypes) else value
  458. if tag not in self.tagtype:
  459. if info.type:
  460. self.tagtype[tag] = info.type
  461. else:
  462. self.tagtype[tag] = 7
  463. if all(isinstance(v, IFDRational) for v in values):
  464. self.tagtype[tag] = 5
  465. elif all(isinstance(v, int) for v in values):
  466. if all(v < 2 ** 16 for v in values):
  467. self.tagtype[tag] = 3
  468. else:
  469. self.tagtype[tag] = 4
  470. elif all(isinstance(v, float) for v in values):
  471. self.tagtype[tag] = 12
  472. else:
  473. if py3:
  474. if all(isinstance(v, str) for v in values):
  475. self.tagtype[tag] = 2
  476. else:
  477. # Never treat data as binary by default on Python 2.
  478. self.tagtype[tag] = 2
  479. if self.tagtype[tag] == 7 and py3:
  480. values = [value.encode("ascii", 'replace') if isinstance(
  481. value, str) else value]
  482. elif self.tagtype[tag] == 5:
  483. values = [float(v) if isinstance(v, int) else v
  484. for v in values]
  485. values = tuple(info.cvt_enum(value) for value in values)
  486. dest = self._tags_v1 if legacy_api else self._tags_v2
  487. # Three branches:
  488. # Spec'd length == 1, Actual length 1, store as element
  489. # Spec'd length == 1, Actual > 1, Warn and truncate. Formerly barfed.
  490. # No Spec, Actual length 1, Formerly (<4.2) returned a 1 element tuple.
  491. # Don't mess with the legacy api, since it's frozen.
  492. if (info.length == 1) or \
  493. (info.length is None and len(values) == 1 and not legacy_api):
  494. # Don't mess with the legacy api, since it's frozen.
  495. if legacy_api and self.tagtype[tag] in [5, 10]: # rationals
  496. values = values,
  497. try:
  498. dest[tag], = values
  499. except ValueError:
  500. # We've got a builtin tag with 1 expected entry
  501. warnings.warn(
  502. "Metadata Warning, tag %s had too many entries: %s, expected 1" % (
  503. tag, len(values)))
  504. dest[tag] = values[0]
  505. else:
  506. # Spec'd length > 1 or undefined
  507. # Unspec'd, and length > 1
  508. dest[tag] = values
  509. def __delitem__(self, tag):
  510. self._tags_v2.pop(tag, None)
  511. self._tags_v1.pop(tag, None)
  512. self._tagdata.pop(tag, None)
  513. def __iter__(self):
  514. return iter(set(self._tagdata) | set(self._tags_v2))
  515. def _unpack(self, fmt, data):
  516. return struct.unpack(self._endian + fmt, data)
  517. def _pack(self, fmt, *values):
  518. return struct.pack(self._endian + fmt, *values)
  519. def _register_loader(idx, size):
  520. def decorator(func):
  521. from .TiffTags import TYPES
  522. if func.__name__.startswith("load_"):
  523. TYPES[idx] = func.__name__[5:].replace("_", " ")
  524. _load_dispatch[idx] = size, func
  525. return func
  526. return decorator
  527. def _register_writer(idx):
  528. def decorator(func):
  529. _write_dispatch[idx] = func
  530. return func
  531. return decorator
  532. def _register_basic(idx_fmt_name):
  533. from .TiffTags import TYPES
  534. idx, fmt, name = idx_fmt_name
  535. TYPES[idx] = name
  536. size = struct.calcsize("=" + fmt)
  537. _load_dispatch[idx] = size, lambda self, data, legacy_api=True: (
  538. self._unpack("{}{}".format(len(data) // size, fmt), data))
  539. _write_dispatch[idx] = lambda self, *values: (
  540. b"".join(self._pack(fmt, value) for value in values))
  541. list(map(_register_basic,
  542. [(3, "H", "short"),
  543. (4, "L", "long"),
  544. (6, "b", "signed byte"),
  545. (8, "h", "signed short"),
  546. (9, "l", "signed long"),
  547. (11, "f", "float"),
  548. (12, "d", "double")]))
  549. @_register_loader(1, 1) # Basic type, except for the legacy API.
  550. def load_byte(self, data, legacy_api=True):
  551. return data
  552. @_register_writer(1) # Basic type, except for the legacy API.
  553. def write_byte(self, data):
  554. return data
  555. @_register_loader(2, 1)
  556. def load_string(self, data, legacy_api=True):
  557. if data.endswith(b"\0"):
  558. data = data[:-1]
  559. return data.decode("latin-1", "replace")
  560. @_register_writer(2)
  561. def write_string(self, value):
  562. # remerge of https://github.com/python-pillow/Pillow/pull/1416
  563. if sys.version_info.major == 2:
  564. value = value.decode('ascii', 'replace')
  565. return b"" + value.encode('ascii', 'replace') + b"\0"
  566. @_register_loader(5, 8)
  567. def load_rational(self, data, legacy_api=True):
  568. vals = self._unpack("{}L".format(len(data) // 4), data)
  569. def combine(a, b): return (a, b) if legacy_api else IFDRational(a, b)
  570. return tuple(combine(num, denom)
  571. for num, denom in zip(vals[::2], vals[1::2]))
  572. @_register_writer(5)
  573. def write_rational(self, *values):
  574. return b"".join(self._pack("2L", *_limit_rational(frac, 2 ** 31))
  575. for frac in values)
  576. @_register_loader(7, 1)
  577. def load_undefined(self, data, legacy_api=True):
  578. return data
  579. @_register_writer(7)
  580. def write_undefined(self, value):
  581. return value
  582. @_register_loader(10, 8)
  583. def load_signed_rational(self, data, legacy_api=True):
  584. vals = self._unpack("{}l".format(len(data) // 4), data)
  585. def combine(a, b): return (a, b) if legacy_api else IFDRational(a, b)
  586. return tuple(combine(num, denom)
  587. for num, denom in zip(vals[::2], vals[1::2]))
  588. @_register_writer(10)
  589. def write_signed_rational(self, *values):
  590. return b"".join(self._pack("2L", *_limit_rational(frac, 2 ** 30))
  591. for frac in values)
  592. def _ensure_read(self, fp, size):
  593. ret = fp.read(size)
  594. if len(ret) != size:
  595. raise IOError("Corrupt EXIF data. " +
  596. "Expecting to read %d bytes but only got %d. " %
  597. (size, len(ret)))
  598. return ret
  599. def load(self, fp):
  600. self.reset()
  601. self._offset = fp.tell()
  602. try:
  603. for i in range(self._unpack("H", self._ensure_read(fp, 2))[0]):
  604. tag, typ, count, data = self._unpack("HHL4s",
  605. self._ensure_read(fp, 12))
  606. if DEBUG:
  607. tagname = TiffTags.lookup(tag).name
  608. typname = TYPES.get(typ, "unknown")
  609. print("tag: %s (%d) - type: %s (%d)" %
  610. (tagname, tag, typname, typ), end=" ")
  611. try:
  612. unit_size, handler = self._load_dispatch[typ]
  613. except KeyError:
  614. if DEBUG:
  615. print("- unsupported type", typ)
  616. continue # ignore unsupported type
  617. size = count * unit_size
  618. if size > 4:
  619. here = fp.tell()
  620. offset, = self._unpack("L", data)
  621. if DEBUG:
  622. print("Tag Location: %s - Data Location: %s" %
  623. (here, offset), end=" ")
  624. fp.seek(offset)
  625. data = ImageFile._safe_read(fp, size)
  626. fp.seek(here)
  627. else:
  628. data = data[:size]
  629. if len(data) != size:
  630. warnings.warn("Possibly corrupt EXIF data. "
  631. "Expecting to read %d bytes but only got %d."
  632. " Skipping tag %s" % (size, len(data), tag))
  633. continue
  634. if not data:
  635. continue
  636. self._tagdata[tag] = data
  637. self.tagtype[tag] = typ
  638. if DEBUG:
  639. if size > 32:
  640. print("- value: <table: %d bytes>" % size)
  641. else:
  642. print("- value:", self[tag])
  643. self.next, = self._unpack("L", self._ensure_read(fp, 4))
  644. except IOError as msg:
  645. warnings.warn(str(msg))
  646. return
  647. def save(self, fp):
  648. if fp.tell() == 0: # skip TIFF header on subsequent pages
  649. # tiff header -- PIL always starts the first IFD at offset 8
  650. fp.write(self._prefix + self._pack("HL", 42, 8))
  651. # FIXME What about tagdata?
  652. fp.write(self._pack("H", len(self._tags_v2)))
  653. entries = []
  654. offset = fp.tell() + len(self._tags_v2) * 12 + 4
  655. stripoffsets = None
  656. # pass 1: convert tags to binary format
  657. # always write tags in ascending order
  658. for tag, value in sorted(self._tags_v2.items()):
  659. if tag == STRIPOFFSETS:
  660. stripoffsets = len(entries)
  661. typ = self.tagtype.get(tag)
  662. if DEBUG:
  663. print("Tag %s, Type: %s, Value: %s" % (tag, typ, value))
  664. values = value if isinstance(value, tuple) else (value,)
  665. data = self._write_dispatch[typ](self, *values)
  666. if DEBUG:
  667. tagname = TiffTags.lookup(tag).name
  668. typname = TYPES.get(typ, "unknown")
  669. print("save: %s (%d) - type: %s (%d)" %
  670. (tagname, tag, typname, typ), end=" ")
  671. if len(data) >= 16:
  672. print("- value: <table: %d bytes>" % len(data))
  673. else:
  674. print("- value:", values)
  675. # count is sum of lengths for string and arbitrary data
  676. count = len(data) if typ in [2, 7] else len(values)
  677. # figure out if data fits into the entry
  678. if len(data) <= 4:
  679. entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
  680. else:
  681. entries.append((tag, typ, count, self._pack("L", offset),
  682. data))
  683. offset += (len(data) + 1) // 2 * 2 # pad to word
  684. # update strip offset data to point beyond auxiliary data
  685. if stripoffsets is not None:
  686. tag, typ, count, value, data = entries[stripoffsets]
  687. if data:
  688. raise NotImplementedError(
  689. "multistrip support not yet implemented")
  690. value = self._pack("L", self._unpack("L", value)[0] + offset)
  691. entries[stripoffsets] = tag, typ, count, value, data
  692. # pass 2: write entries to file
  693. for tag, typ, count, value, data in entries:
  694. if DEBUG > 1:
  695. print(tag, typ, count, repr(value), repr(data))
  696. fp.write(self._pack("HHL4s", tag, typ, count, value))
  697. # -- overwrite here for multi-page --
  698. fp.write(b"\0\0\0\0") # end of entries
  699. # pass 3: write auxiliary data to file
  700. for tag, typ, count, value, data in entries:
  701. fp.write(data)
  702. if len(data) & 1:
  703. fp.write(b"\0")
  704. return offset
  705. ImageFileDirectory_v2._load_dispatch = _load_dispatch
  706. ImageFileDirectory_v2._write_dispatch = _write_dispatch
  707. for idx, name in TYPES.items():
  708. name = name.replace(" ", "_")
  709. setattr(ImageFileDirectory_v2, "load_" + name, _load_dispatch[idx][1])
  710. setattr(ImageFileDirectory_v2, "write_" + name, _write_dispatch[idx])
  711. del _load_dispatch, _write_dispatch, idx, name
  712. # Legacy ImageFileDirectory support.
  713. class ImageFileDirectory_v1(ImageFileDirectory_v2):
  714. """This class represents the **legacy** interface to a TIFF tag directory.
  715. Exposes a dictionary interface of the tags in the directory::
  716. ifd = ImageFileDirectory_v1()
  717. ifd[key] = 'Some Data'
  718. ifd.tagtype[key] = 2
  719. print(ifd[key])
  720. ('Some Data',)
  721. Also contains a dictionary of tag types as read from the tiff image file,
  722. `~PIL.TiffImagePlugin.ImageFileDirectory_v1.tagtype`.
  723. Values are returned as a tuple.
  724. .. deprecated:: 3.0.0
  725. """
  726. def __init__(self, *args, **kwargs):
  727. ImageFileDirectory_v2.__init__(self, *args, **kwargs)
  728. self._legacy_api = True
  729. tags = property(lambda self: self._tags_v1)
  730. tagdata = property(lambda self: self._tagdata)
  731. @classmethod
  732. def from_v2(cls, original):
  733. """ Returns an
  734. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`
  735. instance with the same data as is contained in the original
  736. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
  737. instance.
  738. :returns: :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`
  739. """
  740. ifd = cls(prefix=original.prefix)
  741. ifd._tagdata = original._tagdata
  742. ifd.tagtype = original.tagtype
  743. ifd.next = original.next # an indicator for multipage tiffs
  744. return ifd
  745. def to_v2(self):
  746. """ Returns an
  747. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
  748. instance with the same data as is contained in the original
  749. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`
  750. instance.
  751. :returns: :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
  752. """
  753. ifd = ImageFileDirectory_v2(prefix=self.prefix)
  754. ifd._tagdata = dict(self._tagdata)
  755. ifd.tagtype = dict(self.tagtype)
  756. ifd._tags_v2 = dict(self._tags_v2)
  757. return ifd
  758. def __contains__(self, tag):
  759. return tag in self._tags_v1 or tag in self._tagdata
  760. def __len__(self):
  761. return len(set(self._tagdata) | set(self._tags_v1))
  762. def __iter__(self):
  763. return iter(set(self._tagdata) | set(self._tags_v1))
  764. def __setitem__(self, tag, value):
  765. for legacy_api in (False, True):
  766. self._setitem(tag, value, legacy_api)
  767. def __getitem__(self, tag):
  768. if tag not in self._tags_v1: # unpack on the fly
  769. data = self._tagdata[tag]
  770. typ = self.tagtype[tag]
  771. size, handler = self._load_dispatch[typ]
  772. for legacy in (False, True):
  773. self._setitem(tag, handler(self, data, legacy), legacy)
  774. val = self._tags_v1[tag]
  775. if not isinstance(val, (tuple, bytes)):
  776. val = val,
  777. return val
  778. # undone -- switch this pointer when IFD_LEGACY_API == False
  779. ImageFileDirectory = ImageFileDirectory_v1
  780. ##
  781. # Image plugin for TIFF files.
  782. class TiffImageFile(ImageFile.ImageFile):
  783. format = "TIFF"
  784. format_description = "Adobe TIFF"
  785. _close_exclusive_fp_after_loading = False
  786. def _open(self):
  787. "Open the first image in a TIFF file"
  788. # Header
  789. ifh = self.fp.read(8)
  790. # image file directory (tag dictionary)
  791. self.tag_v2 = ImageFileDirectory_v2(ifh)
  792. # legacy tag/ifd entries will be filled in later
  793. self.tag = self.ifd = None
  794. # setup frame pointers
  795. self.__first = self.__next = self.tag_v2.next
  796. self.__frame = -1
  797. self.__fp = self.fp
  798. self._frame_pos = []
  799. self._n_frames = None
  800. self._is_animated = None
  801. if DEBUG:
  802. print("*** TiffImageFile._open ***")
  803. print("- __first:", self.__first)
  804. print("- ifh: ", ifh)
  805. # and load the first frame
  806. self._seek(0)
  807. @property
  808. def n_frames(self):
  809. if self._n_frames is None:
  810. current = self.tell()
  811. try:
  812. while True:
  813. self._seek(self.tell() + 1)
  814. except EOFError:
  815. self._n_frames = self.tell() + 1
  816. self.seek(current)
  817. return self._n_frames
  818. @property
  819. def is_animated(self):
  820. if self._is_animated is None:
  821. if self._n_frames is not None:
  822. self._is_animated = self._n_frames != 1
  823. else:
  824. current = self.tell()
  825. try:
  826. self.seek(1)
  827. self._is_animated = True
  828. except EOFError:
  829. self._is_animated = False
  830. self.seek(current)
  831. return self._is_animated
  832. def seek(self, frame):
  833. "Select a given frame as current image"
  834. if not self._seek_check(frame):
  835. return
  836. self._seek(frame)
  837. # Create a new core image object on second and
  838. # subsequent frames in the image. Image may be
  839. # different size/mode.
  840. Image._decompression_bomb_check(self.size)
  841. self.im = Image.core.new(self.mode, self.size)
  842. def _seek(self, frame):
  843. self.fp = self.__fp
  844. while len(self._frame_pos) <= frame:
  845. if not self.__next:
  846. raise EOFError("no more images in TIFF file")
  847. if DEBUG:
  848. print("Seeking to frame %s, on frame %s, "
  849. "__next %s, location: %s" %
  850. (frame, self.__frame, self.__next, self.fp.tell()))
  851. # reset python3 buffered io handle in case fp
  852. # was passed to libtiff, invalidating the buffer
  853. self.fp.tell()
  854. self.fp.seek(self.__next)
  855. self._frame_pos.append(self.__next)
  856. if DEBUG:
  857. print("Loading tags, location: %s" % self.fp.tell())
  858. self.tag_v2.load(self.fp)
  859. self.__next = self.tag_v2.next
  860. self.__frame += 1
  861. self.fp.seek(self._frame_pos[frame])
  862. self.tag_v2.load(self.fp)
  863. self.__next = self.tag_v2.next
  864. # fill the legacy tag/ifd entries
  865. self.tag = self.ifd = ImageFileDirectory_v1.from_v2(self.tag_v2)
  866. self.__frame = frame
  867. self._setup()
  868. def tell(self):
  869. "Return the current frame number"
  870. return self.__frame
  871. @property
  872. def size(self):
  873. return self._size
  874. @size.setter
  875. def size(self, value):
  876. warnings.warn(
  877. 'Setting the size of a TIFF image directly is deprecated, and will'
  878. ' be removed in a future version. Use the resize method instead.',
  879. DeprecationWarning
  880. )
  881. self._size = value
  882. def load(self):
  883. if self.use_load_libtiff:
  884. return self._load_libtiff()
  885. return super(TiffImageFile, self).load()
  886. def load_end(self):
  887. # allow closing if we're on the first frame, there's no next
  888. # This is the ImageFile.load path only, libtiff specific below.
  889. if self.__frame == 0 and not self.__next:
  890. self._close_exclusive_fp_after_loading = True
  891. def _load_libtiff(self):
  892. """ Overload method triggered when we detect a compressed tiff
  893. Calls out to libtiff """
  894. pixel = Image.Image.load(self)
  895. if self.tile is None:
  896. raise IOError("cannot load this image")
  897. if not self.tile:
  898. return pixel
  899. self.load_prepare()
  900. if not len(self.tile) == 1:
  901. raise IOError("Not exactly one tile")
  902. # (self._compression, (extents tuple),
  903. # 0, (rawmode, self._compression, fp))
  904. extents = self.tile[0][1]
  905. args = list(self.tile[0][3]) + [self.tag_v2.offset]
  906. # To be nice on memory footprint, if there's a
  907. # file descriptor, use that instead of reading
  908. # into a string in python.
  909. # libtiff closes the file descriptor, so pass in a dup.
  910. try:
  911. fp = hasattr(self.fp, "fileno") and os.dup(self.fp.fileno())
  912. # flush the file descriptor, prevents error on pypy 2.4+
  913. # should also eliminate the need for fp.tell for py3
  914. # in _seek
  915. if hasattr(self.fp, "flush"):
  916. self.fp.flush()
  917. except IOError:
  918. # io.BytesIO have a fileno, but returns an IOError if
  919. # it doesn't use a file descriptor.
  920. fp = False
  921. if fp:
  922. args[2] = fp
  923. decoder = Image._getdecoder(self.mode, 'libtiff', tuple(args),
  924. self.decoderconfig)
  925. try:
  926. decoder.setimage(self.im, extents)
  927. except ValueError:
  928. raise IOError("Couldn't set the image")
  929. if hasattr(self.fp, "getvalue"):
  930. # We've got a stringio like thing passed in. Yay for all in memory.
  931. # The decoder needs the entire file in one shot, so there's not
  932. # a lot we can do here other than give it the entire file.
  933. # unless we could do something like get the address of the
  934. # underlying string for stringio.
  935. #
  936. # Rearranging for supporting byteio items, since they have a fileno
  937. # that returns an IOError if there's no underlying fp. Easier to
  938. # deal with here by reordering.
  939. if DEBUG:
  940. print("have getvalue. just sending in a string from getvalue")
  941. n, err = decoder.decode(self.fp.getvalue())
  942. elif hasattr(self.fp, "fileno"):
  943. # we've got a actual file on disk, pass in the fp.
  944. if DEBUG:
  945. print("have fileno, calling fileno version of the decoder.")
  946. self.fp.seek(0)
  947. # 4 bytes, otherwise the trace might error out
  948. n, err = decoder.decode(b"fpfp")
  949. else:
  950. # we have something else.
  951. if DEBUG:
  952. print("don't have fileno or getvalue. just reading")
  953. # UNDONE -- so much for that buffer size thing.
  954. n, err = decoder.decode(self.fp.read())
  955. self.tile = []
  956. self.readonly = 0
  957. # libtiff closed the fp in a, we need to close self.fp, if possible
  958. if self._exclusive_fp:
  959. if self.__frame == 0 and not self.__next:
  960. self.fp.close()
  961. self.fp = None # might be shared
  962. if err < 0:
  963. raise IOError(err)
  964. return Image.Image.load(self)
  965. def _setup(self):
  966. "Setup this image object based on current tags"
  967. if 0xBC01 in self.tag_v2:
  968. raise IOError("Windows Media Photo files not yet supported")
  969. # extract relevant tags
  970. self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
  971. self._planar_configuration = self.tag_v2.get(PLANAR_CONFIGURATION, 1)
  972. # photometric is a required tag, but not everyone is reading
  973. # the specification
  974. photo = self.tag_v2.get(PHOTOMETRIC_INTERPRETATION, 0)
  975. fillorder = self.tag_v2.get(FILLORDER, 1)
  976. if DEBUG:
  977. print("*** Summary ***")
  978. print("- compression:", self._compression)
  979. print("- photometric_interpretation:", photo)
  980. print("- planar_configuration:", self._planar_configuration)
  981. print("- fill_order:", fillorder)
  982. print("- YCbCr subsampling:", self.tag.get(530))
  983. # size
  984. xsize = self.tag_v2.get(IMAGEWIDTH)
  985. ysize = self.tag_v2.get(IMAGELENGTH)
  986. self._size = xsize, ysize
  987. if DEBUG:
  988. print("- size:", self.size)
  989. sampleFormat = self.tag_v2.get(SAMPLEFORMAT, (1,))
  990. if (len(sampleFormat) > 1
  991. and max(sampleFormat) == min(sampleFormat) == 1):
  992. # SAMPLEFORMAT is properly per band, so an RGB image will
  993. # be (1,1,1). But, we don't support per band pixel types,
  994. # and anything more than one band is a uint8. So, just
  995. # take the first element. Revisit this if adding support
  996. # for more exotic images.
  997. sampleFormat = (1,)
  998. bps_tuple = self.tag_v2.get(BITSPERSAMPLE, (1,))
  999. extra_tuple = self.tag_v2.get(EXTRASAMPLES, ())
  1000. if photo in (2, 6, 8): # RGB, YCbCr, LAB
  1001. bps_count = 3
  1002. elif photo == 5: # CMYK
  1003. bps_count = 4
  1004. else:
  1005. bps_count = 1
  1006. bps_count += len(extra_tuple)
  1007. # Some files have only one value in bps_tuple,
  1008. # while should have more. Fix it
  1009. if bps_count > len(bps_tuple) and len(bps_tuple) == 1:
  1010. bps_tuple = bps_tuple * bps_count
  1011. # mode: check photometric interpretation and bits per pixel
  1012. key = (self.tag_v2.prefix, photo, sampleFormat, fillorder,
  1013. bps_tuple, extra_tuple)
  1014. if DEBUG:
  1015. print("format key:", key)
  1016. try:
  1017. self.mode, rawmode = OPEN_INFO[key]
  1018. except KeyError:
  1019. if DEBUG:
  1020. print("- unsupported format")
  1021. raise SyntaxError("unknown pixel mode")
  1022. if DEBUG:
  1023. print("- raw mode:", rawmode)
  1024. print("- pil mode:", self.mode)
  1025. self.info["compression"] = self._compression
  1026. xres = self.tag_v2.get(X_RESOLUTION, 1)
  1027. yres = self.tag_v2.get(Y_RESOLUTION, 1)
  1028. if xres and yres:
  1029. resunit = self.tag_v2.get(RESOLUTION_UNIT)
  1030. if resunit == 2: # dots per inch
  1031. self.info["dpi"] = xres, yres
  1032. elif resunit == 3: # dots per centimeter. convert to dpi
  1033. self.info["dpi"] = xres * 2.54, yres * 2.54
  1034. elif resunit is None: # used to default to 1, but now 2)
  1035. self.info["dpi"] = xres, yres
  1036. # For backward compatibility,
  1037. # we also preserve the old behavior
  1038. self.info["resolution"] = xres, yres
  1039. else: # No absolute unit of measurement
  1040. self.info["resolution"] = xres, yres
  1041. # build tile descriptors
  1042. x = y = layer = 0
  1043. self.tile = []
  1044. self.use_load_libtiff = READ_LIBTIFF or self._compression != 'raw'
  1045. if self.use_load_libtiff:
  1046. # Decoder expects entire file as one tile.
  1047. # There's a buffer size limit in load (64k)
  1048. # so large g4 images will fail if we use that
  1049. # function.
  1050. #
  1051. # Setup the one tile for the whole image, then
  1052. # use the _load_libtiff function.
  1053. # libtiff handles the fillmode for us, so 1;IR should
  1054. # actually be 1;I. Including the R double reverses the
  1055. # bits, so stripes of the image are reversed. See
  1056. # https://github.com/python-pillow/Pillow/issues/279
  1057. if fillorder == 2:
  1058. # Replace fillorder with fillorder=1
  1059. key = key[:3] + (1,) + key[4:]
  1060. if DEBUG:
  1061. print("format key:", key)
  1062. # this should always work, since all the
  1063. # fillorder==2 modes have a corresponding
  1064. # fillorder=1 mode
  1065. self.mode, rawmode = OPEN_INFO[key]
  1066. # libtiff always returns the bytes in native order.
  1067. # we're expecting image byte order. So, if the rawmode
  1068. # contains I;16, we need to convert from native to image
  1069. # byte order.
  1070. if rawmode == 'I;16':
  1071. rawmode = 'I;16N'
  1072. if ';16B' in rawmode:
  1073. rawmode = rawmode.replace(';16B', ';16N')
  1074. if ';16L' in rawmode:
  1075. rawmode = rawmode.replace(';16L', ';16N')
  1076. # Offset in the tile tuple is 0, we go from 0,0 to
  1077. # w,h, and we only do this once -- eds
  1078. a = (rawmode, self._compression, False)
  1079. self.tile.append(
  1080. (self._compression,
  1081. (0, 0, xsize, ysize),
  1082. 0, a))
  1083. elif STRIPOFFSETS in self.tag_v2 or TILEOFFSETS in self.tag_v2:
  1084. # striped image
  1085. if STRIPOFFSETS in self.tag_v2:
  1086. offsets = self.tag_v2[STRIPOFFSETS]
  1087. h = self.tag_v2.get(ROWSPERSTRIP, ysize)
  1088. w = self.size[0]
  1089. else:
  1090. # tiled image
  1091. offsets = self.tag_v2[TILEOFFSETS]
  1092. w = self.tag_v2.get(322)
  1093. h = self.tag_v2.get(323)
  1094. for offset in offsets:
  1095. if x + w > xsize:
  1096. stride = w * sum(bps_tuple) / 8 # bytes per line
  1097. else:
  1098. stride = 0
  1099. tile_rawmode = rawmode
  1100. if self._planar_configuration == 2:
  1101. # each band on it's own layer
  1102. tile_rawmode = rawmode[layer]
  1103. # adjust stride width accordingly
  1104. stride /= bps_count
  1105. a = (tile_rawmode, int(stride), 1)
  1106. self.tile.append(
  1107. (self._compression,
  1108. (x, y, min(x+w, xsize), min(y+h, ysize)),
  1109. offset, a))
  1110. x = x + w
  1111. if x >= self.size[0]:
  1112. x, y = 0, y + h
  1113. if y >= self.size[1]:
  1114. x = y = 0
  1115. layer += 1
  1116. else:
  1117. if DEBUG:
  1118. print("- unsupported data organization")
  1119. raise SyntaxError("unknown data organization")
  1120. # Fix up info.
  1121. if ICCPROFILE in self.tag_v2:
  1122. self.info['icc_profile'] = self.tag_v2[ICCPROFILE]
  1123. # fixup palette descriptor
  1124. if self.mode == "P":
  1125. palette = [o8(b // 256) for b in self.tag_v2[COLORMAP]]
  1126. self.palette = ImagePalette.raw("RGB;L", b"".join(palette))
  1127. #
  1128. # --------------------------------------------------------------------
  1129. # Write TIFF files
  1130. # little endian is default except for image modes with
  1131. # explicit big endian byte-order
  1132. SAVE_INFO = {
  1133. # mode => rawmode, byteorder, photometrics,
  1134. # sampleformat, bitspersample, extra
  1135. "1": ("1", II, 1, 1, (1,), None),
  1136. "L": ("L", II, 1, 1, (8,), None),
  1137. "LA": ("LA", II, 1, 1, (8, 8), 2),
  1138. "P": ("P", II, 3, 1, (8,), None),
  1139. "PA": ("PA", II, 3, 1, (8, 8), 2),
  1140. "I": ("I;32S", II, 1, 2, (32,), None),
  1141. "I;16": ("I;16", II, 1, 1, (16,), None),
  1142. "I;16S": ("I;16S", II, 1, 2, (16,), None),
  1143. "F": ("F;32F", II, 1, 3, (32,), None),
  1144. "RGB": ("RGB", II, 2, 1, (8, 8, 8), None),
  1145. "RGBX": ("RGBX", II, 2, 1, (8, 8, 8, 8), 0),
  1146. "RGBA": ("RGBA", II, 2, 1, (8, 8, 8, 8), 2),
  1147. "CMYK": ("CMYK", II, 5, 1, (8, 8, 8, 8), None),
  1148. "YCbCr": ("YCbCr", II, 6, 1, (8, 8, 8), None),
  1149. "LAB": ("LAB", II, 8, 1, (8, 8, 8), None),
  1150. "I;32BS": ("I;32BS", MM, 1, 2, (32,), None),
  1151. "I;16B": ("I;16B", MM, 1, 1, (16,), None),
  1152. "I;16BS": ("I;16BS", MM, 1, 2, (16,), None),
  1153. "F;32BF": ("F;32BF", MM, 1, 3, (32,), None),
  1154. }
  1155. def _save(im, fp, filename):
  1156. try:
  1157. rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
  1158. except KeyError:
  1159. raise IOError("cannot write mode %s as TIFF" % im.mode)
  1160. ifd = ImageFileDirectory_v2(prefix=prefix)
  1161. compression = im.encoderinfo.get('compression', im.info.get('compression'))
  1162. if compression is None:
  1163. compression = 'raw'
  1164. libtiff = WRITE_LIBTIFF or compression != 'raw'
  1165. # required for color libtiff images
  1166. ifd[PLANAR_CONFIGURATION] = getattr(im, '_planar_configuration', 1)
  1167. ifd[IMAGEWIDTH] = im.size[0]
  1168. ifd[IMAGELENGTH] = im.size[1]
  1169. # write any arbitrary tags passed in as an ImageFileDirectory
  1170. info = im.encoderinfo.get("tiffinfo", {})
  1171. if DEBUG:
  1172. print("Tiffinfo Keys: %s" % list(info))
  1173. if isinstance(info, ImageFileDirectory_v1):
  1174. info = info.to_v2()
  1175. for key in info:
  1176. ifd[key] = info.get(key)
  1177. try:
  1178. ifd.tagtype[key] = info.tagtype[key]
  1179. except:
  1180. pass # might not be an IFD, Might not have populated type
  1181. # additions written by Greg Couch, gregc@cgl.ucsf.edu
  1182. # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
  1183. if hasattr(im, 'tag_v2'):
  1184. # preserve tags from original TIFF image file
  1185. for key in (RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION,
  1186. IPTC_NAA_CHUNK, PHOTOSHOP_CHUNK, XMP):
  1187. if key in im.tag_v2:
  1188. ifd[key] = im.tag_v2[key]
  1189. ifd.tagtype[key] = im.tag_v2.tagtype[key]
  1190. # preserve ICC profile (should also work when saving other formats
  1191. # which support profiles as TIFF) -- 2008-06-06 Florian Hoech
  1192. if "icc_profile" in im.info:
  1193. ifd[ICCPROFILE] = im.info["icc_profile"]
  1194. for key, name in [(IMAGEDESCRIPTION, "description"),
  1195. (X_RESOLUTION, "resolution"),
  1196. (Y_RESOLUTION, "resolution"),
  1197. (X_RESOLUTION, "x_resolution"),
  1198. (Y_RESOLUTION, "y_resolution"),
  1199. (RESOLUTION_UNIT, "resolution_unit"),
  1200. (SOFTWARE, "software"),
  1201. (DATE_TIME, "date_time"),
  1202. (ARTIST, "artist"),
  1203. (COPYRIGHT, "copyright")]:
  1204. if name in im.encoderinfo:
  1205. ifd[key] = im.encoderinfo[name]
  1206. dpi = im.encoderinfo.get("dpi")
  1207. if dpi:
  1208. ifd[RESOLUTION_UNIT] = 2
  1209. ifd[X_RESOLUTION] = dpi[0]
  1210. ifd[Y_RESOLUTION] = dpi[1]
  1211. if bits != (1,):
  1212. ifd[BITSPERSAMPLE] = bits
  1213. if len(bits) != 1:
  1214. ifd[SAMPLESPERPIXEL] = len(bits)
  1215. if extra is not None:
  1216. ifd[EXTRASAMPLES] = extra
  1217. if format != 1:
  1218. ifd[SAMPLEFORMAT] = format
  1219. ifd[PHOTOMETRIC_INTERPRETATION] = photo
  1220. if im.mode == "P":
  1221. lut = im.im.getpalette("RGB", "RGB;L")
  1222. ifd[COLORMAP] = tuple(i8(v) * 256 for v in lut)
  1223. # data orientation
  1224. stride = len(bits) * ((im.size[0]*bits[0]+7)//8)
  1225. ifd[ROWSPERSTRIP] = im.size[1]
  1226. ifd[STRIPBYTECOUNTS] = stride * im.size[1]
  1227. ifd[STRIPOFFSETS] = 0 # this is adjusted by IFD writer
  1228. # no compression by default:
  1229. ifd[COMPRESSION] = COMPRESSION_INFO_REV.get(compression, 1)
  1230. if libtiff:
  1231. if DEBUG:
  1232. print("Saving using libtiff encoder")
  1233. print("Items: %s" % sorted(ifd.items()))
  1234. _fp = 0
  1235. if hasattr(fp, "fileno"):
  1236. try:
  1237. fp.seek(0)
  1238. _fp = os.dup(fp.fileno())
  1239. except io.UnsupportedOperation:
  1240. pass
  1241. # STRIPOFFSETS and STRIPBYTECOUNTS are added by the library
  1242. # based on the data in the strip.
  1243. blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS]
  1244. atts = {}
  1245. # bits per sample is a single short in the tiff directory, not a list.
  1246. atts[BITSPERSAMPLE] = bits[0]
  1247. # Merge the ones that we have with (optional) more bits from
  1248. # the original file, e.g x,y resolution so that we can
  1249. # save(load('')) == original file.
  1250. legacy_ifd = {}
  1251. if hasattr(im, 'tag'):
  1252. legacy_ifd = im.tag.to_v2()
  1253. for tag, value in itertools.chain(ifd.items(),
  1254. getattr(im, 'tag_v2', {}).items(),
  1255. legacy_ifd.items()):
  1256. # Libtiff can only process certain core items without adding
  1257. # them to the custom dictionary. It will segfault if it attempts
  1258. # to add a custom tag without the dictionary entry
  1259. #
  1260. # UNDONE -- add code for the custom dictionary
  1261. if tag not in TiffTags.LIBTIFF_CORE:
  1262. continue
  1263. if tag not in atts and tag not in blocklist:
  1264. if isinstance(value, str if py3 else unicode):
  1265. atts[tag] = value.encode('ascii', 'replace') + b"\0"
  1266. elif isinstance(value, IFDRational):
  1267. atts[tag] = float(value)
  1268. else:
  1269. atts[tag] = value
  1270. if DEBUG:
  1271. print("Converted items: %s" % sorted(atts.items()))
  1272. # libtiff always expects the bytes in native order.
  1273. # we're storing image byte order. So, if the rawmode
  1274. # contains I;16, we need to convert from native to image
  1275. # byte order.
  1276. if im.mode in ('I;16B', 'I;16'):
  1277. rawmode = 'I;16N'
  1278. a = (rawmode, compression, _fp, filename, atts)
  1279. e = Image._getencoder(im.mode, 'libtiff', a, im.encoderconfig)
  1280. e.setimage(im.im, (0, 0)+im.size)
  1281. while True:
  1282. # undone, change to self.decodermaxblock:
  1283. l, s, d = e.encode(16*1024)
  1284. if not _fp:
  1285. fp.write(d)
  1286. if s:
  1287. break
  1288. if s < 0:
  1289. raise IOError("encoder error %d when writing image file" % s)
  1290. else:
  1291. offset = ifd.save(fp)
  1292. ImageFile._save(im, fp, [
  1293. ("raw", (0, 0)+im.size, offset, (rawmode, stride, 1))
  1294. ])
  1295. # -- helper for multi-page save --
  1296. if "_debug_multipage" in im.encoderinfo:
  1297. # just to access o32 and o16 (using correct byte order)
  1298. im._debug_multipage = ifd
  1299. class AppendingTiffWriter:
  1300. fieldSizes = [
  1301. 0, # None
  1302. 1, # byte
  1303. 1, # ascii
  1304. 2, # short
  1305. 4, # long
  1306. 8, # rational
  1307. 1, # sbyte
  1308. 1, # undefined
  1309. 2, # sshort
  1310. 4, # slong
  1311. 8, # srational
  1312. 4, # float
  1313. 8, # double
  1314. ]
  1315. # StripOffsets = 273
  1316. # FreeOffsets = 288
  1317. # TileOffsets = 324
  1318. # JPEGQTables = 519
  1319. # JPEGDCTables = 520
  1320. # JPEGACTables = 521
  1321. Tags = {273, 288, 324, 519, 520, 521}
  1322. def __init__(self, fn, new=False):
  1323. if hasattr(fn, 'read'):
  1324. self.f = fn
  1325. self.close_fp = False
  1326. else:
  1327. self.name = fn
  1328. self.close_fp = True
  1329. try:
  1330. self.f = io.open(fn, "w+b" if new else "r+b")
  1331. except IOError:
  1332. self.f = io.open(fn, "w+b")
  1333. self.beginning = self.f.tell()
  1334. self.setup()
  1335. def setup(self):
  1336. # Reset everything.
  1337. self.f.seek(self.beginning, os.SEEK_SET)
  1338. self.whereToWriteNewIFDOffset = None
  1339. self.offsetOfNewPage = 0
  1340. self.IIMM = IIMM = self.f.read(4)
  1341. if not IIMM:
  1342. # empty file - first page
  1343. self.isFirst = True
  1344. return
  1345. self.isFirst = False
  1346. if IIMM == b"II\x2a\x00":
  1347. self.setEndian("<")
  1348. elif IIMM == b"MM\x00\x2a":
  1349. self.setEndian(">")
  1350. else:
  1351. raise RuntimeError("Invalid TIFF file header")
  1352. self.skipIFDs()
  1353. self.goToEnd()
  1354. def finalize(self):
  1355. if self.isFirst:
  1356. return
  1357. # fix offsets
  1358. self.f.seek(self.offsetOfNewPage)
  1359. IIMM = self.f.read(4)
  1360. if not IIMM:
  1361. # raise RuntimeError("nothing written into new page")
  1362. # Make it easy to finish a frame without committing to a new one.
  1363. return
  1364. if IIMM != self.IIMM:
  1365. raise RuntimeError("IIMM of new page doesn't match IIMM of "
  1366. "first page")
  1367. IFDoffset = self.readLong()
  1368. IFDoffset += self.offsetOfNewPage
  1369. self.f.seek(self.whereToWriteNewIFDOffset)
  1370. self.writeLong(IFDoffset)
  1371. self.f.seek(IFDoffset)
  1372. self.fixIFD()
  1373. def newFrame(self):
  1374. # Call this to finish a frame.
  1375. self.finalize()
  1376. self.setup()
  1377. def __enter__(self):
  1378. return self
  1379. def __exit__(self, exc_type, exc_value, traceback):
  1380. if self.close_fp:
  1381. self.close()
  1382. return False
  1383. def tell(self):
  1384. return self.f.tell() - self.offsetOfNewPage
  1385. def seek(self, offset, whence):
  1386. if whence == os.SEEK_SET:
  1387. offset += self.offsetOfNewPage
  1388. self.f.seek(offset, whence)
  1389. return self.tell()
  1390. def goToEnd(self):
  1391. self.f.seek(0, os.SEEK_END)
  1392. pos = self.f.tell()
  1393. # pad to 16 byte boundary
  1394. padBytes = 16 - pos % 16
  1395. if 0 < padBytes < 16:
  1396. self.f.write(bytes(bytearray(padBytes)))
  1397. self.offsetOfNewPage = self.f.tell()
  1398. def setEndian(self, endian):
  1399. self.endian = endian
  1400. self.longFmt = self.endian + "L"
  1401. self.shortFmt = self.endian + "H"
  1402. self.tagFormat = self.endian + "HHL"
  1403. def skipIFDs(self):
  1404. while True:
  1405. IFDoffset = self.readLong()
  1406. if IFDoffset == 0:
  1407. self.whereToWriteNewIFDOffset = self.f.tell() - 4
  1408. break
  1409. self.f.seek(IFDoffset)
  1410. numTags = self.readShort()
  1411. self.f.seek(numTags * 12, os.SEEK_CUR)
  1412. def write(self, data):
  1413. return self.f.write(data)
  1414. def readShort(self):
  1415. value, = struct.unpack(self.shortFmt, self.f.read(2))
  1416. return value
  1417. def readLong(self):
  1418. value, = struct.unpack(self.longFmt, self.f.read(4))
  1419. return value
  1420. def rewriteLastShortToLong(self, value):
  1421. self.f.seek(-2, os.SEEK_CUR)
  1422. bytesWritten = self.f.write(struct.pack(self.longFmt, value))
  1423. if bytesWritten is not None and bytesWritten != 4:
  1424. raise RuntimeError("wrote only %u bytes but wanted 4" %
  1425. bytesWritten)
  1426. def rewriteLastShort(self, value):
  1427. self.f.seek(-2, os.SEEK_CUR)
  1428. bytesWritten = self.f.write(struct.pack(self.shortFmt, value))
  1429. if bytesWritten is not None and bytesWritten != 2:
  1430. raise RuntimeError("wrote only %u bytes but wanted 2" %
  1431. bytesWritten)
  1432. def rewriteLastLong(self, value):
  1433. self.f.seek(-4, os.SEEK_CUR)
  1434. bytesWritten = self.f.write(struct.pack(self.longFmt, value))
  1435. if bytesWritten is not None and bytesWritten != 4:
  1436. raise RuntimeError("wrote only %u bytes but wanted 4" %
  1437. bytesWritten)
  1438. def writeShort(self, value):
  1439. bytesWritten = self.f.write(struct.pack(self.shortFmt, value))
  1440. if bytesWritten is not None and bytesWritten != 2:
  1441. raise RuntimeError("wrote only %u bytes but wanted 2" %
  1442. bytesWritten)
  1443. def writeLong(self, value):
  1444. bytesWritten = self.f.write(struct.pack(self.longFmt, value))
  1445. if bytesWritten is not None and bytesWritten != 4:
  1446. raise RuntimeError("wrote only %u bytes but wanted 4" %
  1447. bytesWritten)
  1448. def close(self):
  1449. self.finalize()
  1450. self.f.close()
  1451. def fixIFD(self):
  1452. numTags = self.readShort()
  1453. for i in range(numTags):
  1454. tag, fieldType, count = struct.unpack(self.tagFormat,
  1455. self.f.read(8))
  1456. fieldSize = self.fieldSizes[fieldType]
  1457. totalSize = fieldSize * count
  1458. isLocal = (totalSize <= 4)
  1459. if not isLocal:
  1460. offset = self.readLong()
  1461. offset += self.offsetOfNewPage
  1462. self.rewriteLastLong(offset)
  1463. if tag in self.Tags:
  1464. curPos = self.f.tell()
  1465. if isLocal:
  1466. self.fixOffsets(count, isShort=(fieldSize == 2),
  1467. isLong=(fieldSize == 4))
  1468. self.f.seek(curPos + 4)
  1469. else:
  1470. self.f.seek(offset)
  1471. self.fixOffsets(count, isShort=(fieldSize == 2),
  1472. isLong=(fieldSize == 4))
  1473. self.f.seek(curPos)
  1474. offset = curPos = None
  1475. elif isLocal:
  1476. # skip the locally stored value that is not an offset
  1477. self.f.seek(4, os.SEEK_CUR)
  1478. def fixOffsets(self, count, isShort=False, isLong=False):
  1479. if not isShort and not isLong:
  1480. raise RuntimeError("offset is neither short nor long")
  1481. for i in range(count):
  1482. offset = self.readShort() if isShort else self.readLong()
  1483. offset += self.offsetOfNewPage
  1484. if isShort and offset >= 65536:
  1485. # offset is now too large - we must convert shorts to longs
  1486. if count != 1:
  1487. raise RuntimeError("not implemented") # XXX TODO
  1488. # simple case - the offset is just one and therefore it is
  1489. # local (not referenced with another offset)
  1490. self.rewriteLastShortToLong(offset)
  1491. self.f.seek(-10, os.SEEK_CUR)
  1492. self.writeShort(4) # rewrite the type to LONG
  1493. self.f.seek(8, os.SEEK_CUR)
  1494. elif isShort:
  1495. self.rewriteLastShort(offset)
  1496. else:
  1497. self.rewriteLastLong(offset)
  1498. def _save_all(im, fp, filename):
  1499. encoderinfo = im.encoderinfo.copy()
  1500. encoderconfig = im.encoderconfig
  1501. append_images = list(encoderinfo.get("append_images", []))
  1502. if not hasattr(im, "n_frames") and not append_images:
  1503. return _save(im, fp, filename)
  1504. cur_idx = im.tell()
  1505. try:
  1506. with AppendingTiffWriter(fp) as tf:
  1507. for ims in [im]+append_images:
  1508. ims.encoderinfo = encoderinfo
  1509. ims.encoderconfig = encoderconfig
  1510. if not hasattr(ims, "n_frames"):
  1511. nfr = 1
  1512. else:
  1513. nfr = ims.n_frames
  1514. for idx in range(nfr):
  1515. ims.seek(idx)
  1516. ims.load()
  1517. _save(ims, tf, filename)
  1518. tf.newFrame()
  1519. finally:
  1520. im.seek(cur_idx)
  1521. #
  1522. # --------------------------------------------------------------------
  1523. # Register
  1524. Image.register_open(TiffImageFile.format, TiffImageFile, _accept)
  1525. Image.register_save(TiffImageFile.format, _save)
  1526. Image.register_save_all(TiffImageFile.format, _save_all)
  1527. Image.register_extensions(TiffImageFile.format, [".tif", ".tiff"])
  1528. Image.register_mime(TiffImageFile.format, "image/tiff")