From f377925f7a03faa9d6384aaabe84795d24f45643 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 7 Jul 2019 12:35:37 +1000 Subject: [PATCH 01/29] Updated freetype to 2.10.1 --- winbuild/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/winbuild/config.py b/winbuild/config.py index cd7cc2698..6f2a9779c 100644 --- a/winbuild/config.py +++ b/winbuild/config.py @@ -35,9 +35,9 @@ libs = { "dir": "tiff-4.0.10", }, "freetype": { - "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.0.tar.gz", # noqa: E501 - "filename": PILLOW_DEPENDS_DIR + "freetype-2.10.0.tar.gz", - "dir": "freetype-2.10.0", + "url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.1.tar.gz", # noqa: E501 + "filename": PILLOW_DEPENDS_DIR + "freetype-2.10.1.tar.gz", + "dir": "freetype-2.10.1", }, "lcms": { "url": SF_MIRROR + "/project/lcms/lcms/2.7/lcms2-2.7.zip", From fa2f27244cd4e9a215b4ff7d9e4f405713a49177 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 29 Jul 2019 19:32:12 +1000 Subject: [PATCH 02/29] Updated libimagequant to 2.12.5 --- depends/install_imagequant.sh | 2 +- docs/installation.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/depends/install_imagequant.sh b/depends/install_imagequant.sh index 1813bae09..0120dbc0b 100755 --- a/depends/install_imagequant.sh +++ b/depends/install_imagequant.sh @@ -1,7 +1,7 @@ #!/bin/bash # install libimagequant -archive=libimagequant-2.12.3 +archive=libimagequant-2.12.5 ./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/master/$archive.tar.gz diff --git a/docs/installation.rst b/docs/installation.rst index 5f0156b63..5dbc66988 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -169,7 +169,7 @@ Many of Pillow's features require external libraries: * **libimagequant** provides improved color quantization - * Pillow has been tested with libimagequant **2.6-2.12.3** + * Pillow has been tested with libimagequant **2.6-2.12.5** * Libimagequant is licensed GPLv3, which is more restrictive than the Pillow license, therefore we will not be distributing binaries with libimagequant support enabled. From 8696f06fbe1b2a6b30fb5e64284bbb75055e5044 Mon Sep 17 00:00:00 2001 From: djy0 Date: Fri, 2 Aug 2019 08:47:38 +0800 Subject: [PATCH 03/29] Update test_file_gif.py --- Tests/test_file_gif.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 2ba370c3f..56cb9f5d5 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -472,7 +472,7 @@ class TestFileGif(PillowTestCase): except EOFError: pass - def test_identical_frames(self): + def test_partially_identical_frames(self): duration_list = [1000, 1500, 2000, 4000] out = self.tempfile("temp.gif") @@ -495,6 +495,37 @@ class TestFileGif(PillowTestCase): # Assert that the new duration is the total of the identical frames self.assertEqual(reread.info["duration"], 4500) + def test_totally_identical_frames(self): + duration_list = [1000, 1500, 2000, 4000] + + out = self.tempfile("temp.gif") + + image_path = "Tests/images/bc7-argb-8bpp_MipMaps-1.png" + im_list = [ + Image.open(image_path), + Image.open(image_path), + Image.open(image_path), + Image.open(image_path), + ] + mask = Image.new("RGBA", im_list[0].size, (255, 255, 255, 0)) + + frames = [] + for image in im_list: + frames.append(Image.alpha_composite(mask, image)) + + # duration as list + frames[0].save(out, + save_all=True, append_images=frames[1:], optimize=False, duration=duration_list, loop=0, + transparency=0) + + reread = Image.open(out) + + # Assert that the first three frames were combined + self.assertEqual(reread.n_frames, 1) + + # Assert that the new duration is the total of the identical frames + self.assertEqual(reread.info["duration"], 8500) + def test_number_of_loops(self): number_of_loops = 2 From fcaf27d51cfb9f92eb46a1194ae4ad75d1d65d5b Mon Sep 17 00:00:00 2001 From: djy0 Date: Fri, 2 Aug 2019 08:54:04 +0800 Subject: [PATCH 04/29] Update GifImagePlugin.py --- src/PIL/GifImagePlugin.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index bbf6dc9d6..b5323d252 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -472,6 +472,10 @@ def _write_multiple_frames(im, fp, palette): else: bbox = None im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) + + # see: https://github.com/python-pillow/Pillow/issues/4002 + if len(im_frames) == 1 and 'duration' in im_frames[0]['encoderinfo']: + im.encoderinfo['duration'] = im_frames[0]['encoderinfo']['duration'] if len(im_frames) > 1: for frame_data in im_frames: From 3c971bec4197b211ff95e5022a800ac50d982f8f Mon Sep 17 00:00:00 2001 From: djy0 Date: Fri, 2 Aug 2019 09:51:27 +0800 Subject: [PATCH 05/29] format --- Tests/test_file_gif.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 56cb9f5d5..b90a73627 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -514,10 +514,16 @@ class TestFileGif(PillowTestCase): frames.append(Image.alpha_composite(mask, image)) # duration as list - frames[0].save(out, - save_all=True, append_images=frames[1:], optimize=False, duration=duration_list, loop=0, - transparency=0) - + frames[0].save( + out, + save_all=True, + append_images=frames[1:], + optimize=False, + duration=duration_list, + loop=0, + transparency=0, + ) + reread = Image.open(out) # Assert that the first three frames were combined From 3499f50e5220eb6dfe2498f26036b20a99e5070c Mon Sep 17 00:00:00 2001 From: djy0 Date: Fri, 2 Aug 2019 09:54:19 +0800 Subject: [PATCH 06/29] format --- src/PIL/GifImagePlugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index b5323d252..b359f7259 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -474,8 +474,8 @@ def _write_multiple_frames(im, fp, palette): im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) # see: https://github.com/python-pillow/Pillow/issues/4002 - if len(im_frames) == 1 and 'duration' in im_frames[0]['encoderinfo']: - im.encoderinfo['duration'] = im_frames[0]['encoderinfo']['duration'] + if len(im_frames) == 1 and "duration" in im_frames[0]["encoderinfo"]: + im.encoderinfo["duration"] = im_frames[0]["encoderinfo"]["duration"] if len(im_frames) > 1: for frame_data in im_frames: From 63c15dc3ba04c0cacd7a5414d3d2e6b8b9d84e73 Mon Sep 17 00:00:00 2001 From: djy0 Date: Fri, 2 Aug 2019 10:36:33 +0800 Subject: [PATCH 07/29] format --- Tests/test_file_gif.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index b90a73627..1704c76a5 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -523,7 +523,6 @@ class TestFileGif(PillowTestCase): loop=0, transparency=0, ) - reread = Image.open(out) # Assert that the first three frames were combined From dc9c0dbfbe286cbcb33c11a0c32af5c4d45e0131 Mon Sep 17 00:00:00 2001 From: djy0 Date: Fri, 2 Aug 2019 10:37:17 +0800 Subject: [PATCH 08/29] format --- src/PIL/GifImagePlugin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index b359f7259..d2f6cd1d3 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -472,7 +472,6 @@ def _write_multiple_frames(im, fp, palette): else: bbox = None im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) - # see: https://github.com/python-pillow/Pillow/issues/4002 if len(im_frames) == 1 and "duration" in im_frames[0]["encoderinfo"]: im.encoderinfo["duration"] = im_frames[0]["encoderinfo"]["duration"] From 0872cb43777606ddd55cd9803694469ebb21e843 Mon Sep 17 00:00:00 2001 From: djy0 Date: Sun, 4 Aug 2019 17:32:02 +0800 Subject: [PATCH 09/29] fix comment --- Tests/test_file_gif.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index 1704c76a5..a4d021f58 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -525,7 +525,7 @@ class TestFileGif(PillowTestCase): ) reread = Image.open(out) - # Assert that the first three frames were combined + # Assert that all four frames were combined self.assertEqual(reread.n_frames, 1) # Assert that the new duration is the total of the identical frames From 88be36c27aade7af422d5bf934d05a8a4b51d7d3 Mon Sep 17 00:00:00 2001 From: chadawagner Date: Tue, 30 Jul 2019 11:26:04 -0700 Subject: [PATCH 10/29] check prior fp result, do not use if False --- 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 dabcf8eb4..fb394af16 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1164,7 +1164,7 @@ class TiffImageFile(ImageFile.ImageFile): if DEBUG: print("have getvalue. just sending in a string from getvalue") n, err = decoder.decode(self.fp.getvalue()) - elif hasattr(self.fp, "fileno"): + elif fp: # we've got a actual file on disk, pass in the fp. if DEBUG: print("have fileno, calling fileno version of the decoder.") From 597ca79b1b01f446615323c67686dd205523ba96 Mon Sep 17 00:00:00 2001 From: chadawagner Date: Tue, 30 Jul 2019 11:28:44 -0700 Subject: [PATCH 11/29] rewind before decode, consistent with other cases --- src/PIL/TiffImagePlugin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index fb394af16..bb86c53aa 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1175,6 +1175,7 @@ class TiffImageFile(ImageFile.ImageFile): # we have something else. if DEBUG: print("don't have fileno or getvalue. just reading") + self.fp.seek(0) # UNDONE -- so much for that buffer size thing. n, err = decoder.decode(self.fp.read()) From 457a97dde8232eb4b70e8704749ddd4094a4d257 Mon Sep 17 00:00:00 2001 From: chadawagner Date: Fri, 2 Aug 2019 17:26:10 -0700 Subject: [PATCH 12/29] added test for reading TIFF from non-disk file obj --- Tests/test_file_libtiff.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index bc5003f5f..4ddde047a 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -81,6 +81,19 @@ class TestFileLibTiff(LibTiffTestCase): self.assertEqual(im.size, (500, 500)) self._assert_noerr(im) + def test_g4_non_disk_file_object(self): + """Testing loading from non-disk non-bytesio file object""" + test_file = "Tests/images/hopper_g4_500.tif" + s = io.BytesIO() + with open(test_file, "rb") as f: + s.write(f.read()) + s.seek(0) + r = io.BufferedReader(s) + im = Image.open(r) + + self.assertEqual(im.size, (500, 500)) + self._assert_noerr(im) + def test_g4_eq_png(self): """ Checking that we're actually getting the data that we expect""" png = Image.open("Tests/images/hopper_bw_500.png") From 8fb437d37fdfb8215fc40c3a8437eed7827a7046 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 12 Aug 2019 20:04:18 +1000 Subject: [PATCH 13/29] Improved ImageFont documentation [ci skip] --- src/PIL/ImageFont.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index e2e6af332..077e7cadc 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -549,8 +549,12 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): This function requires the _imagingft service. :param font: A filename or file-like object containing a TrueType font. - Under Windows, if the file is not found in this filename, - the loader also looks in Windows :file:`fonts/` directory. + If the file is not found in this filename, the loader may also + search in other directories, such as the :file:`fonts/` + directory on Windows or :file:`/Library/Fonts/`, + :file:`/System/Library/Fonts/` and :file:`~/Library/Fonts/` on + macOS. + :param size: The requested size, in points. :param index: Which font face to load (default is first available face). :param encoding: Which font encoding to use (default is Unicode). Common From b307fb4808b9c0b879b23c7fdc1f5a1ef29d9baf Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 12 Aug 2019 20:19:49 +1000 Subject: [PATCH 14/29] Noted a Windows limit on opening fonts [ci skip] --- src/PIL/ImageFont.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 077e7cadc..8279503be 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -546,6 +546,11 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): This function loads a font object from the given file or file-like object, and creates a font object for a font of the given size. + Note that Pillow uses FreeType to open font files. If you are opening many + fonts simultaneously on Windows, be aware that Windows limits the number of + files that can be open in C at once to 512. If you approach that limit, an + ``OSError`` may be thrown, reporting that FreeType "cannot open resource". + This function requires the _imagingft service. :param font: A filename or file-like object containing a TrueType font. From eb0a61a47e28b9801b0e2d1c761e8f657d290e90 Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Mon, 12 Aug 2019 20:42:27 +1000 Subject: [PATCH 15/29] Simplified text [ci skip] Co-Authored-By: Hugo van Kemenade --- src/PIL/ImageFont.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 8279503be..659e589de 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -546,7 +546,7 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): This function loads a font object from the given file or file-like object, and creates a font object for a font of the given size. - Note that Pillow uses FreeType to open font files. If you are opening many + Pillow uses FreeType to open font files. If you are opening many fonts simultaneously on Windows, be aware that Windows limits the number of files that can be open in C at once to 512. If you approach that limit, an ``OSError`` may be thrown, reporting that FreeType "cannot open resource". From 86c64aafd278f77fa25329c24286a26a6aa1cf56 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 12 Aug 2019 20:43:32 +1000 Subject: [PATCH 16/29] Formatted text [ci skip] --- src/PIL/ImageFont.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 659e589de..16c1052f4 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -546,9 +546,9 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): This function loads a font object from the given file or file-like object, and creates a font object for a font of the given size. - Pillow uses FreeType to open font files. If you are opening many - fonts simultaneously on Windows, be aware that Windows limits the number of - files that can be open in C at once to 512. If you approach that limit, an + Pillow uses FreeType to open font files. If you are opening many fonts + simultaneously on Windows, be aware that Windows limits the number of files + that can be open in C at once to 512. If you approach that limit, an ``OSError`` may be thrown, reporting that FreeType "cannot open resource". This function requires the _imagingft service. From 03452d138d076fd475f5527a079963803cda21bf Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Tue, 13 Aug 2019 19:29:42 +1000 Subject: [PATCH 17/29] Update CHANGES.rst [ci skip] --- CHANGES.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 45e388625..57e0d1e44 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,12 +7,21 @@ Changelog (Pillow) - This is the last Pillow release to support Python 2.7 #3642 +- Added fallback for finding ld on MinGW Cygwin #4019 + [radarhere] + +- Remove indirect dependencies from requirements.txt #3976 + [hugovk] + - Depends: Update libwebp to 1.0.3 #3983 [radarhere] - Change overflow check to use PY_SSIZE_T_MAX #3964 [radarhere] +- Report reason for pytest skips #3942 + [hugovk] + 6.1.0 (2019-07-01) ------------------ From 108512eae26e0b1dcbcd4ca47f168796f443ecff Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 15 Aug 2019 20:41:48 +1000 Subject: [PATCH 18/29] Cleaned up strings --- src/PIL/ImageShow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/ImageShow.py b/src/PIL/ImageShow.py index 29b15351d..13df7dfbe 100644 --- a/src/PIL/ImageShow.py +++ b/src/PIL/ImageShow.py @@ -179,7 +179,7 @@ else: with open(path, "r") as f: command = self.get_command_ex(file, **options)[0] subprocess.Popen( - ["im=$(cat);" + command + " $im;" "rm -f $im"], shell=True, stdin=f + ["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f ) os.remove(path) return 1 From 75fe92fa88d14aabb3bee68cc06f29266c97c959 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Fri, 16 Aug 2019 19:16:06 +1000 Subject: [PATCH 19/29] Updated documentation [ci skip] --- src/PIL/Image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index 7d2bb1e7e..8b92aae45 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -2110,7 +2110,7 @@ class Image(object): debugging purposes. On Unix platforms, this method saves the image to a temporary - PPM file, and calls the **display**, **eog** or **xv** + PNG file, and calls the **display**, **eog** or **xv** utility, depending on which one can be found. On macOS, this method saves the image to a temporary PNG file, and From 58dc0afed375bac336483485deb1a211ed742800 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 17 Aug 2019 20:04:33 +1000 Subject: [PATCH 20/29] Updated CHANGES.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 57e0d1e44..52236c7e7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,7 +13,7 @@ Changelog (Pillow) - Remove indirect dependencies from requirements.txt #3976 [hugovk] -- Depends: Update libwebp to 1.0.3 #3983 +- Depends: Update libwebp to 1.0.3 #3983, libimagequant to 2.12.5 #3993 [radarhere] - Change overflow check to use PY_SSIZE_T_MAX #3964 From 5b120164b5491b7b928a0c43f3911198e8fdf9ff Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 17 Aug 2019 20:32:24 +1000 Subject: [PATCH 21/29] Corrected underline [ci skip] --- Tests/README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/README.rst b/Tests/README.rst index d64a34bd7..da3297bce 100644 --- a/Tests/README.rst +++ b/Tests/README.rst @@ -4,7 +4,7 @@ Pillow Tests Test scripts are named ``test_xxx.py`` and use the ``unittest`` module. A base class and helper functions can be found in ``helper.py``. Dependencies ------------ +------------ Install:: From cd99deff1ed1d6239a170ca50379605c0106d9cf Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 18 Aug 2019 12:32:23 +0300 Subject: [PATCH 22/29] Fix for Python 3.10 --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a36e192ec..76bdfb159 100755 --- a/setup.py +++ b/setup.py @@ -432,7 +432,9 @@ class pil_build_ext(build_ext): # pythonX.Y.dll.a is in the /usr/lib/pythonX.Y/config directory _add_directory( library_dirs, - os.path.join("/usr/lib", "python%s" % sys.version[:3], "config"), + os.path.join( + "/usr/lib", "python{}.{}".format(*sys.version_info), "config" + ), ) elif sys.platform == "darwin": From 34330a7aa0b3f0585f5540c59f40690769cb22e5 Mon Sep 17 00:00:00 2001 From: chadawagner Date: Mon, 19 Aug 2019 09:46:07 -0700 Subject: [PATCH 23/29] Update Tests/test_file_libtiff.py Co-Authored-By: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- Tests/test_file_libtiff.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py index 4ddde047a..6339d878a 100644 --- a/Tests/test_file_libtiff.py +++ b/Tests/test_file_libtiff.py @@ -82,7 +82,7 @@ class TestFileLibTiff(LibTiffTestCase): self._assert_noerr(im) def test_g4_non_disk_file_object(self): - """Testing loading from non-disk non-bytesio file object""" + """Testing loading from non-disk non-BytesIO file object""" test_file = "Tests/images/hopper_g4_500.tif" s = io.BytesIO() with open(test_file, "rb") as f: From 4834157658e00366c2cb909fe645a0b0fb5c2a5c Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 20 Aug 2019 20:42:58 +1000 Subject: [PATCH 24/29] Documented OS support for saved files [ci skip] --- src/PIL/IcoImagePlugin.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PIL/IcoImagePlugin.py b/src/PIL/IcoImagePlugin.py index c4c72e78a..fc728d6fb 100644 --- a/src/PIL/IcoImagePlugin.py +++ b/src/PIL/IcoImagePlugin.py @@ -263,6 +263,9 @@ class IcoImageFile(ImageFile.ImageFile): Handles classic, XP and Vista icon formats. + When saving, PNG compression is used. Support for this was only added in + Windows Vista. + This plugin is a refactored version of Win32IconImagePlugin by Bryan Davis . https://code.google.com/archive/p/casadebender/wikis/Win32IconImagePlugin.wiki From a44e918a5b647d5eb75e0bf3fe3df4d6501cb78d Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 22 Aug 2019 19:10:00 +1000 Subject: [PATCH 25/29] Updated CHANGES.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 52236c7e7..34405615a 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,7 +13,7 @@ Changelog (Pillow) - Remove indirect dependencies from requirements.txt #3976 [hugovk] -- Depends: Update libwebp to 1.0.3 #3983, libimagequant to 2.12.5 #3993 +- Depends: Update libwebp to 1.0.3 #3983, libimagequant to 2.12.5 #3993, freetype to 2.10.1 #3991 [radarhere] - Change overflow check to use PY_SSIZE_T_MAX #3964 From 2dbfabe6d5e553e9bf6510f8d2439bc90757309e Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 24 Aug 2019 08:10:45 +1000 Subject: [PATCH 26/29] Simplifications --- Tests/test_file_gif.py | 50 +++++++++++++-------------------------- src/PIL/GifImagePlugin.py | 8 ++++--- 2 files changed, 22 insertions(+), 36 deletions(-) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py index a4d021f58..4ff9727e1 100644 --- a/Tests/test_file_gif.py +++ b/Tests/test_file_gif.py @@ -472,7 +472,7 @@ class TestFileGif(PillowTestCase): except EOFError: pass - def test_partially_identical_frames(self): + def test_identical_frames(self): duration_list = [1000, 1500, 2000, 4000] out = self.tempfile("temp.gif") @@ -495,41 +495,25 @@ class TestFileGif(PillowTestCase): # Assert that the new duration is the total of the identical frames self.assertEqual(reread.info["duration"], 4500) - def test_totally_identical_frames(self): - duration_list = [1000, 1500, 2000, 4000] + def test_identical_frames_to_single_frame(self): + for duration in ([1000, 1500, 2000, 4000], (1000, 1500, 2000, 4000), 8500): + out = self.tempfile("temp.gif") + im_list = [ + Image.new("L", (100, 100), "#000"), + Image.new("L", (100, 100), "#000"), + Image.new("L", (100, 100), "#000"), + ] - out = self.tempfile("temp.gif") + im_list[0].save( + out, save_all=True, append_images=im_list[1:], duration=duration + ) + reread = Image.open(out) - image_path = "Tests/images/bc7-argb-8bpp_MipMaps-1.png" - im_list = [ - Image.open(image_path), - Image.open(image_path), - Image.open(image_path), - Image.open(image_path), - ] - mask = Image.new("RGBA", im_list[0].size, (255, 255, 255, 0)) + # Assert that all frames were combined + self.assertEqual(reread.n_frames, 1) - frames = [] - for image in im_list: - frames.append(Image.alpha_composite(mask, image)) - - # duration as list - frames[0].save( - out, - save_all=True, - append_images=frames[1:], - optimize=False, - duration=duration_list, - loop=0, - transparency=0, - ) - reread = Image.open(out) - - # Assert that all four frames were combined - self.assertEqual(reread.n_frames, 1) - - # Assert that the new duration is the total of the identical frames - self.assertEqual(reread.info["duration"], 8500) + # Assert that the new duration is the total of the identical frames + self.assertEqual(reread.info["duration"], 8500) def test_number_of_loops(self): number_of_loops = 2 diff --git a/src/PIL/GifImagePlugin.py b/src/PIL/GifImagePlugin.py index d2f6cd1d3..07f5ab683 100644 --- a/src/PIL/GifImagePlugin.py +++ b/src/PIL/GifImagePlugin.py @@ -472,9 +472,6 @@ def _write_multiple_frames(im, fp, palette): else: bbox = None im_frames.append({"im": im_frame, "bbox": bbox, "encoderinfo": encoderinfo}) - # see: https://github.com/python-pillow/Pillow/issues/4002 - if len(im_frames) == 1 and "duration" in im_frames[0]["encoderinfo"]: - im.encoderinfo["duration"] = im_frames[0]["encoderinfo"]["duration"] if len(im_frames) > 1: for frame_data in im_frames: @@ -492,6 +489,11 @@ def _write_multiple_frames(im, fp, palette): offset = frame_data["bbox"][:2] _write_frame_data(fp, im_frame, offset, frame_data["encoderinfo"]) return True + elif "duration" in im.encoderinfo and isinstance( + im.encoderinfo["duration"], (list, tuple) + ): + # Since multiple frames will not be written, add together the frame durations + im.encoderinfo["duration"] = sum(im.encoderinfo["duration"]) def _save_all(im, fp, filename): From 2df15ec7c277ffede9e92448dd4ec40af01fbc68 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 24 Aug 2019 21:40:24 +1000 Subject: [PATCH 27/29] Updated CHANGES.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 34405615a..f86d61b82 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,9 @@ Changelog (Pillow) - This is the last Pillow release to support Python 2.7 #3642 +- Fix bug in TIFF loading of BufferedReader #3998 + [chadawagner] + - Added fallback for finding ld on MinGW Cygwin #4019 [radarhere] From 4fef7de801ef70a7265adb19b88c549b84b0d9b4 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 26 Aug 2019 20:45:52 +1000 Subject: [PATCH 28/29] Updated CHANGES.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index f86d61b82..064497dcf 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,9 @@ Changelog (Pillow) - This is the last Pillow release to support Python 2.7 #3642 +- Fix bug when merging identical images to GIF with a list of durations #4003 + [djy0, radarhere] + - Fix bug in TIFF loading of BufferedReader #3998 [chadawagner] From 35a7d11f4375080f9d9fc04ad448b8d14830da96 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 29 Aug 2019 19:02:19 +1000 Subject: [PATCH 29/29] Fixed typo [ci skip] --- Tests/test_file_tiff_metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py index 8761e431e..851cbed3f 100644 --- a/Tests/test_file_tiff_metadata.py +++ b/Tests/test_file_tiff_metadata.py @@ -222,7 +222,7 @@ class TestFileTiffMetadata(PillowTestCase): self.assertEqual(0, reloaded.tag_v2[41988].numerator) self.assertEqual(0, reloaded.tag_v2[41988].denominator) - def test_expty_values(self): + def test_empty_values(self): data = io.BytesIO( b"II*\x00\x08\x00\x00\x00\x03\x00\x1a\x01\x05\x00\x00\x00\x00\x00" b"\x00\x00\x00\x00\x1b\x01\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00"