From 1141e636d9af3b2310fb9d70f872dac53cd0a957 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 10 Jul 2014 02:00:26 +0300 Subject: [PATCH 01/58] More tests for Image.py --- Tests/test_image.py | 49 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/Tests/test_image.py b/Tests/test_image.py index 174964ce7..c1c2c3d86 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -1,4 +1,4 @@ -from helper import unittest, PillowTestCase +from helper import unittest, PillowTestCase, lena from PIL import Image @@ -55,6 +55,53 @@ class TestImage(PillowTestCase): self.assertFalse(item == None) self.assertFalse(item == num) + def test_expand_x(self): + # Arrange + im = lena() + orig_size = im.size + xmargin = 5 + + # Act + im = im._expand(xmargin) + + # Assert + self.assertEqual(im.size[0], orig_size[0] + 2*xmargin) + self.assertEqual(im.size[1], orig_size[1] + 2*xmargin) + + def test_expand_xy(self): + # Arrange + im = lena() + orig_size = im.size + xmargin = 5 + ymargin = 3 + + # Act + im = im._expand(xmargin, ymargin) + + # Assert + self.assertEqual(im.size[0], orig_size[0] + 2*xmargin) + self.assertEqual(im.size[1], orig_size[1] + 2*ymargin) + + def test_getbands(self): + # Arrange + im = lena() + + # Act + bands = im.getbands() + + # Assert + self.assertEqual(bands, ('R', 'G', 'B')) + + def test_getbbox(self): + # Arrange + im = lena() + + # Act + bbox = im.getbbox() + + # Assert + self.assertEqual(bbox, (0, 0, 128, 128)) + if __name__ == '__main__': unittest.main() From 123fe38ef73e5dc7485e14d1d35a47e93fa680b0 Mon Sep 17 00:00:00 2001 From: hugovk Date: Tue, 15 Jul 2014 00:42:31 +0300 Subject: [PATCH 02/58] Test Image's __ne__ and alpha_composite --- Tests/test_image.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Tests/test_image.py b/Tests/test_image.py index c1c2c3d86..85b0bba0e 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -102,6 +102,44 @@ class TestImage(PillowTestCase): # Assert self.assertEqual(bbox, (0, 0, 128, 128)) + def test_ne(self): + # Arrange + im1 = Image.new('RGB', (25, 25), 'black') + im2 = Image.new('RGB', (25, 25), 'white') + + # Act / Assert + self.assertTrue(im1 != im2) + + def test_alpha_composite(self): + # http://stackoverflow.com/questions/3374878 + # Arrange + import ImageDraw + + expected_colors = sorted([ + (1122, (128, 127, 0, 255)), + (1089, (0, 255, 0, 255)), + (3300, (255, 0, 0, 255)), + (1156, (170, 85, 0, 192)), + (1122, (0, 255, 0, 128)), + (1122, (255, 0, 0, 128)), + (1089, (0, 255, 0, 0))]) + + dst = Image.new('RGBA', size=(100, 100), color=(0, 255, 0, 255)) + draw = ImageDraw.Draw(dst) + draw.rectangle((0, 33, 100, 66), fill=(0, 255, 0, 128)) + draw.rectangle((0, 67, 100, 100), fill=(0, 255, 0, 0)) + src = Image.new('RGBA', size=(100, 100), color=(255, 0, 0, 255)) + draw = ImageDraw.Draw(src) + draw.rectangle((33, 0, 66, 100), fill=(255, 0, 0, 128)) + draw.rectangle((67, 0, 100, 100), fill=(255, 0, 0, 0)) + + # Act + img = Image.alpha_composite(dst, src) + + # Assert + img_colors = sorted(img.getcolors()) + self.assertEqual(img_colors, expected_colors) + if __name__ == '__main__': unittest.main() From 42032b3286ab7305ad53491ddec19014b37deb0a Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Tue, 15 Jul 2014 00:44:12 +0300 Subject: [PATCH 03/58] Fix `ImageStat.mean` docs The docs referred to `ImageStat.pixel`, which isn't a thing at all. In addition, make it absolutely clear that all of the attributes return per-band data. --- docs/reference/ImageStat.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/reference/ImageStat.rst b/docs/reference/ImageStat.rst index c8dfe3062..b8925bf8c 100644 --- a/docs/reference/ImageStat.rst +++ b/docs/reference/ImageStat.rst @@ -22,32 +22,32 @@ for a region of an image. .. py:attribute:: count - Total number of pixels. + Total number of pixels for each band in the image. .. py:attribute:: sum - Sum of all pixels. + Sum of all pixels for each band in the image. .. py:attribute:: sum2 - Squared sum of all pixels. + Squared sum of all pixels for each band in the image. - .. py:attribute:: pixel + .. py:attribute:: mean - Average pixel level. + Average (arithmetic mean) pixel level for each band in the image. .. py:attribute:: median - Median pixel level. + Median pixel level for each band in the image. .. py:attribute:: rms - RMS (root-mean-square). + RMS (root-mean-square) for each band in the image. .. py:attribute:: var - Variance. + Variance for each band in the image. .. py:attribute:: stddev - Standard deviation. + Standard deviation for each band in the image. From 45319bd028c99fdab9fb496340c65a46c8927aba Mon Sep 17 00:00:00 2001 From: hugovk Date: Tue, 15 Jul 2014 00:48:01 +0300 Subject: [PATCH 04/58] Fix import --- Tests/test_image.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/test_image.py b/Tests/test_image.py index 85b0bba0e..cd46c9713 100644 --- a/Tests/test_image.py +++ b/Tests/test_image.py @@ -113,7 +113,7 @@ class TestImage(PillowTestCase): def test_alpha_composite(self): # http://stackoverflow.com/questions/3374878 # Arrange - import ImageDraw + from PIL import ImageDraw expected_colors = sorted([ (1122, (128, 127, 0, 255)), From 8c74cde6f8643edb1daf91a9154dd848b5a55b38 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Mon, 14 Jul 2014 17:51:18 -0400 Subject: [PATCH 05/58] Update --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 3dcc553f4..95ccd414d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ +- Fix `ImageStat` docs + [akx] + - Added docs for ExifTags [Wintermute3] From 529ef12f1fb163992b4c787371aa25acd6b487a3 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:02:12 -0700 Subject: [PATCH 06/58] Doc targets + help for makefile --- Makefile | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 3dcfe8d13..98e0c647a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,16 @@ +.PHONY: pre clean install test inplace coverage test-dep help docs livedocs +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " clean remove build products" + @echo " install make and install" + @echo " test run tests on installed pillow" + @echo " inplace make inplace extension" + @echo " coverage run coverage test (in progress)" + @echo " docs make html docs" + @echo " docserver run an http server on the docs directory" + @echo " test-dep install coveraget and test dependencies" pre: virtualenv . @@ -18,12 +30,11 @@ clean: rm -r build || true find . -name __pycache__ | xargs rm -r || true - install: python setup.py install python selftest.py --installed -test: install +test: python test-installed.py inplace: clean @@ -42,3 +53,9 @@ coverage: test-dep: pip install coveralls nose nose-cov pep8 pyflakes + +docs: + $(MAKE) -C docs html + +docserver: + cd docs/_build/html && python -mSimpleHTTPServer 2> /dev/null& \ No newline at end of file From a0cfa466d96fff20feb204f623770bbd3a049083 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:11:00 -0700 Subject: [PATCH 07/58] Fixing warnings when building docs --- PIL/ImageCms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PIL/ImageCms.py b/PIL/ImageCms.py index fc176952e..c62bffee2 100644 --- a/PIL/ImageCms.py +++ b/PIL/ImageCms.py @@ -637,7 +637,7 @@ def getProfileName(profile): (pyCMS) Gets the internal product name for the given profile. - If profile isn't a valid CmsProfile object or filename to a profile, + If profile isn't a valid CmsProfile object or filename to a profile, a PyCMSError is raised If an error occurs while trying to obtain the name tag, a PyCMSError is raised. @@ -876,7 +876,7 @@ def isIntentSupported(profile, intent, direction): input/output/proof profile as you desire. Some profiles are created specifically for one "direction", can cannot - be used for others. Some profiles can only be used for certain + be used for others. Some profiles can only be used for certain rendering intents... so it's best to either verify this before trying to create a transform with them (using this function), or catch the potential PyCMSError that will occur if they don't support the modes From d80eef46ce8e07333d80e10a6f9730b22bdf5728 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:13:01 -0700 Subject: [PATCH 08/58] Fixing warnings when building docs --- docs/PIL.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/PIL.rst b/docs/PIL.rst index 3b4706511..07d45810e 100644 --- a/docs/PIL.rst +++ b/docs/PIL.rst @@ -61,6 +61,7 @@ can be found here. :show-inheritance: .. intentionally skipped documenting this because it's not documented anywhere + :mod:`ImageDraw2` Module ------------------------ @@ -70,6 +71,7 @@ can be found here. :show-inheritance: .. intentionally skipped documenting this because it's deprecated + :mod:`ImageFileIO` Module ------------------------- From a0d6cf01ce275d66fa26de7c8ea7743a18011219 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:24:54 -0700 Subject: [PATCH 09/58] Fixing doc warnings, reformatting docstring comments --- PIL/OleFileIO.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/PIL/OleFileIO.py b/PIL/OleFileIO.py index 8a3c77be4..e5ecc6e56 100644 --- a/PIL/OleFileIO.py +++ b/PIL/OleFileIO.py @@ -15,8 +15,11 @@ Improved version of the OleFileIO module from PIL library v1.1.6 See: http://www.pythonware.com/products/pil/index.htm The Python Imaging Library (PIL) is + Copyright (c) 1997-2005 by Secret Labs AB + Copyright (c) 1995-2005 by Fredrik Lundh + OleFileIO_PL changes are Copyright (c) 2005-2014 by Philippe Lagadec See source code and LICENSE.txt for information on usage and redistribution. @@ -1701,10 +1704,12 @@ class OleFileIO: Open a stream as a read-only file object (BytesIO). filename: path of stream in storage tree (except root entry), either: + - a string using Unix path syntax, for example: 'storage_1/storage_1.2/stream' - a list of storage filenames, path to the desired stream/storage. Example: ['storage_1', 'storage_1.2', 'stream'] + return: file object (read-only) raise IOError if filename not found, or if this is not a stream. """ @@ -1722,6 +1727,7 @@ class OleFileIO: filename: path of stream in storage tree. (see openstream for syntax) return: False if object does not exist, its entry type (>0) otherwise: + - STGTY_STREAM: a stream - STGTY_STORAGE: a storage - STGTY_ROOT: the root entry @@ -1812,7 +1818,7 @@ class OleFileIO: filename: path of stream in storage tree (see openstream for syntax) convert_time: bool, if True timestamps will be converted to Python datetime no_conversion: None or list of int, timestamps not to be converted - (for example total editing time is not a real timestamp) + (for example total editing time is not a real timestamp) return: a dictionary of values indexed by id (integer) """ # make sure no_conversion is a list, just to simplify code below: From 5e12c490343457e16109edacd87f3e39020e26c8 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:32:14 -0700 Subject: [PATCH 10/58] Fixing doc warning --- PIL/PSDraw.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PIL/PSDraw.py b/PIL/PSDraw.py index 88593bb9d..26fdb74ea 100644 --- a/PIL/PSDraw.py +++ b/PIL/PSDraw.py @@ -73,9 +73,8 @@ class PSDraw: def setink(self, ink): """ - .. warning:: + .. warning:: This has been in the PIL API for ages but was never implemented. - This has been in the PIL API for ages but was never implemented. """ print("*** NOT YET IMPLEMENTED ***") From 551cdedb45d890a42850a78d2a1d6bae98b5da7c Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:57:58 -0700 Subject: [PATCH 11/58] Pulled ImageCms into it's own docpage --- docs/PIL.rst | 8 -------- docs/reference/ImageCms.rst | 13 +++++++++++++ docs/reference/index.rst | 1 + 3 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 docs/reference/ImageCms.rst diff --git a/docs/PIL.rst b/docs/PIL.rst index 07d45810e..537b2fd8f 100644 --- a/docs/PIL.rst +++ b/docs/PIL.rst @@ -52,14 +52,6 @@ can be found here. :undoc-members: :show-inheritance: -:mod:`ImageCms` Module ----------------------- - -.. automodule:: PIL.ImageCms - :members: - :undoc-members: - :show-inheritance: - .. intentionally skipped documenting this because it's not documented anywhere :mod:`ImageDraw2` Module diff --git a/docs/reference/ImageCms.rst b/docs/reference/ImageCms.rst new file mode 100644 index 000000000..2d5bb1388 --- /dev/null +++ b/docs/reference/ImageCms.rst @@ -0,0 +1,13 @@ +.. py:module:: PIL.ImageCms +.. py:currentmodule:: PIL.ImageCms + +:py:mod:`ImageCms` Module +========================= + +The :py:mod:`ImageCms` module provides color profile management +support using the LittleCMS2 color management engine, based on Kevin +Cazabon's PyCMS library. + +.. automodule:: PIL.ImageCms + :members: + :noindex: diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 66310e3e7..fca2b387b 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -8,6 +8,7 @@ Reference Image ImageChops ImageColor + ImageCms ImageDraw ImageEnhance ImageFile From 6a928ff6e2bd66cfb14089f9755a272765a42f76 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 21:59:42 -0700 Subject: [PATCH 12/58] Removed leading docstring --- PIL/ImageCms.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/PIL/ImageCms.py b/PIL/ImageCms.py index c62bffee2..456bcbb96 100644 --- a/PIL/ImageCms.py +++ b/PIL/ImageCms.py @@ -1,19 +1,18 @@ -""" -The Python Imaging Library. -$Id$ +## The Python Imaging Library. +## $Id$ -Optional color managment support, based on Kevin Cazabon's PyCMS -library. +## Optional color managment support, based on Kevin Cazabon's PyCMS +## library. -History: -2009-03-08 fl Added to PIL. +## History: -Copyright (C) 2002-2003 Kevin Cazabon -Copyright (c) 2009 by Fredrik Lundh +## 2009-03-08 fl Added to PIL. -See the README file for information on usage and redistribution. See -below for the original description. -""" +## Copyright (C) 2002-2003 Kevin Cazabon +## Copyright (c) 2009 by Fredrik Lundh + +## See the README file for information on usage and redistribution. See +## below for the original description. from __future__ import print_function From 5eef39f3fb93635d4aaf55d593d0bb683d21366e Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 22:00:29 -0700 Subject: [PATCH 13/58] Asserting copyright over lcms2 port --- PIL/ImageCms.py | 1 + _imagingcms.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/PIL/ImageCms.py b/PIL/ImageCms.py index 456bcbb96..4ea6409d6 100644 --- a/PIL/ImageCms.py +++ b/PIL/ImageCms.py @@ -10,6 +10,7 @@ ## Copyright (C) 2002-2003 Kevin Cazabon ## Copyright (c) 2009 by Fredrik Lundh +## Copyright (c) 2013 by Eric Soroos ## See the README file for information on usage and redistribution. See ## below for the original description. diff --git a/_imagingcms.c b/_imagingcms.c index df26e1a2d..1b7ef49e1 100644 --- a/_imagingcms.c +++ b/_imagingcms.c @@ -6,6 +6,8 @@ * http://www.cazabon.com * Adapted/reworked for PIL by Fredrik Lundh * Copyright (c) 2009 Fredrik Lundh + * Updated to LCMS2 + * Copyright (c) 2013 Eric Soroos * * pyCMS home page: http://www.cazabon.com/pyCMS * littleCMS home page: http://www.littlecms.com From 4a5d73cb1e1dbc0e781d03d24e62f31d73f14291 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Mon, 14 Jul 2014 22:25:02 -0700 Subject: [PATCH 14/58] Fixing errors when compiling docs --- docs/reference/Image.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/reference/Image.rst b/docs/reference/Image.rst index bf64c835d..11666dd0b 100644 --- a/docs/reference/Image.rst +++ b/docs/reference/Image.rst @@ -49,7 +49,10 @@ Functions .. autofunction:: open - .. warning:: > To protect against potential DOS attacks caused by "`decompression bombs`_" (i.e. malicious files which decompress into a huge amount of data and are designed to crash or cause disruption by using up a lot of memory), Pillow will issue a `DecompressionBombWarning` if the image is over a certain limit. If desired, the warning can be turned into an error with `warnings.simplefilter('error', Image.DecompressionBombWarning)` or suppressed entirely with `warnings.simplefilter('ignore', Image.DecompressionBombWarning)`. See also `the logging documentation`_ to have warnings output to the logging facility instead of stderr. + .. warning:: To protect against potential DOS attacks caused by "`decompression bombs`_" (i.e. malicious files which decompress into a huge amount of data and are designed to crash or cause disruption by using up a lot of memory), Pillow will issue a `DecompressionBombWarning` if the image is over a certain limit. If desired, the warning can be turned into an error with `warnings.simplefilter('error', Image.DecompressionBombWarning)` or suppressed entirely with `warnings.simplefilter('ignore', Image.DecompressionBombWarning)`. See also `the logging documentation`_ to have warnings output to the logging facility instead of stderr. + + .. _decompression bombs: https://en.wikipedia.org/wiki/Zip_bomb + .. _the logging documentation: https://docs.python.org/2/library/logging.html?highlight=logging#integration-with-the-warnings-module Image processing ^^^^^^^^^^^^^^^^ From 11ac1e34cf1f5bdbe17951f102e25fc283723570 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Tue, 15 Jul 2014 04:18:39 -0400 Subject: [PATCH 15/58] Update [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 95ccd414d..6aaf8536c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ +- Doc cleanup + [wiredfool] + - Fix `ImageStat` docs [akx] From 6c9940e9d1f3051a93d896d8efe7911442c600fe Mon Sep 17 00:00:00 2001 From: hugovk Date: Tue, 15 Jul 2014 12:23:02 +0300 Subject: [PATCH 16/58] More tests for SpiderImagePlugin.py --- Tests/test_file_spider.py | 49 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/Tests/test_file_spider.py b/Tests/test_file_spider.py index 622bfd624..65e4d2782 100644 --- a/Tests/test_file_spider.py +++ b/Tests/test_file_spider.py @@ -3,13 +3,13 @@ from helper import unittest, PillowTestCase, lena from PIL import Image from PIL import SpiderImagePlugin -test_file = "Tests/images/lena.spider" +TEST_FILE = "Tests/images/lena.spider" class TestImageSpider(PillowTestCase): def test_sanity(self): - im = Image.open(test_file) + im = Image.open(TEST_FILE) im.load() self.assertEqual(im.mode, "F") self.assertEqual(im.size, (128, 128)) @@ -30,7 +30,50 @@ class TestImageSpider(PillowTestCase): self.assertEqual(im2.format, "SPIDER") def test_isSpiderImage(self): - self.assertTrue(SpiderImagePlugin.isSpiderImage(test_file)) + self.assertTrue(SpiderImagePlugin.isSpiderImage(TEST_FILE)) + + def test_tell(self): + # Arrange + im = Image.open(TEST_FILE) + + # Act + index = im.tell() + + # Assert + self.assertEqual(index, 0) + + def test_loadImageSeries(self): + # Arrange + not_spider_file = "Tests/images/lena.ppm" + file_list = [TEST_FILE, not_spider_file, "path/not_found.ext"] + + # Act + img_list = SpiderImagePlugin.loadImageSeries(file_list) + + # Assert + self.assertEqual(len(img_list), 1) + self.assertIsInstance(img_list[0], Image.Image) + self.assertEqual(img_list[0].size, (128, 128)) + + def test_loadImageSeries_no_input(self): + # Arrange + file_list = None + + # Act + img_list = SpiderImagePlugin.loadImageSeries(file_list) + + # Assert + self.assertEqual(img_list, None) + + def test_isInt_not_a_number(self): + # Arrange + not_a_number = "a" + + # Act + ret = SpiderImagePlugin.isInt(not_a_number) + + # Assert + self.assertEqual(ret, 0) if __name__ == '__main__': From 94ac5319606565f53f6a0fcadd3345cb918af6bd Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Tue, 15 Jul 2014 06:01:37 -0400 Subject: [PATCH 17/58] Update [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 6aaf8536c..21166f1b4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ +- More tests for SpiderImagePlugin.py + [hugovk] + - Doc cleanup [wiredfool] From 4fe5d520fbd7668df0c5998753be3ed158af32b0 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Tue, 15 Jul 2014 06:02:34 -0400 Subject: [PATCH 18/58] Bump Though I hate the 'dev' designation I want something to indicate master is where development for the next major version happens. I think we've previously disagreed on simply 'X.X.X' so I'm going with 'X.X.Xdev' to see if that is more palatable. :-) --- PIL/__init__.py | 2 +- _imaging.c | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PIL/__init__.py b/PIL/__init__.py index d446aa19b..8702d24cd 100644 --- a/PIL/__init__.py +++ b/PIL/__init__.py @@ -12,7 +12,7 @@ # ;-) VERSION = '1.1.7' # PIL version -PILLOW_VERSION = '2.5.0' # Pillow +PILLOW_VERSION = '2.6.0dev' # Pillow _plugins = ['BmpImagePlugin', 'BufrStubImagePlugin', diff --git a/_imaging.c b/_imaging.c index 92258032f..de2603cbc 100644 --- a/_imaging.c +++ b/_imaging.c @@ -71,7 +71,7 @@ * See the README file for information on usage and redistribution. */ -#define PILLOW_VERSION "2.5.0" +#define PILLOW_VERSION "2.6.0dev" #include "Python.h" diff --git a/setup.py b/setup.py index e94e34d28..5017b56e9 100644 --- a/setup.py +++ b/setup.py @@ -90,7 +90,7 @@ except (ImportError, OSError): NAME = 'Pillow' -PILLOW_VERSION = '2.5.0' +PILLOW_VERSION = '2.6.0dev' TCL_ROOT = None JPEG_ROOT = None JPEG2K_ROOT = None From 4b40839970b76e00921b0beef3a1403fde229a55 Mon Sep 17 00:00:00 2001 From: Alex Clark Date: Tue, 15 Jul 2014 06:15:31 -0400 Subject: [PATCH 19/58] Revert "Bump" This reverts commit 4fe5d520fbd7668df0c5998753be3ed158af32b0. Hah, foiled by PEP8 --- PIL/__init__.py | 2 +- _imaging.c | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PIL/__init__.py b/PIL/__init__.py index 8702d24cd..d446aa19b 100644 --- a/PIL/__init__.py +++ b/PIL/__init__.py @@ -12,7 +12,7 @@ # ;-) VERSION = '1.1.7' # PIL version -PILLOW_VERSION = '2.6.0dev' # Pillow +PILLOW_VERSION = '2.5.0' # Pillow _plugins = ['BmpImagePlugin', 'BufrStubImagePlugin', diff --git a/_imaging.c b/_imaging.c index de2603cbc..92258032f 100644 --- a/_imaging.c +++ b/_imaging.c @@ -71,7 +71,7 @@ * See the README file for information on usage and redistribution. */ -#define PILLOW_VERSION "2.6.0dev" +#define PILLOW_VERSION "2.5.0" #include "Python.h" diff --git a/setup.py b/setup.py index 5017b56e9..e94e34d28 100644 --- a/setup.py +++ b/setup.py @@ -90,7 +90,7 @@ except (ImportError, OSError): NAME = 'Pillow' -PILLOW_VERSION = '2.6.0dev' +PILLOW_VERSION = '2.5.0' TCL_ROOT = None JPEG_ROOT = None JPEG2K_ROOT = None From 17223001df8d849a92cd552ba9b3f4fa700c5a3d Mon Sep 17 00:00:00 2001 From: hugovk Date: Tue, 15 Jul 2014 18:38:10 +0300 Subject: [PATCH 20/58] flake8 --- PIL/ImagePalette.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/PIL/ImagePalette.py b/PIL/ImagePalette.py index 59886827a..ee3c22544 100644 --- a/PIL/ImagePalette.py +++ b/PIL/ImagePalette.py @@ -23,13 +23,13 @@ from PIL import Image, ImageColor class ImagePalette: "Color palette for palette mapped images" - def __init__(self, mode = "RGB", palette = None, size = 0): + def __init__(self, mode="RGB", palette=None, size=0): self.mode = mode - self.rawmode = None # if set, palette contains raw data + self.rawmode = None # if set, palette contains raw data self.palette = palette or list(range(256))*len(self.mode) self.colors = {} self.dirty = None - if ((size == 0 and len(self.mode)*256 != len(self.palette)) or + if ((size == 0 and len(self.mode)*256 != len(self.palette)) or (size != 0 and size != len(self.palette))): raise ValueError("wrong palette size") @@ -55,7 +55,7 @@ class ImagePalette: return self.palette arr = array.array("B", self.palette) if hasattr(arr, 'tobytes'): - #py3k has a tobytes, tostring is deprecated. + # py3k has a tobytes, tostring is deprecated. return arr.tobytes() return arr.tostring() @@ -109,6 +109,7 @@ class ImagePalette: fp.write("\n") fp.close() + # -------------------------------------------------------------------- # Internal @@ -119,6 +120,7 @@ def raw(rawmode, data): palette.dirty = 1 return palette + # -------------------------------------------------------------------- # Factories @@ -128,23 +130,27 @@ def _make_linear_lut(black, white): for i in range(256): lut.append(white*i//255) else: - raise NotImplementedError # FIXME + raise NotImplementedError # FIXME return lut + def _make_gamma_lut(exp, mode="RGB"): lut = [] for i in range(256): lut.append(int(((i / 255.0) ** exp) * 255.0 + 0.5)) return lut + def new(mode, data): return Image.core.new_palette(mode, data) + def negative(mode="RGB"): palette = list(range(256)) palette.reverse() return ImagePalette(mode, palette * len(mode)) + def random(mode="RGB"): from random import randint palette = [] @@ -152,6 +158,7 @@ def random(mode="RGB"): palette.append(randint(0, 255)) return ImagePalette(mode, palette) + def sepia(white="#fff0c0"): r, g, b = ImageColor.getrgb(white) r = _make_linear_lut(0, r) @@ -159,9 +166,11 @@ def sepia(white="#fff0c0"): b = _make_linear_lut(0, b) return ImagePalette("RGB", r + g + b) + def wedge(mode="RGB"): return ImagePalette(mode, list(range(256)) * len(mode)) + def load(filename): # FIXME: supports GIMP gradients only @@ -177,8 +186,8 @@ def load(filename): p = GimpPaletteFile.GimpPaletteFile(fp) lut = p.getpalette() except (SyntaxError, ValueError): - #import traceback - #traceback.print_exc() + # import traceback + # traceback.print_exc() pass if not lut: @@ -188,8 +197,8 @@ def load(filename): p = GimpGradientFile.GimpGradientFile(fp) lut = p.getpalette() except (SyntaxError, ValueError): - #import traceback - #traceback.print_exc() + # import traceback + # traceback.print_exc() pass if not lut: @@ -206,4 +215,4 @@ def load(filename): if not lut: raise IOError("cannot load palette") - return lut # data, rawmode + return lut # data, rawmode From 7dfec434fa9b89c0788e9704dad99652f71cfd31 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 15 Jul 2014 16:20:20 -0700 Subject: [PATCH 21/58] Pulled ImageMorph into its own page --- docs/PIL.rst | 7 ------- docs/reference/ImageMorph.rst | 13 +++++++++++++ docs/reference/index.rst | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 docs/reference/ImageMorph.rst diff --git a/docs/PIL.rst b/docs/PIL.rst index 537b2fd8f..5b429dc4b 100644 --- a/docs/PIL.rst +++ b/docs/PIL.rst @@ -72,13 +72,6 @@ can be found here. :undoc-members: :show-inheritance: -:mod:`ImageMorph` Module ------------------------- - -.. automodule:: PIL.ImageMorph - :members: - :undoc-members: - :show-inheritance: :mod:`ImageShow` Module ----------------------- diff --git a/docs/reference/ImageMorph.rst b/docs/reference/ImageMorph.rst new file mode 100644 index 000000000..eaf3b1c5e --- /dev/null +++ b/docs/reference/ImageMorph.rst @@ -0,0 +1,13 @@ +.. py:module:: PIL.ImageMorph +.. py:currentmodule:: PIL.ImageMorph + +:py:mod:`ImageMorph` Module +=========================== + +The :py:mod:`ImageMorph` module provides morphology operations on images. + +.. automodule:: PIL.ImageMorph + :members: + :undoc-members: + :show-inheritance: + :noindex: diff --git a/docs/reference/index.rst b/docs/reference/index.rst index fca2b387b..d6baf216e 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -16,6 +16,7 @@ Reference ImageFont ImageGrab ImageMath + ImageMorph ImageOps ImagePalette ImagePath From b6c33596b3bd4058877b4ca9eb7bdc46a20da5e6 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 15 Jul 2014 16:56:59 -0700 Subject: [PATCH 22/58] Broke out OleFileIO into its own page, Added docs from the readme --- PIL/OleFileIO.py | 34 ++-- docs/PIL.rst | 8 - docs/reference/OleFileIO.rst | 364 +++++++++++++++++++++++++++++++++++ docs/reference/index.rst | 1 + 4 files changed, 381 insertions(+), 26 deletions(-) create mode 100644 docs/reference/OleFileIO.rst diff --git a/PIL/OleFileIO.py b/PIL/OleFileIO.py index e5ecc6e56..57c9c349e 100644 --- a/PIL/OleFileIO.py +++ b/PIL/OleFileIO.py @@ -1,31 +1,29 @@ #!/usr/local/bin/python # -*- coding: latin-1 -*- -""" -OleFileIO_PL: -Module to read Microsoft OLE2 files (also called Structured Storage or -Microsoft Compound Document File Format), such as Microsoft Office -documents, Image Composer and FlashPix files, Outlook messages, ... -This version is compatible with Python 2.6+ and 3.x +## OleFileIO_PL: +## Module to read Microsoft OLE2 files (also called Structured Storage or +## Microsoft Compound Document File Format), such as Microsoft Office +## documents, Image Composer and FlashPix files, Outlook messages, ... +## This version is compatible with Python 2.6+ and 3.x -version 0.30 2014-02-04 Philippe Lagadec - http://www.decalage.info +## version 0.30 2014-02-04 Philippe Lagadec - http://www.decalage.info -Project website: http://www.decalage.info/python/olefileio +## Project website: http://www.decalage.info/python/olefileio -Improved version of the OleFileIO module from PIL library v1.1.6 -See: http://www.pythonware.com/products/pil/index.htm +## Improved version of the OleFileIO module from PIL library v1.1.6 +## See: http://www.pythonware.com/products/pil/index.htm -The Python Imaging Library (PIL) is +## The Python Imaging Library (PIL) is - Copyright (c) 1997-2005 by Secret Labs AB - - Copyright (c) 1995-2005 by Fredrik Lundh +## Copyright (c) 1997-2005 by Secret Labs AB +## Copyright (c) 1995-2005 by Fredrik Lundh -OleFileIO_PL changes are Copyright (c) 2005-2014 by Philippe Lagadec +## OleFileIO_PL changes are Copyright (c) 2005-2014 by Philippe Lagadec -See source code and LICENSE.txt for information on usage and redistribution. +## See source code and LICENSE.txt for information on usage and redistribution. + +## WARNING: THIS IS (STILL) WORK IN PROGRESS. -WARNING: THIS IS (STILL) WORK IN PROGRESS. -""" # Starting with OleFileIO_PL v0.30, only Python 2.6+ and 3.x is supported # This import enables print() as a function rather than a keyword diff --git a/docs/PIL.rst b/docs/PIL.rst index 5b429dc4b..8bf89c685 100644 --- a/docs/PIL.rst +++ b/docs/PIL.rst @@ -97,14 +97,6 @@ can be found here. :undoc-members: :show-inheritance: -:mod:`OleFileIO` Module ------------------------ - -.. automodule:: PIL.OleFileIO - :members: - :undoc-members: - :show-inheritance: - :mod:`PaletteFile` Module ------------------------- diff --git a/docs/reference/OleFileIO.rst b/docs/reference/OleFileIO.rst new file mode 100644 index 000000000..74c4b7b36 --- /dev/null +++ b/docs/reference/OleFileIO.rst @@ -0,0 +1,364 @@ +.. py:module:: PIL.OleFileIO +.. py:currentmodule:: PIL.OleFileIO + +:py:mod:`OleFileIO` Module +=========================== + +The :py:mod:`OleFileIO` module reads Microsoft OLE2 files (also called +Structured Storage or Microsoft Compound Document File Format), such +as Microsoft Office documents, Image Composer and FlashPix files, and +Outlook messages. + +This module is the `OleFileIO\_PL`_ project by Philippe Lagadec, v0.30, +merged back into Pillow. + +.. _OleFileIO\_PL: http://www.decalage.info/python/olefileio + +How to use this module +---------------------- + +For more information, see also the file **PIL/OleFileIO.py**, sample +code at the end of the module itself, and docstrings within the code. + +About the structure of OLE files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An OLE file can be seen as a mini file system or a Zip archive: It +contains **streams** of data that look like files embedded within the +OLE file. Each stream has a name. For example, the main stream of a MS +Word document containing its text is named "WordDocument". + +An OLE file can also contain **storages**. A storage is a folder that +contains streams or other storages. For example, a MS Word document with +VBA macros has a storage called "Macros". + +Special streams can contain **properties**. A property is a specific +value that can be used to store information such as the metadata of a +document (title, author, creation date, etc). Property stream names +usually start with the character '05'. + +For example, a typical MS Word document may look like this: + +:: + + \x05DocumentSummaryInformation (stream) + \x05SummaryInformation (stream) + WordDocument (stream) + Macros (storage) + PROJECT (stream) + PROJECTwm (stream) + VBA (storage) + Module1 (stream) + ThisDocument (stream) + _VBA_PROJECT (stream) + dir (stream) + ObjectPool (storage) + +Test if a file is an OLE container +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use isOleFile to check if the first bytes of the file contain the Magic +for OLE files, before opening it. isOleFile returns True if it is an OLE +file, False otherwise. + +.. code-block:: python + + assert OleFileIO.isOleFile('myfile.doc') + +Open an OLE file from disk +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Create an OleFileIO object with the file path as parameter: + +.. code-block:: python + + ole = OleFileIO.OleFileIO('myfile.doc') + +Open an OLE file from a file-like object +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is useful if the file is not on disk, e.g. already stored in a +string or as a file-like object. + +.. code-block:: python + + ole = OleFileIO.OleFileIO(f) + +For example the code below reads a file into a string, then uses BytesIO +to turn it into a file-like object. + +.. code-block:: python + + data = open('myfile.doc', 'rb').read() + f = io.BytesIO(data) # or StringIO.StringIO for Python 2.x + ole = OleFileIO.OleFileIO(f) + +How to handle malformed OLE files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, the parser is configured to be as robust and permissive as +possible, allowing to parse most malformed OLE files. Only fatal errors +will raise an exception. It is possible to tell the parser to be more +strict in order to raise exceptions for files that do not fully conform +to the OLE specifications, using the raise\_defect option: + +.. code-block:: python + + ole = OleFileIO.OleFileIO('myfile.doc', raise_defects=DEFECT_INCORRECT) + +When the parsing is done, the list of non-fatal issues detected is +available as a list in the parsing\_issues attribute of the OleFileIO +object: + +.. code-block:: python + + print('Non-fatal issues raised during parsing:') + if ole.parsing_issues: + for exctype, msg in ole.parsing_issues: + print('- %s: %s' % (exctype.__name__, msg)) + else: + print('None') + +Syntax for stream and storage path +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Two different syntaxes are allowed for methods that need or return the +path of streams and storages: + +1) Either a **list of strings** including all the storages from the root + up to the stream/storage name. For example a stream called + "WordDocument" at the root will have ['WordDocument'] as full path. A + stream called "ThisDocument" located in the storage "Macros/VBA" will + be ['Macros', 'VBA', 'ThisDocument']. This is the original syntax + from PIL. While hard to read and not very convenient, this syntax + works in all cases. + +2) Or a **single string with slashes** to separate storage and stream + names (similar to the Unix path syntax). The previous examples would + be 'WordDocument' and 'Macros/VBA/ThisDocument'. This syntax is + easier, but may fail if a stream or storage name contains a slash. + +Both are case-insensitive. + +Switching between the two is easy: + +.. code-block:: python + + slash_path = '/'.join(list_path) + list_path = slash_path.split('/') + +Get the list of streams +~~~~~~~~~~~~~~~~~~~~~~~ + +listdir() returns a list of all the streams contained in the OLE file, +including those stored in storages. Each stream is listed itself as a +list, as described above. + +.. code-block:: python + + print(ole.listdir()) + +Sample result: + +.. code-block:: python + + [['\x01CompObj'], ['\x05DocumentSummaryInformation'], ['\x05SummaryInformation'] + , ['1Table'], ['Macros', 'PROJECT'], ['Macros', 'PROJECTwm'], ['Macros', 'VBA', + 'Module1'], ['Macros', 'VBA', 'ThisDocument'], ['Macros', 'VBA', '_VBA_PROJECT'] + , ['Macros', 'VBA', 'dir'], ['ObjectPool'], ['WordDocument']] + +As an option it is possible to choose if storages should also be listed, +with or without streams: + +.. code-block:: python + + ole.listdir (streams=False, storages=True) + +Test if known streams/storages exist: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +exists(path) checks if a given stream or storage exists in the OLE file. + +.. code-block:: python + + if ole.exists('worddocument'): + print("This is a Word document.") + if ole.exists('macros/vba'): + print("This document seems to contain VBA macros.") + +Read data from a stream +~~~~~~~~~~~~~~~~~~~~~~~ + +openstream(path) opens a stream as a file-like object. + +The following example extracts the "Pictures" stream from a PPT file: + +.. code-block:: python + + pics = ole.openstream('Pictures') + data = pics.read() + + +Get information about a stream/storage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Several methods can provide the size, type and timestamps of a given +stream/storage: + +get\_size(path) returns the size of a stream in bytes: + +.. code-block:: python + + s = ole.get_size('WordDocument') + +get\_type(path) returns the type of a stream/storage, as one of the +following constants: STGTY\_STREAM for a stream, STGTY\_STORAGE for a +storage, STGTY\_ROOT for the root entry, and False for a non existing +path. + +.. code-block:: python + + t = ole.get_type('WordDocument') + +get\_ctime(path) and get\_mtime(path) return the creation and +modification timestamps of a stream/storage, as a Python datetime object +with UTC timezone. Please note that these timestamps are only present if +the application that created the OLE file explicitly stored them, which +is rarely the case. When not present, these methods return None. + +.. code-block:: python + + c = ole.get_ctime('WordDocument') + m = ole.get_mtime('WordDocument') + +The root storage is a special case: You can get its creation and +modification timestamps using the OleFileIO.root attribute: + +.. code-block:: python + + c = ole.root.getctime() + m = ole.root.getmtime() + +Extract metadata +~~~~~~~~~~~~~~~~ + +get\_metadata() will check if standard property streams exist, parse all +the properties they contain, and return an OleMetadata object with the +found properties as attributes. + +.. code-block:: python + + meta = ole.get_metadata() + print('Author:', meta.author) + print('Title:', meta.title) + print('Creation date:', meta.create_time) + # print all metadata: + meta.dump() + +Available attributes include: + +:: + + codepage, title, subject, author, keywords, comments, template, + last_saved_by, revision_number, total_edit_time, last_printed, create_time, + last_saved_time, num_pages, num_words, num_chars, thumbnail, + creating_application, security, codepage_doc, category, presentation_target, + bytes, lines, paragraphs, slides, notes, hidden_slides, mm_clips, + scale_crop, heading_pairs, titles_of_parts, manager, company, links_dirty, + chars_with_spaces, unused, shared_doc, link_base, hlinks, hlinks_changed, + version, dig_sig, content_type, content_status, language, doc_version + +See the source code of the OleMetadata class for more information. + +Parse a property stream +~~~~~~~~~~~~~~~~~~~~~~~ + +get\_properties(path) can be used to parse any property stream that is +not handled by get\_metadata. It returns a dictionary indexed by +integers. Each integer is the index of the property, pointing to its +value. For example in the standard property stream +'05SummaryInformation', the document title is property #2, and the +subject is #3. + +.. code-block:: python + + p = ole.getproperties('specialprops') + +By default as in the original PIL version, timestamp properties are +converted into a number of seconds since Jan 1,1601. With the option +convert\_time, you can obtain more convenient Python datetime objects +(UTC timezone). If some time properties should not be converted (such as +total editing time in '05SummaryInformation'), the list of indexes can +be passed as no\_conversion: + +.. code-block:: python + + p = ole.getproperties('specialprops', convert_time=True, no_conversion=[10]) + +Close the OLE file +~~~~~~~~~~~~~~~~~~ + +Unless your application is a simple script that terminates after +processing an OLE file, do not forget to close each OleFileIO object +after parsing to close the file on disk. + +.. code-block:: python + + ole.close() + +Use OleFileIO as a script +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +OleFileIO can also be used as a script from the command-line to +display the structure of an OLE file and its metadata, for example: + +:: + + PIL/OleFileIO.py myfile.doc + +You can use the option -c to check that all streams can be read fully, +and -d to generate very verbose debugging information. + +How to contribute +----------------- + +The code is available in `a Mercurial repository on +bitbucket `_. You may use +it to submit enhancements or to report any issue. + +If you would like to help us improve this module, or simply provide +feedback, please `contact me `_. You can +help in many ways: + +- test this module on different platforms / Python versions +- find and report bugs +- improve documentation, code samples, docstrings +- write unittest test cases +- provide tricky malformed files + +How to report bugs +------------------ + +To report a bug, for example a normal file which is not parsed +correctly, please use the `issue reporting +page `_, +or if you prefer to do it privately, use this `contact +form `_. Please provide all the +information about the context and how to reproduce the bug. + +If possible please join the debugging output of OleFileIO. For this, +launch the following command : + +:: + + PIL/OleFileIO.py -d -c file >debug.txt + + +Classes and Methods +------------------- + +.. automodule:: PIL.OleFileIO + :members: + :undoc-members: + :show-inheritance: + :noindex: diff --git a/docs/reference/index.rst b/docs/reference/index.rst index d6baf216e..2f10b861d 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -26,5 +26,6 @@ Reference ImageTk ImageWin ExifTags + OleFileIO PSDraw ../PIL From 09b0d1cfa6ce30fea5ce8adbfea009085e955c7e Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 15 Jul 2014 21:24:52 -0700 Subject: [PATCH 23/58] converted to current docutils format --- PIL/OleFileIO.py | 159 +++++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/PIL/OleFileIO.py b/PIL/OleFileIO.py index 57c9c349e..e35bfa679 100644 --- a/PIL/OleFileIO.py +++ b/PIL/OleFileIO.py @@ -371,8 +371,9 @@ for key in list(vars().keys()): def isOleFile (filename): """ Test if file is an OLE container (according to its header). - filename: file name or path (str, unicode) - return: True if OLE, False otherwise. + + :param filename: file name or path (str, unicode) + :returns: True if OLE, False otherwise. """ f = open(filename, 'rb') header = f.read(len(MAGIC)) @@ -398,8 +399,8 @@ def i16(c, o = 0): """ Converts a 2-bytes (16 bits) string to an integer. - c: string containing bytes to convert - o: offset of bytes to convert in string + :param c: string containing bytes to convert + :param o: offset of bytes to convert in string """ return i8(c[o]) | (i8(c[o+1])<<8) @@ -408,8 +409,8 @@ def i32(c, o = 0): """ Converts a 4-bytes (32 bits) string to an integer. - c: string containing bytes to convert - o: offset of bytes to convert in string + :param c: string containing bytes to convert + :param o: offset of bytes to convert in string """ ## return int(ord(c[o])+(ord(c[o+1])<<8)+(ord(c[o+2])<<16)+(ord(c[o+3])<<24)) ## # [PL]: added int() because "<<" gives long int since Python 2.4 @@ -420,7 +421,8 @@ def i32(c, o = 0): def _clsid(clsid): """ Converts a CLSID to a human-readable string. - clsid: string of length 16. + + :param clsid: string of length 16. """ assert len(clsid) == 16 # if clsid is only made of null bytes, return an empty string: @@ -440,8 +442,8 @@ def _unicode(s, errors='replace'): """ Map unicode string to Latin 1. (Python with Unicode support) - s: UTF-16LE unicode string to convert to Latin-1 - errors: 'replace', 'ignore' or 'strict'. + :param s: UTF-16LE unicode string to convert to Latin-1 + :param errors: 'replace', 'ignore' or 'strict'. """ #TODO: test if it OleFileIO works with Unicode strings, instead of # converting to Latin-1. @@ -651,14 +653,14 @@ class _OleStream(io.BytesIO): """ Constructor for _OleStream class. - fp : file object, the OLE container or the MiniFAT stream - sect : sector index of first sector in the stream - size : total size of the stream - offset : offset in bytes for the first FAT or MiniFAT sector - sectorsize: size of one sector - fat : array/list of sector indexes (FAT or MiniFAT) - filesize : size of OLE file (for debugging) - return : a BytesIO instance containing the OLE stream + :param fp : file object, the OLE container or the MiniFAT stream + :param sect : sector index of first sector in the stream + :param size : total size of the stream + :param offset : offset in bytes for the first FAT or MiniFAT sector + :param sectorsize: size of one sector + :param fat : array/list of sector indexes (FAT or MiniFAT) + :param filesize : size of OLE file (for debugging) + :returns : a BytesIO instance containing the OLE stream """ debug('_OleStream.__init__:') debug(' sect=%d (%X), size=%d, offset=%d, sectorsize=%d, len(fat)=%d, fp=%s' @@ -794,9 +796,9 @@ class _OleDirectoryEntry: Constructor for an _OleDirectoryEntry object. Parses a 128-bytes entry from the OLE Directory stream. - entry : string (must be 128 bytes long) - sid : index of this directory entry in the OLE file directory - olefile: OleFileIO containing this directory entry + :param entry : string (must be 128 bytes long) + :param sid : index of this directory entry in the OLE file directory + :param olefile: OleFileIO containing this directory entry """ self.sid = sid # ref to olefile is stored for future use @@ -990,7 +992,7 @@ class _OleDirectoryEntry: """ Return modification time of a directory entry. - return: None if modification time is null, a python datetime object + :returns: None if modification time is null, a python datetime object otherwise (UTC timezone) new in version 0.26 @@ -1004,7 +1006,7 @@ class _OleDirectoryEntry: """ Return creation time of a directory entry. - return: None if modification time is null, a python datetime object + :returns: None if modification time is null, a python datetime object otherwise (UTC timezone) new in version 0.26 @@ -1021,7 +1023,8 @@ class OleFileIO: OLE container object This class encapsulates the interface to an OLE 2 structured - storage file. Use the {@link listdir} and {@link openstream} methods to + storage file. Use the :py:meth:`~PIL.OleFileIO.OleFileIO.listdir` and + :py:meth:`~PIL.OleFileIO.OleFileIO.openstream` methods to access the contents of this file. Object names are given as a list of strings, one for each subentry @@ -1049,8 +1052,8 @@ class OleFileIO: """ Constructor for OleFileIO class. - filename: file to open. - raise_defects: minimal level for defects to be raised as exceptions. + :param filename: file to open. + :param raise_defects: minimal level for defects to be raised as exceptions. (use DEFECT_FATAL for a typical application, DEFECT_INCORRECT for a security-oriented application, see source code for details) """ @@ -1069,13 +1072,13 @@ class OleFileIO: It may raise an IOError exception according to the minimal level chosen for the OleFileIO object. - defect_level: defect level, possible values are: + :param defect_level: defect level, possible values are: DEFECT_UNSURE : a case which looks weird, but not sure it's a defect DEFECT_POTENTIAL : a potential defect DEFECT_INCORRECT : an error according to specifications, but parsing can go on DEFECT_FATAL : an error which cannot be ignored, parsing is impossible - message: string describing the defect, used with raised exception. - exception_type: exception class to be raised, IOError by default + :param message: string describing the defect, used with raised exception. + :param exception_type: exception class to be raised, IOError by default """ # added by [PL] if defect_level >= self._raise_defects_level: @@ -1090,7 +1093,7 @@ class OleFileIO: Open an OLE2 file. Reads the header, FAT and directory. - filename: string-like or file-like object + :param filename: string-like or file-like object """ #[PL] check if filename is a string-like or file-like object: # (it is better to check for a read() method) @@ -1277,8 +1280,8 @@ class OleFileIO: Checks if a stream has not been already referenced elsewhere. This method should only be called once for each known stream, and only if stream size is not null. - first_sect: index of first sector of the stream in FAT - minifat: if True, stream is located in the MiniFAT, else in the FAT + :param first_sect: index of first sector of the stream in FAT + :param minifat: if True, stream is located in the MiniFAT, else in the FAT """ if minifat: debug('_check_duplicate_stream: sect=%d in MiniFAT' % first_sect) @@ -1372,8 +1375,9 @@ class OleFileIO: def loadfat_sect(self, sect): """ Adds the indexes of the given sector to the FAT - sect: string containing the first FAT sector, or array of long integers - return: index of last FAT sector. + + :param sect: string containing the first FAT sector, or array of long integers + :returns: index of last FAT sector. """ # a FAT sector is an array of ulong integers. if isinstance(sect, array.array): @@ -1506,8 +1510,9 @@ class OleFileIO: def getsect(self, sect): """ Read given sector from file on disk. - sect: sector index - returns a string containing the sector data. + + :param sect: sector index + :returns: a string containing the sector data. """ # [PL] this original code was wrong when sectors are 4KB instead of # 512 bytes: @@ -1531,7 +1536,8 @@ class OleFileIO: def loaddirectory(self, sect): """ Load the directory. - sect: sector index of directory stream. + + :param sect: sector index of directory stream. """ # The directory is stored in a standard # substream, independent of its size. @@ -1568,9 +1574,10 @@ class OleFileIO: Load a directory entry from the directory. This method should only be called once for each storage/stream when loading the directory. - sid: index of storage/stream in the directory. - return: a _OleDirectoryEntry object - raise: IOError if the entry has always been referenced. + + :param sid: index of storage/stream in the directory. + :returns: a _OleDirectoryEntry object + :exception IOError: if the entry has always been referenced. """ # check if SID is OK: if sid<0 or sid>=len(self.direntries): @@ -1599,9 +1606,9 @@ class OleFileIO: Open a stream, either in FAT or MiniFAT according to its size. (openstream helper) - start: index of first sector - size: size of stream (or nothing if size is unknown) - force_FAT: if False (default), stream will be opened in FAT or MiniFAT + :param start: index of first sector + :param size: size of stream (or nothing if size is unknown) + :param force_FAT: if False (default), stream will be opened in FAT or MiniFAT according to size. If True, it will always be opened in FAT. """ debug('OleFileIO.open(): sect=%d, size=%d, force_FAT=%s' % @@ -1631,11 +1638,11 @@ class OleFileIO: def _list(self, files, prefix, node, streams=True, storages=False): """ (listdir helper) - files: list of files to fill in - prefix: current location in storage tree (list of names) - node: current node (_OleDirectoryEntry object) - streams: bool, include streams if True (True by default) - new in v0.26 - storages: bool, include storages if True (False by default) - new in v0.26 + :param files: list of files to fill in + :param prefix: current location in storage tree (list of names) + :param node: current node (_OleDirectoryEntry object) + :param streams: bool, include streams if True (True by default) - new in v0.26 + :param storages: bool, include storages if True (False by default) - new in v0.26 (note: the root storage is never included) """ prefix = prefix + [node.name] @@ -1658,9 +1665,9 @@ class OleFileIO: """ Return a list of streams stored in this file - streams: bool, include streams if True (True by default) - new in v0.26 - storages: bool, include storages if True (False by default) - new in v0.26 - (note: the root storage is never included) + :param streams: bool, include streams if True (True by default) - new in v0.26 + :param storages: bool, include storages if True (False by default) - new in v0.26 + (note: the root storage is never included) """ files = [] self._list(files, [], self.root, streams, storages) @@ -1672,12 +1679,13 @@ class OleFileIO: Returns directory entry of given filename. (openstream helper) Note: this method is case-insensitive. - filename: path of stream in storage tree (except root entry), either: + :param filename: path of stream in storage tree (except root entry), either: + - a string using Unix path syntax, for example: 'storage_1/storage_1.2/stream' - a list of storage filenames, path to the desired stream/storage. Example: ['storage_1', 'storage_1.2', 'stream'] - return: sid of requested filename + :returns: sid of requested filename raise IOError if file not found """ @@ -1701,15 +1709,15 @@ class OleFileIO: """ Open a stream as a read-only file object (BytesIO). - filename: path of stream in storage tree (except root entry), either: + :param filename: path of stream in storage tree (except root entry), either: - a string using Unix path syntax, for example: 'storage_1/storage_1.2/stream' - a list of storage filenames, path to the desired stream/storage. Example: ['storage_1', 'storage_1.2', 'stream'] - return: file object (read-only) - raise IOError if filename not found, or if this is not a stream. + :returns: file object (read-only) + :exception IOError: if filename not found, or if this is not a stream. """ sid = self._find(filename) entry = self.direntries[sid] @@ -1723,8 +1731,8 @@ class OleFileIO: Test if given filename exists as a stream or a storage in the OLE container, and return its type. - filename: path of stream in storage tree. (see openstream for syntax) - return: False if object does not exist, its entry type (>0) otherwise: + :param filename: path of stream in storage tree. (see openstream for syntax) + :returns: False if object does not exist, its entry type (>0) otherwise: - STGTY_STREAM: a stream - STGTY_STORAGE: a storage @@ -1742,10 +1750,10 @@ class OleFileIO: """ Return modification time of a stream/storage. - filename: path of stream/storage in storage tree. (see openstream for - syntax) - return: None if modification time is null, a python datetime object - otherwise (UTC timezone) + :param filename: path of stream/storage in storage tree. (see openstream for + syntax) + :returns: None if modification time is null, a python datetime object + otherwise (UTC timezone) new in version 0.26 """ @@ -1758,10 +1766,10 @@ class OleFileIO: """ Return creation time of a stream/storage. - filename: path of stream/storage in storage tree. (see openstream for - syntax) - return: None if creation time is null, a python datetime object - otherwise (UTC timezone) + :param filename: path of stream/storage in storage tree. (see openstream for + syntax) + :returns: None if creation time is null, a python datetime object + otherwise (UTC timezone) new in version 0.26 """ @@ -1775,8 +1783,8 @@ class OleFileIO: Test if given filename exists as a stream or a storage in the OLE container. - filename: path of stream in storage tree. (see openstream for syntax) - return: True if object exist, else False. + :param filename: path of stream in storage tree. (see openstream for syntax) + :returns: True if object exist, else False. """ try: sid = self._find(filename) @@ -1789,9 +1797,10 @@ class OleFileIO: """ Return size of a stream in the OLE container, in bytes. - filename: path of stream in storage tree (see openstream for syntax) - return: size in bytes (long integer) - raise: IOError if file not found, TypeError if this is not a stream. + :param filename: path of stream in storage tree (see openstream for syntax) + :returns: size in bytes (long integer) + :exception IOError: if file not found + :exception TypeError: if this is not a stream """ sid = self._find(filename) entry = self.direntries[sid] @@ -1813,11 +1822,11 @@ class OleFileIO: """ Return properties described in substream. - filename: path of stream in storage tree (see openstream for syntax) - convert_time: bool, if True timestamps will be converted to Python datetime - no_conversion: None or list of int, timestamps not to be converted - (for example total editing time is not a real timestamp) - return: a dictionary of values indexed by id (integer) + :param filename: path of stream in storage tree (see openstream for syntax) + :param convert_time: bool, if True timestamps will be converted to Python datetime + :param no_conversion: None or list of int, timestamps not to be converted + (for example total editing time is not a real timestamp) + :returns: a dictionary of values indexed by id (integer) """ # make sure no_conversion is a list, just to simplify code below: if no_conversion == None: From 5db868e0602385319c75375bd9756e4fd71ab0fc Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 14:20:15 +0300 Subject: [PATCH 24/58] Created with ImageMagick: convert lena.ppm lena.ras --- Tests/images/lena.ras | Bin 0 -> 49184 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/lena.ras diff --git a/Tests/images/lena.ras b/Tests/images/lena.ras new file mode 100644 index 0000000000000000000000000000000000000000..b5893e758a88b7fa8f358cb2ee1a4d4fc28c57bc GIT binary patch literal 49184 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 z Date: Wed, 16 Jul 2014 14:24:23 +0300 Subject: [PATCH 25/58] Sanity test for SunImagePlugin.py --- Tests/test_file_sun.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Tests/test_file_sun.py diff --git a/Tests/test_file_sun.py b/Tests/test_file_sun.py new file mode 100644 index 000000000..c52564f91 --- /dev/null +++ b/Tests/test_file_sun.py @@ -0,0 +1,23 @@ +from helper import unittest, PillowTestCase + +from PIL import Image + + +class TestFileSun(PillowTestCase): + + def test_sanity(self): + # Arrange + # Created with ImageMagick: convert lena.ppm lena.ras + test_file = "Tests/images/lena.ras" + + # Act + im = Image.open(test_file) + + # Assert + self.assertEqual(im.size, (128, 128)) + + +if __name__ == '__main__': + unittest.main() + +# End of file From 43dab9113e0088921cddec263d6621089a7c5114 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 14:26:30 +0300 Subject: [PATCH 26/58] flake8 --- PIL/SunImagePlugin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PIL/SunImagePlugin.py b/PIL/SunImagePlugin.py index 0db02ad25..e0a7aa6ee 100644 --- a/PIL/SunImagePlugin.py +++ b/PIL/SunImagePlugin.py @@ -29,6 +29,7 @@ i32 = _binary.i32be def _accept(prefix): return i32(prefix) == 0x59a66a95 + ## # Image plugin for Sun raster files. @@ -70,9 +71,9 @@ class SunImageFile(ImageFile.ImageFile): stride = (((self.size[0] * depth + 7) // 8) + 3) & (~3) if compression == 1: - self.tile = [("raw", (0,0)+self.size, offset, (rawmode, stride))] + self.tile = [("raw", (0, 0)+self.size, offset, (rawmode, stride))] elif compression == 2: - self.tile = [("sun_rle", (0,0)+self.size, offset, rawmode)] + self.tile = [("sun_rle", (0, 0)+self.size, offset, rawmode)] # # registry From cc27e8d532e2ef603fa283d68ec1b56896d7d858 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 21:26:47 +0300 Subject: [PATCH 27/58] Created with ImageMagick then renamed: convert lena.ppm lena.sgi --- Tests/images/lena.rgb | Bin 0 -> 54179 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/lena.rgb diff --git a/Tests/images/lena.rgb b/Tests/images/lena.rgb new file mode 100644 index 0000000000000000000000000000000000000000..82552c7586247c2bceaff3562e247bd097c8fe9d GIT binary patch literal 54179 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 H((eBO+M#Kh literal 0 HcmV?d00001 From e29c2d49c0f94afaf801b3e96ed80c6113f5fe9d Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 21:27:06 +0300 Subject: [PATCH 28/58] Created with ImageMagick then renamed: convert lena.ppm -monochrome lena.sgi --- Tests/images/lena.bw | Bin 0 -> 8507 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/lena.bw diff --git a/Tests/images/lena.bw b/Tests/images/lena.bw new file mode 100644 index 0000000000000000000000000000000000000000..e2981ef5c3174ad1f8dccec0ec30944cdec596ab GIT binary patch literal 8507 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 Date: Wed, 16 Jul 2014 21:27:31 +0300 Subject: [PATCH 29/58] Created with ImageMagick: convert transparent.png transparent.sgi --- Tests/images/transparent.sgi | Bin 0 -> 43896 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/transparent.sgi diff --git a/Tests/images/transparent.sgi b/Tests/images/transparent.sgi new file mode 100644 index 0000000000000000000000000000000000000000..482572df5561858412faa3e2980ad57548206cf7 GIT binary patch literal 43896 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 literal 0 HcmV?d00001 From 2b3d655833140972659d8077fdf91f4033a2a239 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 21:28:17 +0300 Subject: [PATCH 30/58] Sanity tests for SgiImagePlugin.py --- Tests/test_file_sgi.py | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Tests/test_file_sgi.py diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py new file mode 100644 index 000000000..395b3b10d --- /dev/null +++ b/Tests/test_file_sgi.py @@ -0,0 +1,52 @@ +from helper import unittest, PillowTestCase + +from PIL import Image + + +class TestFileSgi(PillowTestCase): + + def sanity(self, filename, expected_mode, expected_size=(128, 128)): + # Act + im = Image.open(filename) + + # Assert + self.assertEqual(im.mode, expected_mode) + self.assertEqual(im.size, expected_size) + print filename, im.mode + + def test_rgb(self): + # Arrange + # Created with ImageMagick then renamed: + # convert lena.ppm lena.sgi + test_file = "Tests/images/lena.rgb" + expected_mode = "RGB" + + # Act / Assert + self.sanity(test_file, expected_mode) + + def test_l(self): + # Arrange + # Created with ImageMagick then renamed: + # convert lena.ppm -monochrome lena.sgi + test_file = "Tests/images/lena.bw" + expected_mode = "L" + + # Act / Assert + self.sanity(test_file, expected_mode) + + def test_rgba(self): + # Arrange + # Created with ImageMagick: + # convert transparent.png transparent.sgi + test_file = "Tests/images/transparent.sgi" + expected_mode = "RGBA" + expected_size = (200, 150) + + # Act / Assert + self.sanity(test_file, expected_mode, expected_size) + + +if __name__ == '__main__': + unittest.main() + +# End of file From 3322bfbad0ed8eb137cbe5635c263f700fff2146 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 21:30:41 +0300 Subject: [PATCH 31/58] flake8 --- PIL/SgiImagePlugin.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/PIL/SgiImagePlugin.py b/PIL/SgiImagePlugin.py index b60df473c..bf3c18a43 100644 --- a/PIL/SgiImagePlugin.py +++ b/PIL/SgiImagePlugin.py @@ -31,6 +31,7 @@ i32 = _binary.i32be def _accept(prefix): return i16(prefix) == 474 + ## # Image plugin for SGI images. @@ -65,17 +66,18 @@ class SgiImageFile(ImageFile.ImageFile): # size self.size = i16(s[6:]), i16(s[8:]) - # decoder info if compression == 0: offset = 512 pagesize = self.size[0]*self.size[1]*layout[0] self.tile = [] for layer in self.mode: - self.tile.append(("raw", (0,0)+self.size, offset, (layer,0,-1))) + self.tile.append( + ("raw", (0, 0)+self.size, offset, (layer, 0, -1))) offset = offset + pagesize elif compression == 1: - self.tile = [("sgi_rle", (0,0)+self.size, 512, (self.mode, 0, -1))] + self.tile = [ + ("sgi_rle", (0, 0)+self.size, 512, (self.mode, 0, -1))] # # registry @@ -86,4 +88,4 @@ Image.register_extension("SGI", ".bw") Image.register_extension("SGI", ".rgb") Image.register_extension("SGI", ".rgba") -Image.register_extension("SGI", ".sgi") # really? +Image.register_extension("SGI", ".sgi") From bc34bda2b8d89db7d13d11ec47ac63919e34775e Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 21:35:43 +0300 Subject: [PATCH 32/58] Remove stray print --- Tests/test_file_sgi.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py index 395b3b10d..e94f0d989 100644 --- a/Tests/test_file_sgi.py +++ b/Tests/test_file_sgi.py @@ -12,7 +12,6 @@ class TestFileSgi(PillowTestCase): # Assert self.assertEqual(im.mode, expected_mode) self.assertEqual(im.size, expected_size) - print filename, im.mode def test_rgb(self): # Arrange From 1ff695873f1dc9cf880007df2b9b0f17c63a1281 Mon Sep 17 00:00:00 2001 From: hugovk Date: Wed, 16 Jul 2014 23:44:35 +0300 Subject: [PATCH 33/58] Cursor image by Miss Mycroft, 'Released under the Release to Public Domain license' http://www.rw-designer.com/cursor-detail/61757 --- Tests/images/deerstalker.cur | Bin 0 -> 4286 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/deerstalker.cur diff --git a/Tests/images/deerstalker.cur b/Tests/images/deerstalker.cur new file mode 100644 index 0000000000000000000000000000000000000000..16e4bfa52e6c870feba0582df6812b668edf2ed3 GIT binary patch literal 4286 zcmeHJSxj727`{joTKj-jOVvby)>>-X#1|Wv)Im*4fxs{@Fw8K+Y|K9FGQ%<~Qn00z zrB-NC2BF3l($*IrTyPMONEm#u1vOf&vS^!-v=o$WxcC14=fD`+R46#{iJN?L)_eZ% zeE)KXVIE@qn2->LKJAY%Oc3_M5Fv0QJ25fw zhOarG#(@{w&yQFv1~8h^5Lz%<^q|vgz+}>cTAfO{BqWHyX3M)hG&H32B?r%fC#s;x z206JIkezFVtZXZ!XP6LXw5GG(570W1f^1rK1f2pBtw!!4AIe%5E*%dtExIa^;K`r2OiJ-3;%@& z&vPLytxoP}MJbe(JHVEo4QABeduOdy4KkU8`ar2tKw@G%gonQd3F3H&h&T+zCB^ey zU0qcepF7se!`1n@n`lsZtPJvOS&R0yDr#4yR#5Hbav5#KViDRsgt{nD6B*?ZD~yG@ z`r2P_-2B6W@f3>iTML(w(cgsir%tjJm8DSRuv7bby%vZM$o=JVDM%zFCsHT}p)dwi zDvV2v2@P4t`M9`PP+`0@InT1=Rs1G&FiqX4tn00u)E1<^r; zd1y4~(2fjsms0)pxSo}rLHCl_XlOh=P3ouj%(b@ouArvw1m@VHU2->_PK(f>-U`Zr z+@EMe^3rNGK}Mz(ELJ1U)k~Kz_F)ZQlkb;v#9Y|ce(}P%HQh*kPxLpN7yE>V0q>8s z5dC8Y6Y4|m{#ITN-6KBMF8QCtKhZb^eVmbLfjoOI zjT6Fy=uuc?pPQV#b6_Q#PcqCkToD1ur?D*&b@(!?QPOrw{$De+%pRBFo@@zSvH)tU~A&%BPQM?d@aWP;o z$e}Sp=E?Z|mgb-F`;FII^#ODcJk2m3+zA9rn%wmw-eYrbZ;y-QVrG^Fq_QM9bofnL zcf!J+gM$ZOftOxBfVD?Ne9yW%UBg$deEad}*vNL6|@!sBDBcsEK&Sq!dnKKPHk5-gVz1MJhw)I>~&*0Eim3PlN+ke&k-t$mXKLBnM z4;;}ITXx-b#e4Qrtc82W|91-y_}mEq;28jxDTO&kfCxnRBN&`xf|nrRv6f&G5#XN( crc{6k?q Date: Wed, 16 Jul 2014 23:45:18 +0300 Subject: [PATCH 34/58] Sanity test for CurImagePlugin.py --- Tests/test_file_cur.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Tests/test_file_cur.py diff --git a/Tests/test_file_cur.py b/Tests/test_file_cur.py new file mode 100644 index 000000000..5dc096968 --- /dev/null +++ b/Tests/test_file_cur.py @@ -0,0 +1,23 @@ +from helper import unittest, PillowTestCase + +from PIL import Image, CurImagePlugin + + +class TestFileCur(PillowTestCase): + + def test_sanity(self): + # Arrange + test_file = "Tests/images/deerstalker.cur" + + # Act + im = Image.open(test_file) + + # Assert + self.assertEqual(im.size, (32, 32)) + self.assertIsInstance(im, CurImagePlugin.CurImageFile) + + +if __name__ == '__main__': + unittest.main() + +# End of file From 9acbaa4aeecd7a6fed957a7e20c27cda5bd88caf Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 00:12:54 +0300 Subject: [PATCH 35/58] Flake8 and fix typo --- PIL/CurImagePlugin.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/PIL/CurImagePlugin.py b/PIL/CurImagePlugin.py index 4cf2882e2..0178957ee 100644 --- a/PIL/CurImagePlugin.py +++ b/PIL/CurImagePlugin.py @@ -33,6 +33,7 @@ i32 = _binary.i32le def _accept(prefix): return prefix[:4] == b"\0\0\2\0" + ## # Image plugin for Windows Cursor files. @@ -48,7 +49,7 @@ class CurImageFile(BmpImagePlugin.BmpImageFile): # check magic s = self.fp.read(6) if not _accept(s): - raise SyntaxError("not an CUR file") + raise SyntaxError("not a CUR file") # pick the largest cursor in the file m = b"" @@ -58,14 +59,14 @@ class CurImageFile(BmpImagePlugin.BmpImageFile): m = s elif i8(s[0]) > i8(m[0]) and i8(s[1]) > i8(m[1]): m = s - #print "width", i8(s[0]) - #print "height", i8(s[1]) - #print "colors", i8(s[2]) - #print "reserved", i8(s[3]) - #print "hotspot x", i16(s[4:]) - #print "hotspot y", i16(s[6:]) - #print "bytes", i32(s[8:]) - #print "offset", i32(s[12:]) + # print "width", i8(s[0]) + # print "height", i8(s[1]) + # print "colors", i8(s[2]) + # print "reserved", i8(s[3]) + # print "hotspot x", i16(s[4:]) + # print "hotspot y", i16(s[6:]) + # print "bytes", i32(s[8:]) + # print "offset", i32(s[12:]) # load as bitmap self._bitmap(i32(m[12:]) + offset) @@ -73,7 +74,7 @@ class CurImageFile(BmpImagePlugin.BmpImageFile): # patch up the bitmap height self.size = self.size[0], self.size[1]//2 d, e, o, a = self.tile[0] - self.tile[0] = d, (0,0)+self.size, o, a + self.tile[0] = d, (0, 0)+self.size, o, a return From 84b13ff1ae8156e248d76a8e5637504056106666 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 01:19:52 +0300 Subject: [PATCH 36/58] Created with ImageMagick: convert lena.ppm lena.dcx --- Tests/images/lena.dcx | Bin 0 -> 62138 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Tests/images/lena.dcx diff --git a/Tests/images/lena.dcx b/Tests/images/lena.dcx new file mode 100644 index 0000000000000000000000000000000000000000..d05370be8e42bc69430ce6ced5f4757c700215b1 GIT binary patch literal 62138 zcmeFZXLnmywk`PH=ntIp+Z8 zoO331HYEpHvLq|ZmMmwx%C2-{-M;tTo(rt{1Mg!G%LV})04MCZ*IIMUwf0#sygvWG z{+Ivs%fDYn;Fl5jWdwd1fnP@8ml6171b!KTUq;}U5%^^Uei?yZM&Oqb`2YC`{2%|@ zfBxU;5)1L)|J1+#CGemA^Z(Qj4}Qdb!M@?X;9hfY@b`1>EACtFJMKsBw|IQE6&jtG zTbNm3i%Y8<^)+qm7u$sKHainI8Fdxf+3f_sVQH|#b3e!*UGukm=p z{R8(e+`n`G%-tWE-dN{u?rm;!H+Q+)9NXK$+1=!BaW}U&aQ?3bhX(ovy1Ki%`$lKR z2D;ob9n+hwW|P(E_U3wnCFMmW0Tv9D7nK#2mK9Z$max*2;$U&GyoeQ-l$Dg0u>dPB zFDPZj`2~KjL+2`Q>>TRuY~Sx{>+ERnU|oGZA)Nga?gjU0hsKcO&GGtKo;T>va~I?V zbFy>Cx=Zs4a=ki>*JN;eJ&r<^P%0K>N`&dsR3;HAak;vp~rCueGOBE`yQLB`Rj4CltC1+MQGZ?*2gT|~is+h@Xw>0*KT3vjxRK^!* zjB=%psWUZVjVMzWv~gbp%CEUEF_d3n=w4$`zXznh=YHmX$9=xhH#|DCFh4iHy10g+ zODZZ0i&<%L zd2v}`AXpGA3>23ISs4Lb>Sx6Th56nbkI@=v=wyA^VS7(kdq-P$2kY+Y#RWaZ89f_P zIO>O8*DCljsYseBk!!_i8doZN13bx0zrrgr)SrOmAMpHaJ2W&qzr4ie z*~0u9u3|q7=pBGZkdp1)WuE}Rr`YlkfIY+(veXCo{4u_P&$&<7JwOV31&|N^Ivwu8 zx<0~pKEnQPar?Wgb5pxO`^8_udx5igjdS^$fMsN~^vMg%w149MU+&+yzu%Zz+1y>< z*xP2e_OJt>89uo?-0cOWq?dK~c6N7kcMVUDPjpv1#X^mi8O?f~!RYcAu>3%AVMU-Y zSX5G04*RSqDK06_FDotzlok1lgC&7rMM)tmDlG67<$Ln|IZnOSQ{CFzAL?Q~tg{ER zrI&SfbT8p_pW~G7`V4lL+n2NNV|n?({rutrpTUA(U=05R z@B43n_3PpJosCU$xVt;Mc-qIgk=wY#JzA0r#JxRTouRglp3o>88x2)j`4Y9sZq=D} zMq7@{<16$P6~n^@%7TTZtRz@e2B%wIR7(Ds1e1h5bd`Zu;v+_JF*W=CedxJ&!CDw@F9J4c{CRc0FTb)*e z+N@5EjpwDyQj?NX(vk&fOejfZT7%pu*GMx}ViCNo%q%l2)JBO?%Fk5lq)N3)uFxn| zLZu2`M$IIAv4+`Z8>ns6pyi;-G_yLxX0bzT-bt#>5$XNq1YQ8}>9bIx;%k-%)On$PBPk zvrVgK4!4)(7nT&lGE0ksz_YBNq_n8G2;MeWQe0F}R8?72T*!)9Q83?Miin%h5V}?QJcSxSr>L^kJRd=JMuYxA_cnfECLR9X@i{t~Fbw21mZv z?6R4SB9@XMNQ&X5O5@@alhRczQ=%8h6jFprO{Ubsm#bt_u}P~^$Rx^)Osh^J70Z-z zShU#4lnR|VLoX5Pd^W4wXUfX9=ISk0rgH&NSA9>YRVm1jYOn)^N~sqr73!pj%NHUr zbY!1|>lfUQ?EA2-e#<>yAMTr3T8H1AU0e^3-TN>mE({aF@c_d}PL>SvDFeiS6b6bd zkMQY3GDo~8@Cf z5)t8F!`}DLM?!nRC z0XEnV+ST95I$GKqcDTpvC3nkUa=Ls4*~|~;U0y3c{PyvqXP8N=acRvtc8A+$a0}B? zl6VQ}aT!T5De0*h(ln-#@ii)iR;|nsDn(ME2(~F>3b{-n5ld7CjZ&ZxXca=eRH7CM zWg3~72_#0X&Fe8{nT-~!-RX8>cG@)lj^3`KG`?6QQ^?fDY@QWR23NgL@8k7T3YlT^ ze1z}a!$6a%KA}&!Pj1m~DWK9fKH%QpV@tEk_<%y^mjLli*ijJw{sz+u{N^TiBtu0G!Al^cR!{V5!0UKv6ze5-csxYqJ<~Dw;!VV6=a~ z47Xv`k3KiB6f%nww{V&6J?`1onFGfU&JTm9}FhruBgif^z4 zmYkBoOHC2*1T0;~!~#$ln?%Hy@@0InQY)76GX!d3rbHx`>4g+!GsP;AS|t#IDXBzh z5{u30&SAa+o5r9wsqGG{4zAZ49PDc~C1wi5=?an5ELZ4x!ZX*;p1&A|4wmp&3;h8@ zO78A^?!|6slx%aE&8@Fs*xnDj+YgYaki|U!8V5K%Vz5o1O3su*CfVGbul7)I%UvJ;gBpVs%9q6rf2qg-W#mKZelRhgaH!oP| zEdrbXF9<)IpI1~|3Xh5CBfKsW2^ z?dfQ3X>8fV1bu-y_OZ>(+`j!>e{q%Y=;4#^uu~@tI-l9(v1VCwj3&E6&JyDiSZZQy zB1=h1O-YwXg*>T9sMKqeLXl3LnW0o$_~~g9CX-79nGB9os+EdV5}{NeflpSb1Wcqd zc>Otf-fWg-)9GS0PS9=5FQ}Ziey7Q}B81)a3I{wv(egudJAWBFcg^iWmD7jfOTLSO{0Ci{oE(V*} zEM=+0f(dFQGhyya(0{<)VIQt+Bfq44l=74>ad6}+2nHl}nT=kytKe%5Cb~Cd%n4vl}*Iy`3oj;Dzz*((t?oW(Dv?^sGl}F9A$o%0CUOg!gYSHV zZ@v$^z8wah=qC~tb_d@hItAN>&ka9gp4{9d8cosnIiMs9eYFpAgvL2JXH}jZSuhr|+%xG~q zv%Pr*MZUs7p+8WN?+=t$1PclSz|@oDFUa#Tf3Sc7V-_qdDD)$I<`uZ}?ADw>O-pB2 zs5{h;l%>13yQ{OSoi*0XVtUc^dt9Y=xbuC%Qt?}d4j(#wcW2*jDvTS5U}Bvyzr)H0)vsk9=d5G#Zd zjX){UrpZyf}P&n+TPj$b$SdxMgv7^0@*5T6OY%h zP|}hpB_+4}6e%eI`)}Nz$7hzwdE6N!*08To$wdQwL!*;pLxcST`+Z#%x-^l{q1o4} z)aERfoA1fZ3*>qI`To2D01Kg^H0aCs75H3UPj0ri09r#3CW?^iD-0s&GPlc;RaD*F z8tU!q3iZN9yZVucwl>t))Z*Mn#>cXDU_*~BF|sDdL@>fj|jWm zuh@@(kzDULNLRkWGr{`Va@*j{?8-cwU0T`ZZZTwzFjLa^D08_71j&aIeqbedkgq+E zi#~>Fegr}2=FS>X;(ao0BDIvGQaB|7d?$?h2OQhlS=`1Pp`7PA_z!7A2WsR&PWlb7 zd_$oVA@l`)`z<4i`xovBn?r0L6tWD3#H=zhxir+mBH*F!7i|ZDJ~> zGnjL7J%xFN{-V6XU?p;k(t<#7&=2CK9lvz)3_E(kP1~g_t->NnISU+5mu~J zOI2c-CPf3KP@2w@$dR0QUDjNGwuy3DXn=O5Myh7k>d~oA6-$$flg~$7zJ4|CS`3T0 z90rlV{B0OeqLyTx2YeCR_!^a5u0WN&Lb{9Cfd+laJ8hWk;!8j*}I$3ki;6VRScePzCkZZIC ztx0Rnb|C);;Q_BLEG_f~^B@bAu>8h`p2og`#pPA*{q4D}29_Q4<{^X0&kODskX@J^ z{wmg3-`>{Q)!Ny{y4zXXEtqH{qy^$dUveMg8Ata`Sg03f zTA&$a8i6X0Nz?+ROmEA!WjV7Q2CLDc)m!v3C9+k$rg(gKqB2#WNH`mF{ZizW=md72 zT?ji`(&fKL*6=w%KA=XFy}aJ)9T=NhUYgxp-QI-Vkv)=HbfCT83xjsxXTyFM+wa4E z_qqF&^?w|8wj>r2^Zg`@2O;yx(*7;%i@Z1aW@1v5L*Cq5U)aL?r-1em?C~>zN225_ z_+CXX`io4WmPpwE8|!W?FNGq&2D@tw zX?&?pZ?Yg8HRt3pFA@{P(4t^rkuSd>;47@H?6+`E z=$kBSsT!K=?H7vVD!t4CJTv8)!c0+yT&Hn+Yz}vhMP+eVv}%J)Z-MwAl<2EQr^idg z$>$<2T#AS}d-=xM^QX_j5`Gs}<-fszJ;H?|FehW7Z zCk(Q)45vVHAcfSYVQ2y4K4}XCDRHNl?D;}IBB2%xBeQRtOod1z>6 zq&1jV)iX3QHr`iaPRtN1nOvjN>&y<9k9mEpz*p!G7Ut)%lGfbH`nvs==7z@5;Nslo z+Vu7o&ihu#p6xHp%MGv`uRY6wWVW!TxwWaerM07%wKTOi*0ILg8dg_ZUAl%7Blq?) z_t0CvK6dW-*^?)Zo;!Q!h(62h6ecBz3>vH5qUR@HiN28-6Pt+Cl$V;3&J&?#BFq${ z5+gG^OXW^qLABq-3O%KHozCHLVD29Y8um0f-x-gL98 zwR>=8ZhCQP0T##r!ag1(1rgnS5RRy%@jm75>@v2rw@yhv=o7*&h1QS4CiMcZ36-z$ zfJ8gJ!*P4~5;S@Mjyl-h23y?3PRZ}S=3d+)lcWIpS$GS*BT__y+reux=D&a({SWRx zcGHEKN|V~C$OP|~>HFA3Z?(-*-ZL>eG%`?U7bfr}HVsqi3^ph8_1ZL&CgUSGD)j1-<&B1%c+L(^3X%uct-W;K|yvr2;P^+Qdpx2ketsC2Y-ZfH)#g}NCg zx;KFj$@9;!yT?G{H6Z^27=gU5&8|_s1m7T3*~Z%V26jU!9+}_)coa?#v?AiZq#F^_ zeS%lSpLPlz5 z$j{w*`5u2h^UYg*9-rUGN(-xtN?K}1diw_E*EV-H_Le!ehx6t-EoQeT+l}8iOa@C~ z4TBZ$H#K)Ql-Jj^1IVhnnx@8@`eB^TH(S4E?;MFZ_1>Z196tK)k<)Kw*_HCx$asl1 z%fzg5S?u-L==h{K=<`s~6Vez@iqu3Yka&68481|;x43e&=JG&IU8lEwq;q(rbF6Q9 zYNSq>t`bNEVt%?HMV6spR-4HRT5YjwL<)&TszA9$!%Pafbz~`rT|9p|I`Yc-i)2>rn31zxB?cBN3-h9R(FSapc0g|98M` z;6+_eX}(g05Vb*;$a^G2$Pd z2#vIl4sA|v&d;U`c^N2fiiJrjLb=-JGFnYWi_yuD&nQu4RijFyKn=Cb9dYH_h3hvi zvnz4Y*RI|;eFAp(M~w1^4Q+cExbL~280kd6# zRBKI$O%4xs*H{vg`3jv}tJE6I7N-jh1I(A7>#ks)Y*&^)ud28-;BRVct!W%u9$4Ri z47?8f;2XB^#NcZ7B{G%S;xJkaI-|c~zoVrNN_$O5V^d>W9Z}jk*3{hEU2*cnk)tQy zJAM2&5yuamx^m(Fl6h2$VAQGOuCN;k>AaL!VVW>S2pEyBWP;ZMAcfj4 zv$?V~rpCOA;y_V*ZOcIUSlit6?BLSqN`Fd1yqK>_SEVEiHCAYbP;517y;G$(XA6xe zoHCV8ZMKM`Zd~2J6nQBknq7`ch(4K#nD`y{`AAa-!ow@z2X%;%U4FJ!-xeC1n4MsA zvulgE(A&E(LlW#BVD5gzy+p9vWgL=^dr<#2v7LM>qpkytJw-AyBVdEkCxd(pK=0!9 zPiQsxzH?@MWol_|g6hJrQ5z#F^b8YZe+L_={pHJjqOzoS9~k9ps8w&wOpvKCt96-1 zl|-qt#Cf>aBR$1ZmXcL9FfuvR-&JmiP2>ukx86C)P9HlGapKhRGnapTqfc*5PQ4z*PqSH=O|KFrTun%1NxU?;Q*@F!PXz1)783^?cFOJOhZIdg*NPQTSmY$iBnZ_g* zhtlkEsAZxIl}@Wym{1aR=&9u*OMfHcV#L*JS0gT5i@b5=TI|JCAAtOl+iz>{*~OI* zbNv~?@dxhn&8B8HGB-XtGd;hwwu|@&_y|Z6?I7!|!(-T8$2#v28sf=IY=$}r8cJL#B2F-x_hQ2_q zL}~&=$JPvKrby2;nJRq-Uzx8r<8;0nZgM84rDrwtjEs(rbXOVTQY2EPL}SqDnI+rq z^XGYU^9l=?)$Vpee)ktbL?|j7XzHz-*qq|HCGPeb)c<+x3DO6nT=uK2G__s>pKT4) zcd*W`=71u@THV&t(A3aa)6`to)Y93VeEi(s9XZ2J9X=iLn|IEnunUbNK6T=iglL{t zY0=poYDHXROhS5M98Ul>Ha#sv2Hjo4N9L3&6J)BO$yy{frnQ!M1C^!yjZHz?N zY#Gm#cu+Zmx<(F4VNWpr!ZS%fe@iS$-lO`;Z@CZBg<_@ApcP52LW#^_%U{E!dC*z_x|89o>z!a@ zL!FgI#>-S|bW$`X4BrZyB-p{&{2R4Bh9Dy(m=Z*6X@WexR>tv#-{!E7$D(}z!7c>BnE zH?GE)Hn%ELV-pguWuS$`kmb_L_TyuDDZF?TNO*j48rp_3dGd^;6qHD$X-1_&>ojD` z^=?SUm4g+d9$dl5 z?(^Vr-AmYCJD-bR3#Ux4H~x%$pqphvu4}P zK2J7UKnhEm>nm%UE9&YSr&fm>Xm;Z8w=oT={zJWoA3+X&9QF(^qmwcOLR~>a7c8`? z+<5$$GN-z=v97+Zwyv?QFY;F>-+Ax!nZt+9A31g8y%?Uiv7YFU-Mr>kgyn&a_OIHe2=}AIfx_V!%g9e%F^ty9&u54dXYq4*2Z4_O0n=9*( z#6M(PaBPpaFU2Ip$Dy2Nu^W(7O3p=PigY%MN-b9ybk^LcbCDM!uS8wCay8=mg(#uI zmE*Q~hk6HxdwRG3W}zUlkbpKCn+7MwrpITd7naun6PXO2?ezmFA1bC-N-So9g6Xm+fWRl4m^07BC`Ir^rmC)q@v-r?3R6@cV0Hif+$ku7Y3QPu&SZ1vAn*qx^b~}bf28feYy~Ye5%Xd3imuc z!r||k;u3}O{Mzo$){f>1&9S#5G!>1l^>sD1tu39dciC@FM!d(4M4UTx>U`vl!p7FJ zuEDsZnAB@2Nn)KV*ORX{rNrHcO-kh@#Uu-P;e9KsBu(ld#y)Kx}d^1JZS z{Q2y z0`*OCCf`}x#fI5XSD86EF+-tKYl#L~9iDx6r2|T}-Rg7uvV(PjU|mB~WnEE2TW9`3 zB6SDnOWmEs!EfR2{Ca|DN22o-Qm*864~_|N&Ey}q9{2*0Jn>7SYb+< zM3x~z`C6Zk3U^MW&85i?di0ai%WQmYWpRA53)GUxHJuhoqBu2qa`1(E?hZ(>3Xs@C)-_CT+lN-FxU-p{1QV=)iCmg-*d0l zn%a9uC+F6urk9Xa6aU!;YWJsSH_>dh#_ew`Z-z+_iFya66haju`tAXH-@kR$Gq8p5>P*&Dj={%j(W8 zsIM)nY$*$rmRANF7D;@lcB`wx9Pyi9 z9T)rRn(C_?T6)snJ#pmxiT92lig@?Tb0W~ASU zOpTX{5|fh>1?eg2g3J^_Tw2T(#)2^Oor=t00tq#~alFwa^xOOoT+QHe2=dQ$=3thQ6 zrL3TDG&B(ECjIB@{U2Z+-+;>2w)OUnFHTG^&cVCBzsGSqu;n{DYd8wq+r(wxqS=H> z=LUv?TB~pEZOj9MZvf{3F{QNeIbQ#*1?YeoQBN&ZN4~@C`FSO;9ivL+8$z9WM4v3> zNaf<}x$sU&283tkK0zT@iGDn>LY-+;r{u$?h}nMtx#=VTQe?Z)A`S^^_Tt zGK6BZtZHGcHcxhreba8Tg6}%A@(R7avNm67a|6rEcFgQ;FHtWPx>T?)>aZXZKs5J0 zz$8Xbz5oK&$k{YcEmD`B_A=x7!$*Geo-(hls;s8f`}VuXP8@?0bmF~3r_TH)zNxLM zd7y7_C?PIwKOt3}1M!t*>3I+YVp&RJT5@UvJg-C$h)EO+l*t)lk!IhN>(sgP<$9?y zzip82tbK2GZfRy>RQm{h3R#nffe?ow?N+moG+~ITe>?mSiZ53Fj_E zvWpk4vB=Apu0&qWC=NREe4c#oKz|6$-zymZZxBg|?LuAHWKC$-m|0|#i|Y%R!W=Tr ze`WJa)Jn%;odNKCh}lgIdk+8$)ueB2EUbXgkf)`n34HL1?3Mg6^Z~pgs{0hLza{bu zuzuwJ*j0D4}97v3N9M%w@ zpmZe8Of@xjvBA-i&T1P==1Y+pDE0eRyUS|kK2#WW*|uzp+mm0&O6!UOmGxemkMQJn zw%6y@!k+G(j*F88SU z=sQQ)@pBR9&K^E?77d!E?d7#Y$R9#6vB^m{qLR%T^vZgS68??&n56jVosj?n426MM@f4VZLZXW_xoj{P9Q4#+sil@v40Nm-Xse`l1e1@6@E{Z zX;Oy>=L7OeA^}B95^{+Fz1n{Rgei7DEMLPnzlLB$(f8?cmROXLif{jn^Z5p~o*xrZ zQEZ}$kVTD2ytLt8bX zGg_T~Yj&QI1?vhbipz4nS)C|}P0w-f&tb?Qf}xd$I)UMSi4h*OMiIIX!ezbJ+)wwV@G(JDI zxIVhJHNLpBiiKC0hm5MpPd6h47N^CKZ8oGuo?&MrmzIagPd{FWycT)oay+|y?Rs?N zg=;whpC>0!l$Yyo?-?2F3#|i>ub}`^?ehoj#b#N3_t3=r-1O8UGzM;G3FWDu=T}j- zgr}fN=z;Oxp27G&*xi@~imy@fAOW2^Ef2a4!gh;y#LUQ|=|PpSFTio%uOXM*l#wJ<8g&vK>PpJYDh%np9k7}w`;XE^a;YfYTG}x* zJ~q%>V!9TeCc0>?K7;mdtiEfb8vYBwllP`!?xBCA;3oC`6`>k?#z~_o;ela*d7a? zCe@Z9nI|&HfM+gTKYR81g=+>@;ALf4FjeI09UL7W>!YD1I!skhXg=JFxyJhLiTSC8 z#kJL?b&lIuLJ#cM)3cC5_hz}b7OmLYZDhkrFH6pqvl2=j`fxg)$|V5wyn$&?t>*z0oUapC z5xHGaVV>WUpXDDJn`VA*ES6d%`B{}&aN@YgLwP{_rn5PU7CmI zA_m1~G0`c<`IHzsK}tnXTAfDKF)E>u3#M&hCyj7SSb|j{#d(A6R2`#cqHkC66I!rD z($*IoYf->-zr#2}Aw&*Fmi}ArA6FB^TDe3kQyN5)F&vUC4I~ODKy|x^>b6f&tL z*g3++M|*3nF{ylsQm<9%4Jb!h)ZG0x8KfqY8@==T!iv1IEa&*-=-@=h>c-^4%FN>C zdOr=-`}?TYl0@;4Tp^A^Jyq1a`g}0h(#?A6vjpep(;=KAb(~XwDk+>_HNAcO?9n5q zP8>OX=(wY=sg?D0!ybG3QW8~3(Mc(33WvvOv#XM>#742is*1vade+m_IXyL2FfzKlK0V*QHOqZCv;^`)r-frqr)hOYr#Lkw zZg-;{>JVE)eu_cKiHyE+4tZ_F`G_b-d48_9&|BcfI>^!4rJ1pbgHDD6jDL?|eZJDx zH9RrB!qyg6sg!|g+e0+@Je`?cAZuppfEWWpZDIRZWlH5~S~2kk*G`!!Jq~K#)XVTV zj3342gN32wr(Xfb1Lc=;rUU2qJ-$m;PR#iksW!(H&0Q4wsRT!M4JoP{qe|V!#JVV#f6U!%z_Pze zM-M{LBIYYC{UP0rN-VGy%iAYT9XopD^x2dDHNLI2u8;NihB{I4NoDadX;gQ~=T~MLAWzlFHt)_U_6?);`+aJrbH& zo0wl-Un^VO+*n@>_kwX7GPTYu74&ml>kJ0s=H~h=xEN0KWBH})*Uq227lk2h;h-c zzQ!}PnjPp{m>uCR^51fQO2*n~wM?wRGQ3rM??a%Cq!&ja8zb5a>Dq|JwJMRlwsVk; zP4rheQ=n^M4T1?~<8=jeqaCypFC@!mU! z3%lz(hX8p;Z+AzhAT~N7_G+9_<%D2nmM2HDs1#vre9CnehmOLWtn^fBS`y1Mm1ruI z*>n9Y$DPyIJY3Z|T~}S+F&=84?V4I#+nlc(UzuCjT-#ck+g%dsMT!cJ8yW?1T3_5; zTi#`#>|ME$5_#$D#cP*OUv-!Iihb0w9Ps))(+jgx2w5M&%M#Lm2n)+!Yl2c-0W28pMezsK_&#uL%$4AGe z#3m#s@Zv{GP{&D3Nfj}nIzy}~4%(c#mOw*wJvvd>I`cyHp~;&5>F)9J;l9w&=*;Te z;@o=Q%1)ocI5)-mP-0tOSla*vMoiwk5`8`L5<7n-Hc9O-$iEG*5;PA{*mjDUTCWkZ5p2i1csC8-BO3T&7P=2Rir2Y^Jv zNbI1_q8Ip_N;qKy1sgpu>~M=2GFUQsa@0h?pW)lItm+Yd{Q}2+hPg#53z;`*Bjnz{ zfGI=b;{FgNLOv|e8jJ-nB{ED(9J5XDu^E^zm|ff2Su&8@1UaB{d~v3IU~PoWt*%V2?My6gug&k0?e49k zG6MPynP&mZmPt#;(jlxKA((01*ZbiE1LVIudg|oSci%g8Homs4p>qJMsJhV!-qx9v zk{Zuq66F>>)=y;{QZHQ1h)rT~@#thicHC|gv2Ct zU~^Y-OKV$Q$@FY_&B$!W^zQQL;5a~8onG%>YiwO!Spq>`+uE1{7##O-J@U%+xC`f^ zZY1)H10~*)yrSHkKyfbf&P|O?FD(M47Z}-}f$^U(nm=P?x%Q61`Pr$3$+`L2wWTTa z-Tn;2LhxOlXIQe0`U$nbQ0pi#+QCp$OMX}d#;aG1TFAo9OZbHR@N4!Nz$RF!Lyau< z1(I57A*RI|4*(|R%&)<>$Z8KFHbrByf6ATz$h}Av$<#8lNog3v?}`3C!e<0B)%3}{ zXtI2&R`T^4mA$HCY-(<1v@VO6CKSt+3{CKAgHDcB@l7SgMl9nrmlos(8!M_h@@ktJ zySj%bX9h;LCg#WI=f;-N-mx~1PT95Hm96>BrPT#0MJ~g1DH*>HE=qKq%=iv&XMiV) z$9I0s4xc=H>CDMJr7XK@-#EU&z{WWrxtJy_CEJygT$+s4{MjRW(Ob2IZT({q!9y+a$d z!wWl`!wZW`8|$l!<7nprdtw*S8IyAPLXwBlMXcW|!759%;7v@zn z_96~bZcLrNWYol^DfSZ92c0xz__WT76tGY6tuJA+#N7zzSD@k)mFa#Eq{sa1N*5{A zX=0tc0KcK>1t$W(PktRyAKVMCWN6aVDh+kLqcf9pgSD>sWU&g3wh&IxouJ@8Sq#-T zTMfC^ERUnOyrI0w-Q3byTr;yYP_?))IX$^Jwm1$}y98dlvpcoAHnX@si#`D?*9%8s zSne$#{C*f?)W?P2*cbN9%rbHq4Sj+~qIy)=JoYUTy=jtr$sH*6wXlO#M zs;z6FbZMrof4I77ptobUeRgScZFQY3E+ZCmtgLcvb}s^9H}UlOYd82Pau)gB`Nc)W zIc|^73*l;NVGf2)#O7ysYO2%!j{9n(tz~!u7d$gJzrQ+))?8{nh1L)8V{DPTLo4)& z_&(-7*ukh0f|NJDpfnDfNwqw<7spGCKRULt^)9|cjcwEcOiY{_^r`WQZ0~zSWy+%H zW)H-{$(p|azj_u91|Ih|p1Jc^&gW6Rtv@N8-|`EU#3@L%aQob+tZeDyB(>O>ZANoZ@Y7Y7g}f((MFT zZ>YN~F8M}M+_hAVDLb(5kP5D&a+H)D%i^JsBqSGm3@T+>d`dD)*E=L8uhQ+$%Pz_H zbQd(%RfK~11HQJ(rre&U`u369&Y}9D!S;ckw(jZe*~P9g%)8a)&FPx*R{P}AwM&qo z&qQ2Q`tz~^BcUv4#bj*d;uPffB}wl+P3 zr1(b+ISCyfFOQ+kn=mDQ1Gy3omNaR)H_JhbPyN9IZ*0i{Dv@EtNQ>Qbbw)SE%Q zs88^#hdAg1m^Z0eFYtUos@~vuWU}AF9XzAHv(LGYlLTs6hE8JZ!0#U89B3~@n+ayx zA1!1Luj^9D1xluJRP~NeOiv9rnG%yE40lQ(vZYgKx&0Z|RFiL(8q77d!Sd>Y`i92( zo{quRrqNK>Oy5X<>%vfPXlfP}(e=5p>6zvJG49R+wS-YUAB{uQta%$4-=$T5opbpE zYa73M`|PoIPanRlXl-u}4fS;a+)mch*V7e?0%2l8e5TIB+#aJMF)I2-S~`nOPP{>K z2+LE06-bg&6P;#-UafQ5f*yBEZb43GZb?T$No{^(xejYY%DXxTnwq;iN9sC8Sm)xx z>cZT_Jl3LaZf|atHJBT_rp}$Z&dy&t&okr}6&3{wa*7Ilxmj4Yna9RP#z&@*;SjAM zqebHj{=QkmEfv_*47zKUm!`+zhyDz!BGu|H0Qq2*Qb8JIqLLqlp(CG6RhNUMbL4vo z&L`|47&H|Jp5d9SjM(xsOo~Tg&vsBwB8#P3A=x_VUv6$opvChpLPP3L5 zpTy!5;$jl7C&eVjrqVq`_&RZHk`YBgjV@Q|Gi9?}w;$S!tG=YEr_#YHf*oaD1EH?Q zmeTr$;nM2ymFdvz%>3la=K2Z>@tfrhuGaGPEAbbvBt~3`l6d?`@&m=eTwGm#j@Oej zGBY(kxrpvMj~eYM-#j@2#GvrDs+vr_{Y@qawnj`9DJyGzxar?4NQ8VmzZ zdEWz?-<0P(hX(x^nBQNS7@}pMbe{l1^&y_gJ3m7G4W%dS2|_7MnbhioX8waF#)C*p z`ZZR;!(!0$F@+!gJ{EOf)CV=KI5f4_eTqFF7%-7%7&7)tct4h^<>+GZ)bx+BnYn>> zCwf)T)h5OII<-R3#oe0gX)bDUt7@yTCbFQpw5`cs*;WILTkCsUs@$1vT|?+q8R_n4 zgHs*t(E8ECio@-1Vcj;Z!KQLE-B^e)rr7_%NKKbzocrSM-aUKr$kpSgl^re3y-1N* zS9hofw@>Tsxse=~6c@{vSY6qWCU_xzT4*)Nwa2 zUXF{roN_Tv>kW8|0^Wenh1K=`y!=4+*woC#0^KbOhJ>;Mx#&M~Z=iAvV(AK-U7cH* z8vt;B#&%kY^%M6Qic0u8u5ulJaIYGw1e2WkSNpA-nrL7ljKJO69YS{=lmFS20VQON z&X<@0U%^|@iXC#~^q@KfB|_iqe+T5=uMBNts@+TwD#UV&#JGWd90URK3I}xkz)z5l zM*RB|sR|+1;I8SL#kEY;o8wbND!ELKW^$D@y@}hOLt5HXVGrgOH~MSps_OGfYO2~= z+S2l^876r{r=+-lqOOvS=bq_ibsRTI<;qN* zEVBg|Qws%QNe}YAe=7#i;xD?N$YYIKgO-$>n%)Vpgt2yKLVUVPrp8iN+**!b2!mT0 z?g};7U3o=$m8`rzA9uW~ZE18?<(j0TsL`Q7S#gvkOL-zncBp4(fNI0kJdc$uR6q<@ zns9++rXYTy%ydaEV19Y%?W0HDK6&(*25Th;`@oC4dgvx<-Dm({>1ik{@C3$eXO7>d z=3R@7N{xY%ksKX&^?FKm5o$>4Ox(64%kEYi-8QYu>hfg=oK~|zE9tHu9_*EyoyK^T zEw;Y1bYOV0e;T#*na%aZ)wQja^`+wLF-hi`jmQfZ&z-q={)QgQI7`b4gT5Tx2E&Kt zyv#ctUPeYm`fv8hKuOB@dbhrCeK_JXj*#J@9`Z0KedV*rR*)K<>scgZ=|Z zYLcV7YuyQPx26Y&=9()*BV|@iyV{kRl9td9CrOG1Qdd+IzJh5U+#rIGBv(s;^c#+A zYVYb_fZzQo$P=rSe4|iAg&la?Tl90vD-UwmzuwD9rdP?eRu?p(>B;Gl_Ux4Sbg4$J z)}dWjlc}b>^Y&16hsWs(n2IV(>H;MdrIn3!+R6ea?un##R0(4u0uf0^-g@s)C78*F zKo9HZkl0WkE(y&viJ(aNc?yxjxy(Jhe)t$W`R+M(q_m~3YXrBC=|>ptA^1X_@hp`k zMkR<v-k2P7g~g>rC-TApH7b{x_!6;FF0^0?n9YgR8AeyGkS|z*|6gvNmyN`JU1m>Tzk((%f|#z0cnflVS}qL}^=j)3wa^1b(TYMsht_tgwc zjz^hD)!|;1$7mrxn<=Q`E}*yih$E?i@gxZ6Drl0 zv?n#E{?A`86)zBqa5fCfKIjIQbTwh;ihN3fPGX4>k@e$aZyh>$V)-7Y10LJuYb4x#ZFy>~a z7M3Q*+qr*X|Bhh#65qp;kFiyZB@B|<&9Tx3n~<(9U`69}!05Lavnva9)g^vW{dFbx zdI4bI#%lO`kcz(8KPctXy1B1MU7A!o`T|D&9Ht@*MO1*UKE|TH$U{{}AcKDB@Gjf}m*#D)?es%it>a!QtcY zojQ5w@a2SKzV>Q1JTfrc*FD&c``q<*c67F-fy&0G^0XFHmdD~zB*mfa4T51pRNU3% zsN@-6fq<8z)u&*!mESCOxRo}SxiF{5Auy%!bY4Shfw?NNH$pjNA0Dg;O`wl@d}3~X zd0}NDy#V(Lk$Y{8qn9pYA#%ipcxj3=H>;|sw6eCKq`VLd=yRC2$g|842DdPTufvq) zN3=>2epn&a18sPGhE1<8%=W>O=>DDm9ERcP6mTQ@@gWEe0KBt}Ax371Vp6rX9>HAI z*(eni2Q#8PChp4}%nU4mgre{n9srNM*nhRS7Jh%SgI4j2sJtte*!)p?WcpC zrRJQ5nqnJne&nyND7TkN&e~6$Idcy*Z@w}KD$U1?k*zI*?doyJ!r`xV_nRIry9yb`Yr8Qqqi%xAeM@72=SK~`WrM4;7 z+cCrju?S;$Y+`2KoaSsOM?bQ^XyCo8SCV6}ko;;C&!3Z9gIn18tAoY0MR`TRKp`ud zTV5HT!#UrBmm_jReKNm?F!VKdyS=G@2sfFUnVpAV1W!eGb)At1vY)*^-r> zkSW&4pzo^jkcn_aD8myy&6bjiYISb8FQ?X>RAs*unQ`UtjdyP(9zUC{e@prQ$a@2j zbJrHO*vj1UI$|Qc=~Bv7Pj2hz$OPK*?;UyT@R74;jvs#S(iul{QwZy1N7+yaZ4bRY zz1@IOm?BAxjgJ!0VQs zSk8+QUNK3cGFWwF%X`dXs~>G0oar2H3k{4<&JWk8#TAq^m3ci`O?}5B&PGIDjyQ8E zIo_I`TMRiDMi?xr!2N1jFyG}x0d;Yms-%P>-4uXYWPXCp+-YkH4NuNbP0ugPuC4xm zJpG4Pc=vDbcbDgR_Q?ve)c*^AgjV_% zP6mBU%FB9>Dt6Et>r>a1y=P1>kBjTN8XAXOmTo~L`QdYXIUTcH$3e<~p}KWn0weQ_ zCqBo_>GC|D1lnl?t3w5%bt@n(jaqpd1*3n6ue+8?qM!>pc%hXm751U3&ww&?K|88d zYmBaugT2GONejPRri4~1@>R9AOGJ$YwBrd35rK9HZh$!V&w*%6o>*x`{nVBYv3i+TDz-f~@R&8R-R~@z^HW z+1y>*z(t6n5!c|{Y@JM8MaubgokoaN+M9)CY+w|j1X@{BRgF^PY|9(!s~`p^FqV4M zj#e%>s4-R9TnUd&N)1Mxp)ApBTHZh0Sz2FRN=$Datt?3de21?ObrQg`h3R?4jB*wy zCy&K<^%IxJ7m9cXe4b0cFG>UHqq8R`#}Dz?{Rdp(Ujx%W;@sb#NX%~mYkG1@PM$q_ za=Z*D{42iZPp{wsA76z87aPAk)BQ-pW^_IcL5oBft&C^Vi30ly5f6D^5lN%jm+$P=7T%;a`NN@ z{&}*yzJ)lqw!E7e^t9OrM6AI2wU z){eIi&yNmIs8U?=;W}=||G}SPF7g)D-}vy&htJPfr~KiOv94x;r_#<2lT)vuRXX?>cnzu=@!RA_(@R6sbe#9~j7r|p)($1%W_5Q%-_A2k9}#ou zl!W#LukXN5uOvWdJxIX=-y@wmO}k1rw7QRB(Ee=k##vUu~ z-^;q6n@93f?&YTOti-p0aJjWcHr7@FLAqR;U6_*9iEAYM8g-Ao*U|?S4t5c%iij(# zYoxH6u##tSCQJ<~0AF1_y+Z>|m8RPzu4XyKjm2!K4Z=N>DSJ&#fcRG9sHpik=(gb*}u36sPq4YgJ!ts5M zbOmiYv`{H_`(JZvDiMpDu8%;Uw7xw!hkNdHKVhrj$!ptMhzc6voqcwLDgcYWb6|6+ zoDTOus4v*ZD$H+YXJnSPRi&h5r9Q~&karI6A3ZwVyEr~QKix;Pq#=_Q5A)5u9$|1| zNb<&=G+Z+|=_!EY^M~vs&}P|O+t}IwlxS^f88U)X^YS`LWmQ>aZF_%LzunqeM>v&$ zZC6)f1|pQVNd&^gsExErky!P18TFPrk;GeHC2WeQm?dQlPK_%9#huyZ`H9s9fY;`> z_D+tD*K9nARTUX^lx7!{R5D3vQE^cLx4~)bkN5(fU?@yb`31Z|v}5`$Cl4=%C1|Ry#I@#zTGAJi zXg!lMja0&)9o>cp{TyzB5f+kr+B%^w@?UuEKOv2!tpVt-G2Y?%aMuCm5W5c>dyImux;--v+-6Sm;?tGl~p8$GeSviWp#;2-s3@U zt5*x{^6Dx+O8ANzK9pRlDuvryHA+nz5WFqD4Q0&wa<;18%n|uUi_3Bgm`2H7Y;taO zX>4eEWdOsMqg`^ayXdKAuo}C)5pYTwg!HDFqDE$AJ{BT(5w?SB} zQ2}8)ZD&WjQY*KhUr!s$*T^|4q5ZF!6h(&6F~+qr8Iq&UjuvfeW9Pv9?&0zN&Wr^N zT~MLgAV1O8tvB_wYvAr5lXioxH`GI%9XA?M@1$l6d3loj38C!Hcf)PVn-LI;lKbl` zk51PQX)6@s&-CV`?{U#xnI_~+E~RItkO#o+<=i3R~2(7IBf>U3HhR!fJdvY3rajxVc{@IfrCt*DwGmGJ9(8v7LO9r{88IH7{>dWk`K zs&f|R234!WE0fzh@zG(ZXh)a#H}`gr9zPtf8{S9IF zugNd=B+4N8Cr$Nwpn1BWa;L4IO}=xEzeJ@T-$5-$8&}kEX$PC$kyo8;I3a3vO}DPK zr9l&!LkIWZDDDu7q>XLZ%|JkEa-vvPCx3m>Y3u0-*Z{9;NNu=FN>U5*vxEhPlpFtM zFsHzfl<$cPxd>?q8_paXO^W-}b#m)NyvYeZil~a(*$Vku1N$Hqy%`TIf zICd4RuWYPstZpu%(3_p&%j@_8F2AY6=x~{gt@V`^oEmVKDg}xfsaP)M3!evtI#E-r z5-@8OM_;6<tVj`O)XgU%MV2e7*&;&yn4NDvyaHfaBz9UbrQZJpt4=yi7;I8g??IW@PsL96$R z`>-8i<{nP|8g)li z87V`U5~XN6?pyL#@(-BtH`~o3>s!fB8zBbY(QQ;UwGuV3y?Ev8P)pr`LLg})nQ|Mi zGag#v{r}6o?)Em)-k=RHLA368XS$a_x&lDU_LgQ1VAEz(&)iG1!RQW!+Z9|i zwiBONqH=y0Pq5hIUCQI3{AW>wG>P8Kn>OO_0vEC$%YH|8W1kfuy zMOT|m;FDotdera}HE`TI8=Ld9_MlL1u+f%Gduc^684?*b=DfnGG* z!88Z606?~B>xv#P(iU8(UnW0o?`Ubmt`pxPWVVlXXDmdBWf$7EP94#P`&=k*`;tHL zXa+*oMplOM)}8JmR$5tF-n|sw8y#6g&h5jO&msrO@9nJ3tnTd}P>}Jz=7KZ=AY|`% z<=wt3+!v zsv4QNx>iyrlnOerYC~4je9>5A=uwN<)%^u!<3!Arm58bf)ZEe1mJSl$+8v8O85^|t zLlclqI@&onCl_y?glY?lizI7xr6pyh9CitlQ7H2nJud%%8_3C^$%BCE8MGssI&G(D z6q3CQI0_{f;1)#A`Bn10shQQS)3cL{Gx8K%-YY~sm9_W~aS|!~$(qqC=<3ndb_XGu z+^RCTd6DGLo}v1tAda6M;A`mQh0cs9P@R?sbb-$`LX)ER{*IR0|KN8%NYtV^{ZqfH zwF`M?3(+XIKzW6w=mkidDs%{0(MB;q79{?ObNT1FrbrnpaI*izm;X4?Wod&1CEN z5KF)4-~nJ?ygGeK@c2A63-8|+9`WuM7ZE0SpxGI=k-;?-3zzE~SQjulo0uGpW537j z9OR4nywa-XcDFBLCKg#WPb`4j$t7Y*y-ZqBU9JU7r9algF|wt`I!0Z4A?gWkw>uWP5yNAvi<=vC!PY>hU8KKjh+gMp{(yn+w`X85+ROY5KYjw2rgr!>CbzT^Mg>`^5s}W|5&7%YRrtR! zK#QDFWE{;y>71JOjesig@^9P|oGUUa3A+R_G?NvLOm1wiFRgBFLl6q| z(AfBBe0(gPm=_4e2?54vJhR1&m(pk3u_DRc0tHQfW9` z-Z;BKp3St^#zq6<2ZzhE*1&LdluVGR1lb0v;^B+)mB!M1rfR9KoQNu`i^~`+iK)kJ z8VFlL-q3Kw<@5WjHWTW;K%eXAWaso46%eK1evL!^1AOF9xbxndnqJ-pJ~^nU~JIb3ZdDEwACWU6p)y z>)G5Un2jgpZDv<|i#)=x8jl3JW8~_>MFZ~GkbCon>RA&o{1ru+4>B_vhkY}EG2)-q zFBQKb1t zxCiM>6;P!&$;D$_bIn*96k6IjK04W3w2B4d#x}_1cWS##2BTxmP<(qNSS!i)rz#A$ z3abm!Z{6swX}DA1TiAd0<~&5@V}sKPcU7@`^yK3BzzrL|jh4+Xk4#$tk3MehSl3 zv(XIkTU=Kk#g|sLPfkzB=?UgXZ{r9l^6c%gnrAyRtpiQQ#u>g<(qtDZYXfp_@`o>A zGm4L(>v4Yd^vZGQf&V)B`T52sPX9V|QsdFv@Ar>Zkkr1vYZCP(KYfDPxdBysYuAg% zctB|4fYbzUNCOyEp!mVnwhl_Sq70k&o}8YaX*)VQ)DpF4dglN$<@x>^uyM^$#e{-M zXWzie_)^o|h)R*wk;zXF->ABsTm9WTce@{aXW6%Vo_ufjEcsryhYUFvqpfuc+s6Je zMTwEeJt`!@^#!-t>%Iq28pz8^&ng=5PpqtN%wJ+41c#fRUBQ%nCLRs>vCU6h&a4(2 z?Y$n8y<1WZu2yHAga}17{Mv4J$FPz&BooyP*XTJ*jCLkZm7c@yE6($p9Fs?oD-(cT z-4yDUm-8F_L!MV$;j>GMWRv=Wa)6>riSe z#{`p~^`k47qcc5PoHQ4rj{}XwKYD2GGCCr9i3x}cySAsJ zxlJR9yhWi=|LkMpv%p-)EUEE6MK$)pRYium+l%K9J0YpoC{+dK4uJ33UG!Ji$W^Vn zR&BFJtB01?!q%)KH$^E@^E$qxys5a6YPn5PZWI|>K|F(K8L*cEA}h_qfX_Kd9OG*n z2q(ZSy%_4w&&(sNjN81qUQS^V=6~ro#Z#f#%~gtNLA|$hISXR-{PZMbg$8OX1=Yw= zlbZ3o9q`3-WR_EyD2d+Qr;1 zmtDrn&Lo9h#zuLMKY%#7)FIE$E@88B8MWi8Y9I_5q>v#WGP>NJfYs=*`ukl*hppd@ zTF>DJPGXPFHfC3FzF#4c_!gc(fBYA2mdTm5-N#1&%Tm1c*H_v9SFc+9yna_a99?9& z+TC^4wX>2&QiY&MFEol(#H?;)u%o*}V_a@f?$V4De?VXPFTfiA?TJ`4V>I1={Z9YQTX$ZcdbarlvITEemZoN8 zr||VDx9bK1qlq1g+xXCul~G=tR#cGk1}71!$Sp|E%w^o}8H%hfFJ8{ftpgJ}H@!%v z=jSHJhN8oRl|m6g6jOFOta_`nP0B4NTvExyzxCtV28+(Y;<3Fw2hq`^0<+l2%_*IS zvQI(#mTUdV!AcP$JD-);Y#{l?YE7>tG=I7!XR&!D#hjwN4AHQg3h9-URkB+3Rxik( zb~EZfyW7_9vH~LNa-hz0?rv`Hti@MwxL+mzLMZ75aQ);*v8i3U_T=tWqWVUytPW$&7SYpV{2?voex3YkY+BbjfgUFu^)vT8+=X^qs50W; zF+BQSi%cJUs~1ZSYW=ueW_9}JCbg;^-8WoV*O%ERSE~VOXrxK(HR%v?;^Y~5a9vR)h`~G+w66;lyxesz5+!PLtbQLh~r{i~`!;?S& zPSF*uWM-bsk(tTqiQ(wrfInDMRaRZjW!AMDy2C+FqkvroHXKh_$>miHXuDb)OaiXC zE?m+b87pSg@K`x)Mv07TQJdo%k5?<0MY()gCNKHkA)DVWYt;m{E?Thf@Q& zt^Frh#rSZ-FpLui7O+z-bgCfL-y4qAG|20nQfQ~5>jqncZwC|oY8NQ?*vRAVp#_A( zKf=mCxXNNE=kX6f1An_QlNi}f{v^`ep_Pq8_in=5-q_lv2qX!8)M?|3wz?1uVJupU zQ=lP*seA~G7u@jW4Bxe}4arTpY|f`NI09cB0dEROQ$1oG+$k+>xbL zWo1_?`tCx*MQ|tm{=NHYqOW^wNNx7A0sI6;rj514eIhx!OQphc-U5oCYZ`L(SE6cjLqM_tRkGqs& z$aA_*&&4gehOuErb}p;P&=GD^g3`uj$lYcv5_B7!{T{ca-(?Tzu}j(EGFoh&C}ulb zOYvzO+JB<5`r}oG_nYJomR1kR!&i?c^wAUi(I1olXcAQQ4m32P|JgF9k~Aor4C?k8 z8KtLEmJ8&y_i@Uf!H6GjL1*?Q3V}Z%qW=8KhiE$*>=u;W-|Qye-`K-f{cyzDSKl%? zp8UuiP?LsE|H_0iX^8n zk6ly1&1wia&8yEh1&y5svp^k9oID@ykz>Gb0+IN%$~=B>;w|DbO1UcalvKvRI;c`r zm(Ayb%bBoH*<^K~Xd})(e;;%M+#`?|U0a!(#qpwvi7-jM?zcF-_46mM-b#KB)XtaW zy^Ut^j7QU0L9C4fW0Rc%i9)3&E!7hn2!U7|y?+(bC=%?NCfE}p*mN?0pk^U8~AJFIvOs{w0+kp4^h^L5Th9Nhn{ zc1dN4+aVr`h1JC*pHWmd>}e!YgB$7C0> zxpL*Xs6ZVuY$25pNO9G3_QMNf{lmgnM=I5P@e{xjP9P%vNF zIDr}n%@Zh;{d@gA9%(~8^yll<-Tuhrd^6Os8=BeT|Fm&p^i0jN`+{2dgewi`SR@^{lyD-mCCKIO58BS1lUYj&`B0 zp}iE?`~I^xFV67ibeu$c+280|n&q`MJlD+L!^clfm;FSdZq@6C62rTME54PPvozG3 zjd5kCHJp`lCnF{G-oL%JFaqVr?mkcw!=&m|96JI#I`Nkst0)4Fufnss`rm z3;`ca1y@XjEWmHg#smr76~z56OOIy!X{Ab%}*~dIlS{{QAti=I`{&i zI8|yaTE9_2GfFa|pgu}Mp?M26D>dG4;nRP<`h80Br|IH52Z3gj+m!tI%&@AqO}ap+ zp3n7lcfG#tTH=T@gT99g@11AoRIlxN?e%p(^!Lq8GNG8waZT+2DD`;WTUXzt)AtzW zdOP#9jMM_9rA&A)SIoEd_6(%ozjZe^{ieSS)4GrRYC~jn8cS%G*H-oq5B5g}20gx2 zy!n^Umu8|NvqiaetLmUu9N#A<);!P}z zDd!d!)@r~oAi-u)WjVJRos)jjE(+K26|Ti515avc*BOXU~5fV_XyNi3IT&I$Ii`FaGh;jJu~(qpry&Ic4mr z{t7`}0Ylek?jNvPLd1nFlADZq25@$C+(xUrzv3qR8u#GB z4y|K9!xYF&L3n1Xd8WBhC~fG7nX1lq8kIP~N2g$J{!%)PM1@M4AgDrq4ike*sA>4?si6DR&LtG zSWZ@UTGrSA7Q4^Q#HWyS#wJK?h=jJTT#z=bDJdSmyvM7q5HJdvG7VZ&URRHzoXOG7 zbqyG*bCBqO&ovyLoSln}#iDjU zzK1JmAvB183k9d?ZEzgle$wv`8k+)5)1%l>-B72p>)M1n8%l+Q-++7`M9doPBC?Lp zV5sXLN}DGXVDvR59>D>>x|$2o0{yReS-M+`vI0Llb{M<6G%)2y%@D2{gZB}{W7@Z* zn`;4xhUI7o1*Z2(*_#R=ArfCp=b^&+rd9wzWFf-|xixU7W?XVnBSNUXM&4AGqs|HS zmhAbC|Wg zW~<%lSBZG#yyiN!x!LMcii5Rhp;{i7S5hsjVQ`41w33xut~GD07v)sS8YKEYYj7;K z8J`#)@VI*WG|l}Flbs~Sj3)UsKG8h%>*N=Ub8F~gzO%YEJrar4HkpHp7MWVrAXj>N4_@wp zX!_zY`RbXlYZ)Pr=JnUg*mUI{WrEVa^Y36&DuF_kZfMv9BpSa%1y1M%iH##mq`gPi zg#Y_gF6vPqT}8| z;3HyXhpx9S+}~Jh%+8f5GqO@iW_oriyP(hOxc8m!hE3$1ncEL)k;H|^r{n8;=cnXo zb7gEK>hw)KPyXt~{_;dLWR+rSkaG9o(%sjX8RoHxt%XbIT_oaTqm!c}fx(9~AY8c~ z-4XOY`gY$hFRg;KU$GDZ%Mc3csNpN1H)kUI_t~9Psm{}1`BdZ*{yn`+hg~6 z`)yvgt&b)&R&2<%`v$_}>kFF^f5h+9yWoD5HbAczDp2%w@<$8t3xGT>Ph0%klQM^O zVBV+JHUeH_F36te z|C^Q`FxnNnJ|a{1XzJm6?{?OymGqgWV*?60qI{MQ3DpQj#CnfFVeLygBEF<{{4@DO z6)qljc9AWPtL$uV-Y=~lRBPwQ3&jpsimJ}&mFMO?xOw*`E59fr^$Bmk9`M7VKl{#& z2hwhrCp0v(gbi_rN89VOgP|d}D|(EN^U>x~d??h-tO!upq@a{|u5N{{`H` zZ{dJgBz={QQn5y=;_|zz+x3?yCMb#FZF_BBL?eKi-j6C8y}0x!5u2J0)jRnRzz1Y6 zz|Fim$4mb=Y<4}r{WGPgi7SBa$S&?rY#&3iW!5LG@OFg*(sFl8VOEPII5uCLn|}8W zTbt4LB2irS|1)?1@Vfwx;-`-9f^z~9>H*QBggmYhosyWK^62^i%RM=CMTAhwn*5_ zwjS41hbHEdNg}R;vnMqbOj2AbV%v9|#pPM``X@*E#RXZMO0197`5c4Jp+F?+arQKI zHPp5by?haH*sYzy5>{blUeRc8ZEgV{s)ja)!Rq!|9Zs`_n5}>jd;IQ+DWuVBi({if zpOqMJdNlW^h&>uVf1mtvA-=Y^^Jv^O7;5zm`kX6@N?CJVb9CbH+}zKvmM1@WmHcLv zU#ASLQ$6A<>0!J8)uE?1;qPF+|3s{$-Ir^w!G9nI(prT^R0{F@VprT`3U*gf|5~e8 z%tJ(g&VXnzMz;)C3*>v~v;Nl0=QRJMsmm3h`;uO;^mG1+&Ob{s)2uTarvN@Ldqg$$ zt&Txixw0v*#nPml%6=myBQ>L`!C@&Zed9a#qW0v+o}0JQSz@it8;VTK&MeKYtZpui zyImtrbBMO+f3Y|lkNR3~-{+KN|NBVDct1rmI=Hs9NM;u|5|fFkaT4|I<72%8|9b}y z9_>1OpZ3(D>c?jkWXe08p?;^WO~7K8xA>=Z9j-uqcz!r^UXsUSb9jb&eSJ|ub}FZ- z?WiuFSyad>Q(~i((QARQDpuF_Hpq+((#}Dkn_W(eURA{?swm6Na`c&tOBLO^ekV$a z@EAcE-w$l3-Hpxh;rZ3sxs|QW>DX}CMRYjK|GYXLI>PxILfsE%V&@kpFDzkLzj;#b zn`+W2x+GPRS3sNe)+)-9@9rHX-`7=1)ro2RWjY+VmR&{X8vaJPvGfNOv40O9NR`2; zsKM`$&ioI4{RM3HljKKZ3XOZPwdN%G!4r*`N<&_E&;V`6ok$xp)SiH`Kzr@cE4<*} zsUsuNx*iQ)UE7dMV>46JY|}euTV9ZI`cchmEoLQ zp5Zve31YKTmvfU7iKu@F)cz|&QZga!^wA~+TB^b_KBKrWN6~Ew^@p7r8LJ|y?d(>Y z{5nI^sA6nKB&ik`Ww(q~>kD&BizDr=qdB?RIc&%tqZ4T8?zas%LZ04kzPhVN-tBvs ze81Dy*RCutWV0~T_l&yO%#K#0x!=@hzO;wjW)HyGZs?ALP)<(G9_(#T42=%@%}yL1 z)Q(}z>y!ri0b9FEXXj5{(LtYlz%CdZ)9=WdMymQ`P2+M>xdFprfR1cg-Zs64)25cB z(G&vaS0d(L!!@Zi^7pQ6NH;&zrZz=vLv@IJ@v=$WW-&C?jwe4o70Uk^ps0w}rvP;V zS_1z>MgtJb6F4twNmQ)#A-hr&B!3{k7eNZXgcLXukZ*fSXKlY-l?*X@O0zk~IKOSAKd=>);QaWWQKqlz;0KBRaz3`l_ThBH=^N^Wscp}fOO z^;~qddIgboxLYiKlX%uBiA}U5-z_fF6gTCw+j6rr#v-#L*1QKfxwYJCiM&;f-R=%s zz~wWw)aWEF9rEt=Gmq1*QWjx8%*x7;OgbJEn)MMZjJMjYCSrG5Jtm9Y=CVgeU_g|% zn}@Vk4SC1$G|`&y8a(tj81jqd#M;^O&9%s3f5ogyG(5gFQ_*7+Rn*StmBKO{FO2m{ zfQg@K;~d}Er?4js2ow?pStn`@8@l>Ucz)lN z4AN7;7hVe;AW272NGmRy{Jjmus$ao->4cX;nJ}BbN=s=>{UfRh2$I&g=XS{nIb97( zYZMwoXLFOg=BBSG#o`!Gyv{DW@y0!KPR6Z&n}Mj++H1G&rrpu1xo`AmFjW`1fiHaR?@DpKOy|KPAF+Uy+46Nc5>70&sJ}8F$_sK67CO1!?@3ahB`Aa%tpK$NT ztF_DL#Wkk#$sN$9lRv4HbZTUp^#j=Q+Wjb|leX1plZ|e*`6E`yt-{`v6W;u|nEZqaY~YNR!XO^tp-#-YtpSKWv(YGv-0HP7oseYXGOX4z|M!;IOK{Pc}GHR-QqwJHq# zz!(h2E)%oBx6e+E5v+fC^>TY57V5wMASJV+I49-)>1eJ!F}|`mJrAH)Y$hHX86_c# z-k{Jkq%#x*fI|2x^7Bed5bgvvQ@=e#M<1;gR+@A<1sq0e z=c1w~N%D&t@*gndY%yt2W5oxCLoUCQm<^7Gdad_(E#h_e$P3FkEFP;UgFWfuwi|ow z<~~&OHj~W`Jci!j@&v;1xuun5C{k=6#fGsCBeITc5G`)lkX|%c4VnCMKE8DNJo&>q zk9oL5(B}-qjAJpSZBwjLV=VXO>!OW_o>ElMRL=oo=+a-pnQ zDuqe)UMS_6hE}@c_p|kSd98iL>1Y-tfB16bEqns1L{0A&I>4onZg82=-g^n&5+1B8 zM}zivWx{F}yO0rbh%_xmi_hcs6B}Bi9%Db24>_EWx1OC}B0EPrXMspzT4wk?IsP)?ZDYj%yq>Et81Y6iKp=6rGp+>Q%4t89&GGi-G+3U zgx&D;Hbh9Jj`$zwtXVdIq7)mDSod3ytaiK@7Kg8!jFZtPMa z=&PXvLe~U;cIAP8zob6+CrmJbv?qVAuHaTM$~#8DWyc!Q)nJ`Os+@5N#e)ozo?jwr ztJB*VYVnO*iHVEDdJFURz08852low4eGadGV03(BXmVc9d;-llCg)1kddtNBxf(Cy&KBEmKSP%;tN{ZQP zlf&QH?=kl%d1c(Hnc=SPrJ7PPzu7c6G&dwSDzZzaJlmuEw)~=eMhO>iin3ZP71j0_ zdvsQd-RVNt%sudM?0Cm#)3>v$$~efrOR{r)z1_NoUYpy2?yJodF!b7tI*Z3PJiCU~ zGIN`djz7N~7<7!R!U5>sP#R2W6@Xw0ZLv2`jt#NFR+Cm^>SlWGDEe8zXa(r z$?xhgnLRCyOSC^lFGCtMX(*-c_!aC&gX{J1i6SkiLMj!kpo3q`<&Nv?WX+vperKEf z6*;^*7%=z9_u+q-Vvr)VOd)~mI-d^5{yvug|UXQvQ|_IpDC_wdq{3BN}7k@mR1PX1(J>~!t%THj#1s@Y}= zby#9`Q>!I?_$FxH|MNH`(}{Gutw%f3*gP{2VLF=5z-Cn6AM*-=4cMq9C>G|bV8pA^ z4D}2036|5#Rn`%|yH$P!%pf!naTqj$QmO$}IiO2O$XgIK{u%xfttGBacwJA>4a4xm z(xNIBqoQeWaTmat^R=L)%+#doJJa2N`Qi*t$Pmo|efFma)=qdM&Pr#3kS`@mUg&#V1Ch z!EHDpmA|8GQ3~C;0@LHuQ@GVg&aJ*;qwoUAWEOVVoAn zwz*>a%bk;A;o~xfnn@TnnFUplxWwSK3E+OC0YrDR(cIZ>pBfm1v=HJQQJPoe zXi=-WDYL@l9ss~`#oyxx=a)%g*A z?@N5MP%A*00R8VcmNx&#o7nLsYw748?Q$p=&T;eolxFAnl~#e2G)c9p-X_?!jTfSD z?7yL!pdaWegi`Y*zs=4qVl#R5gRAJ!JUrX<@oTM30oDENihO)`CVHFf*zz*@ zX`42fa__$IZfbGqy|gmE+6H-$;K0aeqEP`xi>0qq?~1ZJyC+>~Dfd(IGK<6+?3-=g zAO;fiixjjznZT~Q*noE*AMFYqhdYpVXQ=;CP1~Oq=M`axZcUfd8v*~IkI$>`uM2mT zS2as@(vD%DzIk>jrh627^0GqFSIl7Yatj#6Sqy-nWR1<(P79)3F{=#Q&&s)is`fm- z)S`u8U11rcKu}zgr}oz?u>s4CLc(pwc*$%x=}h4S(imhjTRUgRC;Lz*ayeoL_)x!w z$>`%vGxu+jKU_(EG|C^&j}6pMu=-woFxry*|3${#IM; z5U2k`@S3j$U};)PYk4ZELnpy>;`=l7PU#pQ$|A}-bzQTgD=^wNCJ(=b-=k7>*AohQ z4JP4-Zv*s1-hOfM5FI<953dp!nv`DSN3U*bQc%QVDzszE2Zv{mFV@1+8Gc(-BF$yz zmr0AqHS*3TOQ|>(O8)v~r+FnUB{Lg%c}8(+UL7tKhc7q~o|q(llims;d-udbcz9?8 z;K7uPvfOHMdhdMkYr?!83eJ8aJ1+%)Mq_I#qRHt@<$kgw0L*vW?JfYrdpP1d4U7BCt z+=d+L-hM}~)7L+=iDwLiu`5H;2mZgv`(q0bDNi)(1wxliy;K(&@+pHj7W>}?GU3_pe+QQ0HvigfHm%R{OTOK(HEzYtwApmFFjouAJu@L^ju{jTZm z(Iz@0LCJxAoT%#YGw7PQ0;x_od5L9OR1M+kB24}bof&+xYe-LCZVA8+EkjGkXQz)I zuDPdqqS1EE1J=!3!bWa5v%9M)wUYv#i>=>r>LFXfwj!Gr`;2rSy z;eHSc;uMuIm_o7MIASt7dfnDBPEAn&m#L>-DR1nG3?w$@ZT-5+a_mtq$}cIXDiq~6j%(|!c9YW>v^Z>j zcfZM{Z}5$7uYe-}mB@pm)vdL512OfDt)UA-H~d}oJaAxNOpotgJXKnBSlrz-KGNlA z4@KxKk7CCtdGa5?R<$;?XeV$jN}F3;eoJq_-cwS>Vi#xS7PG6_3br)j*IJRTz~6$zPCO=J z)VMd+*A^~!k9W|5h|Ou*vDIp29{2EdmVez6{T;+Dy~)qE4^%OQJkX#&b1#fHYo_<6 zj$gqPUt`m_wq4$-F>0-Ss?eZq6@YrWt(CePwptJ<<>S{MUh$l1I0mlCSSwPt*}DuA zgHz^McPBy*ozT-QK~xusGEZpn00h~~7tfv?o}%CKzes?;y^5IM!pYEgA>U?Z7v$$O z)`n*HA6`7VSoVv#+iLxTzIz$%>4L{~F$aS^*l!!1+}X>|&dSM3$<8XyFJ-2Q#3fSF z29R_hI50jI4tPBltI@eSK9O_pMp_Q$H!^M`qc*4TU@fsQw>UR5y)>J^w(Id>w+-JF zm~K>l1{z)zvPwJIFddUoP@G>~)oOADg8i;;DOa?o=;pha{1D%o{E_A9TtmlxZ**;< zYY>oMRzYcA31M?f8R8l?qk>yqFH>tejC~!Ab+S5)TEk950lTP_%`IkBl!}UxQ_qHU z#O$+Lh}G+|_uHKI?$+?$#>(E#!3B`DGmES9l*#Bm-Nh&RXQqPG;G5)+XCluwg6*S? zT$fJpIMFgkd_!9!<47g`_bo}iyuGEqqouX0+tzFL>&CVpfysq$jjCo-c``aLqV>Xc zril*rTLUtI95@gC(CAqIu)ZEHiBUX2)tKAT`kV?lCSN{#@@QulL-&9DGr#-?z2FeB zY3maiX9jtY#?)zp@eOkR@O&#!$DD4K78oDAredW(werI125+B1H=TUPnVOZ7`yjnA z<1#P5xTrd(Lax=BJYN6s$lwqeoC5THIWg|6PQR5wigNS#5;=?iAa#Fz0@56_b5nD; z+a}0x*lEEO@_I)HMT&fmB;{I~5+uV?RzW^PSWk3%pTpa4uNCl?TAFG{I4n=2GWn~C zmYtC8k##6AZENK47)1q4E~~txw1{0&&ManCR$xtGBVt0gPOEo$NXXc$;vuu-loXY+ z1ma?De(|`w$K=3-!XCh$Mknd->1-W2+}t=n+Fx1TT3_ATU1`9o+1TC*BHz!i;v;1` zP)UL>S0bBRrs07)QAn)XH;%4NI=jf33s+c^LXAF)vb{~+)TJl7&Yp;WQRO(w6j)8KH|Mf%6g0&JX+)i!oogP{93)fMGtmDFr! z*ElPc$&aj)FBW|I8EB<-k!n)TV3jiqiVLCfQBqpW$Y7TX8n{wZ2>$T}!BCjy8c$satJVC6*G_v*bq|E9Q0?!M5=FE?G~LT5s*>w)lx< z`V8k!zcr+ga5zfkq}|Tn;t`-R@_mUBO^{w?k9ux6G(g7c@pV6ii+)7t&P&>N0-)>J z#re_NA>JHjqnXGhHQjY}_ZR&7myFz$ba{JQB))x)6;&HPX+>*8Ub?8@fvkW%$tn&f zTn&>`oGx~5TIPeo{IvYr#i?m|1-W@8ocye+20Yr)iTJ|O-p1b6?q+=G79%q)i*Y|U zt(ji|RPw#!rKxprhNeh-7A3*hK-lTMx;ZG7mwsc{s$17I3N=fuK7iL7Aqm%G zYaefG4esFNsod;mFhA{Q()lgzNYfonUp$s6u$0Q%-qE}=93GBMDiMDuCJ_A-m>WN^ ztNyJQxUcq>U%|hb;T2Py1kV`O^g1c0&CFuzn;koTZ1FTEu7 zyW_g@F5N(%X-Lw=%_He)g{3KFB;$Tc4#_Cu<_gm9FqOpY4vbC4SGG>Kw&&wLcQcFf zvqdB~y`zR#Emzz>TA!Ypotr_BoShyY9f|s_6EGDWOVaR2Ct^rUaF;;M;?-^+I+F}e zwM5-x0e{5PE$5agDk^yqAfXF-`y8Xn4OyAP!UOrxquaIrB zf<*}<&a(POnY3$#E^`0n)y_4Vk)Vnjb%6yl($k@7;tRGHTHB}m^JB;B$K!l?gWNe> z8&bBb+FClyeTFV~z+@%fDeNVn+l#KLU$kJOTYKK!5G&=R(L~yHbCUy+>4`=--VYz1 zKYB@(FyDRaCDarTc2;mA|3CurKd=`4L4Ax;{XVuR#P?F~-OVB@|NQpB;rZEyucB-z zaHok?oS#STZ4Q@k?5&fImGEfmy;PFH5#5obW~XPTXBIPAg$PY0>>`o6(>^?&SXrN) z9t$W^vN8*^*m>Cn>P8`7Rrla@inxO#BolckDov9P?lv<3`PMaS&OjV;jn>*?(2G)*l~#fGaTS1>nibkUv(-7rmI*7)z2&RUs5X=u`TXU0cE za|4|?gyiYo{^c0~Uggb47l(W6D|pvyL;ab$7c$1*B|ixgQL808^UmEYh0ry%B@t2Ypd%k3iiSd-1x*Fj7*M?4Gs7m7&5?E*XSBrS_8`e zbdLA>-HamS5zO2QPD2lI^f+BQkv923?H*TMTUT3ECOVI+yPE^c(es6-mmWMLHPsLv z#!{8y0#*U1ppaEs*WS@-f#e+K7ETh4uPoMsm|0d+%B>Jp2&zSFPF&L@(>ChNdMkX& zV(cY`k#+bxKs7@HW_B(#V!GQ@islfA5O|g-%=~)X`a9$Wzjid*gdL`~W{@}i3+qja z#nn)ROzIy+1iiKSgPbBIiWUdfcSMMVH8lnk2umvpDyb#?Zi37JY; zr|uf}LjfKefKQPxf$)7C{rC}0$s1%aQtMJA) zu~gz@A^NH;y&{EKR*+Yfo6_c=$j^%|LFv&}G1HZq!)0WOQtoA?J;=%-C0RLAb$^f` zB^wxxC#GXlt8|SJ9d^HKVHOrWC@NNzqxO(+Cq2Y#v>Eih$SU2DaL8`L*FXyks-EBr zzO|>ipH?j8^GZsY7-Bbf_WR9lo6bEb;EH)fTu}wL@RB{L^7K_A7)#WT$9S9y!l^1@ zmKH#^4^uaGg+S3pRGJ>0!P<*)8=-qO4+d+iq3T!;jaMR;h`Q9qUM!kuR5$B;dL4F` zp?7j&JO=1mWYALuAZ~e8+-GRkIgvzM3$D-&(0_r&ei3!=i7UkJmbz}Qop0r)g-gl3Z#|^{rk^Yxs zW)TY@Kt7cE2(uuUgWOPB1H!JlyHDE;b#N@G1{-N*jqFE?!KvgDI2T7q+WR`2`!rh2 zyHt8ri(Jz*G#Z73`plH8tO%_We)Y~)+!3<2FTwNw3&x_Z^;ewl=VO~zQln7C%R5Ky z)sl^g;9MW5zQbdyn&tLDvt(GQuGOmK?K*E)bNKYlD|^wN03{2dXN4t_G}WLucS`D^ zsykSrqbqA3^Yw>(-WUqfm*lO-FVD!q>dMsU%zk1J1v2$0dRKu8HmW8O|I|c0?!;}%F{!r8-_z;In#^Tq-W1$RyOoofl3!ev zlU~-|=XBsYiVj6b#^Q53&*;iP!16F1`n2*pS#{Wu&aGBWM#e^mNyuaAZPzp_)O}3? z2xsBjp*VXiM%k032`YJVNnO}1Ew3ud;i?=#$fz3|CH2fg!r&zeh5iOc)x&x3VbAc) zL40t9JHjqy7jg1|b}uhwmses#x(A2EyB|Z9XyJKVm!d6?`ScoCYFAxG4$dRf$ zfVVUlu^hOuzD^;9zLfw$`Ty(bJG>gpuQdOW^|9OCRYes!iKK{-gmTU~=L`}EB!WOF z3q;NtiYh_@m1FBwx2Nsi_5^!oZ1;@YlaB3~@!H;T8qe-Idwm$g5Y*GV@7~`H z-~GM~08K||c#H)qSj^-5$6IqrGg_krv=+b{QR4O87xzUn4s*N2DGrWnjl+&rZ8%n% zUEV8428vOwa9Zb3xx8A;5E(XS5sM$7!&IE(D_XyvNHoMR&2{IMhANUpYnEqqV zXdM~OkGRj_<?*8lB9R$yElU6{;SeXJBZ2Di7QcTRRVq&Yu(r3{F3T+U*^L zWl3)|J`!?!jTWgvDH5bs${;A|BDKTl74V*%z5C}UTQllqFc@Mtsh(JX)vNr=q)RT~ zxVSN|$2?QwE*adW;hDAaF8h_>iABWA+AJcI-2}(si6MtpxKN`JMS2K>pa54D5JLk} z#9M@xfuLCly^5Pax1}ElC!!jNGYFjrx%<1fFF}X$;`m@2Ho@CExP$=SsL5E1v0>u=p5-I0=Lc&Gbzwu?qqxF<*FKRmv-($a93 z-`dsOLTJX?NaiNFKRA^b$)$? z@X3Uc!Qpr;9L0tLNRi4WQ>ZobTi8w}$tN;6Y>u2KX0D%N4^J12%V4IT{%I2fpsvuY zrm1Z9G5&zer4^e*Nq)dNIytw#xgM%~Z1zYMBQ_26?j4565V9>~Je_i=>ySGoLSGmRwLc>5|d3J=?)$0f(hob)QfV1*B zo=oMasp5VKi-L(FG?#TeHNWw2gMZ28^zuYpjLD(P`}k5tKh3V!8Qe~f*Jk$srv@y| z6`+FHJUV#x@{N<&13VBjfd~vmeX%Gu==b@Zn36ZRy|%oOc9Ix8F-IEXa-`vn)8{XD zjf-%{ky0rFx}l2a?+@&lz$BBq#llROt>G(2g+5QIys~$6;4(s^pBr_U#JYrDGPP3q zY}$N?rk_=9RK%fTD?rgf-!fm?4)Wj)`I_m`JTconNLTLf?)?j}4^d*2? zk@?VA8m^jLLm}Nd&ts+e+0tyOn3)+Hk53gx-@*Msw)?AhBMhC`XdZ9@v6gUZd41Z~ zMK#2L9zE((C5Yr6N@p*4;Ug9&x&d7Xll5%{NkBaU=2cedKMQ~CRT zK`>#IDkqKVK^O-v%XYx)5LF6-8=$=YM#30i2&fiAy$*EFA>tdDi^B}%x0SyWj60=p z$3Q0rPK!eQm3#ySCdfB)MY)QJslQ zE?>x(R@b+856(_uhaMi6PvN>zO87T$g`eN@;BIXc7huX+%%|bkbbKgTEJ58<)eig1 zGmczmFa;e7ox_Ru&hN}dJ85By=I&K-W&gK^G&yi0m z--CW4q}*b9Bs`W)503Ahnzh@NpYR0nDYFzL8T6h9Z+8txa8#g-5lP7dLl`X1AMbw)ZV7@+ZtLa z4J|lBKvic7PQVJ&3`ixG=T_F?ggd>wf)#AUQ-@M{bSi(<-B?$R z;n~x-@EBEX_E}b8klFlRozm`hwzHQG7vtSM7O0*Qv9M~2P4A}j`boXQc^(r-oEZtg z;ASZC;*`ygRlcBgQD_u0+X<2h@i8bwmS@-QV~+tM{i>%6 z>j=4qJWqX7qwY{rJ(+ymY#PF{Q;NtJ>gEn9{FboN5v366u2@*d%Hx zqKyIMcF1-JzlA0-{|q<-#BExI?;!4?-&cMtm7C$EH=Aj27a_xY`{e4`_1PnEgntG5 z{-N?;?|)zUmy_N7lhZd3R<<9mZ{2OpK0HX?X5{Z*W0y~ka*4Yg_1!%U9rY^HH(8Ch zI`ExbDW)(kha>f>=ih9Q>f73zdhXS8Tt59h6Of|KWOCWUY#GkERgfFIc=`;1AQ8#| zbvh7{!RH@-)Vft%SS}ami%<$o#$%H&;0#CVj%XhESC66MHMs{ZYOP=I>89rnmPdN< zhM|dYJmNBrP`OlAKb6Ds4G|=LJt7&?7L3NH9!;0~4DY(=Tm_j)VfA#;I0|Zq98(!I za9>^Cu*VM^0m}FG97Uti zpx}M?8a`IuzI=6sojii?`%kbOay?WJ{P19R=h3U@8*2~u*B8D~H*@?j^$k+y=*iXN zr$_mT+FMlIy_#F~m&}W_)xwc5-vXA#QlILH1cmtI^xS zgP6)~G3asR>7&h&`YxS+G@6XMY-51WVc@Y&(b7OKU%{qx8KS|0$+>-=&F}KbT?_(+ z+J`YHG+@T;k||8U0;CNZ>;Z?zJ)9U#r}E|Hb)aNJEaTXdmR6#37>FFgfiP5hVXHZ^ zzB9M6yE>s@f=n?8*>co!g^nRzhr#8UItEvFgU5$EjON2%p2@5{iCQaK@L1X6h>2sB zxKt~)(T&UX{8@x=1wL56%c2L)FNiFkoew_*u?ggPXi*iFabH2~L_HGZeN_qBs{cVr z_x_jI@6PC_(0fG_v>RmW$4{@W&rY9!eSZ(OtJZS=35O$gx^sB-;uzaLT3bwi{Z{Pw zEPJ1<{uKb@c5T-w;&J-)bpj&La7hRZ-1CWzgJ|A#xby$I&l$#$(a9Hx@%j zA*eDu9@H!J9=};*90><3$RsZgqx zMftNsD!B#HO>s(WnqN4~EFGRE7D8&xpxtMR01pwWin23ENdc7w$jcx}`2;j4!S{Xw z@v@5YK_%V40mK7!OnzJWM=Cs8K%5VE4(#^vvnSX0VP*Z7;B6?H{tI0%7EQqa{Kf;hfS*xwh^ZfcBi|0RiTmLKqTau67&Lh1j{N; zS$j$ScnYg8%22QE??a0LOPG#;_~_+M}g5oZWXqo zZ>r47vo@PGG7Ou-cHdwysh^&fw9<9z5r8*c~XX8;brApS0McG*EgPq z29~HR_2ttcxkjd!2~|^rVlS-yOJzk1XJU0_Q7YqTT!-g72AkJDc?5489@y*(cn+F; zqJW7&$>`vK78jVVI#H_{@GF>NqaTl48lec#Lc*_TSOxp^&FdFHHGT02WcNM;+o4E_ zJnxV2B>hhShCO`r_`$~J{>pl$@U>fk&xl+sz)7f-^F1ilIje(+8Kt@JWJ;xah=dbP%>G0Sz$_~_AbvV$l` zP3pMYlu!_u1bQEZ;Z+iq3<{srzaVE8Hn!(_n!39P`SWrYY!XnJFozUy1!fykC$?f5 zqtg-?8jU3~lZBPF!*gg8z!_XQ!)ZMJ(BN<=820%CK9i=nnp!xUi;87Du0%}dh_oVw zOvT`5o>xA-jD+FZQNTn52`~aZblYTVmDD118FUi6L==$wdhL@~KDQ<1du858@W^R) zE&w8sQlUMCp!<%%F8Fa*g~QF^&0E$#R{z_iHHQR4yL`G z_{N5odO{swcpG}_YWnNwACL{PNMO40Hm;t`A;mjdy2S3-*m#?D0<>3(*&;9i<u2s~G~CgbY(nS&w#l2PnrFU3emV&P2lZVl0_S zMbMfs7+qPNn9glB*g^x?=wvaKUR-_f@afBE?_NFY5(Qx`#}^p%4G(zyUe`o1HMd!? z$&sKC596qfO0mks<&9swxs1l)0#R@Iruc$8{G-bIh(*pDIRoaf(}d{~+b;l7TrnNPDULD~l${_vD{84A=0$YMq5nsptJV$G<(=v%2T@)j zMirzD^vT=TZ*H~--@LxMfS`{WiYR*j4m|KTl^?x*d9{0gBY%9bw)lSjgKsKVPF5Mj z!^^?8w41>^cx6RsKN9}5AtdZ9fq&QQLEi}~^^45RYizBu*x73mqo}r0It8FS( zD$JI0*;y=ID9x9b*0zuLPp{#S0sA2Xp>Zy(jGZN6Z2+5Fn9UcaQ`mI61TR5;`JMTY z->k8zcvg!}tuh)qh?>>y0+XZzF~nrX<{lOCdTD|njVkAoD5N2xEGSNK=JyXBG zaocsO!0`V1v_>lE=Sa8=F(wy)`Y4|sI;(tqogRgYMjC~{cmi$#!|ckp^D1f7EW+eg z%a|6Q_ zos7wN!O2Vxn=N5^=%|#6b4$zE`p*6%>D1Rytb)a7T>I7s`YZPCuV9QSFC(%a~AyK}KjDp_;hr549x;PtJwjrWAO`Vj~I!@eFHbELWF4hZWu zb%=eD_)v#@GCeb!E6i3ql$S)uvdyKc~P8{bR7`6gE$~V8+&mXM$Pn3_PXZ&fx6N z%gJ)djB$?G2SfJmb`pav)Z)Mjx23g2L|`h$bPL^3s92EhYxpx5tSzmPKe z8PF9O3it*CKATRanAz7A+stS;x|;*|~Cd7T}SPac1Y=uWjw0JiJ7VLm%{+To#o>r`FlE9xMWi_fv`D z%I3+lr||Gr-bR@Uaxa-Hl$dP6c*v=Dl#j;b0y0&=q$wn7xyGhtbn$395G#MTAA?(l zG6+_$i*qu^2CeZ|!p&Un1=2K}I&LxEL zM<*Rxy+O6zKY`z&zoU!=)eKc{tnPMzPeQu+-%AFliv!q^%*yKg%=9SKpqaS?NJB(`<60&f0R zb6d+D?c^cVJ_Q`JAVPS%rnVcjh{vNJi4y75OtCNvJE&=hnX|>&`Q_F1-GloVkgFh# zFIY_k6y)DlzTj%K3IPik&nb%G{P`ME68Pbx5RU+2$tIr^_I?fWo{p|2W@&fD+avNN z0Khn42%AY97KI9Q8w{?H2?}*&YH91OHnoBg$o;tPmd*|WnXfVMa5N2OF}qDbsbtXU zl~$kK8SsVzF)UeF+&eyhcJ=o8yBGbRaQb1WN8yRhVSQ+IMZ@eRQs`8bSs)P^baITW z_qk88KRb$o|NI2zG6=8mi^^Xdc{ySkriFHk+G*3dL<)nJpE}MZ#s&mdwOt}sIMPqy zjY7wL#Qq3^4DzTS!EuHTIAl4LouF9xcK{_v{Cp5E-=nS=+JZyl)+$NVFTt^XGrM}Y zyOc==tSadceAh4Gwf_tIBXBQYUr`9MvS{AXT zn?{*C*%`)5qOr)(K+rtICH9bM3@%I3FJw~1B(ex&%~n27xJL9ngl++`t)r8~=3&xC zqEe+dIDi(}>2vGNN=ywl^Lu^KSaL42^x*Uw7-g}y7gV-NDyGpXo$Wa0_@p*o$cQOD zfI}BMcuGv{R56M8g_-OT-1{#c41v}D37icvN})sU<7Y9E+^ztSoY}3@J4GCsAuMK2 zZOvwP0j!RRq^iOy1T^rsf_w|!9Ga)zB$f~)ffpJKgo0&tUWdXYG%3IwH|_?d0*nH0 z2#e709UXSR+g?35+FqC+8_@G7;P1bO@AwaJwVy9|M>470;aWPAU)f8?LT-&flfHhI z>kV&%6y)o3{|x(96Q!x9r2|jv?&xj2UE9vNTjQP&o8nkg?d@AlFc1w5M5%WaAX*F6 z98BrvbF*0tc+j%N^1{mc_TkB6Xab^$59cb{egem`>fC<2Udy00-swYkXBFP(_n!*d z$((+n(=5OwwgDxRjFYhqiTlT6l>T8XJ~9@y{H6@9l+jIOXo<|pmuty1 zjnt0o#7H10FBRarxJtR&YQwZnn_pwoyBr#`&SrH7hewAYo!vdVeg%Y^&lOy?MkSTe zxLt(4+=P0#6eM*Jsr>@IoR6^#19Da$5u06l0M*~OF2>>GPr!62vHUd&(xm6_ zj=3qc12SNB6dMab-^({5t@FPG(ZVH>ltm~lhg_v9`cLVsuY;@XOR0h4(c!zCx(d#Fw0W*Y*`e4J0>?K-Fj)AAwnsS*ii@C-5gS z8#2|G;B-)jgZU6L532B+ToUz0Q7-wbe0hCqd2Okunv(j}OkQ zY_FGx17S}uW=kAiuPB3SXIGD(J&4$A8wj|b+E#jF51~mWsHv0PGqf^!OE?-(&@|lZ z6}H^QNzAYXot#MJVSJK>dJVWO3VCQ{xAhRZ+K6O^ST2R4NvDQN%xbfM!n4V)0DsfEJ)zNLEVsCKdiETI zr7Dk@0wt!=VM>6FMbnagI+fVV*1_bF!c|x;1_r*5Zc3!qfIR-m26!0S7DP=bgs%VY z7*8xQ`ZWf%Q9dXdp9?dS+`yuKX>wK~lxcv6#8Wr`*<>j8P=gjVh)`sNW)~O-B_Y*R zAI>r`6D;Jz&j!448CXBPdh+Z+fp@3287NnA&8>~9M(rT$uJJ=q@EbSzTkh3EJiOBZ z8Wq9l@OWZ$G6f4zu+&?~mltP?0N*bFDbVWH_CEACfdl!5R|YN{dj2U9h-w2`alqpn z8IlU5Y60D7*Rhzr=0M1-Vi1T;-D*n$+nds}ToI50_xNQPnFO^jy`R}1W{j70KDXUsG^q_vi_<>_%7Uep!~KWXudt6_ z53|%#mD!{*C}eU8o52*&X)2?H&h6Lvf@T8;qx4vui4q(_FLs~8jYU};3Qa$&d?%{p zNM(MvX-cZi2ppz4ZXrh=klI(nPL4`s99TMf0cRcPSi?S7wTFjlG?Z3UbHl1x{?rP& zIl7Rap|2s|`a5JUFc!)it9#d9P3FsMyPF4R7cWlluk9W!Wl9^RiJ3$OJKiqGgLbE} z8!zx4KHdxYSI-|mdHyiPY`)#p*vD=+H?+9xiG)av*ZMVP17lc3{ix%1T^CQ`h4t&$ zD5yS9CO?4@K&}Ymw7E}8SF{PMT@wI*B0GZ66wU?gv~$XH^J zmMvn5Vk15)jR5|K1Z#Rz+x;keT`bPMsF~>y>^qwYPMLNE=vHGWRi0;i@Qf>PhP!)G*O~Z=~Y&p z7*hyk5kuNR? zz2Qx@V_9b3>+@%{0=Wf}j5m-FBd8>b_W+lHqYI)w26Gy)1?2aiRMQI7Ge*{_#>bl` z7WU6zyDHBGg8Ly*<-d=lSJpRoE*?LB1&E+Z<$QH*DGlO=lN%>{tEr&PWsA2pll3oA zEin;VdvyKe#i5YYdatI9(n%uUt@Sn1sd*w}vI$@QrqI!GtFft>V-F7mBLHk29ZODN zAox{CmvR8WgfIvMz6)hovfkJ`IlH_@2_k}`AuJ$FXUIy2+ZBk0LjysleaNLy>t$3H zon?-C+y3!sChjVqpzU{wkHH7rjD|VKEuhVhPM; z~3L*6x^%dE{`mRpSJw<7Tc@!@Q&K4w z$^~Mb7G^t4y3!pss7ZKS7qeeuPz^y|^kew_*-J1W!ZxA?$j_&N8H20x*$4FYltvJd z4on!!DrVBo9}MR_uz~arOol=V%7(uST~-9RKxyLtkB2w81X&;zOB6ksdhRkoa8-oJn!iTYMZ?gccX_ZQP6nfy%Y!PUcJ$f(l~ET3Y{bwcRw z!Z`eRXzc;WOq|O*Z#C33_mMcAcxS`y{#ur{d$i>?Xhw+H=1!r)0)U%1u>OosOv1(t zFaQ8BArCQfZniuNc(-|MX?ttuc>m<=*_)e4kGu}nT(g)~ZuJdLjRM*-6E-M?ER9mA z4o{Bh>CH{`bd9CE6K?@q^`}!Qs>}%pW!nFV3+yFOxbZSEey)iI|g Date: Thu, 17 Jul 2014 01:20:19 +0300 Subject: [PATCH 37/58] Tests for DcxImagePlugin.dcx --- Tests/test_file_dcx.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Tests/test_file_dcx.py diff --git a/Tests/test_file_dcx.py b/Tests/test_file_dcx.py new file mode 100644 index 000000000..9a6183651 --- /dev/null +++ b/Tests/test_file_dcx.py @@ -0,0 +1,45 @@ +from helper import unittest, PillowTestCase, lena + +from PIL import Image, DcxImagePlugin + +# Created with ImageMagick: convert lena.ppm lena.dcx +TEST_FILE = "Tests/images/lena.dcx" + + +class TestFileDcx(PillowTestCase): + + def test_sanity(self): + # Arrange + + # Act + im = Image.open(TEST_FILE) + + # Assert + self.assertEqual(im.size, (128, 128)) + self.assertIsInstance(im, DcxImagePlugin.DcxImageFile) + orig = lena() + self.assert_image_equal(im, orig) + + def test_tell(self): + # Arrange + im = Image.open(TEST_FILE) + + # Act + frame = im.tell() + + # Assert + self.assertEqual(frame, 0) + + def test_seek_too_far(self): + # Arrange + im = Image.open(TEST_FILE) + frame = 999 # too big on purpose + + # Act / Assert + self.assertRaises(EOFError, lambda: im.seek(frame)) + + +if __name__ == '__main__': + unittest.main() + +# End of file From 3c8f858aadbad93dc02aae611fd96e0ce8ecf02f Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 01:21:56 +0300 Subject: [PATCH 38/58] flake8 --- PIL/DcxImagePlugin.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PIL/DcxImagePlugin.py b/PIL/DcxImagePlugin.py index 631875e68..0940b3935 100644 --- a/PIL/DcxImagePlugin.py +++ b/PIL/DcxImagePlugin.py @@ -27,13 +27,15 @@ from PIL import Image, _binary from PIL.PcxImagePlugin import PcxImageFile -MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then? +MAGIC = 0x3ADE68B1 # QUIZ: what's this value, then? i32 = _binary.i32le + def _accept(prefix): return i32(prefix) == MAGIC + ## # Image plugin for the Intel DCX format. From 665293e9b9ddf19264f55e26498fc7092d9c96be Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 02:38:57 +0300 Subject: [PATCH 39/58] More tests for XpmImagePlugin.py --- Tests/test_file_xpm.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Tests/test_file_xpm.py b/Tests/test_file_xpm.py index d79f5fbda..7eef04676 100644 --- a/Tests/test_file_xpm.py +++ b/Tests/test_file_xpm.py @@ -16,6 +16,17 @@ class TestFileXpm(PillowTestCase): self.assertEqual(im.size, (128, 128)) self.assertEqual(im.format, "XPM") + def test_load_read(self): + # Arrange + im = Image.open(file) + dummy_bytes = 1 + + # Act + data = im.load_read(dummy_bytes) + + # Assert + self.assertEqual(len(data), 16384) + if __name__ == '__main__': unittest.main() From 8db043b35f7d587d4a5db23e72db3a335dc88eae Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 02:40:14 +0300 Subject: [PATCH 40/58] flake8 --- PIL/XpmImagePlugin.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PIL/XpmImagePlugin.py b/PIL/XpmImagePlugin.py index 701a23b64..517580895 100644 --- a/PIL/XpmImagePlugin.py +++ b/PIL/XpmImagePlugin.py @@ -29,6 +29,7 @@ xpm_head = re.compile(b"\"([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)") def _accept(prefix): return prefix[:9] == b"/* XPM */" + ## # Image plugin for X11 pixel maps. @@ -86,9 +87,9 @@ class XpmImageFile(ImageFile.ImageFile): elif rgb[0:1] == b"#": # FIXME: handle colour names (see ImagePalette.py) rgb = int(rgb[1:], 16) - palette[c] = o8((rgb >> 16) & 255) +\ - o8((rgb >> 8) & 255) +\ - o8(rgb & 255) + palette[c] = (o8((rgb >> 16) & 255) + + o8((rgb >> 8) & 255) + + o8(rgb & 255)) else: # unknown colour raise ValueError("cannot read this XPM file") From 1e24dcd3170193ff3485f6053a217cb000f27af3 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 10:42:43 +0300 Subject: [PATCH 41/58] Check some pixel colors to ensure image is loaded properly --- Tests/test_file_cur.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/test_file_cur.py b/Tests/test_file_cur.py index 5dc096968..54bfe84fe 100644 --- a/Tests/test_file_cur.py +++ b/Tests/test_file_cur.py @@ -15,6 +15,10 @@ class TestFileCur(PillowTestCase): # Assert self.assertEqual(im.size, (32, 32)) self.assertIsInstance(im, CurImagePlugin.CurImageFile) + # Check some pixel colors to ensure image is loaded properly + self.assertEqual(im.getpixel((10, 1)), (0, 0, 0)) + self.assertEqual(im.getpixel((11, 1)), (253, 254, 254)) + self.assertEqual(im.getpixel((16, 16)), (84, 87, 86)) if __name__ == '__main__': From cf8f191c54aaec0d39938edbb12f3fd37b16aef6 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Thu, 17 Jul 2014 09:51:44 -0700 Subject: [PATCH 42/58] Updated Changes.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 21166f1b4..4ea730cf6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,7 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ -- More tests for SpiderImagePlugin.py +- More tests for SpiderImagePlugin, CurImagePlugin, DcxImagePlugin [hugovk] - Doc cleanup From 14d1ac6389fc47f9c44210991cce990f68d0b185 Mon Sep 17 00:00:00 2001 From: hugovk Date: Thu, 17 Jul 2014 23:23:50 +0300 Subject: [PATCH 43/58] Rename bad variable name 'file' to 'TEST_FILE', remove unused 'data' variable --- Tests/test_file_xpm.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Tests/test_file_xpm.py b/Tests/test_file_xpm.py index 7eef04676..16a811a4c 100644 --- a/Tests/test_file_xpm.py +++ b/Tests/test_file_xpm.py @@ -3,14 +3,13 @@ from helper import unittest, PillowTestCase from PIL import Image # sample ppm stream -file = "Tests/images/lena.xpm" -data = open(file, "rb").read() +TEST_FILE = "Tests/images/lena.xpm" class TestFileXpm(PillowTestCase): def test_sanity(self): - im = Image.open(file) + im = Image.open(TEST_FILE) im.load() self.assertEqual(im.mode, "P") self.assertEqual(im.size, (128, 128)) @@ -18,7 +17,7 @@ class TestFileXpm(PillowTestCase): def test_load_read(self): # Arrange - im = Image.open(file) + im = Image.open(TEST_FILE) dummy_bytes = 1 # Act From d30eb007ef26dff16d788b2070737f3bb0f2c2b3 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Fri, 18 Jul 2014 10:40:08 -0700 Subject: [PATCH 44/58] Fix scrambled XPM image, don't mmap when load_read/load_seek is defined. Fixes #806 --- PIL/ImageFile.py | 34 +++++++++++++++++++--------------- Tests/test_file_xpm.py | 5 ++++- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/PIL/ImageFile.py b/PIL/ImageFile.py index adb27f2bd..5e4745d76 100644 --- a/PIL/ImageFile.py +++ b/PIL/ImageFile.py @@ -133,11 +133,27 @@ class ImageFile(Image.Image): return pixel self.map = None - + use_mmap = self.filename and len(self.tile) == 1 + # As of pypy 2.1.0, memory mapping was failing here. + use_mmap = use_mmap and not hasattr(sys, 'pypy_version_info') + readonly = 0 - if self.filename and len(self.tile) == 1 and not hasattr(sys, 'pypy_version_info'): - # As of pypy 2.1.0, memory mapping was failing here. + # look for read/seek overrides + try: + read = self.load_read + # don't use mmap if there are custom read/seek functions + use_mmap = False + except AttributeError: + read = self.fp.read + + try: + seek = self.load_seek + use_mmap = False + except AttributeError: + seek = self.fp.seek + + if use_mmap: # try memory mapping d, e, o, a = self.tile[0] if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES: @@ -165,19 +181,7 @@ class ImageFile(Image.Image): self.load_prepare() - # look for read/seek overrides - try: - read = self.load_read - except AttributeError: - read = self.fp.read - - try: - seek = self.load_seek - except AttributeError: - seek = self.fp.seek - if not self.map: - # sort tiles in file order self.tile.sort(key=_tilesort) diff --git a/Tests/test_file_xpm.py b/Tests/test_file_xpm.py index 16a811a4c..4fc393808 100644 --- a/Tests/test_file_xpm.py +++ b/Tests/test_file_xpm.py @@ -1,4 +1,4 @@ -from helper import unittest, PillowTestCase +from helper import unittest, PillowTestCase, lena from PIL import Image @@ -15,6 +15,9 @@ class TestFileXpm(PillowTestCase): self.assertEqual(im.size, (128, 128)) self.assertEqual(im.format, "XPM") + #large error due to quantization->44 colors. + self.assert_image_similar(im.convert('RGB'), lena('RGB'), 60) + def test_load_read(self): # Arrange im = Image.open(TEST_FILE) From 31f8da78b7395b64bee8077a81a6d30b3084cf2c Mon Sep 17 00:00:00 2001 From: Hugo Date: Sat, 19 Jul 2014 00:31:43 +0300 Subject: [PATCH 45/58] Update CHANGES.rst [CI skip] --- CHANGES.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4ea730cf6..da7ffcb84 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,8 +4,8 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ -- More tests for SpiderImagePlugin, CurImagePlugin, DcxImagePlugin - [hugovk] +- Fix Scrambled XPM #808 + [wiredfool] - Doc cleanup [wiredfool] @@ -16,7 +16,7 @@ Changelog (Pillow) - Added docs for ExifTags [Wintermute3] -- More tests for ImageFont, ImageMath, and _util +- More tests for CurImagePlugin, DcxImagePlugin, ImageFont, ImageMath, SpiderImagePlugin, XpmImagePlugin and _util [hugovk] - Fix return value of FreeTypeFont.textsize() does not include font offsets From 3c39a44f6e5331432a86d486449d7019f90728a3 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 19 Jul 2014 01:45:57 +0300 Subject: [PATCH 46/58] Make _make_gamma_lut() public --- PIL/ImagePalette.py | 2 +- Tests/test_imagepalette.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/PIL/ImagePalette.py b/PIL/ImagePalette.py index ee3c22544..67bf593e6 100644 --- a/PIL/ImagePalette.py +++ b/PIL/ImagePalette.py @@ -134,7 +134,7 @@ def _make_linear_lut(black, white): return lut -def _make_gamma_lut(exp, mode="RGB"): +def make_gamma_lut(exp): lut = [] for i in range(256): lut.append(int(((i / 255.0) ** exp) * 255.0 + 0.5)) diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index be82f4dcb..af742edd1 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -44,6 +44,25 @@ class TestImagePalette(PillowTestCase): self.assertIsInstance(p, ImagePalette) self.assertEqual(p.palette, palette.tobytes()) + def test_make_gamma_lut(self): + # Arrange + from PIL.ImagePalette import make_gamma_lut + exp = 5 + + # Act + lut = make_gamma_lut(exp) + + # Assert + self.assertIsInstance(lut, list) + self.assertEqual(len(lut), 256) + # Check a few values + self.assertEqual(lut[0], 0) + self.assertEqual(lut[63], 0) + self.assertEqual(lut[127], 8) + self.assertEqual(lut[191], 60) + self.assertEqual(lut[255], 255) + + if __name__ == '__main__': unittest.main() From 65cbdae4492061f824bdbb45ed9450d91ad85162 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 19 Jul 2014 18:46:12 +0300 Subject: [PATCH 47/58] Run nose in verbose mode so we can see the tests being run/skipped. Override __str__ in PillowTestCase for nicer output, and make sure all tests are derived from PillowTestCase. --- .travis.yml | 4 ++-- Tests/helper.py | 4 ++++ Tests/test_image_tobytes.py | 4 ++-- Tests/test_pyroma.py | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c9c1e75a1..942ee95c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,11 +33,11 @@ script: # Don't cover PyPy: it fails intermittently and is x5.8 slower (#640) - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time python selftest.py; fi - - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time nosetests Tests/test_*.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time nosetests -v Tests/test_*.py; fi # Cover the others - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* selftest.py; fi - - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* -m nose Tests/test_*.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* -m nose -v Tests/test_*.py; fi after_success: - coverage report diff --git a/Tests/helper.py b/Tests/helper.py index c00e105e4..64f29bd5d 100644 --- a/Tests/helper.py +++ b/Tests/helper.py @@ -19,6 +19,10 @@ class PillowTestCase(unittest.TestCase): # holds last result object passed to run method: self.currentResult = None + # Nicer output for --verbose + def __str__(self): + return self.__class__.__name__ + "." + self._testMethodName + def run(self, result=None): self.currentResult = result # remember result for use later unittest.TestCase.run(self, result) # call superclass run method diff --git a/Tests/test_image_tobytes.py b/Tests/test_image_tobytes.py index 3be9128c1..6dbf7d6f2 100644 --- a/Tests/test_image_tobytes.py +++ b/Tests/test_image_tobytes.py @@ -1,7 +1,7 @@ -from helper import unittest, lena +from helper import unittest, PillowTestCase, lena -class TestImageToBytes(unittest.TestCase): +class TestImageToBytes(PillowTestCase): def test_sanity(self): data = lena().tobytes() diff --git a/Tests/test_pyroma.py b/Tests/test_pyroma.py index c10156cc0..295ef1057 100644 --- a/Tests/test_pyroma.py +++ b/Tests/test_pyroma.py @@ -7,7 +7,7 @@ except ImportError: pass -class TestPyroma(unittest.TestCase): +class TestPyroma(PillowTestCase): def setUp(self): try: From 64bf7d466f20e0036cc6a45d8bbbee0f9a0f03ac Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 19 Jul 2014 18:57:21 +0300 Subject: [PATCH 48/58] Fail fast: -x to stop running tests after the first error or failure --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 942ee95c9..09e523c39 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,11 +33,11 @@ script: # Don't cover PyPy: it fails intermittently and is x5.8 slower (#640) - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time python selftest.py; fi - - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time nosetests -v Tests/test_*.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time nosetests -vx Tests/test_*.py; fi # Cover the others - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* selftest.py; fi - - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* -m nose -v Tests/test_*.py; fi + - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py; fi after_success: - coverage report From 0c12058e37fdc9decf8aa98bcced71cbdfada55c Mon Sep 17 00:00:00 2001 From: hugovk Date: Sat, 19 Jul 2014 20:21:18 +0300 Subject: [PATCH 49/58] Use unique class names to match filenames --- Tests/test_image_array.py | 2 +- Tests/test_imagefile.py | 2 +- Tests/test_imagegrab.py | 4 ++-- Tests/test_lib_image.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/test_image_array.py b/Tests/test_image_array.py index a0f5f29e1..c5e49fc39 100644 --- a/Tests/test_image_array.py +++ b/Tests/test_image_array.py @@ -5,7 +5,7 @@ from PIL import Image im = lena().resize((128, 100)) -class TestImageCrop(PillowTestCase): +class TestImageArray(PillowTestCase): def test_toarray(self): def test(mode): diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py index d7f7f2a56..78fb3427f 100644 --- a/Tests/test_imagefile.py +++ b/Tests/test_imagefile.py @@ -14,7 +14,7 @@ MAXBLOCK = ImageFile.MAXBLOCK SAFEBLOCK = ImageFile.SAFEBLOCK -class TestImagePutData(PillowTestCase): +class TestImageFile(PillowTestCase): def test_parser(self): diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py index 2275d34a1..13affe6b9 100644 --- a/Tests/test_imagegrab.py +++ b/Tests/test_imagegrab.py @@ -3,7 +3,7 @@ from helper import unittest, PillowTestCase try: from PIL import ImageGrab - class TestImageCopy(PillowTestCase): + class TestImageGrab(PillowTestCase): def test_grab(self): im = ImageGrab.grab() @@ -14,7 +14,7 @@ try: self.assert_image(im, im.mode, im.size) except ImportError: - class TestImageCopy(PillowTestCase): + class TestImageGrab(PillowTestCase): def test_skip(self): self.skipTest("ImportError") diff --git a/Tests/test_lib_image.py b/Tests/test_lib_image.py index e0a903b00..1a16deff2 100644 --- a/Tests/test_lib_image.py +++ b/Tests/test_lib_image.py @@ -3,7 +3,7 @@ from helper import unittest, PillowTestCase from PIL import Image -class TestSanity(PillowTestCase): +class TestLibImage(PillowTestCase): def test_setmode(self): From 15c92359ccf750d79b3474b95aa815149564f15f Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 20 Jul 2014 00:51:26 +0300 Subject: [PATCH 50/58] Merge some similar tests to a single file --- Tests/test_image_filter.py | 4 ++++ Tests/test_image_mode.py | 21 ++++++++++++++++++++ Tests/test_image_transform.py | 16 +++++++++++++++ Tests/test_imagefilter.py | 37 ----------------------------------- Tests/test_imagemode.py | 32 ------------------------------ Tests/test_imagetransform.py | 27 ------------------------- 6 files changed, 41 insertions(+), 96 deletions(-) delete mode 100644 Tests/test_imagefilter.py delete mode 100644 Tests/test_imagemode.py delete mode 100644 Tests/test_imagetransform.py diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py index 4a85b0a2e..2452479cc 100644 --- a/Tests/test_image_filter.py +++ b/Tests/test_image_filter.py @@ -29,6 +29,10 @@ class TestImageFilter(PillowTestCase): filter(ImageFilter.MinFilter) filter(ImageFilter.ModeFilter) filter(ImageFilter.Kernel((3, 3), list(range(9)))) + filter(ImageFilter.GaussianBlur) + filter(ImageFilter.GaussianBlur(5)) + filter(ImageFilter.UnsharpMask) + filter(ImageFilter.UnsharpMask(10)) self.assertRaises(TypeError, lambda: filter("hello")) diff --git a/Tests/test_image_mode.py b/Tests/test_image_mode.py index 25c35c607..74ed9b7aa 100644 --- a/Tests/test_image_mode.py +++ b/Tests/test_image_mode.py @@ -10,6 +10,27 @@ class TestImageMode(PillowTestCase): im = lena() im.mode + from PIL import ImageMode + + ImageMode.getmode("1") + ImageMode.getmode("L") + ImageMode.getmode("P") + ImageMode.getmode("RGB") + ImageMode.getmode("I") + ImageMode.getmode("F") + + m = ImageMode.getmode("1") + self.assertEqual(m.mode, "1") + self.assertEqual(m.bands, ("1",)) + self.assertEqual(m.basemode, "L") + self.assertEqual(m.basetype, "L") + + m = ImageMode.getmode("RGB") + self.assertEqual(m.mode, "RGB") + self.assertEqual(m.bands, ("R", "G", "B")) + self.assertEqual(m.basemode, "RGB") + self.assertEqual(m.basetype, "L") + def test_properties(self): def check(mode, *result): signature = ( diff --git a/Tests/test_image_transform.py b/Tests/test_image_transform.py index 1873ee9a4..42a3d78f3 100644 --- a/Tests/test_image_transform.py +++ b/Tests/test_image_transform.py @@ -5,6 +5,22 @@ from PIL import Image class TestImageTransform(PillowTestCase): + def test_sanity(self): + from PIL import ImageTransform + + im = Image.new("L", (100, 100)) + + seq = tuple(range(10)) + + transform = ImageTransform.AffineTransform(seq[:6]) + im.transform((100, 100), transform) + transform = ImageTransform.ExtentTransform(seq[:4]) + im.transform((100, 100), transform) + transform = ImageTransform.QuadTransform(seq[:8]) + im.transform((100, 100), transform) + transform = ImageTransform.MeshTransform([(seq[:4], seq[:8])]) + im.transform((100, 100), transform) + def test_extent(self): im = lena('RGB') (w, h) = im.size diff --git a/Tests/test_imagefilter.py b/Tests/test_imagefilter.py deleted file mode 100644 index f7edb409a..000000000 --- a/Tests/test_imagefilter.py +++ /dev/null @@ -1,37 +0,0 @@ -from helper import unittest, PillowTestCase - -from PIL import ImageFilter - - -class TestImageFilter(PillowTestCase): - - def test_sanity(self): - # see test_image_filter for more tests - - # Check these run. Exceptions cause failures. - ImageFilter.MaxFilter - ImageFilter.MedianFilter - ImageFilter.MinFilter - ImageFilter.ModeFilter - ImageFilter.Kernel((3, 3), list(range(9))) - ImageFilter.GaussianBlur - ImageFilter.GaussianBlur(5) - ImageFilter.UnsharpMask - ImageFilter.UnsharpMask(10) - - ImageFilter.BLUR - ImageFilter.CONTOUR - ImageFilter.DETAIL - ImageFilter.EDGE_ENHANCE - ImageFilter.EDGE_ENHANCE_MORE - ImageFilter.EMBOSS - ImageFilter.FIND_EDGES - ImageFilter.SMOOTH - ImageFilter.SMOOTH_MORE - ImageFilter.SHARPEN - - -if __name__ == '__main__': - unittest.main() - -# End of file diff --git a/Tests/test_imagemode.py b/Tests/test_imagemode.py deleted file mode 100644 index 2c5730d74..000000000 --- a/Tests/test_imagemode.py +++ /dev/null @@ -1,32 +0,0 @@ -from helper import unittest, PillowTestCase - -from PIL import ImageMode - - -class TestImageMode(PillowTestCase): - - def test_sanity(self): - ImageMode.getmode("1") - ImageMode.getmode("L") - ImageMode.getmode("P") - ImageMode.getmode("RGB") - ImageMode.getmode("I") - ImageMode.getmode("F") - - m = ImageMode.getmode("1") - self.assertEqual(m.mode, "1") - self.assertEqual(m.bands, ("1",)) - self.assertEqual(m.basemode, "L") - self.assertEqual(m.basetype, "L") - - m = ImageMode.getmode("RGB") - self.assertEqual(m.mode, "RGB") - self.assertEqual(m.bands, ("R", "G", "B")) - self.assertEqual(m.basemode, "RGB") - self.assertEqual(m.basetype, "L") - - -if __name__ == '__main__': - unittest.main() - -# End of file diff --git a/Tests/test_imagetransform.py b/Tests/test_imagetransform.py deleted file mode 100644 index f5741df32..000000000 --- a/Tests/test_imagetransform.py +++ /dev/null @@ -1,27 +0,0 @@ -from helper import unittest, PillowTestCase - -from PIL import Image -from PIL import ImageTransform - - -class TestImageTransform(PillowTestCase): - - def test_sanity(self): - im = Image.new("L", (100, 100)) - - seq = tuple(range(10)) - - transform = ImageTransform.AffineTransform(seq[:6]) - im.transform((100, 100), transform) - transform = ImageTransform.ExtentTransform(seq[:4]) - im.transform((100, 100), transform) - transform = ImageTransform.QuadTransform(seq[:8]) - im.transform((100, 100), transform) - transform = ImageTransform.MeshTransform([(seq[:4], seq[:8])]) - im.transform((100, 100), transform) - - -if __name__ == '__main__': - unittest.main() - -# End of file From fef3ceb2c02ef241a508ee020fe2617e10e33e42 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 20 Jul 2014 01:50:05 +0300 Subject: [PATCH 51/58] If we can't read a file due to unsupported compression, raise an error --- PIL/SgiImagePlugin.py | 10 +++++----- Tests/test_file_sgi.py | 18 +++--------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/PIL/SgiImagePlugin.py b/PIL/SgiImagePlugin.py index bf3c18a43..2b8fcd8e4 100644 --- a/PIL/SgiImagePlugin.py +++ b/PIL/SgiImagePlugin.py @@ -45,7 +45,7 @@ class SgiImageFile(ImageFile.ImageFile): # HEAD s = self.fp.read(512) if i16(s) != 474: - raise SyntaxError("not an SGI image file") + raise ValueError("Not an SGI image file") # relevant header entries compression = i8(s[2]) @@ -61,7 +61,7 @@ class SgiImageFile(ImageFile.ImageFile): elif layout == (1, 3, 4): self.mode = "RGBA" else: - raise SyntaxError("unsupported SGI image mode") + raise ValueError("Unsupported SGI image mode") # size self.size = i16(s[6:]), i16(s[8:]) @@ -76,8 +76,7 @@ class SgiImageFile(ImageFile.ImageFile): ("raw", (0, 0)+self.size, offset, (layer, 0, -1))) offset = offset + pagesize elif compression == 1: - self.tile = [ - ("sgi_rle", (0, 0)+self.size, 512, (self.mode, 0, -1))] + raise ValueError("SGI RLE encoding not supported") # # registry @@ -87,5 +86,6 @@ Image.register_open("SGI", SgiImageFile, _accept) Image.register_extension("SGI", ".bw") Image.register_extension("SGI", ".rgb") Image.register_extension("SGI", ".rgba") - Image.register_extension("SGI", ".sgi") + +# End of file diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py index e94f0d989..84b184b63 100644 --- a/Tests/test_file_sgi.py +++ b/Tests/test_file_sgi.py @@ -5,44 +5,32 @@ from PIL import Image class TestFileSgi(PillowTestCase): - def sanity(self, filename, expected_mode, expected_size=(128, 128)): - # Act - im = Image.open(filename) - - # Assert - self.assertEqual(im.mode, expected_mode) - self.assertEqual(im.size, expected_size) - def test_rgb(self): # Arrange # Created with ImageMagick then renamed: # convert lena.ppm lena.sgi test_file = "Tests/images/lena.rgb" - expected_mode = "RGB" # Act / Assert - self.sanity(test_file, expected_mode) + self.assertRaises(ValueError, lambda: Image.open(test_file)) def test_l(self): # Arrange # Created with ImageMagick then renamed: # convert lena.ppm -monochrome lena.sgi test_file = "Tests/images/lena.bw" - expected_mode = "L" # Act / Assert - self.sanity(test_file, expected_mode) + self.assertRaises(ValueError, lambda: Image.open(test_file)) def test_rgba(self): # Arrange # Created with ImageMagick: # convert transparent.png transparent.sgi test_file = "Tests/images/transparent.sgi" - expected_mode = "RGBA" - expected_size = (200, 150) # Act / Assert - self.sanity(test_file, expected_mode, expected_size) + self.assertRaises(ValueError, lambda: Image.open(test_file)) if __name__ == '__main__': From 6381d6250375f290b02a249d8b01e7836abab46a Mon Sep 17 00:00:00 2001 From: wiredfool Date: Sat, 19 Jul 2014 21:25:25 -0700 Subject: [PATCH 52/58] Update CHANGES.rst [ci skip] --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index da7ffcb84..5652479a1 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,7 +16,7 @@ Changelog (Pillow) - Added docs for ExifTags [Wintermute3] -- More tests for CurImagePlugin, DcxImagePlugin, ImageFont, ImageMath, SpiderImagePlugin, XpmImagePlugin and _util +- More tests for CurImagePlugin, DcxImagePlugin, ImageFont, ImageMath, SpiderImagePlugin, SgiImagePlugin, XpmImagePlugin and _util [hugovk] - Fix return value of FreeTypeFont.textsize() does not include font offsets From 37691bc1e4d3f2bbf444e53510db4fecf81fe7b1 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 20 Jul 2014 10:13:26 +0300 Subject: [PATCH 53/58] Make _make_linear_lut public and issue deprecation warnings from old private methods --- PIL/ImagePalette.py | 21 ++++++++++++++++ Tests/test_imagepalette.py | 49 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/PIL/ImagePalette.py b/PIL/ImagePalette.py index 67bf593e6..3b9e96172 100644 --- a/PIL/ImagePalette.py +++ b/PIL/ImagePalette.py @@ -17,6 +17,7 @@ # import array +import warnings from PIL import Image, ImageColor @@ -125,6 +126,26 @@ def raw(rawmode, data): # Factories def _make_linear_lut(black, white): + warnings.warn( + '_make_linear_lut() is deprecated. ' + 'Please call make_linear_lut() instead.', + DeprecationWarning, + stacklevel=2 + ) + return make_linear_lut(black, white) + + +def _make_gamma_lut(exp): + warnings.warn( + '_make_gamma_lut() is deprecated. ' + 'Please call make_gamma_lut() instead.', + DeprecationWarning, + stacklevel=2 + ) + return make_gamma_lut(exp) + + +def make_linear_lut(black, white): lut = [] if black == 0: for i in range(256): diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index af742edd1..8356b5d60 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -44,6 +44,34 @@ class TestImagePalette(PillowTestCase): self.assertIsInstance(p, ImagePalette) self.assertEqual(p.palette, palette.tobytes()) + def test_make_linear_lut(self): + # Arrange + from PIL.ImagePalette import make_linear_lut + black = 0 + white = 255 + + # Act + lut = make_linear_lut(black, white) + + # Assert + self.assertIsInstance(lut, list) + self.assertEqual(len(lut), 256) + # Check values + for i in range(0, len(lut)): + self.assertEqual(lut[i], i) + + def test_make_linear_lut_not_yet_implemented(self): + # Update after FIXME + # Arrange + from PIL.ImagePalette import make_linear_lut + black = 1 + white = 255 + + # Act + self.assertRaises( + NotImplementedError, + lambda: make_linear_lut(black, white)) + def test_make_gamma_lut(self): # Arrange from PIL.ImagePalette import make_gamma_lut @@ -62,6 +90,27 @@ class TestImagePalette(PillowTestCase): self.assertEqual(lut[191], 60) self.assertEqual(lut[255], 255) + def test_private_make_linear_lut_warning(self): + # Arrange + from PIL.ImagePalette import _make_linear_lut + black = 0 + white = 255 + + # Act / Assert + self.assert_warning( + DeprecationWarning, + lambda: _make_linear_lut(black, white)) + + def test_private_make_gamma_lut_warning(self): + # Arrange + from PIL.ImagePalette import _make_gamma_lut + exp = 5 + + # Act / Assert + self.assert_warning( + DeprecationWarning, + lambda: _make_gamma_lut(exp)) + if __name__ == '__main__': unittest.main() From 751f67205838f37e55fb3865f9b6410d7f5e89b1 Mon Sep 17 00:00:00 2001 From: hugovk Date: Sun, 20 Jul 2014 21:08:14 +0300 Subject: [PATCH 54/58] Call public, non-warning versions internally --- PIL/ImagePalette.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PIL/ImagePalette.py b/PIL/ImagePalette.py index 3b9e96172..e59e7a88a 100644 --- a/PIL/ImagePalette.py +++ b/PIL/ImagePalette.py @@ -182,9 +182,9 @@ def random(mode="RGB"): def sepia(white="#fff0c0"): r, g, b = ImageColor.getrgb(white) - r = _make_linear_lut(0, r) - g = _make_linear_lut(0, g) - b = _make_linear_lut(0, b) + r = make_linear_lut(0, r) + g = make_linear_lut(0, g) + b = make_linear_lut(0, b) return ImagePalette("RGB", r + g + b) From 8c60de375d8b76d487f99964edbf26e7596ea2aa Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 21 Jul 2014 12:15:23 +0300 Subject: [PATCH 55/58] Workaround to test PyQt: https://github.com/travis-ci/travis-ci/issues/2219#issuecomment-41804942 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 09e523c39..b37588843 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ python: - "pypy" - 2.6 - 2.7 + - "2.7_with_system_site_packages" # For PyQt4 - 3.2 - 3.3 - 3.4 From d06735b49eba1e10e8e498755414ceb0ce778168 Mon Sep 17 00:00:00 2001 From: hugovk Date: Mon, 21 Jul 2014 23:18:46 +0300 Subject: [PATCH 56/58] More ImagePalette.py tests and remove unused and uncallable new() --- PIL/ImagePalette.py | 6 +----- Tests/test_imagepalette.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/PIL/ImagePalette.py b/PIL/ImagePalette.py index e59e7a88a..62f8814f1 100644 --- a/PIL/ImagePalette.py +++ b/PIL/ImagePalette.py @@ -18,7 +18,7 @@ import array import warnings -from PIL import Image, ImageColor +from PIL import ImageColor class ImagePalette: @@ -162,10 +162,6 @@ def make_gamma_lut(exp): return lut -def new(mode, data): - return Image.core.new_palette(mode, data) - - def negative(mode="RGB"): palette = list(range(256)) palette.reverse() diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index 8356b5d60..e56c61390 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -111,6 +111,41 @@ class TestImagePalette(PillowTestCase): DeprecationWarning, lambda: _make_gamma_lut(exp)) + def test_rawmode_valueerrors(self): + # Arrange + from PIL.ImagePalette import raw + palette = raw("RGB", list(range(256))*3) + + # Act / Assert + self.assertRaises(ValueError, lambda: palette.tobytes()) + self.assertRaises(ValueError, lambda: palette.getcolor((1, 2, 3))) + f = self.tempfile("temp.lut") + self.assertRaises(ValueError, lambda: palette.save(f)) + + def test_getdata(self): + # Arrange + data_in = list(range(256))*3 + palette = ImagePalette("RGB", data_in) + + # Act + mode, data_out = palette.getdata() + + # Assert + self.assertEqual(mode, "RGB;L") + + def test_rawmode_getdata(self): + # Arrange + from PIL.ImagePalette import raw + data_in = list(range(256))*3 + palette = raw("RGB", data_in) + + # Act + rawmode, data_out = palette.getdata() + + # Assert + self.assertEqual(rawmode, "RGB") + self.assertEqual(data_in, data_out) + if __name__ == '__main__': unittest.main() From 55792f8927263e9935469e375c3fbc0ed1fe15b0 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Jul 2014 16:22:28 -0700 Subject: [PATCH 57/58] Updated Changes.rst [ci skip] --- CHANGES.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 5652479a1..c93572cbd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,9 @@ Changelog (Pillow) 2.6.0 (unreleased) ------------------ +- Removed unusable ImagePalette.new() + [hugovk] + - Fix Scrambled XPM #808 [wiredfool] @@ -16,7 +19,7 @@ Changelog (Pillow) - Added docs for ExifTags [Wintermute3] -- More tests for CurImagePlugin, DcxImagePlugin, ImageFont, ImageMath, SpiderImagePlugin, SgiImagePlugin, XpmImagePlugin and _util +- More tests for CurImagePlugin, DcxImagePlugin, ImageFont, ImageMath, ImagePalette, SpiderImagePlugin, SgiImagePlugin, XpmImagePlugin and _util [hugovk] - Fix return value of FreeTypeFont.textsize() does not include font offsets From 1b170dad680ae0769dfb94bb720fe3807d899041 Mon Sep 17 00:00:00 2001 From: wiredfool Date: Tue, 22 Jul 2014 16:43:08 -0700 Subject: [PATCH 58/58] Partial opacity text example, parameters on ImageDraw.Draw [ci skip] --- docs/reference/ImageDraw.rst | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/reference/ImageDraw.rst b/docs/reference/ImageDraw.rst index 30aa15a9b..c24a9dd99 100644 --- a/docs/reference/ImageDraw.rst +++ b/docs/reference/ImageDraw.rst @@ -74,6 +74,34 @@ To load a OpenType/TrueType font, use the truetype function in the :py:mod:`~PIL.ImageFont` module. Note that this function depends on third-party libraries, and may not available in all PIL builds. +Example: Draw Partial Opacity Text +---------------------------------- + +.. code-block:: python + + from PIL import Image, ImageDraw, ImageFont + # get an image + base = Image.open('Pillow/Tests/images/lena.png').convert('RGBA') + + # make a blank image for the text, initialized to transparent text color + txt = Image.new('RGBA', base.size, (255,255,255,0)) + + # get a font + fnt = ImageFont.truetype('Pillow/Tests/fonts/FreeMono.ttf', 40) + # get a drawing context + d = ImageDraw.Draw(txt) + + # draw text, half opacity + d.text((10,10), "Hello", font=fnt, fill=(255,255,255,128)) + # draw text, full opacity + d.text((10,60), "World", font=fnt, fill=(255,255,255,255)) + + out = Image.alpha_composite(base, txt) + + out.show() + + + Functions --------- @@ -83,6 +111,13 @@ Functions Note that the image will be modified in place. + :param im: The image to draw in. + :param mode: Optional mode to use for color values. For RGB + images, this argument can be RGB or RGBA (to blend the + drawing into the image). For all other modes, this argument + must be the same as the image mode. If omitted, the mode + defaults to the mode of the image. + Methods -------