From d728cd58754f6701ffb3487609eabe39602238f5 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 26 May 2020 16:38:38 +1000 Subject: [PATCH] Allow libtiff to write COLORMAP tag --- Tests/test_file_libtiff.py | 13 +++++++++++++ src/PIL/TiffImagePlugin.py | 1 - src/PIL/TiffTags.py | 1 - src/encode.c | 23 +++++++++++++++++++++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 855a9ab3a..9c18eca26 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -203,6 +203,7 @@ class TestFileLibTiff(LibTiffTestCase): del core_items[tag] except KeyError: pass + del core_items[320] # colormap is special, tested below # Type codes: # 2: "ascii", @@ -479,6 +480,18 @@ class TestFileLibTiff(LibTiffTestCase): with Image.open(out) as im2: assert_image_equal(im, im2) + def test_palette_save(self, tmp_path): + im = hopper("P") + out = str(tmp_path / "temp.tif") + + TiffImagePlugin.WRITE_LIBTIFF = True + im.save(out) + TiffImagePlugin.WRITE_LIBTIFF = False + + with Image.open(out) as reloaded: + # colormap/palette tag + assert len(reloaded.tag_v2[320]) == 768 + def xtest_bw_compression_w_rgb(self, tmp_path): """ This test passes, but when running all tests causes a failure due to output on stderr from the error thrown by libtiff. We need to diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index ee183ccba..6fc8cc8cf 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1524,7 +1524,6 @@ def _save(im, fp, filename): # BITSPERSAMPLE, etc), passing arrays with a different length will result in # segfaults. Block these tags until we add extra validation. blocklist = [ - COLORMAP, REFERENCEBLACKWHITE, SAMPLEFORMAT, STRIPBYTECOUNTS, diff --git a/src/PIL/TiffTags.py b/src/PIL/TiffTags.py index 6cc9ff7f3..e1c1b701b 100644 --- a/src/PIL/TiffTags.py +++ b/src/PIL/TiffTags.py @@ -483,7 +483,6 @@ LIBTIFF_CORE = { 65537, } -LIBTIFF_CORE.remove(320) # Array of short, crashes LIBTIFF_CORE.remove(301) # Array of short, crashes LIBTIFF_CORE.remove(532) # Array of long, crashes diff --git a/src/encode.c b/src/encode.c index 03a39448d..d64f47d2b 100644 --- a/src/encode.c +++ b/src/encode.c @@ -671,7 +671,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) // This list also exists in TiffTags.py const int core_tags[] = { 256, 257, 258, 259, 262, 263, 266, 269, 274, 277, 278, 280, 281, 340, - 341, 282, 283, 284, 286, 287, 296, 297, 321, 338, 32995, 32998, 32996, + 341, 282, 283, 284, 286, 287, 296, 297, 320, 321, 338, 32995, 32998, 32996, 339, 32997, 330, 531, 530, 65537 }; @@ -801,7 +801,26 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args) TRACE(("Setting from Tuple: %d \n", key_int)); len = PyTuple_Size(value); - if (type == TIFF_SHORT) { + if (key_int == TIFFTAG_COLORMAP) { + int stride = 256; + if (len != 768) { + PyErr_SetString(PyExc_ValueError, "Requiring 768 items for for Colormap"); + return NULL; + } + UINT16 *av; + /* malloc check ok, calloc checks for overflow */ + av = calloc(len, sizeof(UINT16)); + if (av) { + for (i=0;istate, (ttag_t) key_int, + av, + av + stride, + av + stride * 2); + free(av); + } + } else if (type == TIFF_SHORT) { UINT16 *av; /* malloc check ok, calloc checks for overflow */ av = calloc(len, sizeof(UINT16));