implement tiff exif multistrip support

This commit is contained in:
Yay295 2024-08-18 20:39:14 -05:00
parent 1ee3bd1d9e
commit 362ffaf9b7
3 changed files with 29 additions and 4 deletions

View File

@ -108,7 +108,8 @@ class TestFileTiff:
assert_image_equal_tofile(im, "Tests/images/hopper.tif") assert_image_equal_tofile(im, "Tests/images/hopper.tif")
with Image.open("Tests/images/hopper_bigtiff.tif") as im: 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 yet supported for offset data when saving multiple frames.
del im.tag_v2[273] del im.tag_v2[273]
outfile = str(tmp_path / "temp.tif") outfile = str(tmp_path / "temp.tif")

View File

@ -181,6 +181,28 @@ def test_change_stripbytecounts_tag_type(tmp_path: Path) -> None:
assert reloaded.tag_v2.tagtype[TiffImagePlugin.STRIPBYTECOUNTS] == TiffTags.LONG 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: def test_no_duplicate_50741_tag() -> None:
assert TAG_IDS["MakerNoteSafety"] == 50741 assert TAG_IDS["MakerNoteSafety"] == 50741
assert TAG_IDS["BestQualityScale"] == 50780 assert TAG_IDS["BestQualityScale"] == 50780

View File

@ -991,9 +991,11 @@ class ImageFileDirectory_v2(_IFDv2Base):
if stripoffsets is not None: if stripoffsets is not None:
tag, typ, count, value, data = entries[stripoffsets] tag, typ, count, value, data = entries[stripoffsets]
if data: if data:
msg = "multistrip support not yet implemented" size, handler = self._load_dispatch[typ]
raise NotImplementedError(msg) values = [val + offset for val in handler(self, data, self.legacy_api)]
value = self._pack("L", self._unpack("L", value)[0] + offset) 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 entries[stripoffsets] = tag, typ, count, value, data
# pass 2: write entries to file # pass 2: write entries to file