Skip to content

Commit cc3fdcc

Browse files
committed
implement tiff exif multistrip support
1 parent 35a70e4 commit cc3fdcc

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

Tests/test_file_tiff.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ def test_bigtiff(self, tmp_path: Path) -> None:
108108
assert_image_equal_tofile(im, "Tests/images/hopper.tif")
109109

110110
with Image.open("Tests/images/hopper_bigtiff.tif") as im:
111-
# multistrip support not yet implemented
111+
# The data type of this file's StripOffsets tag is LONG8,
112+
# which is not currently supported when saving.
112113
del im.tag_v2[273]
113114

114115
outfile = str(tmp_path / "temp.tif")

Tests/test_file_tiff_metadata.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,28 @@ def test_change_stripbytecounts_tag_type(tmp_path: Path) -> None:
181181
assert reloaded.tag_v2.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] == TiffTags.LONG
182182

183183

184+
def test_save_multiple_stripoffsets() -> None:
185+
ifd = TiffImagePlugin.ImageFileDirectory_v2()
186+
ifd[TiffImagePlugin.STRIPOFFSETS] = (123, 456)
187+
assert ifd.tagtype[TiffImagePlugin.STRIPOFFSETS] == TiffTags.LONG
188+
189+
# all values are in little-endian
190+
assert ifd.tobytes() == (
191+
# number of tags == 1
192+
b"\x01\x00"
193+
# tag id (2 bytes), type (2 bytes), count (4 bytes), value (4 bytes)
194+
# == 273, 4, 2, 18
195+
# == TiffImagePlugin.STRIPOFFSETS, TiffTags.LONG, 2, 18
196+
# the value is the index of the tag data
197+
b"\x11\x01\x04\x00\x02\x00\x00\x00\x12\x00\x00\x00"
198+
# end of tags marker
199+
b"\x00\x00\x00\x00"
200+
# tag data == (149, 482) == (123 + 26, 456 + 26)
201+
# 26 is the number of bytes before this data
202+
b"\x95\x00\x00\x00\xe2\x01\x00\x00"
203+
)
204+
205+
184206
def test_no_duplicate_50741_tag() -> None:
185207
assert TAG_IDS["MakerNoteSafety"] == 50741
186208
assert TAG_IDS["BestQualityScale"] == 50780

src/PIL/TiffImagePlugin.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,9 @@ class ImageFileDirectory_v2(_IFDv2Base):
560560
561561
"""
562562

563-
_load_dispatch: dict[int, Callable[[ImageFileDirectory_v2, bytes, bool], Any]] = {}
563+
_load_dispatch: dict[
564+
int, tuple[int, Callable[[ImageFileDirectory_v2, bytes, bool], Any]]
565+
] = {}
564566
_write_dispatch: dict[int, Callable[..., Any]] = {}
565567

566568
def __init__(
@@ -972,9 +974,11 @@ def tobytes(self, offset: int = 0) -> bytes:
972974
if stripoffsets is not None:
973975
tag, typ, count, value, data = entries[stripoffsets]
974976
if data:
975-
msg = "multistrip support not yet implemented"
976-
raise NotImplementedError(msg)
977-
value = self._pack("L", self._unpack("L", value)[0] + offset)
977+
size, handler = self._load_dispatch[typ]
978+
values = [val + offset for val in handler(self, data, self.legacy_api)]
979+
data = self._write_dispatch[typ](self, *values)
980+
else:
981+
value = self._pack("L", self._unpack("L", value)[0] + offset)
978982
entries[stripoffsets] = tag, typ, count, value, data
979983

980984
# pass 2: write entries to file

0 commit comments

Comments
 (0)