@@ -582,7 +582,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
582
582
583
583
def __init__ (
584
584
self ,
585
- ifh : bytes = b"II\052 \0 \0 \0 \0 \0 " ,
585
+ ifh : bytes = b"II\x2A \x00 \x00 \x00 \x00 \x00 " ,
586
586
prefix : bytes | None = None ,
587
587
group : int | None = None ,
588
588
) -> None :
@@ -949,28 +949,34 @@ def load(self, fp: IO[bytes]) -> None:
949
949
warnings .warn (str (msg ))
950
950
return
951
951
952
+ def _get_ifh (self ):
953
+ ifh = self ._prefix + self ._pack ("H" , 43 if self ._bigtiff else 42 )
954
+ if self ._bigtiff :
955
+ ifh += self ._pack ("HH" , 8 , 0 )
956
+ ifh += self ._pack ("Q" , 16 ) if self ._bigtiff else self ._pack ("L" , 8 )
957
+
958
+ return ifh
959
+
952
960
def tobytes (self , offset : int = 0 ) -> bytes :
953
961
# FIXME What about tagdata?
954
- result = self ._pack ("H" , len (self ._tags_v2 ))
962
+ result = self ._pack ("Q" if self . _bigtiff else " H" , len (self ._tags_v2 ))
955
963
956
964
entries : list [tuple [int , int , int , bytes , bytes ]] = []
957
- offset = offset + len (result ) + len (self ._tags_v2 ) * 12 + 4
965
+ offset += len (result ) + len (self ._tags_v2 ) * ( 20 if self . _bigtiff else 12 ) + 4
958
966
stripoffsets = None
959
967
960
968
# pass 1: convert tags to binary format
961
969
# always write tags in ascending order
970
+ fmt = "Q" if self ._bigtiff else "L"
971
+ fmt_size = 8 if self ._bigtiff else 4
962
972
for tag , value in sorted (self ._tags_v2 .items ()):
963
973
if tag == STRIPOFFSETS :
964
974
stripoffsets = len (entries )
965
975
typ = self .tagtype [tag ]
966
976
logger .debug ("Tag %s, Type: %s, Value: %s" , tag , typ , repr (value ))
967
977
is_ifd = typ == TiffTags .LONG and isinstance (value , dict )
968
978
if is_ifd :
969
- if self ._endian == "<" :
970
- ifh = b"II\x2A \x00 \x08 \x00 \x00 \x00 "
971
- else :
972
- ifh = b"MM\x00 \x2A \x00 \x00 \x00 \x08 "
973
- ifd = ImageFileDirectory_v2 (ifh , group = tag )
979
+ ifd = ImageFileDirectory_v2 (self ._get_ifh (), group = tag )
974
980
values = self ._tags_v2 [tag ]
975
981
for ifd_tag , ifd_value in values .items ():
976
982
ifd [ifd_tag ] = ifd_value
@@ -993,10 +999,10 @@ def tobytes(self, offset: int = 0) -> bytes:
993
999
else :
994
1000
count = len (values )
995
1001
# figure out if data fits into the entry
996
- if len (data ) <= 4 :
997
- entries .append ((tag , typ , count , data .ljust (4 , b"\0 " ), b"" ))
1002
+ if len (data ) <= fmt_size :
1003
+ entries .append ((tag , typ , count , data .ljust (fmt_size , b"\0 " ), b"" ))
998
1004
else :
999
- entries .append ((tag , typ , count , self ._pack ("L" , offset ), data ))
1005
+ entries .append ((tag , typ , count , self ._pack (fmt , offset ), data ))
1000
1006
offset += (len (data ) + 1 ) // 2 * 2 # pad to word
1001
1007
1002
1008
# update strip offset data to point beyond auxiliary data
@@ -1007,13 +1013,15 @@ def tobytes(self, offset: int = 0) -> bytes:
1007
1013
values = [val + offset for val in handler (self , data , self .legacy_api )]
1008
1014
data = self ._write_dispatch [typ ](self , * values )
1009
1015
else :
1010
- value = self ._pack ("L" , self ._unpack ("L" , value )[0 ] + offset )
1016
+ value = self ._pack (fmt , self ._unpack (fmt , value )[0 ] + offset )
1011
1017
entries [stripoffsets ] = tag , typ , count , value , data
1012
1018
1013
1019
# pass 2: write entries to file
1014
1020
for tag , typ , count , value , data in entries :
1015
1021
logger .debug ("%s %s %s %s %s" , tag , typ , count , repr (value ), repr (data ))
1016
- result += self ._pack ("HHL4s" , tag , typ , count , value )
1022
+ result += self ._pack (
1023
+ "HHQ8s" if self ._bigtiff else "HHL4s" , tag , typ , count , value
1024
+ )
1017
1025
1018
1026
# -- overwrite here for multi-page --
1019
1027
result += b"\0 \0 \0 \0 " # end of entries
@@ -1028,8 +1036,7 @@ def tobytes(self, offset: int = 0) -> bytes:
1028
1036
1029
1037
def save (self , fp : IO [bytes ]) -> int :
1030
1038
if fp .tell () == 0 : # skip TIFF header on subsequent pages
1031
- # tiff header -- PIL always starts the first IFD at offset 8
1032
- fp .write (self ._prefix + self ._pack ("HL" , 42 , 8 ))
1039
+ fp .write (self ._get_ifh ())
1033
1040
1034
1041
offset = fp .tell ()
1035
1042
result = self .tobytes (offset )
@@ -1680,10 +1687,13 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
1680
1687
msg = f"cannot write mode { im .mode } as TIFF"
1681
1688
raise OSError (msg ) from e
1682
1689
1683
- ifd = ImageFileDirectory_v2 (prefix = prefix )
1684
-
1685
1690
encoderinfo = im .encoderinfo
1686
1691
encoderconfig = im .encoderconfig
1692
+
1693
+ ifd = ImageFileDirectory_v2 (prefix = prefix )
1694
+ if encoderinfo .get ("big_tiff" ):
1695
+ ifd ._bigtiff = True
1696
+
1687
1697
try :
1688
1698
compression = encoderinfo ["compression" ]
1689
1699
except KeyError :
0 commit comments