@@ -582,7 +582,7 @@ class ImageFileDirectory_v2(_IFDv2Base):
582582
583583 def __init__ (
584584 self ,
585- ifh : bytes = b"II\052 \0 \0 \0 \0 \0 " ,
585+ ifh : bytes = b"II\x2A \x00 \x00 \x00 \x00 \x00 " ,
586586 prefix : bytes | None = None ,
587587 group : int | None = None ,
588588 ) -> None :
@@ -949,28 +949,34 @@ def load(self, fp: IO[bytes]) -> None:
949949 warnings .warn (str (msg ))
950950 return
951951
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+
952960 def tobytes (self , offset : int = 0 ) -> bytes :
953961 # 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 ))
955963
956964 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
958966 stripoffsets = None
959967
960968 # pass 1: convert tags to binary format
961969 # always write tags in ascending order
970+ fmt = "Q" if self ._bigtiff else "L"
971+ fmt_size = 8 if self ._bigtiff else 4
962972 for tag , value in sorted (self ._tags_v2 .items ()):
963973 if tag == STRIPOFFSETS :
964974 stripoffsets = len (entries )
965975 typ = self .tagtype [tag ]
966976 logger .debug ("Tag %s, Type: %s, Value: %s" , tag , typ , repr (value ))
967977 is_ifd = typ == TiffTags .LONG and isinstance (value , dict )
968978 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 )
974980 values = self ._tags_v2 [tag ]
975981 for ifd_tag , ifd_value in values .items ():
976982 ifd [ifd_tag ] = ifd_value
@@ -993,10 +999,10 @@ def tobytes(self, offset: int = 0) -> bytes:
993999 else :
9941000 count = len (values )
9951001 # 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"" ))
9981004 else :
999- entries .append ((tag , typ , count , self ._pack ("L" , offset ), data ))
1005+ entries .append ((tag , typ , count , self ._pack (fmt , offset ), data ))
10001006 offset += (len (data ) + 1 ) // 2 * 2 # pad to word
10011007
10021008 # update strip offset data to point beyond auxiliary data
@@ -1007,13 +1013,15 @@ def tobytes(self, offset: int = 0) -> bytes:
10071013 values = [val + offset for val in handler (self , data , self .legacy_api )]
10081014 data = self ._write_dispatch [typ ](self , * values )
10091015 else :
1010- value = self ._pack ("L" , self ._unpack ("L" , value )[0 ] + offset )
1016+ value = self ._pack (fmt , self ._unpack (fmt , value )[0 ] + offset )
10111017 entries [stripoffsets ] = tag , typ , count , value , data
10121018
10131019 # pass 2: write entries to file
10141020 for tag , typ , count , value , data in entries :
10151021 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+ )
10171025
10181026 # -- overwrite here for multi-page --
10191027 result += b"\0 \0 \0 \0 " # end of entries
@@ -1028,8 +1036,7 @@ def tobytes(self, offset: int = 0) -> bytes:
10281036
10291037 def save (self , fp : IO [bytes ]) -> int :
10301038 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 ())
10331040
10341041 offset = fp .tell ()
10351042 result = self .tobytes (offset )
@@ -1680,10 +1687,13 @@ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
16801687 msg = f"cannot write mode { im .mode } as TIFF"
16811688 raise OSError (msg ) from e
16821689
1683- ifd = ImageFileDirectory_v2 (prefix = prefix )
1684-
16851690 encoderinfo = im .encoderinfo
16861691 encoderconfig = im .encoderconfig
1692+
1693+ ifd = ImageFileDirectory_v2 (prefix = prefix )
1694+ if encoderinfo .get ("big_tiff" ):
1695+ ifd ._bigtiff = True
1696+
16871697 try :
16881698 compression = encoderinfo ["compression" ]
16891699 except KeyError :
0 commit comments