From 9fa6634f4df3c451fab2d10dd944b45b367eb38c Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 30 Dec 2015 07:54:14 -0800 Subject: [PATCH 1/4] Partial fix for #1597 Haven't excercized all of the metadata that we're allowing yet, and there's clearly still something up with Arrays, as one of them is still crashing and making it impossible to save a palette with a libtiff image. --- PIL/TiffImagePlugin.py | 23 +++++++++------ PIL/TiffTags.py | 56 +++++++++++++++++++++++++++++++++++++ Tests/images/rdf.tif | Bin 0 -> 40421 bytes Tests/test_file_libtiff.py | 11 ++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 Tests/images/rdf.tif diff --git a/PIL/TiffImagePlugin.py b/PIL/TiffImagePlugin.py index b502c5661..096be6f56 100644 --- a/PIL/TiffImagePlugin.py +++ b/PIL/TiffImagePlugin.py @@ -1400,8 +1400,7 @@ def _save(im, fp, filename): # STRIPOFFSETS and STRIPBYTECOUNTS are added by the library # based on the data in the strip. - # ICCPROFILE crashes. - blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ICCPROFILE] + blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS] atts = {} # bits per sample is a single short in the tiff directory, not a list. atts[BITSPERSAMPLE] = bits[0] @@ -1411,16 +1410,22 @@ def _save(im, fp, filename): legacy_ifd = {} if hasattr(im, 'tag'): legacy_ifd = im.tag.to_v2() - for k, v in itertools.chain(ifd.items(), + for tag, value in itertools.chain(ifd.items(), getattr(im, 'tag_v2', {}).items(), legacy_ifd.items()): - if k not in atts and k not in blocklist: - if isinstance(v, unicode if bytes is str else str): - atts[k] = v.encode('ascii', 'replace') + b"\0" - elif isinstance(v, IFDRational): - atts[k] = float(v) + # Libtiff can only process certain core items without adding + # them to the custom dictionary. It will segfault if it attempts + # to add a custom tag without the dictionary entry + # + # UNDONE -- add code for the custom dictionary + if tag not in TiffTags.LIBTIFF_CORE: continue + if tag not in atts and tag not in blocklist: + if isinstance(value, unicode if bytes is str else str): + atts[tag] = value.encode('ascii', 'replace') + b"\0" + elif isinstance(value, IFDRational): + atts[tag] = float(value) else: - atts[k] = v + atts[tag] = value if DEBUG: print("Converted items: %s" % sorted(atts.items())) diff --git a/PIL/TiffTags.py b/PIL/TiffTags.py index 07710fdcc..4e47871d8 100644 --- a/PIL/TiffTags.py +++ b/PIL/TiffTags.py @@ -331,3 +331,59 @@ TYPES = {} # 11: "float", # 12: "double", # } + +# +# These tags are handled by default in libtiff, without +# adding to the custom dictionary. From tif_dir.c, searching for +# case TIFFTAG in the _TIFFVSetField function: +# Line: item. +# 148: case TIFFTAG_SUBFILETYPE: +# 151: case TIFFTAG_IMAGEWIDTH: +# 154: case TIFFTAG_IMAGELENGTH: +# 157: case TIFFTAG_BITSPERSAMPLE: +# 181: case TIFFTAG_COMPRESSION: +# 202: case TIFFTAG_PHOTOMETRIC: +# 205: case TIFFTAG_THRESHHOLDING: +# 208: case TIFFTAG_FILLORDER: +# 214: case TIFFTAG_ORIENTATION: +# 221: case TIFFTAG_SAMPLESPERPIXEL: +# 228: case TIFFTAG_ROWSPERSTRIP: +# 238: case TIFFTAG_MINSAMPLEVALUE: +# 241: case TIFFTAG_MAXSAMPLEVALUE: +# 244: case TIFFTAG_SMINSAMPLEVALUE: +# 247: case TIFFTAG_SMAXSAMPLEVALUE: +# 250: case TIFFTAG_XRESOLUTION: +# 256: case TIFFTAG_YRESOLUTION: +# 262: case TIFFTAG_PLANARCONFIG: +# 268: case TIFFTAG_XPOSITION: +# 271: case TIFFTAG_YPOSITION: +# 274: case TIFFTAG_RESOLUTIONUNIT: +# 280: case TIFFTAG_PAGENUMBER: +# 284: case TIFFTAG_HALFTONEHINTS: +# 288: case TIFFTAG_COLORMAP: +# 294: case TIFFTAG_EXTRASAMPLES: +# 298: case TIFFTAG_MATTEING: +# 305: case TIFFTAG_TILEWIDTH: +# 316: case TIFFTAG_TILELENGTH: +# 327: case TIFFTAG_TILEDEPTH: +# 333: case TIFFTAG_DATATYPE: +# 344: case TIFFTAG_SAMPLEFORMAT: +# 361: case TIFFTAG_IMAGEDEPTH: +# 364: case TIFFTAG_SUBIFD: +# 376: case TIFFTAG_YCBCRPOSITIONING: +# 379: case TIFFTAG_YCBCRSUBSAMPLING: +# 383: case TIFFTAG_TRANSFERFUNCTION: +# 389: case TIFFTAG_REFERENCEBLACKWHITE: +# 393: case TIFFTAG_INKNAMES: + +# some of these are not in our TAGS_V2 dict and were included from tiff.h + +LIBTIFF_CORE = set ([255, 256, 257, 258, 259, 262, 263, 266, 274, 277, + 278, 280, 281, 340, 341, 282, 283, 284, 286, 287, + 296, 297, 321, 320, 338, 32995, 322, 323, 32998, + 32996, 339, 32997, 330, 531, 530, 301, 532, 333, + # as above + 269 # this has been in our tests forever, and works + ]) + +LIBTIFF_CORE.remove(320) # Arrays error? diff --git a/Tests/images/rdf.tif b/Tests/images/rdf.tif new file mode 100644 index 0000000000000000000000000000000000000000..524a9dbc8806329f195026e4381c1e7859fcbe86 GIT binary patch literal 40421 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 literal 0 HcmV?d00001 diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 838b59365..8d7ef072f 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -395,6 +395,17 @@ class TestFileLibTiff(LibTiffTestCase): TiffImagePlugin.WRITE_LIBTIFF = False TiffImagePlugin.READ_LIBTIFF = False + def test_crashing_metadata(self): + # issue 1597 + im = Image.open('Tests/images/rdf.tif') + out = self.tempfile('temp.tif') + + TiffImagePlugin.WRITE_LIBTIFF = True + # this shouldn't crash + im.save(out, format='TIFF') + TiffImagePlugin.WRITE_LIBTIFF = False + + if __name__ == '__main__': unittest.main() From a9d1cda126b09d88d260c69d8c60a4078583752d Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 30 Dec 2015 13:52:01 -0800 Subject: [PATCH 2/4] Docs for crashing fix --- docs/handbook/image-file-formats.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 54d9b7274..a2ab63b8d 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -523,7 +523,13 @@ The :py:meth:`~PIL.Image.Image.save` method can take the following keyword argum .. versionadded:: 3.0.0 -**compression** + .. note:: + + Only some tags are currently supported when writing using + libtiff. The supported list is found in + :py:attr:`~PIL:TiffTags.LIBTIFF_CORE`. + +**compression** A string containing the desired compression method for the file. (valid only with libtiff installed) Valid compression methods are: ``None``, ``"tiff_ccitt"``, ``"group3"``, From 36c48150ea819041e46b2247dcc67f34557f705a Mon Sep 17 00:00:00 2001 From: wiredfool Date: Wed, 30 Dec 2015 13:52:13 -0800 Subject: [PATCH 3/4] Docs formatting --- docs/handbook/image-file-formats.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index a2ab63b8d..f41eaf4af 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -479,7 +479,7 @@ The :py:meth:`~PIL.Image.Image.open` method sets the following The :py:attr:`~PIL.Image.Image.tag_v2` attribute contains a dictionary of TIFF metadata. The keys are numerical indexes from -`~PIL.TiffTags.TAGS_V2`. Values are strings or numbers for single +:py:attr:`~PIL.TiffTags.TAGS_V2`. Values are strings or numbers for single items, multiple values are returned in a tuple of values. Rational numbers are returned as a :py:class:`~PIL.TiffImagePlugin.IFDRational` object. @@ -531,11 +531,11 @@ The :py:meth:`~PIL.Image.Image.save` method can take the following keyword argum **compression** A string containing the desired compression method for the - file. (valid only with libtiff installed) Valid compression - methods are: ``None``, ``"tiff_ccitt"``, ``"group3"``, - ``"group4"``, ``"tiff_jpeg"``, ``"tiff_adobe_deflate"``, - ``"tiff_thunderscan"``, ``"tiff_deflate"``, ``"tiff_sgilog"``, - ``"tiff_sgilog24"``, ``"tiff_raw_16"`` + file. (valid only with libtiff installed) Valid compression + methods are: ``None``, ``"tiff_ccitt"``, ``"group3"``, + ``"group4"``, ``"tiff_jpeg"``, ``"tiff_adobe_deflate"``, + ``"tiff_thunderscan"``, ``"tiff_deflate"``, ``"tiff_sgilog"``, + ``"tiff_sgilog24"``, ``"tiff_raw_16"`` These arguments to set the tiff header fields are an alternative to using the general tags available through tiffinfo. From 36d4f5a9b4380ca46b5820d850b0ade17c6fab33 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 1 Jan 2016 05:30:40 -0800 Subject: [PATCH 4/4] Tests for permitted libtiff metadata --- PIL/TiffTags.py | 15 ++++++++++- Tests/test_file_libtiff.py | 55 +++++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/PIL/TiffTags.py b/PIL/TiffTags.py index 4e47871d8..6bb2409f3 100644 --- a/PIL/TiffTags.py +++ b/PIL/TiffTags.py @@ -386,4 +386,17 @@ LIBTIFF_CORE = set ([255, 256, 257, 258, 259, 262, 263, 266, 274, 277, 269 # this has been in our tests forever, and works ]) -LIBTIFF_CORE.remove(320) # Arrays error? +LIBTIFF_CORE.remove(320) # Array of short, crashes +LIBTIFF_CORE.remove(301) # Array of short, crashes +LIBTIFF_CORE.remove(532) # Array of long, crashes + +LIBTIFF_CORE.remove(255) # We don't have support for subfiletypes +LIBTIFF_CORE.remove(322) # We don't have support for tiled images in libtiff +LIBTIFF_CORE.remove(323) # Tiled images +LIBTIFF_CORE.remove(333) # Ink Names either + +# Note to advanced users: There may be combinations of these +# parameters and values that when added properly, will work and +# produce valid tiff images that may work in your application. +# It is safe to add and remove tags from this set from Pillow's point +# of view so long as you test against libtiff. diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 8d7ef072f..50e6dcc23 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -7,7 +7,7 @@ import logging import itertools import os -from PIL import Image, TiffImagePlugin +from PIL import Image, TiffImagePlugin, TiffTags logger = logging.getLogger(__name__) @@ -172,6 +172,59 @@ class TestFileLibTiff(LibTiffTestCase): for field in requested_fields: self.assertTrue(field in reloaded, "%s not in metadata" %field) + def test_additional_metadata(self): + # these should not crash. Seriously dummy data, most of it doesn't make + # any sense, so we're running up against limits where we're asking + # libtiff to do stupid things. + + # Get the list of the ones that we should be able to write + + core_items = dict((tag, info) for tag, info in [(s,TiffTags.lookup(s)) for s + in TiffTags.LIBTIFF_CORE] + if info.type is not None) + + # Exclude ones that have special meaning that we're already testing them + im = Image.open('Tests/images/hopper_g4.tif') + for tag in im.tag_v2.keys(): + try: + del(core_items[tag]) + except: pass + + # Type codes: + # 2: "ascii", + # 3: "short", + # 4: "long", + # 5: "rational", + # 12: "double", + # type: dummy value + values = { 2: 'test', + 3: 1, + 4: 2**20, + 5: TiffImagePlugin.IFDRational(100,1), + 12: 1.05 } + + + new_ifd = TiffImagePlugin.ImageFileDirectory_v2() + for tag, info in core_items.items(): + if info.length == 1: + new_ifd[tag] = values[info.type] + if info.length == 0: + new_ifd[tag] = tuple(values[info.type] for _ in range(3)) + else: + new_ifd[tag] = tuple(values[info.type] for _ in range(info.length)) + + # Extra samples really doesn't make sense in this application. + del(new_ifd[338]) + + out = self.tempfile("temp.tif") + TiffImagePlugin.WRITE_LIBTIFF = True + + im.save(out, tiffinfo=new_ifd) + + TiffImagePlugin.WRITE_LIBTIFF = False + + + def test_g3_compression(self): i = Image.open('Tests/images/hopper_g4_500.tif') out = self.tempfile("temp.tif")