From 2d284aea12f1d81b702305b34bd1d4c8e082034e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Wed, 6 May 2020 20:12:59 +1000 Subject: [PATCH] Allow writing of UNDEFINED tags --- Tests/test_file_libtiff.py | 27 ++++++++++++++++++++------- src/PIL/TiffImagePlugin.py | 16 +++++++++------- src/encode.c | 7 +------ 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index f1ad18828..855a9ab3a 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -299,13 +299,6 @@ class TestFileLibTiff(LibTiffTestCase): ) continue - if ( - libtiff - and isinstance(value, bytes) - and isinstance(tiffinfo, dict) - ): - value = value.decode() - assert reloaded_value == value # Test with types @@ -682,6 +675,26 @@ class TestFileLibTiff(LibTiffTestCase): TiffImagePlugin.READ_LIBTIFF = False assert icc == icc_libtiff + def test_write_icc(self, tmp_path): + def check_write(libtiff): + TiffImagePlugin.WRITE_LIBTIFF = libtiff + + with Image.open("Tests/images/hopper.iccprofile.tif") as img: + icc_profile = img.info["icc_profile"] + + out = str(tmp_path / "temp.tif") + img.save(out, icc_profile=icc_profile) + with Image.open(out) as reloaded: + assert icc_profile == reloaded.info["icc_profile"] + + libtiffs = [] + if Image.core.libtiff_support_custom_tags: + libtiffs.append(True) + libtiffs.append(False) + + for libtiff in libtiffs: + check_write(libtiff) + def test_multipage_compression(self): with Image.open("Tests/images/compression.tif") as im: diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index a18621d23..ee183ccba 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -553,9 +553,10 @@ class ImageFileDirectory_v2(MutableMapping): ) elif all(isinstance(v, float) for v in values): self.tagtype[tag] = TiffTags.DOUBLE - else: - if all(isinstance(v, str) for v in values): - self.tagtype[tag] = TiffTags.ASCII + elif all(isinstance(v, str) for v in values): + self.tagtype[tag] = TiffTags.ASCII + elif all(isinstance(v, bytes) for v in values): + self.tagtype[tag] = TiffTags.BYTE if self.tagtype[tag] == TiffTags.UNDEFINED: values = [ @@ -1548,16 +1549,17 @@ def _save(im, fp, filename): # Custom items are supported for int, float, unicode, string and byte # values. Other types and tuples require a tagtype. if tag not in TiffTags.LIBTIFF_CORE: - if ( - TiffTags.lookup(tag).type == TiffTags.UNDEFINED - or not Image.core.libtiff_support_custom_tags - ): + if not Image.core.libtiff_support_custom_tags: continue if tag in ifd.tagtype: types[tag] = ifd.tagtype[tag] elif not (isinstance(value, (int, float, str, bytes))): continue + else: + type = TiffTags.lookup(tag).type + if type: + types[tag] = type if tag not in atts and tag not in blocklist: if isinstance(value, str): atts[tag] = value.encode("ascii", "replace") + b"\0" diff --git a/src/encode.c b/src/encode.c index 6506edb96..03a39448d 100644 --- a/src/encode.c +++ b/src/encode.c @@ -761,11 +761,6 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) } } - if (PyBytes_Check(value) && type == TIFF_UNDEFINED) { - // For backwards compatibility - type = TIFF_ASCII; - } - if (PyTuple_Check(value)) { Py_ssize_t len; len = PyTuple_Size(value); @@ -797,7 +792,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) } } - if (type == TIFF_BYTE) { + if (type == TIFF_BYTE || type == TIFF_UNDEFINED) { status = ImagingLibTiffSetField(&encoder->state, (ttag_t) key_int, PyBytes_Size(value), PyBytes_AsString(value));