From 2245df0ac30976960781f291bc45a2ad56cee064 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 6 Apr 2024 20:59:06 +1100 Subject: [PATCH] Only preserve IPTC_NAA_CHUNK tag if type is BYTE or UNDEFINED --- Tests/test_file_tiff.py | 13 +++++++++++++ src/PIL/TiffImagePlugin.py | 30 ++++++++++++++++++------------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 8821fb46a..0bc1e2d0e 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -621,6 +621,19 @@ class TestFileTiff: assert_image_equal_tofile(im, tmpfile) + def test_iptc(self, tmp_path: Path) -> None: + # Do not preserve IPTC_NAA_CHUNK by default if type is LONG + outfile = str(tmp_path / "temp.tif") + im = hopper() + ifd = TiffImagePlugin.ImageFileDirectory_v2() + ifd[33723] = 1 + ifd.tagtype[33723] = 4 + im.tag_v2 = ifd + im.save(outfile) + + with Image.open(outfile) as im: + assert 33723 not in im.tag_v2 + def test_rowsperstrip(self, tmp_path: Path) -> None: outfile = str(tmp_path / "temp.tif") im = hopper() diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 8bfcd2907..c3683efb3 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1653,6 +1653,16 @@ def _save(im, fp, filename): except Exception: pass # might not be an IFD. Might not have populated type + legacy_ifd = {} + if hasattr(im, "tag"): + legacy_ifd = im.tag.to_v2() + + supplied_tags = {**legacy_ifd, **getattr(im, "tag_v2", {})} + if SAMPLEFORMAT in supplied_tags: + # SAMPLEFORMAT is determined by the image format and should not be copied + # from legacy_ifd. + del supplied_tags[SAMPLEFORMAT] + # additions written by Greg Couch, gregc@cgl.ucsf.edu # inspired by image-sig posting from Kevin Cazabon, kcazabon@home.com if hasattr(im, "tag_v2"): @@ -1666,8 +1676,14 @@ def _save(im, fp, filename): XMP, ): if key in im.tag_v2: - ifd[key] = im.tag_v2[key] - ifd.tagtype[key] = im.tag_v2.tagtype[key] + if key == IPTC_NAA_CHUNK and im.tag_v2.tagtype[key] not in ( + TiffTags.BYTE, + TiffTags.UNDEFINED, + ): + del supplied_tags[key] + else: + ifd[key] = im.tag_v2[key] + ifd.tagtype[key] = im.tag_v2.tagtype[key] # preserve ICC profile (should also work when saving other formats # which support profiles as TIFF) -- 2008-06-06 Florian Hoech @@ -1807,16 +1823,6 @@ def _save(im, fp, filename): # Merge the ones that we have with (optional) more bits from # the original file, e.g x,y resolution so that we can # save(load('')) == original file. - legacy_ifd = {} - if hasattr(im, "tag"): - legacy_ifd = im.tag.to_v2() - - # SAMPLEFORMAT is determined by the image format and should not be copied - # from legacy_ifd. - supplied_tags = {**getattr(im, "tag_v2", {}), **legacy_ifd} - if SAMPLEFORMAT in supplied_tags: - del supplied_tags[SAMPLEFORMAT] - for tag, value in itertools.chain(ifd.items(), supplied_tags.items()): # Libtiff can only process certain core items without adding # them to the custom dictionary.