TiffImagePlugin.py 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200
  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 annotations
  42. import io
  43. import itertools
  44. import logging
  45. import math
  46. import os
  47. import struct
  48. import warnings
  49. from collections.abc import MutableMapping
  50. from fractions import Fraction
  51. from numbers import Number, Rational
  52. from typing import IO, TYPE_CHECKING, Any, Callable, NoReturn
  53. from . import ExifTags, Image, ImageFile, ImageOps, ImagePalette, TiffTags
  54. from ._binary import i16be as i16
  55. from ._binary import i32be as i32
  56. from ._binary import o8
  57. from ._deprecate import deprecate
  58. from .TiffTags import TYPES
  59. logger = logging.getLogger(__name__)
  60. # Set these to true to force use of libtiff for reading or writing.
  61. READ_LIBTIFF = False
  62. WRITE_LIBTIFF = False
  63. IFD_LEGACY_API = True
  64. STRIP_SIZE = 65536
  65. II = b"II" # little-endian (Intel style)
  66. MM = b"MM" # big-endian (Motorola style)
  67. #
  68. # --------------------------------------------------------------------
  69. # Read TIFF files
  70. # a few tag names, just to make the code below a bit more readable
  71. OSUBFILETYPE = 255
  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. TRANSFERFUNCTION = 301
  88. SOFTWARE = 305
  89. DATE_TIME = 306
  90. ARTIST = 315
  91. PREDICTOR = 317
  92. COLORMAP = 320
  93. TILEWIDTH = 322
  94. TILELENGTH = 323
  95. TILEOFFSETS = 324
  96. TILEBYTECOUNTS = 325
  97. SUBIFD = 330
  98. EXTRASAMPLES = 338
  99. SAMPLEFORMAT = 339
  100. JPEGTABLES = 347
  101. YCBCRSUBSAMPLING = 530
  102. REFERENCEBLACKWHITE = 532
  103. COPYRIGHT = 33432
  104. IPTC_NAA_CHUNK = 33723 # newsphoto properties
  105. PHOTOSHOP_CHUNK = 34377 # photoshop properties
  106. ICCPROFILE = 34675
  107. EXIFIFD = 34665
  108. XMP = 700
  109. JPEGQUALITY = 65537 # pseudo-tag by libtiff
  110. # https://github.com/imagej/ImageJA/blob/master/src/main/java/ij/io/TiffDecoder.java
  111. IMAGEJ_META_DATA_BYTE_COUNTS = 50838
  112. IMAGEJ_META_DATA = 50839
  113. COMPRESSION_INFO = {
  114. # Compression => pil compression name
  115. 1: "raw",
  116. 2: "tiff_ccitt",
  117. 3: "group3",
  118. 4: "group4",
  119. 5: "tiff_lzw",
  120. 6: "tiff_jpeg", # obsolete
  121. 7: "jpeg",
  122. 8: "tiff_adobe_deflate",
  123. 32771: "tiff_raw_16", # 16-bit padding
  124. 32773: "packbits",
  125. 32809: "tiff_thunderscan",
  126. 32946: "tiff_deflate",
  127. 34676: "tiff_sgilog",
  128. 34677: "tiff_sgilog24",
  129. 34925: "lzma",
  130. 50000: "zstd",
  131. 50001: "webp",
  132. }
  133. COMPRESSION_INFO_REV = {v: k for k, v in COMPRESSION_INFO.items()}
  134. OPEN_INFO = {
  135. # (ByteOrder, PhotoInterpretation, SampleFormat, FillOrder, BitsPerSample,
  136. # ExtraSamples) => mode, rawmode
  137. (II, 0, (1,), 1, (1,), ()): ("1", "1;I"),
  138. (MM, 0, (1,), 1, (1,), ()): ("1", "1;I"),
  139. (II, 0, (1,), 2, (1,), ()): ("1", "1;IR"),
  140. (MM, 0, (1,), 2, (1,), ()): ("1", "1;IR"),
  141. (II, 1, (1,), 1, (1,), ()): ("1", "1"),
  142. (MM, 1, (1,), 1, (1,), ()): ("1", "1"),
  143. (II, 1, (1,), 2, (1,), ()): ("1", "1;R"),
  144. (MM, 1, (1,), 2, (1,), ()): ("1", "1;R"),
  145. (II, 0, (1,), 1, (2,), ()): ("L", "L;2I"),
  146. (MM, 0, (1,), 1, (2,), ()): ("L", "L;2I"),
  147. (II, 0, (1,), 2, (2,), ()): ("L", "L;2IR"),
  148. (MM, 0, (1,), 2, (2,), ()): ("L", "L;2IR"),
  149. (II, 1, (1,), 1, (2,), ()): ("L", "L;2"),
  150. (MM, 1, (1,), 1, (2,), ()): ("L", "L;2"),
  151. (II, 1, (1,), 2, (2,), ()): ("L", "L;2R"),
  152. (MM, 1, (1,), 2, (2,), ()): ("L", "L;2R"),
  153. (II, 0, (1,), 1, (4,), ()): ("L", "L;4I"),
  154. (MM, 0, (1,), 1, (4,), ()): ("L", "L;4I"),
  155. (II, 0, (1,), 2, (4,), ()): ("L", "L;4IR"),
  156. (MM, 0, (1,), 2, (4,), ()): ("L", "L;4IR"),
  157. (II, 1, (1,), 1, (4,), ()): ("L", "L;4"),
  158. (MM, 1, (1,), 1, (4,), ()): ("L", "L;4"),
  159. (II, 1, (1,), 2, (4,), ()): ("L", "L;4R"),
  160. (MM, 1, (1,), 2, (4,), ()): ("L", "L;4R"),
  161. (II, 0, (1,), 1, (8,), ()): ("L", "L;I"),
  162. (MM, 0, (1,), 1, (8,), ()): ("L", "L;I"),
  163. (II, 0, (1,), 2, (8,), ()): ("L", "L;IR"),
  164. (MM, 0, (1,), 2, (8,), ()): ("L", "L;IR"),
  165. (II, 1, (1,), 1, (8,), ()): ("L", "L"),
  166. (MM, 1, (1,), 1, (8,), ()): ("L", "L"),
  167. (II, 1, (2,), 1, (8,), ()): ("L", "L"),
  168. (MM, 1, (2,), 1, (8,), ()): ("L", "L"),
  169. (II, 1, (1,), 2, (8,), ()): ("L", "L;R"),
  170. (MM, 1, (1,), 2, (8,), ()): ("L", "L;R"),
  171. (II, 1, (1,), 1, (12,), ()): ("I;16", "I;12"),
  172. (II, 0, (1,), 1, (16,), ()): ("I;16", "I;16"),
  173. (II, 1, (1,), 1, (16,), ()): ("I;16", "I;16"),
  174. (MM, 1, (1,), 1, (16,), ()): ("I;16B", "I;16B"),
  175. (II, 1, (1,), 2, (16,), ()): ("I;16", "I;16R"),
  176. (II, 1, (2,), 1, (16,), ()): ("I", "I;16S"),
  177. (MM, 1, (2,), 1, (16,), ()): ("I", "I;16BS"),
  178. (II, 0, (3,), 1, (32,), ()): ("F", "F;32F"),
  179. (MM, 0, (3,), 1, (32,), ()): ("F", "F;32BF"),
  180. (II, 1, (1,), 1, (32,), ()): ("I", "I;32N"),
  181. (II, 1, (2,), 1, (32,), ()): ("I", "I;32S"),
  182. (MM, 1, (2,), 1, (32,), ()): ("I", "I;32BS"),
  183. (II, 1, (3,), 1, (32,), ()): ("F", "F;32F"),
  184. (MM, 1, (3,), 1, (32,), ()): ("F", "F;32BF"),
  185. (II, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"),
  186. (MM, 1, (1,), 1, (8, 8), (2,)): ("LA", "LA"),
  187. (II, 2, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
  188. (MM, 2, (1,), 1, (8, 8, 8), ()): ("RGB", "RGB"),
  189. (II, 2, (1,), 2, (8, 8, 8), ()): ("RGB", "RGB;R"),
  190. (MM, 2, (1,), 2, (8, 8, 8), ()): ("RGB", "RGB;R"),
  191. (II, 2, (1,), 1, (8, 8, 8, 8), ()): ("RGBA", "RGBA"), # missing ExtraSamples
  192. (MM, 2, (1,), 1, (8, 8, 8, 8), ()): ("RGBA", "RGBA"), # missing ExtraSamples
  193. (II, 2, (1,), 1, (8, 8, 8, 8), (0,)): ("RGB", "RGBX"),
  194. (MM, 2, (1,), 1, (8, 8, 8, 8), (0,)): ("RGB", "RGBX"),
  195. (II, 2, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("RGB", "RGBXX"),
  196. (MM, 2, (1,), 1, (8, 8, 8, 8, 8), (0, 0)): ("RGB", "RGBXX"),
  197. (II, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("RGB", "RGBXXX"),
  198. (MM, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0, 0)): ("RGB", "RGBXXX"),
  199. (II, 2, (1,), 1, (8, 8, 8, 8), (1,)): ("RGBA", "RGBa"),
  200. (MM, 2, (1,), 1, (8, 8, 8, 8), (1,)): ("RGBA", "RGBa"),
  201. (II, 2, (1,), 1, (8, 8, 8, 8, 8), (1, 0)): ("RGBA", "RGBaX"),
  202. (MM, 2, (1,), 1, (8, 8, 8, 8, 8), (1, 0)): ("RGBA", "RGBaX"),
  203. (II, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (1, 0, 0)): ("RGBA", "RGBaXX"),
  204. (MM, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (1, 0, 0)): ("RGBA", "RGBaXX"),
  205. (II, 2, (1,), 1, (8, 8, 8, 8), (2,)): ("RGBA", "RGBA"),
  206. (MM, 2, (1,), 1, (8, 8, 8, 8), (2,)): ("RGBA", "RGBA"),
  207. (II, 2, (1,), 1, (8, 8, 8, 8, 8), (2, 0)): ("RGBA", "RGBAX"),
  208. (MM, 2, (1,), 1, (8, 8, 8, 8, 8), (2, 0)): ("RGBA", "RGBAX"),
  209. (II, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (2, 0, 0)): ("RGBA", "RGBAXX"),
  210. (MM, 2, (1,), 1, (8, 8, 8, 8, 8, 8), (2, 0, 0)): ("RGBA", "RGBAXX"),
  211. (II, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10
  212. (MM, 2, (1,), 1, (8, 8, 8, 8), (999,)): ("RGBA", "RGBA"), # Corel Draw 10
  213. (II, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16L"),
  214. (MM, 2, (1,), 1, (16, 16, 16), ()): ("RGB", "RGB;16B"),
  215. (II, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16L"),
  216. (MM, 2, (1,), 1, (16, 16, 16, 16), ()): ("RGBA", "RGBA;16B"),
  217. (II, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGB", "RGBX;16L"),
  218. (MM, 2, (1,), 1, (16, 16, 16, 16), (0,)): ("RGB", "RGBX;16B"),
  219. (II, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16L"),
  220. (MM, 2, (1,), 1, (16, 16, 16, 16), (1,)): ("RGBA", "RGBa;16B"),
  221. (II, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16L"),
  222. (MM, 2, (1,), 1, (16, 16, 16, 16), (2,)): ("RGBA", "RGBA;16B"),
  223. (II, 3, (1,), 1, (1,), ()): ("P", "P;1"),
  224. (MM, 3, (1,), 1, (1,), ()): ("P", "P;1"),
  225. (II, 3, (1,), 2, (1,), ()): ("P", "P;1R"),
  226. (MM, 3, (1,), 2, (1,), ()): ("P", "P;1R"),
  227. (II, 3, (1,), 1, (2,), ()): ("P", "P;2"),
  228. (MM, 3, (1,), 1, (2,), ()): ("P", "P;2"),
  229. (II, 3, (1,), 2, (2,), ()): ("P", "P;2R"),
  230. (MM, 3, (1,), 2, (2,), ()): ("P", "P;2R"),
  231. (II, 3, (1,), 1, (4,), ()): ("P", "P;4"),
  232. (MM, 3, (1,), 1, (4,), ()): ("P", "P;4"),
  233. (II, 3, (1,), 2, (4,), ()): ("P", "P;4R"),
  234. (MM, 3, (1,), 2, (4,), ()): ("P", "P;4R"),
  235. (II, 3, (1,), 1, (8,), ()): ("P", "P"),
  236. (MM, 3, (1,), 1, (8,), ()): ("P", "P"),
  237. (II, 3, (1,), 1, (8, 8), (0,)): ("P", "PX"),
  238. (II, 3, (1,), 1, (8, 8), (2,)): ("PA", "PA"),
  239. (MM, 3, (1,), 1, (8, 8), (2,)): ("PA", "PA"),
  240. (II, 3, (1,), 2, (8,), ()): ("P", "P;R"),
  241. (MM, 3, (1,), 2, (8,), ()): ("P", "P;R"),
  242. (II, 5, (1,), 1, (8, 8, 8, 8), ()): ("CMYK", "CMYK"),
  243. (MM, 5, (1,), 1, (8, 8, 8, 8), ()): ("CMYK", "CMYK"),
  244. (II, 5, (1,), 1, (8, 8, 8, 8, 8), (0,)): ("CMYK", "CMYKX"),
  245. (MM, 5, (1,), 1, (8, 8, 8, 8, 8), (0,)): ("CMYK", "CMYKX"),
  246. (II, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
  247. (MM, 5, (1,), 1, (8, 8, 8, 8, 8, 8), (0, 0)): ("CMYK", "CMYKXX"),
  248. (II, 5, (1,), 1, (16, 16, 16, 16), ()): ("CMYK", "CMYK;16L"),
  249. (II, 6, (1,), 1, (8,), ()): ("L", "L"),
  250. (MM, 6, (1,), 1, (8,), ()): ("L", "L"),
  251. # JPEG compressed images handled by LibTiff and auto-converted to RGBX
  252. # Minimal Baseline TIFF requires YCbCr images to have 3 SamplesPerPixel
  253. (II, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGBX"),
  254. (MM, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGBX"),
  255. (II, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
  256. (MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"),
  257. }
  258. MAX_SAMPLESPERPIXEL = max(len(key_tp[4]) for key_tp in OPEN_INFO)
  259. PREFIXES = [
  260. b"MM\x00\x2A", # Valid TIFF header with big-endian byte order
  261. b"II\x2A\x00", # Valid TIFF header with little-endian byte order
  262. b"MM\x2A\x00", # Invalid TIFF header, assume big-endian
  263. b"II\x00\x2A", # Invalid TIFF header, assume little-endian
  264. b"MM\x00\x2B", # BigTIFF with big-endian byte order
  265. b"II\x2B\x00", # BigTIFF with little-endian byte order
  266. ]
  267. if not getattr(Image.core, "libtiff_support_custom_tags", True):
  268. deprecate("Support for LibTIFF earlier than version 4", 12)
  269. def _accept(prefix: bytes) -> bool:
  270. return prefix[:4] in PREFIXES
  271. def _limit_rational(val, max_val):
  272. inv = abs(val) > 1
  273. n_d = IFDRational(1 / val if inv else val).limit_rational(max_val)
  274. return n_d[::-1] if inv else n_d
  275. def _limit_signed_rational(val, max_val, min_val):
  276. frac = Fraction(val)
  277. n_d = frac.numerator, frac.denominator
  278. if min(n_d) < min_val:
  279. n_d = _limit_rational(val, abs(min_val))
  280. if max(n_d) > max_val:
  281. val = Fraction(*n_d)
  282. n_d = _limit_rational(val, max_val)
  283. return n_d
  284. ##
  285. # Wrapper for TIFF IFDs.
  286. _load_dispatch = {}
  287. _write_dispatch = {}
  288. def _delegate(op):
  289. def delegate(self, *args):
  290. return getattr(self._val, op)(*args)
  291. return delegate
  292. class IFDRational(Rational):
  293. """Implements a rational class where 0/0 is a legal value to match
  294. the in the wild use of exif rationals.
  295. e.g., DigitalZoomRatio - 0.00/0.00 indicates that no digital zoom was used
  296. """
  297. """ If the denominator is 0, store this as a float('nan'), otherwise store
  298. as a fractions.Fraction(). Delegate as appropriate
  299. """
  300. __slots__ = ("_numerator", "_denominator", "_val")
  301. def __init__(self, value, denominator=1):
  302. """
  303. :param value: either an integer numerator, a
  304. float/rational/other number, or an IFDRational
  305. :param denominator: Optional integer denominator
  306. """
  307. if isinstance(value, IFDRational):
  308. self._numerator = value.numerator
  309. self._denominator = value.denominator
  310. self._val = value._val
  311. return
  312. if isinstance(value, Fraction):
  313. self._numerator = value.numerator
  314. self._denominator = value.denominator
  315. else:
  316. self._numerator = value
  317. self._denominator = denominator
  318. if denominator == 0:
  319. self._val = float("nan")
  320. elif denominator == 1:
  321. self._val = Fraction(value)
  322. else:
  323. self._val = Fraction(value, denominator)
  324. @property
  325. def numerator(self):
  326. return self._numerator
  327. @property
  328. def denominator(self):
  329. return self._denominator
  330. def limit_rational(self, max_denominator):
  331. """
  332. :param max_denominator: Integer, the maximum denominator value
  333. :returns: Tuple of (numerator, denominator)
  334. """
  335. if self.denominator == 0:
  336. return self.numerator, self.denominator
  337. f = self._val.limit_denominator(max_denominator)
  338. return f.numerator, f.denominator
  339. def __repr__(self) -> str:
  340. return str(float(self._val))
  341. def __hash__(self) -> int:
  342. return self._val.__hash__()
  343. def __eq__(self, other: object) -> bool:
  344. val = self._val
  345. if isinstance(other, IFDRational):
  346. other = other._val
  347. if isinstance(other, float):
  348. val = float(val)
  349. return val == other
  350. def __getstate__(self):
  351. return [self._val, self._numerator, self._denominator]
  352. def __setstate__(self, state):
  353. IFDRational.__init__(self, 0)
  354. _val, _numerator, _denominator = state
  355. self._val = _val
  356. self._numerator = _numerator
  357. self._denominator = _denominator
  358. """ a = ['add','radd', 'sub', 'rsub', 'mul', 'rmul',
  359. 'truediv', 'rtruediv', 'floordiv', 'rfloordiv',
  360. 'mod','rmod', 'pow','rpow', 'pos', 'neg',
  361. 'abs', 'trunc', 'lt', 'gt', 'le', 'ge', 'bool',
  362. 'ceil', 'floor', 'round']
  363. print("\n".join("__%s__ = _delegate('__%s__')" % (s,s) for s in a))
  364. """
  365. __add__ = _delegate("__add__")
  366. __radd__ = _delegate("__radd__")
  367. __sub__ = _delegate("__sub__")
  368. __rsub__ = _delegate("__rsub__")
  369. __mul__ = _delegate("__mul__")
  370. __rmul__ = _delegate("__rmul__")
  371. __truediv__ = _delegate("__truediv__")
  372. __rtruediv__ = _delegate("__rtruediv__")
  373. __floordiv__ = _delegate("__floordiv__")
  374. __rfloordiv__ = _delegate("__rfloordiv__")
  375. __mod__ = _delegate("__mod__")
  376. __rmod__ = _delegate("__rmod__")
  377. __pow__ = _delegate("__pow__")
  378. __rpow__ = _delegate("__rpow__")
  379. __pos__ = _delegate("__pos__")
  380. __neg__ = _delegate("__neg__")
  381. __abs__ = _delegate("__abs__")
  382. __trunc__ = _delegate("__trunc__")
  383. __lt__ = _delegate("__lt__")
  384. __gt__ = _delegate("__gt__")
  385. __le__ = _delegate("__le__")
  386. __ge__ = _delegate("__ge__")
  387. __bool__ = _delegate("__bool__")
  388. __ceil__ = _delegate("__ceil__")
  389. __floor__ = _delegate("__floor__")
  390. __round__ = _delegate("__round__")
  391. # Python >= 3.11
  392. if hasattr(Fraction, "__int__"):
  393. __int__ = _delegate("__int__")
  394. def _register_loader(idx, size):
  395. def decorator(func):
  396. from .TiffTags import TYPES
  397. if func.__name__.startswith("load_"):
  398. TYPES[idx] = func.__name__[5:].replace("_", " ")
  399. _load_dispatch[idx] = size, func # noqa: F821
  400. return func
  401. return decorator
  402. def _register_writer(idx):
  403. def decorator(func):
  404. _write_dispatch[idx] = func # noqa: F821
  405. return func
  406. return decorator
  407. def _register_basic(idx_fmt_name):
  408. from .TiffTags import TYPES
  409. idx, fmt, name = idx_fmt_name
  410. TYPES[idx] = name
  411. size = struct.calcsize(f"={fmt}")
  412. _load_dispatch[idx] = ( # noqa: F821
  413. size,
  414. lambda self, data, legacy_api=True: (
  415. self._unpack(f"{len(data) // size}{fmt}", data)
  416. ),
  417. )
  418. _write_dispatch[idx] = lambda self, *values: ( # noqa: F821
  419. b"".join(self._pack(fmt, value) for value in values)
  420. )
  421. if TYPE_CHECKING:
  422. _IFDv2Base = MutableMapping[int, Any]
  423. else:
  424. _IFDv2Base = MutableMapping
  425. class ImageFileDirectory_v2(_IFDv2Base):
  426. """This class represents a TIFF tag directory. To speed things up, we
  427. don't decode tags unless they're asked for.
  428. Exposes a dictionary interface of the tags in the directory::
  429. ifd = ImageFileDirectory_v2()
  430. ifd[key] = 'Some Data'
  431. ifd.tagtype[key] = TiffTags.ASCII
  432. print(ifd[key])
  433. 'Some Data'
  434. Individual values are returned as the strings or numbers, sequences are
  435. returned as tuples of the values.
  436. The tiff metadata type of each item is stored in a dictionary of
  437. tag types in
  438. :attr:`~PIL.TiffImagePlugin.ImageFileDirectory_v2.tagtype`. The types
  439. are read from a tiff file, guessed from the type added, or added
  440. manually.
  441. Data Structures:
  442. * ``self.tagtype = {}``
  443. * Key: numerical TIFF tag number
  444. * Value: integer corresponding to the data type from
  445. :py:data:`.TiffTags.TYPES`
  446. .. versionadded:: 3.0.0
  447. 'Internal' data structures:
  448. * ``self._tags_v2 = {}``
  449. * Key: numerical TIFF tag number
  450. * Value: decoded data, as tuple for multiple values
  451. * ``self._tagdata = {}``
  452. * Key: numerical TIFF tag number
  453. * Value: undecoded byte string from file
  454. * ``self._tags_v1 = {}``
  455. * Key: numerical TIFF tag number
  456. * Value: decoded data in the v1 format
  457. Tags will be found in the private attributes ``self._tagdata``, and in
  458. ``self._tags_v2`` once decoded.
  459. ``self.legacy_api`` is a value for internal use, and shouldn't be changed
  460. from outside code. In cooperation with
  461. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`, if ``legacy_api``
  462. is true, then decoded tags will be populated into both ``_tags_v1`` and
  463. ``_tags_v2``. ``_tags_v2`` will be used if this IFD is used in the TIFF
  464. save routine. Tags should be read from ``_tags_v1`` if
  465. ``legacy_api == true``.
  466. """
  467. _load_dispatch: dict[int, Callable[[ImageFileDirectory_v2, bytes, bool], Any]] = {}
  468. _write_dispatch: dict[int, Callable[..., Any]] = {}
  469. def __init__(
  470. self,
  471. ifh: bytes = b"II\052\0\0\0\0\0",
  472. prefix: bytes | None = None,
  473. group: int | None = None,
  474. ) -> None:
  475. """Initialize an ImageFileDirectory.
  476. To construct an ImageFileDirectory from a real file, pass the 8-byte
  477. magic header to the constructor. To only set the endianness, pass it
  478. as the 'prefix' keyword argument.
  479. :param ifh: One of the accepted magic headers (cf. PREFIXES); also sets
  480. endianness.
  481. :param prefix: Override the endianness of the file.
  482. """
  483. if not _accept(ifh):
  484. msg = f"not a TIFF file (header {repr(ifh)} not valid)"
  485. raise SyntaxError(msg)
  486. self._prefix = prefix if prefix is not None else ifh[:2]
  487. if self._prefix == MM:
  488. self._endian = ">"
  489. elif self._prefix == II:
  490. self._endian = "<"
  491. else:
  492. msg = "not a TIFF IFD"
  493. raise SyntaxError(msg)
  494. self._bigtiff = ifh[2] == 43
  495. self.group = group
  496. self.tagtype: dict[int, int] = {}
  497. """ Dictionary of tag types """
  498. self.reset()
  499. (self.next,) = (
  500. self._unpack("Q", ifh[8:]) if self._bigtiff else self._unpack("L", ifh[4:])
  501. )
  502. self._legacy_api = False
  503. prefix = property(lambda self: self._prefix)
  504. offset = property(lambda self: self._offset)
  505. @property
  506. def legacy_api(self) -> bool:
  507. return self._legacy_api
  508. @legacy_api.setter
  509. def legacy_api(self, value: bool) -> NoReturn:
  510. msg = "Not allowing setting of legacy api"
  511. raise Exception(msg)
  512. def reset(self) -> None:
  513. self._tags_v1: dict[int, Any] = {} # will remain empty if legacy_api is false
  514. self._tags_v2: dict[int, Any] = {} # main tag storage
  515. self._tagdata: dict[int, bytes] = {}
  516. self.tagtype = {} # added 2008-06-05 by Florian Hoech
  517. self._next = None
  518. self._offset = None
  519. def __str__(self) -> str:
  520. return str(dict(self))
  521. def named(self):
  522. """
  523. :returns: dict of name|key: value
  524. Returns the complete tag dictionary, with named tags where possible.
  525. """
  526. return {
  527. TiffTags.lookup(code, self.group).name: value
  528. for code, value in self.items()
  529. }
  530. def __len__(self) -> int:
  531. return len(set(self._tagdata) | set(self._tags_v2))
  532. def __getitem__(self, tag):
  533. if tag not in self._tags_v2: # unpack on the fly
  534. data = self._tagdata[tag]
  535. typ = self.tagtype[tag]
  536. size, handler = self._load_dispatch[typ]
  537. self[tag] = handler(self, data, self.legacy_api) # check type
  538. val = self._tags_v2[tag]
  539. if self.legacy_api and not isinstance(val, (tuple, bytes)):
  540. val = (val,)
  541. return val
  542. def __contains__(self, tag):
  543. return tag in self._tags_v2 or tag in self._tagdata
  544. def __setitem__(self, tag, value):
  545. self._setitem(tag, value, self.legacy_api)
  546. def _setitem(self, tag, value, legacy_api):
  547. basetypes = (Number, bytes, str)
  548. info = TiffTags.lookup(tag, self.group)
  549. values = [value] if isinstance(value, basetypes) else value
  550. if tag not in self.tagtype:
  551. if info.type:
  552. self.tagtype[tag] = info.type
  553. else:
  554. self.tagtype[tag] = TiffTags.UNDEFINED
  555. if all(isinstance(v, IFDRational) for v in values):
  556. self.tagtype[tag] = (
  557. TiffTags.RATIONAL
  558. if all(v >= 0 for v in values)
  559. else TiffTags.SIGNED_RATIONAL
  560. )
  561. elif all(isinstance(v, int) for v in values):
  562. if all(0 <= v < 2**16 for v in values):
  563. self.tagtype[tag] = TiffTags.SHORT
  564. elif all(-(2**15) < v < 2**15 for v in values):
  565. self.tagtype[tag] = TiffTags.SIGNED_SHORT
  566. else:
  567. self.tagtype[tag] = (
  568. TiffTags.LONG
  569. if all(v >= 0 for v in values)
  570. else TiffTags.SIGNED_LONG
  571. )
  572. elif all(isinstance(v, float) for v in values):
  573. self.tagtype[tag] = TiffTags.DOUBLE
  574. elif all(isinstance(v, str) for v in values):
  575. self.tagtype[tag] = TiffTags.ASCII
  576. elif all(isinstance(v, bytes) for v in values):
  577. self.tagtype[tag] = TiffTags.BYTE
  578. if self.tagtype[tag] == TiffTags.UNDEFINED:
  579. values = [
  580. v.encode("ascii", "replace") if isinstance(v, str) else v
  581. for v in values
  582. ]
  583. elif self.tagtype[tag] == TiffTags.RATIONAL:
  584. values = [float(v) if isinstance(v, int) else v for v in values]
  585. is_ifd = self.tagtype[tag] == TiffTags.LONG and isinstance(values, dict)
  586. if not is_ifd:
  587. values = tuple(info.cvt_enum(value) for value in values)
  588. dest = self._tags_v1 if legacy_api else self._tags_v2
  589. # Three branches:
  590. # Spec'd length == 1, Actual length 1, store as element
  591. # Spec'd length == 1, Actual > 1, Warn and truncate. Formerly barfed.
  592. # No Spec, Actual length 1, Formerly (<4.2) returned a 1 element tuple.
  593. # Don't mess with the legacy api, since it's frozen.
  594. if not is_ifd and (
  595. (info.length == 1)
  596. or self.tagtype[tag] == TiffTags.BYTE
  597. or (info.length is None and len(values) == 1 and not legacy_api)
  598. ):
  599. # Don't mess with the legacy api, since it's frozen.
  600. if legacy_api and self.tagtype[tag] in [
  601. TiffTags.RATIONAL,
  602. TiffTags.SIGNED_RATIONAL,
  603. ]: # rationals
  604. values = (values,)
  605. try:
  606. (dest[tag],) = values
  607. except ValueError:
  608. # We've got a builtin tag with 1 expected entry
  609. warnings.warn(
  610. f"Metadata Warning, tag {tag} had too many entries: "
  611. f"{len(values)}, expected 1"
  612. )
  613. dest[tag] = values[0]
  614. else:
  615. # Spec'd length > 1 or undefined
  616. # Unspec'd, and length > 1
  617. dest[tag] = values
  618. def __delitem__(self, tag: int) -> None:
  619. self._tags_v2.pop(tag, None)
  620. self._tags_v1.pop(tag, None)
  621. self._tagdata.pop(tag, None)
  622. def __iter__(self):
  623. return iter(set(self._tagdata) | set(self._tags_v2))
  624. def _unpack(self, fmt, data):
  625. return struct.unpack(self._endian + fmt, data)
  626. def _pack(self, fmt, *values):
  627. return struct.pack(self._endian + fmt, *values)
  628. list(
  629. map(
  630. _register_basic,
  631. [
  632. (TiffTags.SHORT, "H", "short"),
  633. (TiffTags.LONG, "L", "long"),
  634. (TiffTags.SIGNED_BYTE, "b", "signed byte"),
  635. (TiffTags.SIGNED_SHORT, "h", "signed short"),
  636. (TiffTags.SIGNED_LONG, "l", "signed long"),
  637. (TiffTags.FLOAT, "f", "float"),
  638. (TiffTags.DOUBLE, "d", "double"),
  639. (TiffTags.IFD, "L", "long"),
  640. (TiffTags.LONG8, "Q", "long8"),
  641. ],
  642. )
  643. )
  644. @_register_loader(1, 1) # Basic type, except for the legacy API.
  645. def load_byte(self, data, legacy_api=True):
  646. return data
  647. @_register_writer(1) # Basic type, except for the legacy API.
  648. def write_byte(self, data):
  649. if isinstance(data, IFDRational):
  650. data = int(data)
  651. if isinstance(data, int):
  652. data = bytes((data,))
  653. return data
  654. @_register_loader(2, 1)
  655. def load_string(self, data, legacy_api=True):
  656. if data.endswith(b"\0"):
  657. data = data[:-1]
  658. return data.decode("latin-1", "replace")
  659. @_register_writer(2)
  660. def write_string(self, value):
  661. # remerge of https://github.com/python-pillow/Pillow/pull/1416
  662. if isinstance(value, int):
  663. value = str(value)
  664. if not isinstance(value, bytes):
  665. value = value.encode("ascii", "replace")
  666. return value + b"\0"
  667. @_register_loader(5, 8)
  668. def load_rational(self, data, legacy_api=True):
  669. vals = self._unpack(f"{len(data) // 4}L", data)
  670. def combine(a, b):
  671. return (a, b) if legacy_api else IFDRational(a, b)
  672. return tuple(combine(num, denom) for num, denom in zip(vals[::2], vals[1::2]))
  673. @_register_writer(5)
  674. def write_rational(self, *values):
  675. return b"".join(
  676. self._pack("2L", *_limit_rational(frac, 2**32 - 1)) for frac in values
  677. )
  678. @_register_loader(7, 1)
  679. def load_undefined(self, data, legacy_api=True):
  680. return data
  681. @_register_writer(7)
  682. def write_undefined(self, value):
  683. if isinstance(value, IFDRational):
  684. value = int(value)
  685. if isinstance(value, int):
  686. value = str(value).encode("ascii", "replace")
  687. return value
  688. @_register_loader(10, 8)
  689. def load_signed_rational(self, data, legacy_api=True):
  690. vals = self._unpack(f"{len(data) // 4}l", data)
  691. def combine(a, b):
  692. return (a, b) if legacy_api else IFDRational(a, b)
  693. return tuple(combine(num, denom) for num, denom in zip(vals[::2], vals[1::2]))
  694. @_register_writer(10)
  695. def write_signed_rational(self, *values):
  696. return b"".join(
  697. self._pack("2l", *_limit_signed_rational(frac, 2**31 - 1, -(2**31)))
  698. for frac in values
  699. )
  700. def _ensure_read(self, fp, size):
  701. ret = fp.read(size)
  702. if len(ret) != size:
  703. msg = (
  704. "Corrupt EXIF data. "
  705. f"Expecting to read {size} bytes but only got {len(ret)}. "
  706. )
  707. raise OSError(msg)
  708. return ret
  709. def load(self, fp):
  710. self.reset()
  711. self._offset = fp.tell()
  712. try:
  713. tag_count = (
  714. self._unpack("Q", self._ensure_read(fp, 8))
  715. if self._bigtiff
  716. else self._unpack("H", self._ensure_read(fp, 2))
  717. )[0]
  718. for i in range(tag_count):
  719. tag, typ, count, data = (
  720. self._unpack("HHQ8s", self._ensure_read(fp, 20))
  721. if self._bigtiff
  722. else self._unpack("HHL4s", self._ensure_read(fp, 12))
  723. )
  724. tagname = TiffTags.lookup(tag, self.group).name
  725. typname = TYPES.get(typ, "unknown")
  726. msg = f"tag: {tagname} ({tag}) - type: {typname} ({typ})"
  727. try:
  728. unit_size, handler = self._load_dispatch[typ]
  729. except KeyError:
  730. logger.debug("%s - unsupported type %s", msg, typ)
  731. continue # ignore unsupported type
  732. size = count * unit_size
  733. if size > (8 if self._bigtiff else 4):
  734. here = fp.tell()
  735. (offset,) = self._unpack("Q" if self._bigtiff else "L", data)
  736. msg += f" Tag Location: {here} - Data Location: {offset}"
  737. fp.seek(offset)
  738. data = ImageFile._safe_read(fp, size)
  739. fp.seek(here)
  740. else:
  741. data = data[:size]
  742. if len(data) != size:
  743. warnings.warn(
  744. "Possibly corrupt EXIF data. "
  745. f"Expecting to read {size} bytes but only got {len(data)}."
  746. f" Skipping tag {tag}"
  747. )
  748. logger.debug(msg)
  749. continue
  750. if not data:
  751. logger.debug(msg)
  752. continue
  753. self._tagdata[tag] = data
  754. self.tagtype[tag] = typ
  755. msg += " - value: " + (
  756. "<table: %d bytes>" % size if size > 32 else repr(data)
  757. )
  758. logger.debug(msg)
  759. (self.next,) = (
  760. self._unpack("Q", self._ensure_read(fp, 8))
  761. if self._bigtiff
  762. else self._unpack("L", self._ensure_read(fp, 4))
  763. )
  764. except OSError as msg:
  765. warnings.warn(str(msg))
  766. return
  767. def tobytes(self, offset=0):
  768. # FIXME What about tagdata?
  769. result = self._pack("H", len(self._tags_v2))
  770. entries = []
  771. offset = offset + len(result) + len(self._tags_v2) * 12 + 4
  772. stripoffsets = None
  773. # pass 1: convert tags to binary format
  774. # always write tags in ascending order
  775. for tag, value in sorted(self._tags_v2.items()):
  776. if tag == STRIPOFFSETS:
  777. stripoffsets = len(entries)
  778. typ = self.tagtype.get(tag)
  779. logger.debug("Tag %s, Type: %s, Value: %s", tag, typ, repr(value))
  780. is_ifd = typ == TiffTags.LONG and isinstance(value, dict)
  781. if is_ifd:
  782. if self._endian == "<":
  783. ifh = b"II\x2A\x00\x08\x00\x00\x00"
  784. else:
  785. ifh = b"MM\x00\x2A\x00\x00\x00\x08"
  786. ifd = ImageFileDirectory_v2(ifh, group=tag)
  787. values = self._tags_v2[tag]
  788. for ifd_tag, ifd_value in values.items():
  789. ifd[ifd_tag] = ifd_value
  790. data = ifd.tobytes(offset)
  791. else:
  792. values = value if isinstance(value, tuple) else (value,)
  793. data = self._write_dispatch[typ](self, *values)
  794. tagname = TiffTags.lookup(tag, self.group).name
  795. typname = "ifd" if is_ifd else TYPES.get(typ, "unknown")
  796. msg = f"save: {tagname} ({tag}) - type: {typname} ({typ})"
  797. msg += " - value: " + (
  798. "<table: %d bytes>" % len(data) if len(data) >= 16 else str(values)
  799. )
  800. logger.debug(msg)
  801. # count is sum of lengths for string and arbitrary data
  802. if is_ifd:
  803. count = 1
  804. elif typ in [TiffTags.BYTE, TiffTags.ASCII, TiffTags.UNDEFINED]:
  805. count = len(data)
  806. else:
  807. count = len(values)
  808. # figure out if data fits into the entry
  809. if len(data) <= 4:
  810. entries.append((tag, typ, count, data.ljust(4, b"\0"), b""))
  811. else:
  812. entries.append((tag, typ, count, self._pack("L", offset), data))
  813. offset += (len(data) + 1) // 2 * 2 # pad to word
  814. # update strip offset data to point beyond auxiliary data
  815. if stripoffsets is not None:
  816. tag, typ, count, value, data = entries[stripoffsets]
  817. if data:
  818. msg = "multistrip support not yet implemented"
  819. raise NotImplementedError(msg)
  820. value = self._pack("L", self._unpack("L", value)[0] + offset)
  821. entries[stripoffsets] = tag, typ, count, value, data
  822. # pass 2: write entries to file
  823. for tag, typ, count, value, data in entries:
  824. logger.debug("%s %s %s %s %s", tag, typ, count, repr(value), repr(data))
  825. result += self._pack("HHL4s", tag, typ, count, value)
  826. # -- overwrite here for multi-page --
  827. result += b"\0\0\0\0" # end of entries
  828. # pass 3: write auxiliary data to file
  829. for tag, typ, count, value, data in entries:
  830. result += data
  831. if len(data) & 1:
  832. result += b"\0"
  833. return result
  834. def save(self, fp):
  835. if fp.tell() == 0: # skip TIFF header on subsequent pages
  836. # tiff header -- PIL always starts the first IFD at offset 8
  837. fp.write(self._prefix + self._pack("HL", 42, 8))
  838. offset = fp.tell()
  839. result = self.tobytes(offset)
  840. fp.write(result)
  841. return offset + len(result)
  842. ImageFileDirectory_v2._load_dispatch = _load_dispatch
  843. ImageFileDirectory_v2._write_dispatch = _write_dispatch
  844. for idx, name in TYPES.items():
  845. name = name.replace(" ", "_")
  846. setattr(ImageFileDirectory_v2, f"load_{name}", _load_dispatch[idx][1])
  847. setattr(ImageFileDirectory_v2, f"write_{name}", _write_dispatch[idx])
  848. del _load_dispatch, _write_dispatch, idx, name
  849. # Legacy ImageFileDirectory support.
  850. class ImageFileDirectory_v1(ImageFileDirectory_v2):
  851. """This class represents the **legacy** interface to a TIFF tag directory.
  852. Exposes a dictionary interface of the tags in the directory::
  853. ifd = ImageFileDirectory_v1()
  854. ifd[key] = 'Some Data'
  855. ifd.tagtype[key] = TiffTags.ASCII
  856. print(ifd[key])
  857. ('Some Data',)
  858. Also contains a dictionary of tag types as read from the tiff image file,
  859. :attr:`~PIL.TiffImagePlugin.ImageFileDirectory_v1.tagtype`.
  860. Values are returned as a tuple.
  861. .. deprecated:: 3.0.0
  862. """
  863. def __init__(self, *args, **kwargs):
  864. super().__init__(*args, **kwargs)
  865. self._legacy_api = True
  866. tags = property(lambda self: self._tags_v1)
  867. tagdata = property(lambda self: self._tagdata)
  868. # defined in ImageFileDirectory_v2
  869. tagtype: dict[int, int]
  870. """Dictionary of tag types"""
  871. @classmethod
  872. def from_v2(cls, original):
  873. """Returns an
  874. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`
  875. instance with the same data as is contained in the original
  876. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
  877. instance.
  878. :returns: :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`
  879. """
  880. ifd = cls(prefix=original.prefix)
  881. ifd._tagdata = original._tagdata
  882. ifd.tagtype = original.tagtype
  883. ifd.next = original.next # an indicator for multipage tiffs
  884. return ifd
  885. def to_v2(self) -> ImageFileDirectory_v2:
  886. """Returns an
  887. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
  888. instance with the same data as is contained in the original
  889. :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v1`
  890. instance.
  891. :returns: :py:class:`~PIL.TiffImagePlugin.ImageFileDirectory_v2`
  892. """
  893. ifd = ImageFileDirectory_v2(prefix=self.prefix)
  894. ifd._tagdata = dict(self._tagdata)
  895. ifd.tagtype = dict(self.tagtype)
  896. ifd._tags_v2 = dict(self._tags_v2)
  897. return ifd
  898. def __contains__(self, tag):
  899. return tag in self._tags_v1 or tag in self._tagdata
  900. def __len__(self) -> int:
  901. return len(set(self._tagdata) | set(self._tags_v1))
  902. def __iter__(self):
  903. return iter(set(self._tagdata) | set(self._tags_v1))
  904. def __setitem__(self, tag, value):
  905. for legacy_api in (False, True):
  906. self._setitem(tag, value, legacy_api)
  907. def __getitem__(self, tag):
  908. if tag not in self._tags_v1: # unpack on the fly
  909. data = self._tagdata[tag]
  910. typ = self.tagtype[tag]
  911. size, handler = self._load_dispatch[typ]
  912. for legacy in (False, True):
  913. self._setitem(tag, handler(self, data, legacy), legacy)
  914. val = self._tags_v1[tag]
  915. if not isinstance(val, (tuple, bytes)):
  916. val = (val,)
  917. return val
  918. # undone -- switch this pointer when IFD_LEGACY_API == False
  919. ImageFileDirectory = ImageFileDirectory_v1
  920. ##
  921. # Image plugin for TIFF files.
  922. class TiffImageFile(ImageFile.ImageFile):
  923. format = "TIFF"
  924. format_description = "Adobe TIFF"
  925. _close_exclusive_fp_after_loading = False
  926. def __init__(self, fp=None, filename=None):
  927. self.tag_v2 = None
  928. """ Image file directory (tag dictionary) """
  929. self.tag = None
  930. """ Legacy tag entries """
  931. super().__init__(fp, filename)
  932. def _open(self) -> None:
  933. """Open the first image in a TIFF file"""
  934. # Header
  935. ifh = self.fp.read(8)
  936. if ifh[2] == 43:
  937. ifh += self.fp.read(8)
  938. self.tag_v2 = ImageFileDirectory_v2(ifh)
  939. # legacy IFD entries will be filled in later
  940. self.ifd = None
  941. # setup frame pointers
  942. self.__first = self.__next = self.tag_v2.next
  943. self.__frame = -1
  944. self._fp = self.fp
  945. self._frame_pos: list[int] = []
  946. self._n_frames: int | None = None
  947. logger.debug("*** TiffImageFile._open ***")
  948. logger.debug("- __first: %s", self.__first)
  949. logger.debug("- ifh: %s", repr(ifh)) # Use repr to avoid str(bytes)
  950. # and load the first frame
  951. self._seek(0)
  952. @property
  953. def n_frames(self):
  954. if self._n_frames is None:
  955. current = self.tell()
  956. self._seek(len(self._frame_pos))
  957. while self._n_frames is None:
  958. self._seek(self.tell() + 1)
  959. self.seek(current)
  960. return self._n_frames
  961. def seek(self, frame: int) -> None:
  962. """Select a given frame as current image"""
  963. if not self._seek_check(frame):
  964. return
  965. self._seek(frame)
  966. # Create a new core image object on second and
  967. # subsequent frames in the image. Image may be
  968. # different size/mode.
  969. Image._decompression_bomb_check(self.size)
  970. self.im = Image.core.new(self.mode, self.size)
  971. def _seek(self, frame: int) -> None:
  972. self.fp = self._fp
  973. # reset buffered io handle in case fp
  974. # was passed to libtiff, invalidating the buffer
  975. self.fp.tell()
  976. while len(self._frame_pos) <= frame:
  977. if not self.__next:
  978. msg = "no more images in TIFF file"
  979. raise EOFError(msg)
  980. logger.debug(
  981. "Seeking to frame %s, on frame %s, __next %s, location: %s",
  982. frame,
  983. self.__frame,
  984. self.__next,
  985. self.fp.tell(),
  986. )
  987. if self.__next >= 2**63:
  988. msg = "Unable to seek to frame"
  989. raise ValueError(msg)
  990. self.fp.seek(self.__next)
  991. self._frame_pos.append(self.__next)
  992. logger.debug("Loading tags, location: %s", self.fp.tell())
  993. self.tag_v2.load(self.fp)
  994. if self.tag_v2.next in self._frame_pos:
  995. # This IFD has already been processed
  996. # Declare this to be the end of the image
  997. self.__next = 0
  998. else:
  999. self.__next = self.tag_v2.next
  1000. if self.__next == 0:
  1001. self._n_frames = frame + 1
  1002. if len(self._frame_pos) == 1:
  1003. self.is_animated = self.__next != 0
  1004. self.__frame += 1
  1005. self.fp.seek(self._frame_pos[frame])
  1006. self.tag_v2.load(self.fp)
  1007. if XMP in self.tag_v2:
  1008. self.info["xmp"] = self.tag_v2[XMP]
  1009. elif "xmp" in self.info:
  1010. del self.info["xmp"]
  1011. self._reload_exif()
  1012. # fill the legacy tag/ifd entries
  1013. self.tag = self.ifd = ImageFileDirectory_v1.from_v2(self.tag_v2)
  1014. self.__frame = frame
  1015. self._setup()
  1016. def tell(self) -> int:
  1017. """Return the current frame number"""
  1018. return self.__frame
  1019. def get_photoshop_blocks(self):
  1020. """
  1021. Returns a dictionary of Photoshop "Image Resource Blocks".
  1022. The keys are the image resource ID. For more information, see
  1023. https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_pgfId-1037727
  1024. :returns: Photoshop "Image Resource Blocks" in a dictionary.
  1025. """
  1026. blocks = {}
  1027. val = self.tag_v2.get(ExifTags.Base.ImageResources)
  1028. if val:
  1029. while val[:4] == b"8BIM":
  1030. id = i16(val[4:6])
  1031. n = math.ceil((val[6] + 1) / 2) * 2
  1032. size = i32(val[6 + n : 10 + n])
  1033. data = val[10 + n : 10 + n + size]
  1034. blocks[id] = {"data": data}
  1035. val = val[math.ceil((10 + n + size) / 2) * 2 :]
  1036. return blocks
  1037. def load(self):
  1038. if self.tile and self.use_load_libtiff:
  1039. return self._load_libtiff()
  1040. return super().load()
  1041. def load_end(self) -> None:
  1042. # allow closing if we're on the first frame, there's no next
  1043. # This is the ImageFile.load path only, libtiff specific below.
  1044. if not self.is_animated:
  1045. self._close_exclusive_fp_after_loading = True
  1046. # reset buffered io handle in case fp
  1047. # was passed to libtiff, invalidating the buffer
  1048. self.fp.tell()
  1049. # load IFD data from fp before it is closed
  1050. exif = self.getexif()
  1051. for key in TiffTags.TAGS_V2_GROUPS:
  1052. if key not in exif:
  1053. continue
  1054. exif.get_ifd(key)
  1055. ImageOps.exif_transpose(self, in_place=True)
  1056. if ExifTags.Base.Orientation in self.tag_v2:
  1057. del self.tag_v2[ExifTags.Base.Orientation]
  1058. def _load_libtiff(self):
  1059. """Overload method triggered when we detect a compressed tiff
  1060. Calls out to libtiff"""
  1061. Image.Image.load(self)
  1062. self.load_prepare()
  1063. if not len(self.tile) == 1:
  1064. msg = "Not exactly one tile"
  1065. raise OSError(msg)
  1066. # (self._compression, (extents tuple),
  1067. # 0, (rawmode, self._compression, fp))
  1068. extents = self.tile[0][1]
  1069. args = list(self.tile[0][3])
  1070. # To be nice on memory footprint, if there's a
  1071. # file descriptor, use that instead of reading
  1072. # into a string in python.
  1073. try:
  1074. fp = hasattr(self.fp, "fileno") and self.fp.fileno()
  1075. # flush the file descriptor, prevents error on pypy 2.4+
  1076. # should also eliminate the need for fp.tell
  1077. # in _seek
  1078. if hasattr(self.fp, "flush"):
  1079. self.fp.flush()
  1080. except OSError:
  1081. # io.BytesIO have a fileno, but returns an OSError if
  1082. # it doesn't use a file descriptor.
  1083. fp = False
  1084. if fp:
  1085. args[2] = fp
  1086. decoder = Image._getdecoder(
  1087. self.mode, "libtiff", tuple(args), self.decoderconfig
  1088. )
  1089. try:
  1090. decoder.setimage(self.im, extents)
  1091. except ValueError as e:
  1092. msg = "Couldn't set the image"
  1093. raise OSError(msg) from e
  1094. close_self_fp = self._exclusive_fp and not self.is_animated
  1095. if hasattr(self.fp, "getvalue"):
  1096. # We've got a stringio like thing passed in. Yay for all in memory.
  1097. # The decoder needs the entire file in one shot, so there's not
  1098. # a lot we can do here other than give it the entire file.
  1099. # unless we could do something like get the address of the
  1100. # underlying string for stringio.
  1101. #
  1102. # Rearranging for supporting byteio items, since they have a fileno
  1103. # that returns an OSError if there's no underlying fp. Easier to
  1104. # deal with here by reordering.
  1105. logger.debug("have getvalue. just sending in a string from getvalue")
  1106. n, err = decoder.decode(self.fp.getvalue())
  1107. elif fp:
  1108. # we've got a actual file on disk, pass in the fp.
  1109. logger.debug("have fileno, calling fileno version of the decoder.")
  1110. if not close_self_fp:
  1111. self.fp.seek(0)
  1112. # 4 bytes, otherwise the trace might error out
  1113. n, err = decoder.decode(b"fpfp")
  1114. else:
  1115. # we have something else.
  1116. logger.debug("don't have fileno or getvalue. just reading")
  1117. self.fp.seek(0)
  1118. # UNDONE -- so much for that buffer size thing.
  1119. n, err = decoder.decode(self.fp.read())
  1120. self.tile = []
  1121. self.readonly = 0
  1122. self.load_end()
  1123. if close_self_fp:
  1124. self.fp.close()
  1125. self.fp = None # might be shared
  1126. if err < 0:
  1127. raise OSError(err)
  1128. return Image.Image.load(self)
  1129. def _setup(self):
  1130. """Setup this image object based on current tags"""
  1131. if 0xBC01 in self.tag_v2:
  1132. msg = "Windows Media Photo files not yet supported"
  1133. raise OSError(msg)
  1134. # extract relevant tags
  1135. self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
  1136. self._planar_configuration = self.tag_v2.get(PLANAR_CONFIGURATION, 1)
  1137. # photometric is a required tag, but not everyone is reading
  1138. # the specification
  1139. photo = self.tag_v2.get(PHOTOMETRIC_INTERPRETATION, 0)
  1140. # old style jpeg compression images most certainly are YCbCr
  1141. if self._compression == "tiff_jpeg":
  1142. photo = 6
  1143. fillorder = self.tag_v2.get(FILLORDER, 1)
  1144. logger.debug("*** Summary ***")
  1145. logger.debug("- compression: %s", self._compression)
  1146. logger.debug("- photometric_interpretation: %s", photo)
  1147. logger.debug("- planar_configuration: %s", self._planar_configuration)
  1148. logger.debug("- fill_order: %s", fillorder)
  1149. logger.debug("- YCbCr subsampling: %s", self.tag.get(YCBCRSUBSAMPLING))
  1150. # size
  1151. xsize = int(self.tag_v2.get(IMAGEWIDTH))
  1152. ysize = int(self.tag_v2.get(IMAGELENGTH))
  1153. self._size = xsize, ysize
  1154. logger.debug("- size: %s", self.size)
  1155. sample_format = self.tag_v2.get(SAMPLEFORMAT, (1,))
  1156. if len(sample_format) > 1 and max(sample_format) == min(sample_format) == 1:
  1157. # SAMPLEFORMAT is properly per band, so an RGB image will
  1158. # be (1,1,1). But, we don't support per band pixel types,
  1159. # and anything more than one band is a uint8. So, just
  1160. # take the first element. Revisit this if adding support
  1161. # for more exotic images.
  1162. sample_format = (1,)
  1163. bps_tuple = self.tag_v2.get(BITSPERSAMPLE, (1,))
  1164. extra_tuple = self.tag_v2.get(EXTRASAMPLES, ())
  1165. if photo in (2, 6, 8): # RGB, YCbCr, LAB
  1166. bps_count = 3
  1167. elif photo == 5: # CMYK
  1168. bps_count = 4
  1169. else:
  1170. bps_count = 1
  1171. bps_count += len(extra_tuple)
  1172. bps_actual_count = len(bps_tuple)
  1173. samples_per_pixel = self.tag_v2.get(
  1174. SAMPLESPERPIXEL,
  1175. 3 if self._compression == "tiff_jpeg" and photo in (2, 6) else 1,
  1176. )
  1177. if samples_per_pixel > MAX_SAMPLESPERPIXEL:
  1178. # DOS check, samples_per_pixel can be a Long, and we extend the tuple below
  1179. logger.error(
  1180. "More samples per pixel than can be decoded: %s", samples_per_pixel
  1181. )
  1182. msg = "Invalid value for samples per pixel"
  1183. raise SyntaxError(msg)
  1184. if samples_per_pixel < bps_actual_count:
  1185. # If a file has more values in bps_tuple than expected,
  1186. # remove the excess.
  1187. bps_tuple = bps_tuple[:samples_per_pixel]
  1188. elif samples_per_pixel > bps_actual_count and bps_actual_count == 1:
  1189. # If a file has only one value in bps_tuple, when it should have more,
  1190. # presume it is the same number of bits for all of the samples.
  1191. bps_tuple = bps_tuple * samples_per_pixel
  1192. if len(bps_tuple) != samples_per_pixel:
  1193. msg = "unknown data organization"
  1194. raise SyntaxError(msg)
  1195. # mode: check photometric interpretation and bits per pixel
  1196. key = (
  1197. self.tag_v2.prefix,
  1198. photo,
  1199. sample_format,
  1200. fillorder,
  1201. bps_tuple,
  1202. extra_tuple,
  1203. )
  1204. logger.debug("format key: %s", key)
  1205. try:
  1206. self._mode, rawmode = OPEN_INFO[key]
  1207. except KeyError as e:
  1208. logger.debug("- unsupported format")
  1209. msg = "unknown pixel mode"
  1210. raise SyntaxError(msg) from e
  1211. logger.debug("- raw mode: %s", rawmode)
  1212. logger.debug("- pil mode: %s", self.mode)
  1213. self.info["compression"] = self._compression
  1214. xres = self.tag_v2.get(X_RESOLUTION, 1)
  1215. yres = self.tag_v2.get(Y_RESOLUTION, 1)
  1216. if xres and yres:
  1217. resunit = self.tag_v2.get(RESOLUTION_UNIT)
  1218. if resunit == 2: # dots per inch
  1219. self.info["dpi"] = (xres, yres)
  1220. elif resunit == 3: # dots per centimeter. convert to dpi
  1221. self.info["dpi"] = (xres * 2.54, yres * 2.54)
  1222. elif resunit is None: # used to default to 1, but now 2)
  1223. self.info["dpi"] = (xres, yres)
  1224. # For backward compatibility,
  1225. # we also preserve the old behavior
  1226. self.info["resolution"] = xres, yres
  1227. else: # No absolute unit of measurement
  1228. self.info["resolution"] = xres, yres
  1229. # build tile descriptors
  1230. x = y = layer = 0
  1231. self.tile = []
  1232. self.use_load_libtiff = READ_LIBTIFF or self._compression != "raw"
  1233. if self.use_load_libtiff:
  1234. # Decoder expects entire file as one tile.
  1235. # There's a buffer size limit in load (64k)
  1236. # so large g4 images will fail if we use that
  1237. # function.
  1238. #
  1239. # Setup the one tile for the whole image, then
  1240. # use the _load_libtiff function.
  1241. # libtiff handles the fillmode for us, so 1;IR should
  1242. # actually be 1;I. Including the R double reverses the
  1243. # bits, so stripes of the image are reversed. See
  1244. # https://github.com/python-pillow/Pillow/issues/279
  1245. if fillorder == 2:
  1246. # Replace fillorder with fillorder=1
  1247. key = key[:3] + (1,) + key[4:]
  1248. logger.debug("format key: %s", key)
  1249. # this should always work, since all the
  1250. # fillorder==2 modes have a corresponding
  1251. # fillorder=1 mode
  1252. self._mode, rawmode = OPEN_INFO[key]
  1253. # libtiff always returns the bytes in native order.
  1254. # we're expecting image byte order. So, if the rawmode
  1255. # contains I;16, we need to convert from native to image
  1256. # byte order.
  1257. if rawmode == "I;16":
  1258. rawmode = "I;16N"
  1259. if ";16B" in rawmode:
  1260. rawmode = rawmode.replace(";16B", ";16N")
  1261. if ";16L" in rawmode:
  1262. rawmode = rawmode.replace(";16L", ";16N")
  1263. # YCbCr images with new jpeg compression with pixels in one plane
  1264. # unpacked straight into RGB values
  1265. if (
  1266. photo == 6
  1267. and self._compression == "jpeg"
  1268. and self._planar_configuration == 1
  1269. ):
  1270. rawmode = "RGB"
  1271. # Offset in the tile tuple is 0, we go from 0,0 to
  1272. # w,h, and we only do this once -- eds
  1273. a = (rawmode, self._compression, False, self.tag_v2.offset)
  1274. self.tile.append(("libtiff", (0, 0, xsize, ysize), 0, a))
  1275. elif STRIPOFFSETS in self.tag_v2 or TILEOFFSETS in self.tag_v2:
  1276. # striped image
  1277. if STRIPOFFSETS in self.tag_v2:
  1278. offsets = self.tag_v2[STRIPOFFSETS]
  1279. h = self.tag_v2.get(ROWSPERSTRIP, ysize)
  1280. w = self.size[0]
  1281. else:
  1282. # tiled image
  1283. offsets = self.tag_v2[TILEOFFSETS]
  1284. w = self.tag_v2.get(TILEWIDTH)
  1285. h = self.tag_v2.get(TILELENGTH)
  1286. for offset in offsets:
  1287. if x + w > xsize:
  1288. stride = w * sum(bps_tuple) / 8 # bytes per line
  1289. else:
  1290. stride = 0
  1291. tile_rawmode = rawmode
  1292. if self._planar_configuration == 2:
  1293. # each band on it's own layer
  1294. tile_rawmode = rawmode[layer]
  1295. # adjust stride width accordingly
  1296. stride /= bps_count
  1297. a = (tile_rawmode, int(stride), 1)
  1298. self.tile.append(
  1299. (
  1300. self._compression,
  1301. (x, y, min(x + w, xsize), min(y + h, ysize)),
  1302. offset,
  1303. a,
  1304. )
  1305. )
  1306. x = x + w
  1307. if x >= self.size[0]:
  1308. x, y = 0, y + h
  1309. if y >= self.size[1]:
  1310. x = y = 0
  1311. layer += 1
  1312. else:
  1313. logger.debug("- unsupported data organization")
  1314. msg = "unknown data organization"
  1315. raise SyntaxError(msg)
  1316. # Fix up info.
  1317. if ICCPROFILE in self.tag_v2:
  1318. self.info["icc_profile"] = self.tag_v2[ICCPROFILE]
  1319. # fixup palette descriptor
  1320. if self.mode in ["P", "PA"]:
  1321. palette = [o8(b // 256) for b in self.tag_v2[COLORMAP]]
  1322. self.palette = ImagePalette.raw("RGB;L", b"".join(palette))
  1323. #
  1324. # --------------------------------------------------------------------
  1325. # Write TIFF files
  1326. # little endian is default except for image modes with
  1327. # explicit big endian byte-order
  1328. SAVE_INFO = {
  1329. # mode => rawmode, byteorder, photometrics,
  1330. # sampleformat, bitspersample, extra
  1331. "1": ("1", II, 1, 1, (1,), None),
  1332. "L": ("L", II, 1, 1, (8,), None),
  1333. "LA": ("LA", II, 1, 1, (8, 8), 2),
  1334. "P": ("P", II, 3, 1, (8,), None),
  1335. "PA": ("PA", II, 3, 1, (8, 8), 2),
  1336. "I": ("I;32S", II, 1, 2, (32,), None),
  1337. "I;16": ("I;16", II, 1, 1, (16,), None),
  1338. "I;16S": ("I;16S", II, 1, 2, (16,), None),
  1339. "F": ("F;32F", II, 1, 3, (32,), None),
  1340. "RGB": ("RGB", II, 2, 1, (8, 8, 8), None),
  1341. "RGBX": ("RGBX", II, 2, 1, (8, 8, 8, 8), 0),
  1342. "RGBA": ("RGBA", II, 2, 1, (8, 8, 8, 8), 2),
  1343. "CMYK": ("CMYK", II, 5, 1, (8, 8, 8, 8), None),
  1344. "YCbCr": ("YCbCr", II, 6, 1, (8, 8, 8), None),
  1345. "LAB": ("LAB", II, 8, 1, (8, 8, 8), None),
  1346. "I;32BS": ("I;32BS", MM, 1, 2, (32,), None),
  1347. "I;16B": ("I;16B", MM, 1, 1, (16,), None),
  1348. "I;16BS": ("I;16BS", MM, 1, 2, (16,), None),
  1349. "F;32BF": ("F;32BF", MM, 1, 3, (32,), None),
  1350. }
  1351. def _save(im, fp, filename):
  1352. try:
  1353. rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
  1354. except KeyError as e:
  1355. msg = f"cannot write mode {im.mode} as TIFF"
  1356. raise OSError(msg) from e
  1357. ifd = ImageFileDirectory_v2(prefix=prefix)
  1358. encoderinfo = im.encoderinfo
  1359. encoderconfig = im.encoderconfig
  1360. try:
  1361. compression = encoderinfo["compression"]
  1362. except KeyError:
  1363. compression = im.info.get("compression")
  1364. if isinstance(compression, int):
  1365. # compression value may be from BMP. Ignore it
  1366. compression = None
  1367. if compression is None:
  1368. compression = "raw"
  1369. elif compression == "tiff_jpeg":
  1370. # OJPEG is obsolete, so use new-style JPEG compression instead
  1371. compression = "jpeg"
  1372. elif compression == "tiff_deflate":
  1373. compression = "tiff_adobe_deflate"
  1374. libtiff = WRITE_LIBTIFF or compression != "raw"
  1375. # required for color libtiff images
  1376. ifd[PLANAR_CONFIGURATION] = 1
  1377. ifd[IMAGEWIDTH] = im.size[0]
  1378. ifd[IMAGELENGTH] = im.size[1]
  1379. # write any arbitrary tags passed in as an ImageFileDirectory
  1380. if "tiffinfo" in encoderinfo:
  1381. info = encoderinfo["tiffinfo"]
  1382. elif "exif" in encoderinfo:
  1383. info = encoderinfo["exif"]
  1384. if isinstance(info, bytes):
  1385. exif = Image.Exif()
  1386. exif.load(info)
  1387. info = exif
  1388. else:
  1389. info = {}
  1390. logger.debug("Tiffinfo Keys: %s", list(info))
  1391. if isinstance(info, ImageFileDirectory_v1):
  1392. info = info.to_v2()
  1393. for key in info:
  1394. if isinstance(info, Image.Exif) and key in TiffTags.TAGS_V2_GROUPS:
  1395. ifd[key] = info.get_ifd(key)
  1396. else:
  1397. ifd[key] = info.get(key)
  1398. try:
  1399. ifd.tagtype[key] = info.tagtype[key]
  1400. except Exception:
  1401. pass # might not be an IFD. Might not have populated type
  1402. legacy_ifd = {}
  1403. if hasattr(im, "tag"):
  1404. legacy_ifd = im.tag.to_v2()
  1405. supplied_tags = {**legacy_ifd, **getattr(im, "tag_v2", {})}
  1406. for tag in (
  1407. # IFD offset that may not be correct in the saved image
  1408. EXIFIFD,
  1409. # Determined by the image format and should not be copied from legacy_ifd.
  1410. SAMPLEFORMAT,
  1411. ):
  1412. if tag in supplied_tags:
  1413. del supplied_tags[tag]
  1414. # additions written by Greg Couch, gregc@cgl.ucsf.edu
  1415. # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com
  1416. if hasattr(im, "tag_v2"):
  1417. # preserve tags from original TIFF image file
  1418. for key in (
  1419. RESOLUTION_UNIT,
  1420. X_RESOLUTION,
  1421. Y_RESOLUTION,
  1422. IPTC_NAA_CHUNK,
  1423. PHOTOSHOP_CHUNK,
  1424. XMP,
  1425. ):
  1426. if key in im.tag_v2:
  1427. if key == IPTC_NAA_CHUNK and im.tag_v2.tagtype[key] not in (
  1428. TiffTags.BYTE,
  1429. TiffTags.UNDEFINED,
  1430. ):
  1431. del supplied_tags[key]
  1432. else:
  1433. ifd[key] = im.tag_v2[key]
  1434. ifd.tagtype[key] = im.tag_v2.tagtype[key]
  1435. # preserve ICC profile (should also work when saving other formats
  1436. # which support profiles as TIFF) -- 2008-06-06 Florian Hoech
  1437. icc = encoderinfo.get("icc_profile", im.info.get("icc_profile"))
  1438. if icc:
  1439. ifd[ICCPROFILE] = icc
  1440. for key, name in [
  1441. (IMAGEDESCRIPTION, "description"),
  1442. (X_RESOLUTION, "resolution"),
  1443. (Y_RESOLUTION, "resolution"),
  1444. (X_RESOLUTION, "x_resolution"),
  1445. (Y_RESOLUTION, "y_resolution"),
  1446. (RESOLUTION_UNIT, "resolution_unit"),
  1447. (SOFTWARE, "software"),
  1448. (DATE_TIME, "date_time"),
  1449. (ARTIST, "artist"),
  1450. (COPYRIGHT, "copyright"),
  1451. ]:
  1452. if name in encoderinfo:
  1453. ifd[key] = encoderinfo[name]
  1454. dpi = encoderinfo.get("dpi")
  1455. if dpi:
  1456. ifd[RESOLUTION_UNIT] = 2
  1457. ifd[X_RESOLUTION] = dpi[0]
  1458. ifd[Y_RESOLUTION] = dpi[1]
  1459. if bits != (1,):
  1460. ifd[BITSPERSAMPLE] = bits
  1461. if len(bits) != 1:
  1462. ifd[SAMPLESPERPIXEL] = len(bits)
  1463. if extra is not None:
  1464. ifd[EXTRASAMPLES] = extra
  1465. if format != 1:
  1466. ifd[SAMPLEFORMAT] = format
  1467. if PHOTOMETRIC_INTERPRETATION not in ifd:
  1468. ifd[PHOTOMETRIC_INTERPRETATION] = photo
  1469. elif im.mode in ("1", "L") and ifd[PHOTOMETRIC_INTERPRETATION] == 0:
  1470. if im.mode == "1":
  1471. inverted_im = im.copy()
  1472. px = inverted_im.load()
  1473. for y in range(inverted_im.height):
  1474. for x in range(inverted_im.width):
  1475. px[x, y] = 0 if px[x, y] == 255 else 255
  1476. im = inverted_im
  1477. else:
  1478. im = ImageOps.invert(im)
  1479. if im.mode in ["P", "PA"]:
  1480. lut = im.im.getpalette("RGB", "RGB;L")
  1481. colormap = []
  1482. colors = len(lut) // 3
  1483. for i in range(3):
  1484. colormap += [v * 256 for v in lut[colors * i : colors * (i + 1)]]
  1485. colormap += [0] * (256 - colors)
  1486. ifd[COLORMAP] = colormap
  1487. # data orientation
  1488. w, h = ifd[IMAGEWIDTH], ifd[IMAGELENGTH]
  1489. stride = len(bits) * ((w * bits[0] + 7) // 8)
  1490. if ROWSPERSTRIP not in ifd:
  1491. # aim for given strip size (64 KB by default) when using libtiff writer
  1492. if libtiff:
  1493. im_strip_size = encoderinfo.get("strip_size", STRIP_SIZE)
  1494. rows_per_strip = 1 if stride == 0 else min(im_strip_size // stride, h)
  1495. # JPEG encoder expects multiple of 8 rows
  1496. if compression == "jpeg":
  1497. rows_per_strip = min(((rows_per_strip + 7) // 8) * 8, h)
  1498. else:
  1499. rows_per_strip = h
  1500. if rows_per_strip == 0:
  1501. rows_per_strip = 1
  1502. ifd[ROWSPERSTRIP] = rows_per_strip
  1503. strip_byte_counts = 1 if stride == 0 else stride * ifd[ROWSPERSTRIP]
  1504. strips_per_image = (h + ifd[ROWSPERSTRIP] - 1) // ifd[ROWSPERSTRIP]
  1505. if strip_byte_counts >= 2**16:
  1506. ifd.tagtype[STRIPBYTECOUNTS] = TiffTags.LONG
  1507. ifd[STRIPBYTECOUNTS] = (strip_byte_counts,) * (strips_per_image - 1) + (
  1508. stride * h - strip_byte_counts * (strips_per_image - 1),
  1509. )
  1510. ifd[STRIPOFFSETS] = tuple(
  1511. range(0, strip_byte_counts * strips_per_image, strip_byte_counts)
  1512. ) # this is adjusted by IFD writer
  1513. # no compression by default:
  1514. ifd[COMPRESSION] = COMPRESSION_INFO_REV.get(compression, 1)
  1515. if im.mode == "YCbCr":
  1516. for tag, value in {
  1517. YCBCRSUBSAMPLING: (1, 1),
  1518. REFERENCEBLACKWHITE: (0, 255, 128, 255, 128, 255),
  1519. }.items():
  1520. ifd.setdefault(tag, value)
  1521. blocklist = [TILEWIDTH, TILELENGTH, TILEOFFSETS, TILEBYTECOUNTS]
  1522. if libtiff:
  1523. if "quality" in encoderinfo:
  1524. quality = encoderinfo["quality"]
  1525. if not isinstance(quality, int) or quality < 0 or quality > 100:
  1526. msg = "Invalid quality setting"
  1527. raise ValueError(msg)
  1528. if compression != "jpeg":
  1529. msg = "quality setting only supported for 'jpeg' compression"
  1530. raise ValueError(msg)
  1531. ifd[JPEGQUALITY] = quality
  1532. logger.debug("Saving using libtiff encoder")
  1533. logger.debug("Items: %s", sorted(ifd.items()))
  1534. _fp = 0
  1535. if hasattr(fp, "fileno"):
  1536. try:
  1537. fp.seek(0)
  1538. _fp = os.dup(fp.fileno())
  1539. except io.UnsupportedOperation:
  1540. pass
  1541. # optional types for non core tags
  1542. types = {}
  1543. # STRIPOFFSETS and STRIPBYTECOUNTS are added by the library
  1544. # based on the data in the strip.
  1545. # OSUBFILETYPE is deprecated.
  1546. # The other tags expect arrays with a certain length (fixed or depending on
  1547. # BITSPERSAMPLE, etc), passing arrays with a different length will result in
  1548. # segfaults. Block these tags until we add extra validation.
  1549. # SUBIFD may also cause a segfault.
  1550. blocklist += [
  1551. OSUBFILETYPE,
  1552. REFERENCEBLACKWHITE,
  1553. STRIPBYTECOUNTS,
  1554. STRIPOFFSETS,
  1555. TRANSFERFUNCTION,
  1556. SUBIFD,
  1557. ]
  1558. # bits per sample is a single short in the tiff directory, not a list.
  1559. atts = {BITSPERSAMPLE: bits[0]}
  1560. # Merge the ones that we have with (optional) more bits from
  1561. # the original file, e.g x,y resolution so that we can
  1562. # save(load('')) == original file.
  1563. for tag, value in itertools.chain(ifd.items(), supplied_tags.items()):
  1564. # Libtiff can only process certain core items without adding
  1565. # them to the custom dictionary.
  1566. # Custom items are supported for int, float, unicode, string and byte
  1567. # values. Other types and tuples require a tagtype.
  1568. if tag not in TiffTags.LIBTIFF_CORE:
  1569. if not getattr(Image.core, "libtiff_support_custom_tags", False):
  1570. continue
  1571. if tag in ifd.tagtype:
  1572. types[tag] = ifd.tagtype[tag]
  1573. elif not (isinstance(value, (int, float, str, bytes))):
  1574. continue
  1575. else:
  1576. type = TiffTags.lookup(tag).type
  1577. if type:
  1578. types[tag] = type
  1579. if tag not in atts and tag not in blocklist:
  1580. if isinstance(value, str):
  1581. atts[tag] = value.encode("ascii", "replace") + b"\0"
  1582. elif isinstance(value, IFDRational):
  1583. atts[tag] = float(value)
  1584. else:
  1585. atts[tag] = value
  1586. if SAMPLEFORMAT in atts and len(atts[SAMPLEFORMAT]) == 1:
  1587. atts[SAMPLEFORMAT] = atts[SAMPLEFORMAT][0]
  1588. logger.debug("Converted items: %s", sorted(atts.items()))
  1589. # libtiff always expects the bytes in native order.
  1590. # we're storing image byte order. So, if the rawmode
  1591. # contains I;16, we need to convert from native to image
  1592. # byte order.
  1593. if im.mode in ("I;16B", "I;16"):
  1594. rawmode = "I;16N"
  1595. # Pass tags as sorted list so that the tags are set in a fixed order.
  1596. # This is required by libtiff for some tags. For example, the JPEGQUALITY
  1597. # pseudo tag requires that the COMPRESS tag was already set.
  1598. tags = list(atts.items())
  1599. tags.sort()
  1600. a = (rawmode, compression, _fp, filename, tags, types)
  1601. encoder = Image._getencoder(im.mode, "libtiff", a, encoderconfig)
  1602. encoder.setimage(im.im, (0, 0) + im.size)
  1603. while True:
  1604. # undone, change to self.decodermaxblock:
  1605. errcode, data = encoder.encode(16 * 1024)[1:]
  1606. if not _fp:
  1607. fp.write(data)
  1608. if errcode:
  1609. break
  1610. if _fp:
  1611. try:
  1612. os.close(_fp)
  1613. except OSError:
  1614. pass
  1615. if errcode < 0:
  1616. msg = f"encoder error {errcode} when writing image file"
  1617. raise OSError(msg)
  1618. else:
  1619. for tag in blocklist:
  1620. del ifd[tag]
  1621. offset = ifd.save(fp)
  1622. ImageFile._save(
  1623. im, fp, [("raw", (0, 0) + im.size, offset, (rawmode, stride, 1))]
  1624. )
  1625. # -- helper for multi-page save --
  1626. if "_debug_multipage" in encoderinfo:
  1627. # just to access o32 and o16 (using correct byte order)
  1628. im._debug_multipage = ifd
  1629. class AppendingTiffWriter:
  1630. fieldSizes = [
  1631. 0, # None
  1632. 1, # byte
  1633. 1, # ascii
  1634. 2, # short
  1635. 4, # long
  1636. 8, # rational
  1637. 1, # sbyte
  1638. 1, # undefined
  1639. 2, # sshort
  1640. 4, # slong
  1641. 8, # srational
  1642. 4, # float
  1643. 8, # double
  1644. 4, # ifd
  1645. 2, # unicode
  1646. 4, # complex
  1647. 8, # long8
  1648. ]
  1649. Tags = {
  1650. 273, # StripOffsets
  1651. 288, # FreeOffsets
  1652. 324, # TileOffsets
  1653. 519, # JPEGQTables
  1654. 520, # JPEGDCTables
  1655. 521, # JPEGACTables
  1656. }
  1657. def __init__(self, fn, new=False):
  1658. if hasattr(fn, "read"):
  1659. self.f = fn
  1660. self.close_fp = False
  1661. else:
  1662. self.name = fn
  1663. self.close_fp = True
  1664. try:
  1665. self.f = open(fn, "w+b" if new else "r+b")
  1666. except OSError:
  1667. self.f = open(fn, "w+b")
  1668. self.beginning = self.f.tell()
  1669. self.setup()
  1670. def setup(self) -> None:
  1671. # Reset everything.
  1672. self.f.seek(self.beginning, os.SEEK_SET)
  1673. self.whereToWriteNewIFDOffset = None
  1674. self.offsetOfNewPage = 0
  1675. self.IIMM = iimm = self.f.read(4)
  1676. if not iimm:
  1677. # empty file - first page
  1678. self.isFirst = True
  1679. return
  1680. self.isFirst = False
  1681. if iimm == b"II\x2a\x00":
  1682. self.setEndian("<")
  1683. elif iimm == b"MM\x00\x2a":
  1684. self.setEndian(">")
  1685. else:
  1686. msg = "Invalid TIFF file header"
  1687. raise RuntimeError(msg)
  1688. self.skipIFDs()
  1689. self.goToEnd()
  1690. def finalize(self) -> None:
  1691. if self.isFirst:
  1692. return
  1693. # fix offsets
  1694. self.f.seek(self.offsetOfNewPage)
  1695. iimm = self.f.read(4)
  1696. if not iimm:
  1697. # Make it easy to finish a frame without committing to a new one.
  1698. return
  1699. if iimm != self.IIMM:
  1700. msg = "IIMM of new page doesn't match IIMM of first page"
  1701. raise RuntimeError(msg)
  1702. ifd_offset = self.readLong()
  1703. ifd_offset += self.offsetOfNewPage
  1704. self.f.seek(self.whereToWriteNewIFDOffset)
  1705. self.writeLong(ifd_offset)
  1706. self.f.seek(ifd_offset)
  1707. self.fixIFD()
  1708. def newFrame(self) -> None:
  1709. # Call this to finish a frame.
  1710. self.finalize()
  1711. self.setup()
  1712. def __enter__(self) -> AppendingTiffWriter:
  1713. return self
  1714. def __exit__(self, *args: object) -> None:
  1715. if self.close_fp:
  1716. self.close()
  1717. def tell(self) -> int:
  1718. return self.f.tell() - self.offsetOfNewPage
  1719. def seek(self, offset, whence=io.SEEK_SET):
  1720. if whence == os.SEEK_SET:
  1721. offset += self.offsetOfNewPage
  1722. self.f.seek(offset, whence)
  1723. return self.tell()
  1724. def goToEnd(self) -> None:
  1725. self.f.seek(0, os.SEEK_END)
  1726. pos = self.f.tell()
  1727. # pad to 16 byte boundary
  1728. pad_bytes = 16 - pos % 16
  1729. if 0 < pad_bytes < 16:
  1730. self.f.write(bytes(pad_bytes))
  1731. self.offsetOfNewPage = self.f.tell()
  1732. def setEndian(self, endian: str) -> None:
  1733. self.endian = endian
  1734. self.longFmt = f"{self.endian}L"
  1735. self.shortFmt = f"{self.endian}H"
  1736. self.tagFormat = f"{self.endian}HHL"
  1737. def skipIFDs(self) -> None:
  1738. while True:
  1739. ifd_offset = self.readLong()
  1740. if ifd_offset == 0:
  1741. self.whereToWriteNewIFDOffset = self.f.tell() - 4
  1742. break
  1743. self.f.seek(ifd_offset)
  1744. num_tags = self.readShort()
  1745. self.f.seek(num_tags * 12, os.SEEK_CUR)
  1746. def write(self, data: bytes) -> int | None:
  1747. return self.f.write(data)
  1748. def readShort(self) -> int:
  1749. (value,) = struct.unpack(self.shortFmt, self.f.read(2))
  1750. return value
  1751. def readLong(self) -> int:
  1752. (value,) = struct.unpack(self.longFmt, self.f.read(4))
  1753. return value
  1754. def rewriteLastShortToLong(self, value: int) -> None:
  1755. self.f.seek(-2, os.SEEK_CUR)
  1756. bytes_written = self.f.write(struct.pack(self.longFmt, value))
  1757. if bytes_written is not None and bytes_written != 4:
  1758. msg = f"wrote only {bytes_written} bytes but wanted 4"
  1759. raise RuntimeError(msg)
  1760. def rewriteLastShort(self, value: int) -> None:
  1761. self.f.seek(-2, os.SEEK_CUR)
  1762. bytes_written = self.f.write(struct.pack(self.shortFmt, value))
  1763. if bytes_written is not None and bytes_written != 2:
  1764. msg = f"wrote only {bytes_written} bytes but wanted 2"
  1765. raise RuntimeError(msg)
  1766. def rewriteLastLong(self, value: int) -> None:
  1767. self.f.seek(-4, os.SEEK_CUR)
  1768. bytes_written = self.f.write(struct.pack(self.longFmt, value))
  1769. if bytes_written is not None and bytes_written != 4:
  1770. msg = f"wrote only {bytes_written} bytes but wanted 4"
  1771. raise RuntimeError(msg)
  1772. def writeShort(self, value: int) -> None:
  1773. bytes_written = self.f.write(struct.pack(self.shortFmt, value))
  1774. if bytes_written is not None and bytes_written != 2:
  1775. msg = f"wrote only {bytes_written} bytes but wanted 2"
  1776. raise RuntimeError(msg)
  1777. def writeLong(self, value: int) -> None:
  1778. bytes_written = self.f.write(struct.pack(self.longFmt, value))
  1779. if bytes_written is not None and bytes_written != 4:
  1780. msg = f"wrote only {bytes_written} bytes but wanted 4"
  1781. raise RuntimeError(msg)
  1782. def close(self) -> None:
  1783. self.finalize()
  1784. self.f.close()
  1785. def fixIFD(self) -> None:
  1786. num_tags = self.readShort()
  1787. for i in range(num_tags):
  1788. tag, field_type, count = struct.unpack(self.tagFormat, self.f.read(8))
  1789. field_size = self.fieldSizes[field_type]
  1790. total_size = field_size * count
  1791. is_local = total_size <= 4
  1792. offset: int | None
  1793. if not is_local:
  1794. offset = self.readLong() + self.offsetOfNewPage
  1795. self.rewriteLastLong(offset)
  1796. if tag in self.Tags:
  1797. cur_pos = self.f.tell()
  1798. if is_local:
  1799. self.fixOffsets(
  1800. count, isShort=(field_size == 2), isLong=(field_size == 4)
  1801. )
  1802. self.f.seek(cur_pos + 4)
  1803. else:
  1804. self.f.seek(offset)
  1805. self.fixOffsets(
  1806. count, isShort=(field_size == 2), isLong=(field_size == 4)
  1807. )
  1808. self.f.seek(cur_pos)
  1809. offset = cur_pos = None
  1810. elif is_local:
  1811. # skip the locally stored value that is not an offset
  1812. self.f.seek(4, os.SEEK_CUR)
  1813. def fixOffsets(
  1814. self, count: int, isShort: bool = False, isLong: bool = False
  1815. ) -> None:
  1816. if not isShort and not isLong:
  1817. msg = "offset is neither short nor long"
  1818. raise RuntimeError(msg)
  1819. for i in range(count):
  1820. offset = self.readShort() if isShort else self.readLong()
  1821. offset += self.offsetOfNewPage
  1822. if isShort and offset >= 65536:
  1823. # offset is now too large - we must convert shorts to longs
  1824. if count != 1:
  1825. msg = "not implemented"
  1826. raise RuntimeError(msg) # XXX TODO
  1827. # simple case - the offset is just one and therefore it is
  1828. # local (not referenced with another offset)
  1829. self.rewriteLastShortToLong(offset)
  1830. self.f.seek(-10, os.SEEK_CUR)
  1831. self.writeShort(TiffTags.LONG) # rewrite the type to LONG
  1832. self.f.seek(8, os.SEEK_CUR)
  1833. elif isShort:
  1834. self.rewriteLastShort(offset)
  1835. else:
  1836. self.rewriteLastLong(offset)
  1837. def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
  1838. encoderinfo = im.encoderinfo.copy()
  1839. encoderconfig = im.encoderconfig
  1840. append_images = list(encoderinfo.get("append_images", []))
  1841. if not hasattr(im, "n_frames") and not append_images:
  1842. return _save(im, fp, filename)
  1843. cur_idx = im.tell()
  1844. try:
  1845. with AppendingTiffWriter(fp) as tf:
  1846. for ims in [im] + append_images:
  1847. ims.encoderinfo = encoderinfo
  1848. ims.encoderconfig = encoderconfig
  1849. if not hasattr(ims, "n_frames"):
  1850. nfr = 1
  1851. else:
  1852. nfr = ims.n_frames
  1853. for idx in range(nfr):
  1854. ims.seek(idx)
  1855. ims.load()
  1856. _save(ims, tf, filename)
  1857. tf.newFrame()
  1858. finally:
  1859. im.seek(cur_idx)
  1860. #
  1861. # --------------------------------------------------------------------
  1862. # Register
  1863. Image.register_open(TiffImageFile.format, TiffImageFile, _accept)
  1864. Image.register_save(TiffImageFile.format, _save)
  1865. Image.register_save_all(TiffImageFile.format, _save_all)
  1866. Image.register_extensions(TiffImageFile.format, [".tif", ".tiff"])
  1867. Image.register_mime(TiffImageFile.format, "image/tiff")