diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 190f83f40fc..92060f37d9e 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -108,7 +108,8 @@ def test_bigtiff(self, tmp_path: Path) -> None: assert_image_equal_tofile(im, "Tests/images/hopper.tif") with Image.open("Tests/images/hopper_bigtiff.tif") as im: - # multistrip support not yet implemented + # The data type of this file's StripOffsets tag is LONG8, + # which is not currently supported when saving. del im.tag_v2[273] outfile = str(tmp_path / "temp.tif") diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index 1e0310001a5..00fe745cf59 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -181,6 +181,28 @@ def test_change_stripbytecounts_tag_type(tmp_path: Path) -> None: assert reloaded.tag_v2.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] == TiffTags.LONG +def test_save_multiple_stripoffsets() -> None: + ifd = TiffImagePlugin.ImageFileDirectory_v2() + ifd[TiffImagePlugin.STRIPOFFSETS] = (123, 456) + assert ifd.tagtype[TiffImagePlugin.STRIPOFFSETS] == TiffTags.LONG + + # all values are in little-endian + assert ifd.tobytes() == ( + # number of tags == 1 + b"\x01\x00" + # tag id (2 bytes), type (2 bytes), count (4 bytes), value (4 bytes) + # == 273, 4, 2, 18 + # == TiffImagePlugin.STRIPOFFSETS, TiffTags.LONG, 2, 18 + # the value is the index of the tag data + b"\x11\x01\x04\x00\x02\x00\x00\x00\x12\x00\x00\x00" + # end of tags marker + b"\x00\x00\x00\x00" + # tag data == (149, 482) == (123 + 26, 456 + 26) + # 26 is the number of bytes before this data + b"\x95\x00\x00\x00\xe2\x01\x00\x00" + ) + + def test_no_duplicate_50741_tag() -> None: assert TAG_IDS["MakerNoteSafety"] == 50741 assert TAG_IDS["BestQualityScale"] == 50780 diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index ab23356d4f3..2e3a35cc245 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -978,9 +978,11 @@ def tobytes(self, offset: int = 0) -> bytes: if stripoffsets is not None: tag, typ, count, value, data = entries[stripoffsets] if data: - msg = "multistrip support not yet implemented" - raise NotImplementedError(msg) - value = self._pack("L", self._unpack("L", value)[0] + offset) + size, handler = self._load_dispatch[typ] + values = [val + offset for val in handler(self, data, self.legacy_api)] + data = self._write_dispatch[typ](self, *values) + else: + value = self._pack("L", self._unpack("L", value)[0] + offset) entries[stripoffsets] = tag, typ, count, value, data # pass 2: write entries to file