From a70da8112dc10713072e11552b3b7bbdcdb34d3d Mon Sep 17 00:00:00 2001 From: Christoph Gohlke Date: Thu, 27 Jun 2019 23:55:01 -0700 Subject: [PATCH 1/4] Add TIFFTAG_SAMPLEFORMAT to blocklist The SAMPLEFORMAT tag is determined by the image format and should not be copied from legacy_ifd. --- src/PIL/TiffImagePlugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 835c460a5c4..cf91211b290 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1540,7 +1540,7 @@ def _save(im, fp, filename): # STRIPOFFSETS and STRIPBYTECOUNTS are added by the library # based on the data in the strip. - blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS] + blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, SAMPLEFORMAT] atts = {} # bits per sample is a single short in the tiff directory, not a list. atts[BITSPERSAMPLE] = bits[0] From 4a69223db98d31413466dbb348519c0f1e4da070 Mon Sep 17 00:00:00 2001 From: Christoph Gohlke Date: Sat, 29 Jun 2019 16:09:53 -0700 Subject: [PATCH 2/4] Add test for sampleformat corruption --- Tests/test_file_tiff.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index 945372f8667..fa1aa49fa58 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -587,6 +587,28 @@ def test_close_on_load_nonexclusive(self): im.load() self.assertFalse(fp.closed) + def test_sampleformat_not_corrupted(self): + # Assert that a TIFF image with SampleFormat=UINT tag is not corrupted + # when saving to a new file. + # Pillow 6.0 fails with "OSError: cannot identify image file". + import base64 + tiff = BytesIO( + base64.b64decode( + b'SUkqAAgAAAAPAP4ABAABAAAAAAAAAAABBAABAAAAAQAAAAEBBAABAAAAAQAA' + b'AAIBAwADAAAAwgAAAAMBAwABAAAACAAAAAYBAwABAAAAAgAAABEBBAABAAAA' + b'4AAAABUBAwABAAAAAwAAABYBBAABAAAAAQAAABcBBAABAAAACwAAABoBBQAB' + b'AAAAyAAAABsBBQABAAAA0AAAABwBAwABAAAAAQAAACgBAwABAAAAAQAAAFMB' + b'AwADAAAA2AAAAAAAAAAIAAgACAABAAAAAQAAAAEAAAABAAAAAQABAAEAAAB4' + b'nGNgYAAAAAMAAQ==' + ) + ) + out = BytesIO() + with Image.open(tiff) as im: + im.save(out, format='tiff') + out.seek(0) + with Image.open(out) as im: + im.load() + @unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") class TestFileTiffW32(PillowTestCase): From cc0d70145b3173c03d51e2cd59d3c81cafb13e0e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 30 Jun 2019 13:11:05 +1000 Subject: [PATCH 3/4] Lint fixes --- Tests/test_file_tiff.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index fa1aa49fa58..e241f6a6ad2 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -592,19 +592,20 @@ def test_sampleformat_not_corrupted(self): # when saving to a new file. # Pillow 6.0 fails with "OSError: cannot identify image file". import base64 + tiff = BytesIO( base64.b64decode( - b'SUkqAAgAAAAPAP4ABAABAAAAAAAAAAABBAABAAAAAQAAAAEBBAABAAAAAQAA' - b'AAIBAwADAAAAwgAAAAMBAwABAAAACAAAAAYBAwABAAAAAgAAABEBBAABAAAA' - b'4AAAABUBAwABAAAAAwAAABYBBAABAAAAAQAAABcBBAABAAAACwAAABoBBQAB' - b'AAAAyAAAABsBBQABAAAA0AAAABwBAwABAAAAAQAAACgBAwABAAAAAQAAAFMB' - b'AwADAAAA2AAAAAAAAAAIAAgACAABAAAAAQAAAAEAAAABAAAAAQABAAEAAAB4' - b'nGNgYAAAAAMAAQ==' + b"SUkqAAgAAAAPAP4ABAABAAAAAAAAAAABBAABAAAAAQAAAAEBBAABAAAAAQAA" + b"AAIBAwADAAAAwgAAAAMBAwABAAAACAAAAAYBAwABAAAAAgAAABEBBAABAAAA" + b"4AAAABUBAwABAAAAAwAAABYBBAABAAAAAQAAABcBBAABAAAACwAAABoBBQAB" + b"AAAAyAAAABsBBQABAAAA0AAAABwBAwABAAAAAQAAACgBAwABAAAAAQAAAFMB" + b"AwADAAAA2AAAAAAAAAAIAAgACAABAAAAAQAAAAEAAAABAAAAAQABAAEAAAB4" + b"nGNgYAAAAAMAAQ==" ) ) out = BytesIO() with Image.open(tiff) as im: - im.save(out, format='tiff') + im.save(out, format="tiff") out.seek(0) with Image.open(out) as im: im.load() From 42588a649330b577bad686e20596c50b9fe4ad03 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 30 Jun 2019 13:25:12 +1000 Subject: [PATCH 4/4] Skip test if libtiff is not installed --- Tests/test_file_tiff.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index e241f6a6ad2..3b0afba6777 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -4,7 +4,7 @@ from .helper import unittest, PillowTestCase, hopper -from PIL import Image, TiffImagePlugin +from PIL import Image, TiffImagePlugin, features from PIL._util import py3 from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION, RESOLUTION_UNIT @@ -587,6 +587,7 @@ def test_close_on_load_nonexclusive(self): im.load() self.assertFalse(fp.closed) + @unittest.skipUnless(features.check("libtiff"), "libtiff not installed") def test_sampleformat_not_corrupted(self): # Assert that a TIFF image with SampleFormat=UINT tag is not corrupted # when saving to a new file.