diff --git a/.appveyor.yml b/.appveyor.yml index 2a4e67dc925..43dfae0aa3e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -76,7 +76,7 @@ build_script: test_script: - cd c:\pillow - '%PYTHON%\%PIP_DIR%\pip.exe install pytest pytest-cov' -- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov-report term --cov-report xml Tests' +- '%PYTHON%\%EXECUTABLE% -m pytest -svx --cov PIL --cov-report term --cov-report xml Tests' #- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest? after_test: diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 545cb0b50d9..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,81 +0,0 @@ -dist: xenial -language: python -cache: pip - -notifications: - irc: "chat.freenode.net#pil" - -# Run fast lint first to get fast feedback. -# Run slow PyPy* next, to give them a headstart and reduce waiting time. -# Run latest 3.x and 2.x next, to get quick compatibility results. -# Then run the remainder, with fastest Docker jobs last. - -matrix: - fast_finish: true - include: - - python: "3.6" - name: "Lint" - env: LINT="true" - - python: "pypy" - name: "PyPy2 Xenial" - - python: "pypy3" - name: "PyPy3 Xenial" - - python: '3.7' - name: "3.7 Xenial" - - python: '2.7' - name: "2.7 Xenial" - - python: "2.7_with_system_site_packages" # For PyQt4 - name: "2.7_with_system_site_packages Xenial" - services: xvfb - - python: '3.6' - name: "3.6 Xenial PYTHONOPTIMIZE=1" - env: PYTHONOPTIMIZE=1 - - python: '3.5' - name: "3.5 Xenial PYTHONOPTIMIZE=2" - env: PYTHONOPTIMIZE=2 - - python: "3.8-dev" - name: "3.8-dev Xenial" - - env: DOCKER="alpine" DOCKER_TAG="master" - - env: DOCKER="arch" DOCKER_TAG="master" # contains PyQt5 - - env: DOCKER="ubuntu-16.04-xenial-amd64" DOCKER_TAG="master" - - env: DOCKER="ubuntu-18.04-bionic-amd64" DOCKER_TAG="master" - - env: DOCKER="debian-9-stretch-x86" DOCKER_TAG="master" - - env: DOCKER="debian-10-buster-x86" DOCKER_TAG="master" - - env: DOCKER="centos-6-amd64" DOCKER_TAG="master" - - env: DOCKER="centos-7-amd64" DOCKER_TAG="master" - - env: DOCKER="amazon-1-amd64" DOCKER_TAG="master" - - env: DOCKER="amazon-2-amd64" DOCKER_TAG="master" - - env: DOCKER="fedora-29-amd64" DOCKER_TAG="master" - - env: DOCKER="fedora-30-amd64" DOCKER_TAG="master" - -services: - - docker - -before_install: - - if [ "$DOCKER" ]; then travis_retry docker pull pythonpillow/$DOCKER:$DOCKER_TAG; fi - -install: - - | - if [ "$LINT" == "true" ]; then - pip install tox - elif [ "$DOCKER" == "" ]; then - .travis/install.sh; - fi - -script: -- | - if [ "$LINT" == "true" ]; then - tox -e lint - elif [ "$DOCKER" == "" ]; then - .travis/script.sh - elif [ "$DOCKER" ]; then - # the Pillow user in the docker container is UID 1000 - sudo chown -R 1000 $TRAVIS_BUILD_DIR - docker run -v $TRAVIS_BUILD_DIR:/Pillow pythonpillow/$DOCKER:$DOCKER_TAG - fi - -after_success: -- | - if [ "$LINT" == "" ]; then - .travis/after_success.sh - fi diff --git a/Tests/test_000_sanity.py b/Tests/test_000_sanity.py deleted file mode 100644 index a6143f084cb..00000000000 --- a/Tests/test_000_sanity.py +++ /dev/null @@ -1,23 +0,0 @@ -import PIL -import PIL.Image - -from .helper import PillowTestCase - - -class TestSanity(PillowTestCase): - def test_sanity(self): - - # Make sure we have the binary extension - PIL.Image.core.new("L", (100, 100)) - - # Create an image and do stuff with it. - im = PIL.Image.new("1", (100, 100)) - self.assertEqual((im.mode, im.size), ("1", (100, 100))) - self.assertEqual(len(im.tobytes()), 1300) - - # Create images in all remaining major modes. - PIL.Image.new("L", (100, 100)) - PIL.Image.new("P", (100, 100)) - PIL.Image.new("RGB", (100, 100)) - PIL.Image.new("I", (100, 100)) - PIL.Image.new("F", (100, 100)) diff --git a/Tests/test_binary.py b/Tests/test_binary.py deleted file mode 100644 index 79d5d2bcb8e..00000000000 --- a/Tests/test_binary.py +++ /dev/null @@ -1,23 +0,0 @@ -from PIL import _binary - -from .helper import PillowTestCase - - -class TestBinary(PillowTestCase): - def test_standard(self): - self.assertEqual(_binary.i8(b"*"), 42) - self.assertEqual(_binary.o8(42), b"*") - - def test_little_endian(self): - self.assertEqual(_binary.i16le(b"\xff\xff\x00\x00"), 65535) - self.assertEqual(_binary.i32le(b"\xff\xff\x00\x00"), 65535) - - self.assertEqual(_binary.o16le(65535), b"\xff\xff") - self.assertEqual(_binary.o32le(65535), b"\xff\xff\x00\x00") - - def test_big_endian(self): - self.assertEqual(_binary.i16be(b"\x00\x00\xff\xff"), 0) - self.assertEqual(_binary.i32be(b"\x00\x00\xff\xff"), 65535) - - self.assertEqual(_binary.o16be(65535), b"\xff\xff") - self.assertEqual(_binary.o32be(65535), b"\x00\x00\xff\xff") diff --git a/Tests/test_bmp_reference.py b/Tests/test_bmp_reference.py deleted file mode 100644 index e6a75e2c370..00000000000 --- a/Tests/test_bmp_reference.py +++ /dev/null @@ -1,112 +0,0 @@ -from __future__ import print_function - -import os - -from PIL import Image - -from .helper import PillowTestCase - -base = os.path.join("Tests", "images", "bmp") - - -class TestBmpReference(PillowTestCase): - def get_files(self, d, ext=".bmp"): - return [ - os.path.join(base, d, f) - for f in os.listdir(os.path.join(base, d)) - if ext in f - ] - - def test_bad(self): - """ These shouldn't crash/dos, but they shouldn't return anything - either """ - for f in self.get_files("b"): - - def open(f): - try: - im = Image.open(f) - im.load() - except Exception: # as msg: - pass - - # Assert that there is no unclosed file warning - self.assert_warning(None, open, f) - - def test_questionable(self): - """ These shouldn't crash/dos, but it's not well defined that these - are in spec """ - supported = [ - "pal8os2v2.bmp", - "rgb24prof.bmp", - "pal1p1.bmp", - "pal8offs.bmp", - "rgb24lprof.bmp", - "rgb32fakealpha.bmp", - "rgb24largepal.bmp", - "pal8os2sp.bmp", - "rgb32bf-xbgr.bmp", - ] - for f in self.get_files("q"): - try: - im = Image.open(f) - im.load() - if os.path.basename(f) not in supported: - print("Please add %s to the partially supported bmp specs." % f) - except Exception: # as msg: - if os.path.basename(f) in supported: - raise - - def test_good(self): - """ These should all work. There's a set of target files in the - html directory that we can compare against. """ - - # Target files, if they're not just replacing the extension - file_map = { - "pal1wb.bmp": "pal1.png", - "pal4rle.bmp": "pal4.png", - "pal8-0.bmp": "pal8.png", - "pal8rle.bmp": "pal8.png", - "pal8topdown.bmp": "pal8.png", - "pal8nonsquare.bmp": "pal8nonsquare-v.png", - "pal8os2.bmp": "pal8.png", - "pal8os2sp.bmp": "pal8.png", - "pal8os2v2.bmp": "pal8.png", - "pal8os2v2-16.bmp": "pal8.png", - "pal8v4.bmp": "pal8.png", - "pal8v5.bmp": "pal8.png", - "rgb16-565pal.bmp": "rgb16-565.png", - "rgb24pal.bmp": "rgb24.png", - "rgb32.bmp": "rgb24.png", - "rgb32bf.bmp": "rgb24.png", - } - - def get_compare(f): - name = os.path.split(f)[1] - if name in file_map: - return os.path.join(base, "html", file_map[name]) - name = os.path.splitext(name)[0] - return os.path.join(base, "html", "%s.png" % name) - - for f in self.get_files("g"): - try: - im = Image.open(f) - im.load() - compare = Image.open(get_compare(f)) - compare.load() - if im.mode == "P": - # assert image similar doesn't really work - # with paletized image, since the palette might - # be differently ordered for an equivalent image. - im = im.convert("RGBA") - compare = im.convert("RGBA") - self.assert_image_similar(im, compare, 5) - - except Exception as msg: - # there are three here that are unsupported: - unsupported = ( - os.path.join(base, "g", "rgb32bf.bmp"), - os.path.join(base, "g", "pal8rle.bmp"), - os.path.join(base, "g", "pal4rle.bmp"), - ) - if f not in unsupported: - self.fail("Unsupported Image %s: %s" % (f, msg)) diff --git a/Tests/test_box_blur.py b/Tests/test_box_blur.py deleted file mode 100644 index c17e7996d09..00000000000 --- a/Tests/test_box_blur.py +++ /dev/null @@ -1,247 +0,0 @@ -from PIL import Image, ImageFilter - -from .helper import PillowTestCase - -sample = Image.new("L", (7, 5)) -# fmt: off -sample.putdata(sum([ - [210, 50, 20, 10, 220, 230, 80], - [190, 210, 20, 180, 170, 40, 110], - [120, 210, 250, 60, 220, 0, 220], - [220, 40, 230, 80, 130, 250, 40], - [250, 0, 80, 30, 60, 20, 110], -], [])) -# fmt: on - - -class TestBoxBlurApi(PillowTestCase): - def test_imageops_box_blur(self): - i = sample.filter(ImageFilter.BoxBlur(1)) - self.assertEqual(i.mode, sample.mode) - self.assertEqual(i.size, sample.size) - self.assertIsInstance(i, Image.Image) - - -class TestBoxBlur(PillowTestCase): - def box_blur(self, image, radius=1, n=1): - return image._new(image.im.box_blur(radius, n)) - - def assertImage(self, im, data, delta=0): - it = iter(im.getdata()) - for data_row in data: - im_row = [next(it) for _ in range(im.size[0])] - if any( - abs(data_v - im_v) > delta for data_v, im_v in zip(data_row, im_row) - ): - self.assertEqual(im_row, data_row) - self.assertRaises(StopIteration, next, it) - - def assertBlur(self, im, radius, data, passes=1, delta=0): - # check grayscale image - self.assertImage(self.box_blur(im, radius, passes), data, delta) - rgba = Image.merge("RGBA", (im, im, im, im)) - for band in self.box_blur(rgba, radius, passes).split(): - self.assertImage(band, data, delta) - - def test_color_modes(self): - self.assertRaises(ValueError, self.box_blur, sample.convert("1")) - self.assertRaises(ValueError, self.box_blur, sample.convert("P")) - self.box_blur(sample.convert("L")) - self.box_blur(sample.convert("LA")) - self.box_blur(sample.convert("LA").convert("La")) - self.assertRaises(ValueError, self.box_blur, sample.convert("I")) - self.assertRaises(ValueError, self.box_blur, sample.convert("F")) - self.box_blur(sample.convert("RGB")) - self.box_blur(sample.convert("RGBA")) - self.box_blur(sample.convert("RGBA").convert("RGBa")) - self.box_blur(sample.convert("CMYK")) - self.assertRaises(ValueError, self.box_blur, sample.convert("YCbCr")) - - def test_radius_0(self): - self.assertBlur( - sample, - 0, - [ - # fmt: off - [210, 50, 20, 10, 220, 230, 80], - [190, 210, 20, 180, 170, 40, 110], - [120, 210, 250, 60, 220, 0, 220], - [220, 40, 230, 80, 130, 250, 40], - [250, 0, 80, 30, 60, 20, 110], - # fmt: on - ], - ) - - def test_radius_0_02(self): - self.assertBlur( - sample, - 0.02, - [ - # fmt: off - [206, 55, 20, 17, 215, 223, 83], - [189, 203, 31, 171, 169, 46, 110], - [125, 206, 241, 69, 210, 13, 210], - [215, 49, 221, 82, 131, 235, 48], - [244, 7, 80, 32, 60, 27, 107], - # fmt: on - ], - delta=2, - ) - - def test_radius_0_05(self): - self.assertBlur( - sample, - 0.05, - [ - # fmt: off - [202, 62, 22, 27, 209, 215, 88], - [188, 194, 44, 161, 168, 56, 111], - [131, 201, 229, 81, 198, 31, 198], - [209, 62, 209, 86, 133, 216, 59], - [237, 17, 80, 36, 60, 35, 103], - # fmt: on - ], - delta=2, - ) - - def test_radius_0_1(self): - self.assertBlur( - sample, - 0.1, - [ - # fmt: off - [196, 72, 24, 40, 200, 203, 93], - [187, 183, 62, 148, 166, 68, 111], - [139, 193, 213, 96, 182, 54, 182], - [201, 78, 193, 91, 133, 191, 73], - [227, 31, 80, 42, 61, 47, 99], - # fmt: on - ], - delta=1, - ) - - def test_radius_0_5(self): - self.assertBlur( - sample, - 0.5, - [ - # fmt: off - [176, 101, 46, 83, 163, 165, 111], - [176, 149, 108, 122, 144, 120, 117], - [164, 171, 159, 141, 134, 119, 129], - [170, 136, 133, 114, 116, 124, 109], - [184, 95, 72, 70, 69, 81, 89], - # fmt: on - ], - delta=1, - ) - - def test_radius_1(self): - self.assertBlur( - sample, - 1, - [ - # fmt: off - [170, 109, 63, 97, 146, 153, 116], - [168, 142, 112, 128, 126, 143, 121], - [169, 166, 142, 149, 126, 131, 114], - [159, 156, 109, 127, 94, 117, 112], - [164, 128, 63, 87, 76, 89, 90], - # fmt: on - ], - delta=1, - ) - - def test_radius_1_5(self): - self.assertBlur( - sample, - 1.5, - [ - # fmt: off - [155, 120, 105, 112, 124, 137, 130], - [160, 136, 124, 125, 127, 134, 130], - [166, 147, 130, 125, 120, 121, 119], - [168, 145, 119, 109, 103, 105, 110], - [168, 134, 96, 85, 85, 89, 97], - # fmt: on - ], - delta=1, - ) - - def test_radius_bigger_then_half(self): - self.assertBlur( - sample, - 3, - [ - # fmt: off - [144, 145, 142, 128, 114, 115, 117], - [148, 145, 137, 122, 109, 111, 112], - [152, 145, 131, 117, 103, 107, 108], - [156, 144, 126, 111, 97, 102, 103], - [160, 144, 121, 106, 92, 98, 99], - # fmt: on - ], - delta=1, - ) - - def test_radius_bigger_then_width(self): - self.assertBlur( - sample, - 10, - [ - [158, 153, 147, 141, 135, 129, 123], - [159, 153, 147, 141, 136, 130, 124], - [159, 154, 148, 142, 136, 130, 124], - [160, 154, 148, 142, 137, 131, 125], - [160, 155, 149, 143, 137, 131, 125], - ], - delta=0, - ) - - def test_extreme_large_radius(self): - self.assertBlur( - sample, - 600, - [ - [162, 162, 162, 162, 162, 162, 162], - [162, 162, 162, 162, 162, 162, 162], - [162, 162, 162, 162, 162, 162, 162], - [162, 162, 162, 162, 162, 162, 162], - [162, 162, 162, 162, 162, 162, 162], - ], - delta=1, - ) - - def test_two_passes(self): - self.assertBlur( - sample, - 1, - [ - # fmt: off - [153, 123, 102, 109, 132, 135, 129], - [159, 138, 123, 121, 133, 131, 126], - [162, 147, 136, 124, 127, 121, 121], - [159, 140, 125, 108, 111, 106, 108], - [154, 126, 105, 87, 94, 93, 97], - # fmt: on - ], - passes=2, - delta=1, - ) - - def test_three_passes(self): - self.assertBlur( - sample, - 1, - [ - # fmt: off - [146, 131, 116, 118, 126, 131, 130], - [151, 138, 125, 123, 126, 128, 127], - [154, 143, 129, 123, 120, 120, 119], - [152, 139, 122, 113, 108, 108, 108], - [148, 132, 112, 102, 97, 99, 100], - # fmt: on - ], - passes=3, - delta=1, - ) diff --git a/Tests/test_color_lut.py b/Tests/test_color_lut.py deleted file mode 100644 index ca82209c248..00000000000 --- a/Tests/test_color_lut.py +++ /dev/null @@ -1,562 +0,0 @@ -from __future__ import division - -from array import array - -from PIL import Image, ImageFilter - -from .helper import PillowTestCase, unittest - -try: - import numpy -except ImportError: - numpy = None - - -class TestColorLut3DCoreAPI(PillowTestCase): - def generate_identity_table(self, channels, size): - if isinstance(size, tuple): - size1D, size2D, size3D = size - else: - size1D, size2D, size3D = (size, size, size) - - table = [ - [ - r / float(size1D - 1) if size1D != 1 else 0, - g / float(size2D - 1) if size2D != 1 else 0, - b / float(size3D - 1) if size3D != 1 else 0, - r / float(size1D - 1) if size1D != 1 else 0, - g / float(size2D - 1) if size2D != 1 else 0, - ][:channels] - for b in range(size3D) - for g in range(size2D) - for r in range(size1D) - ] - return ( - channels, - size1D, - size2D, - size3D, - [item for sublist in table for item in sublist], - ) - - def test_wrong_args(self): - im = Image.new("RGB", (10, 10), 0) - - with self.assertRaisesRegex(ValueError, "filter"): - im.im.color_lut_3d("RGB", Image.CUBIC, *self.generate_identity_table(3, 3)) - - with self.assertRaisesRegex(ValueError, "image mode"): - im.im.color_lut_3d( - "wrong", Image.LINEAR, *self.generate_identity_table(3, 3) - ) - - with self.assertRaisesRegex(ValueError, "table_channels"): - im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(5, 3)) - - with self.assertRaisesRegex(ValueError, "table_channels"): - im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(1, 3)) - - with self.assertRaisesRegex(ValueError, "table_channels"): - im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(2, 3)) - - with self.assertRaisesRegex(ValueError, "Table size"): - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (1, 3, 3)) - ) - - with self.assertRaisesRegex(ValueError, "Table size"): - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (66, 3, 3)) - ) - - with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"): - im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 7) - - with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"): - im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 9) - - with self.assertRaises(TypeError): - im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, "0"] * 8) - - with self.assertRaises(TypeError): - im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, 16) - - def test_correct_args(self): - im = Image.new("RGB", (10, 10), 0) - - im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3)) - - im.im.color_lut_3d("CMYK", Image.LINEAR, *self.generate_identity_table(4, 3)) - - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (2, 3, 3)) - ) - - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (65, 3, 3)) - ) - - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (3, 65, 3)) - ) - - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (3, 3, 65)) - ) - - def test_wrong_mode(self): - with self.assertRaisesRegex(ValueError, "wrong mode"): - im = Image.new("L", (10, 10), 0) - im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3)) - - with self.assertRaisesRegex(ValueError, "wrong mode"): - im = Image.new("RGB", (10, 10), 0) - im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3)) - - with self.assertRaisesRegex(ValueError, "wrong mode"): - im = Image.new("L", (10, 10), 0) - im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3)) - - with self.assertRaisesRegex(ValueError, "wrong mode"): - im = Image.new("RGB", (10, 10), 0) - im.im.color_lut_3d( - "RGBA", Image.LINEAR, *self.generate_identity_table(3, 3) - ) - - with self.assertRaisesRegex(ValueError, "wrong mode"): - im = Image.new("RGB", (10, 10), 0) - im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(4, 3)) - - def test_correct_mode(self): - im = Image.new("RGBA", (10, 10), 0) - im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(3, 3)) - - im = Image.new("RGBA", (10, 10), 0) - im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(4, 3)) - - im = Image.new("RGB", (10, 10), 0) - im.im.color_lut_3d("HSV", Image.LINEAR, *self.generate_identity_table(3, 3)) - - im = Image.new("RGB", (10, 10), 0) - im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(4, 3)) - - def test_identities(self): - g = Image.linear_gradient("L") - im = Image.merge( - "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] - ) - - # Fast test with small cubes - for size in [2, 3, 5, 7, 11, 16, 17]: - self.assert_image_equal( - im, - im._new( - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, size) - ) - ), - ) - - # Not so fast - self.assert_image_equal( - im, - im._new( - im.im.color_lut_3d( - "RGB", Image.LINEAR, *self.generate_identity_table(3, (2, 2, 65)) - ) - ), - ) - - def test_identities_4_channels(self): - g = Image.linear_gradient("L") - im = Image.merge( - "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] - ) - - # Red channel copied to alpha - self.assert_image_equal( - Image.merge("RGBA", (im.split() * 2)[:4]), - im._new( - im.im.color_lut_3d( - "RGBA", Image.LINEAR, *self.generate_identity_table(4, 17) - ) - ), - ) - - def test_copy_alpha_channel(self): - g = Image.linear_gradient("L") - im = Image.merge( - "RGBA", - [ - g, - g.transpose(Image.ROTATE_90), - g.transpose(Image.ROTATE_180), - g.transpose(Image.ROTATE_270), - ], - ) - - self.assert_image_equal( - im, - im._new( - im.im.color_lut_3d( - "RGBA", Image.LINEAR, *self.generate_identity_table(3, 17) - ) - ), - ) - - def test_channels_order(self): - g = Image.linear_gradient("L") - im = Image.merge( - "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] - ) - - # Reverse channels by splitting and using table - # fmt: off - self.assert_image_equal( - Image.merge('RGB', im.split()[::-1]), - im._new(im.im.color_lut_3d('RGB', Image.LINEAR, - 3, 2, 2, 2, [ - 0, 0, 0, 0, 0, 1, - 0, 1, 0, 0, 1, 1, - - 1, 0, 0, 1, 0, 1, - 1, 1, 0, 1, 1, 1, - ]))) - # fmt: on - - def test_overflow(self): - g = Image.linear_gradient("L") - im = Image.merge( - "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] - ) - - # fmt: off - transformed = im._new(im.im.color_lut_3d('RGB', Image.LINEAR, - 3, 2, 2, 2, - [ - -1, -1, -1, 2, -1, -1, - -1, 2, -1, 2, 2, -1, - - -1, -1, 2, 2, -1, 2, - -1, 2, 2, 2, 2, 2, - ])).load() - # fmt: on - self.assertEqual(transformed[0, 0], (0, 0, 255)) - self.assertEqual(transformed[50, 50], (0, 0, 255)) - self.assertEqual(transformed[255, 0], (0, 255, 255)) - self.assertEqual(transformed[205, 50], (0, 255, 255)) - self.assertEqual(transformed[0, 255], (255, 0, 0)) - self.assertEqual(transformed[50, 205], (255, 0, 0)) - self.assertEqual(transformed[255, 255], (255, 255, 0)) - self.assertEqual(transformed[205, 205], (255, 255, 0)) - - # fmt: off - transformed = im._new(im.im.color_lut_3d('RGB', Image.LINEAR, - 3, 2, 2, 2, - [ - -3, -3, -3, 5, -3, -3, - -3, 5, -3, 5, 5, -3, - - -3, -3, 5, 5, -3, 5, - -3, 5, 5, 5, 5, 5, - ])).load() - # fmt: on - self.assertEqual(transformed[0, 0], (0, 0, 255)) - self.assertEqual(transformed[50, 50], (0, 0, 255)) - self.assertEqual(transformed[255, 0], (0, 255, 255)) - self.assertEqual(transformed[205, 50], (0, 255, 255)) - self.assertEqual(transformed[0, 255], (255, 0, 0)) - self.assertEqual(transformed[50, 205], (255, 0, 0)) - self.assertEqual(transformed[255, 255], (255, 255, 0)) - self.assertEqual(transformed[205, 205], (255, 255, 0)) - - -class TestColorLut3DFilter(PillowTestCase): - def test_wrong_args(self): - with self.assertRaisesRegex(ValueError, "should be either an integer"): - ImageFilter.Color3DLUT("small", [1]) - - with self.assertRaisesRegex(ValueError, "should be either an integer"): - ImageFilter.Color3DLUT((11, 11), [1]) - - with self.assertRaisesRegex(ValueError, r"in \[2, 65\] range"): - ImageFilter.Color3DLUT((11, 11, 1), [1]) - - with self.assertRaisesRegex(ValueError, r"in \[2, 65\] range"): - ImageFilter.Color3DLUT((11, 11, 66), [1]) - - with self.assertRaisesRegex(ValueError, "table should have .+ items"): - ImageFilter.Color3DLUT((3, 3, 3), [1, 1, 1]) - - with self.assertRaisesRegex(ValueError, "table should have .+ items"): - ImageFilter.Color3DLUT((3, 3, 3), [[1, 1, 1]] * 2) - - with self.assertRaisesRegex(ValueError, "should have a length of 4"): - ImageFilter.Color3DLUT((3, 3, 3), [[1, 1, 1]] * 27, channels=4) - - with self.assertRaisesRegex(ValueError, "should have a length of 3"): - ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8) - - with self.assertRaisesRegex(ValueError, "Only 3 or 4 output"): - ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8, channels=2) - - def test_convert_table(self): - lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8) - self.assertEqual(tuple(lut.size), (2, 2, 2)) - self.assertEqual(lut.name, "Color 3D LUT") - - # fmt: off - lut = ImageFilter.Color3DLUT((2, 2, 2), [ - (0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), - (12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23)]) - # fmt: on - self.assertEqual(tuple(lut.size), (2, 2, 2)) - self.assertEqual(lut.table, list(range(24))) - - lut = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8, channels=4) - self.assertEqual(tuple(lut.size), (2, 2, 2)) - self.assertEqual(lut.table, list(range(4)) * 8) - - @unittest.skipIf(numpy is None, "Numpy is not installed") - def test_numpy_sources(self): - table = numpy.ones((5, 6, 7, 3), dtype=numpy.float16) - with self.assertRaisesRegex(ValueError, "should have either channels"): - lut = ImageFilter.Color3DLUT((5, 6, 7), table) - - table = numpy.ones((7, 6, 5, 3), dtype=numpy.float16) - lut = ImageFilter.Color3DLUT((5, 6, 7), table) - self.assertIsInstance(lut.table, numpy.ndarray) - self.assertEqual(lut.table.dtype, table.dtype) - self.assertEqual(lut.table.shape, (table.size,)) - - table = numpy.ones((7 * 6 * 5, 3), dtype=numpy.float16) - lut = ImageFilter.Color3DLUT((5, 6, 7), table) - self.assertEqual(lut.table.shape, (table.size,)) - - table = numpy.ones((7 * 6 * 5 * 3), dtype=numpy.float16) - lut = ImageFilter.Color3DLUT((5, 6, 7), table) - self.assertEqual(lut.table.shape, (table.size,)) - - # Check application - Image.new("RGB", (10, 10), 0).filter(lut) - - # Check copy - table[0] = 33 - self.assertEqual(lut.table[0], 1) - - # Check not copy - table = numpy.ones((7 * 6 * 5 * 3), dtype=numpy.float16) - lut = ImageFilter.Color3DLUT((5, 6, 7), table, _copy_table=False) - table[0] = 33 - self.assertEqual(lut.table[0], 33) - - @unittest.skipIf(numpy is None, "Numpy is not installed") - def test_numpy_formats(self): - g = Image.linear_gradient("L") - im = Image.merge( - "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] - ) - - lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) - lut.table = numpy.array(lut.table, dtype=numpy.float32)[:-1] - with self.assertRaisesRegex(ValueError, "should have table_channels"): - im.filter(lut) - - lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) - lut.table = numpy.array(lut.table, dtype=numpy.float32).reshape((7 * 9 * 11), 3) - with self.assertRaisesRegex(ValueError, "should have table_channels"): - im.filter(lut) - - lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) - lut.table = numpy.array(lut.table, dtype=numpy.float16) - self.assert_image_equal(im, im.filter(lut)) - - lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) - lut.table = numpy.array(lut.table, dtype=numpy.float32) - self.assert_image_equal(im, im.filter(lut)) - - lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) - lut.table = numpy.array(lut.table, dtype=numpy.float64) - self.assert_image_equal(im, im.filter(lut)) - - lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b)) - lut.table = numpy.array(lut.table, dtype=numpy.int32) - im.filter(lut) - lut.table = numpy.array(lut.table, dtype=numpy.int8) - im.filter(lut) - - def test_repr(self): - lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8) - self.assertEqual(repr(lut), "") - - lut = ImageFilter.Color3DLUT( - (3, 4, 5), - array("f", [0, 0, 0, 0] * (3 * 4 * 5)), - channels=4, - target_mode="YCbCr", - _copy_table=False, - ) - self.assertEqual( - repr(lut), "" - ) - - -class TestGenerateColorLut3D(PillowTestCase): - def test_wrong_channels_count(self): - with self.assertRaisesRegex(ValueError, "3 or 4 output channels"): - ImageFilter.Color3DLUT.generate( - 5, channels=2, callback=lambda r, g, b: (r, g, b) - ) - - with self.assertRaisesRegex(ValueError, "should have either channels"): - ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b, r)) - - with self.assertRaisesRegex(ValueError, "should have either channels"): - ImageFilter.Color3DLUT.generate( - 5, channels=4, callback=lambda r, g, b: (r, g, b) - ) - - def test_3_channels(self): - lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b)) - self.assertEqual(tuple(lut.size), (5, 5, 5)) - self.assertEqual(lut.name, "Color 3D LUT") - # fmt: off - self.assertEqual(lut.table[:24], [ - 0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.75, 0.0, 0.0, - 1.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, 0.25, 0.0, 0.5, 0.25, 0.0]) - # fmt: on - - def test_4_channels(self): - lut = ImageFilter.Color3DLUT.generate( - 5, channels=4, callback=lambda r, g, b: (b, r, g, (r + g + b) / 2) - ) - self.assertEqual(tuple(lut.size), (5, 5, 5)) - self.assertEqual(lut.name, "Color 3D LUT") - # fmt: off - self.assertEqual(lut.table[:24], [ - 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.125, 0.0, 0.5, 0.0, 0.25, - 0.0, 0.75, 0.0, 0.375, 0.0, 1.0, 0.0, 0.5, 0.0, 0.0, 0.25, 0.125 - ]) - # fmt: on - - def test_apply(self): - lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b)) - - g = Image.linear_gradient("L") - im = Image.merge( - "RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)] - ) - self.assertEqual(im, im.filter(lut)) - - -class TestTransformColorLut3D(PillowTestCase): - def test_wrong_args(self): - source = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b)) - - with self.assertRaisesRegex(ValueError, "Only 3 or 4 output"): - source.transform(lambda r, g, b: (r, g, b), channels=8) - - with self.assertRaisesRegex(ValueError, "should have either channels"): - source.transform(lambda r, g, b: (r, g, b), channels=4) - - with self.assertRaisesRegex(ValueError, "should have either channels"): - source.transform(lambda r, g, b: (r, g, b, 1)) - - with self.assertRaises(TypeError): - source.transform(lambda r, g, b, a: (r, g, b)) - - def test_target_mode(self): - source = ImageFilter.Color3DLUT.generate( - 2, lambda r, g, b: (r, g, b), target_mode="HSV" - ) - - lut = source.transform(lambda r, g, b: (r, g, b)) - self.assertEqual(lut.mode, "HSV") - - lut = source.transform(lambda r, g, b: (r, g, b), target_mode="RGB") - self.assertEqual(lut.mode, "RGB") - - def test_3_to_3_channels(self): - source = ImageFilter.Color3DLUT.generate((3, 4, 5), lambda r, g, b: (r, g, b)) - lut = source.transform(lambda r, g, b: (r * r, g * g, b * b)) - self.assertEqual(tuple(lut.size), tuple(source.size)) - self.assertEqual(len(lut.table), len(source.table)) - self.assertNotEqual(lut.table, source.table) - self.assertEqual( - lut.table[0:10], [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0] - ) - - def test_3_to_4_channels(self): - source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b)) - lut = source.transform(lambda r, g, b: (r * r, g * g, b * b, 1), channels=4) - self.assertEqual(tuple(lut.size), tuple(source.size)) - self.assertNotEqual(len(lut.table), len(source.table)) - self.assertNotEqual(lut.table, source.table) - # fmt: off - self.assertEqual(lut.table[0:16], [ - 0.0, 0.0, 0.0, 1, 0.2**2, 0.0, 0.0, 1, - 0.4**2, 0.0, 0.0, 1, 0.6**2, 0.0, 0.0, 1]) - # fmt: on - - def test_4_to_3_channels(self): - source = ImageFilter.Color3DLUT.generate( - (3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4 - ) - lut = source.transform( - lambda r, g, b, a: (a - r * r, a - g * g, a - b * b), channels=3 - ) - self.assertEqual(tuple(lut.size), tuple(source.size)) - self.assertNotEqual(len(lut.table), len(source.table)) - self.assertNotEqual(lut.table, source.table) - # fmt: off - self.assertEqual(lut.table[0:18], [ - 1.0, 1.0, 1.0, 0.75, 1.0, 1.0, 0.0, 1.0, 1.0, - 1.0, 0.96, 1.0, 0.75, 0.96, 1.0, 0.0, 0.96, 1.0]) - # fmt: on - - def test_4_to_4_channels(self): - source = ImageFilter.Color3DLUT.generate( - (6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4 - ) - lut = source.transform(lambda r, g, b, a: (r * r, g * g, b * b, a - 0.5)) - self.assertEqual(tuple(lut.size), tuple(source.size)) - self.assertEqual(len(lut.table), len(source.table)) - self.assertNotEqual(lut.table, source.table) - # fmt: off - self.assertEqual(lut.table[0:16], [ - 0.0, 0.0, 0.0, 0.5, 0.2**2, 0.0, 0.0, 0.5, - 0.4**2, 0.0, 0.0, 0.5, 0.6**2, 0.0, 0.0, 0.5]) - # fmt: on - - def test_with_normals_3_channels(self): - source = ImageFilter.Color3DLUT.generate( - (6, 5, 4), lambda r, g, b: (r * r, g * g, b * b) - ) - lut = source.transform( - lambda nr, ng, nb, r, g, b: (nr - r, ng - g, nb - b), with_normals=True - ) - self.assertEqual(tuple(lut.size), tuple(source.size)) - self.assertEqual(len(lut.table), len(source.table)) - self.assertNotEqual(lut.table, source.table) - # fmt: off - self.assertEqual(lut.table[0:18], [ - 0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.24, 0.0, 0.0, - 0.24, 0.0, 0.0, 0.8 - (0.8**2), 0, 0, 0, 0, 0]) - # fmt: on - - def test_with_normals_4_channels(self): - source = ImageFilter.Color3DLUT.generate( - (3, 6, 5), lambda r, g, b: (r * r, g * g, b * b, 1), channels=4 - ) - lut = source.transform( - lambda nr, ng, nb, r, g, b, a: (nr - r, ng - g, nb - b, a - 0.5), - with_normals=True, - ) - self.assertEqual(tuple(lut.size), tuple(source.size)) - self.assertEqual(len(lut.table), len(source.table)) - self.assertNotEqual(lut.table, source.table) - # fmt: off - self.assertEqual(lut.table[0:16], [ - 0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 0.0, 0.5, - 0.0, 0.0, 0.0, 0.5, 0.0, 0.16, 0.0, 0.5]) - # fmt: on diff --git a/Tests/test_core_resources.py b/Tests/test_core_resources.py deleted file mode 100644 index eefb1a0efab..00000000000 --- a/Tests/test_core_resources.py +++ /dev/null @@ -1,183 +0,0 @@ -from __future__ import division, print_function - -import sys - -from PIL import Image - -from .helper import PillowTestCase, unittest - -is_pypy = hasattr(sys, "pypy_version_info") - - -class TestCoreStats(PillowTestCase): - def test_get_stats(self): - # Create at least one image - Image.new("RGB", (10, 10)) - - stats = Image.core.get_stats() - self.assertIn("new_count", stats) - self.assertIn("reused_blocks", stats) - self.assertIn("freed_blocks", stats) - self.assertIn("allocated_blocks", stats) - self.assertIn("reallocated_blocks", stats) - self.assertIn("blocks_cached", stats) - - def test_reset_stats(self): - Image.core.reset_stats() - - stats = Image.core.get_stats() - self.assertEqual(stats["new_count"], 0) - self.assertEqual(stats["reused_blocks"], 0) - self.assertEqual(stats["freed_blocks"], 0) - self.assertEqual(stats["allocated_blocks"], 0) - self.assertEqual(stats["reallocated_blocks"], 0) - self.assertEqual(stats["blocks_cached"], 0) - - -class TestCoreMemory(PillowTestCase): - def tearDown(self): - # Restore default values - Image.core.set_alignment(1) - Image.core.set_block_size(1024 * 1024) - Image.core.set_blocks_max(0) - Image.core.clear_cache() - - def test_get_alignment(self): - alignment = Image.core.get_alignment() - - self.assertGreater(alignment, 0) - - def test_set_alignment(self): - for i in [1, 2, 4, 8, 16, 32]: - Image.core.set_alignment(i) - alignment = Image.core.get_alignment() - self.assertEqual(alignment, i) - - # Try to construct new image - Image.new("RGB", (10, 10)) - - self.assertRaises(ValueError, Image.core.set_alignment, 0) - self.assertRaises(ValueError, Image.core.set_alignment, -1) - self.assertRaises(ValueError, Image.core.set_alignment, 3) - - def test_get_block_size(self): - block_size = Image.core.get_block_size() - - self.assertGreaterEqual(block_size, 4096) - - def test_set_block_size(self): - for i in [4096, 2 * 4096, 3 * 4096]: - Image.core.set_block_size(i) - block_size = Image.core.get_block_size() - self.assertEqual(block_size, i) - - # Try to construct new image - Image.new("RGB", (10, 10)) - - self.assertRaises(ValueError, Image.core.set_block_size, 0) - self.assertRaises(ValueError, Image.core.set_block_size, -1) - self.assertRaises(ValueError, Image.core.set_block_size, 4000) - - def test_set_block_size_stats(self): - Image.core.reset_stats() - Image.core.set_blocks_max(0) - Image.core.set_block_size(4096) - Image.new("RGB", (256, 256)) - - stats = Image.core.get_stats() - self.assertGreaterEqual(stats["new_count"], 1) - self.assertGreaterEqual(stats["allocated_blocks"], 64) - if not is_pypy: - self.assertGreaterEqual(stats["freed_blocks"], 64) - - def test_get_blocks_max(self): - blocks_max = Image.core.get_blocks_max() - - self.assertGreaterEqual(blocks_max, 0) - - def test_set_blocks_max(self): - for i in [0, 1, 10]: - Image.core.set_blocks_max(i) - blocks_max = Image.core.get_blocks_max() - self.assertEqual(blocks_max, i) - - # Try to construct new image - Image.new("RGB", (10, 10)) - - self.assertRaises(ValueError, Image.core.set_blocks_max, -1) - if sys.maxsize < 2 ** 32: - self.assertRaises(ValueError, Image.core.set_blocks_max, 2 ** 29) - - @unittest.skipIf(is_pypy, "images are not collected") - def test_set_blocks_max_stats(self): - Image.core.reset_stats() - Image.core.set_blocks_max(128) - Image.core.set_block_size(4096) - Image.new("RGB", (256, 256)) - Image.new("RGB", (256, 256)) - - stats = Image.core.get_stats() - self.assertGreaterEqual(stats["new_count"], 2) - self.assertGreaterEqual(stats["allocated_blocks"], 64) - self.assertGreaterEqual(stats["reused_blocks"], 64) - self.assertEqual(stats["freed_blocks"], 0) - self.assertEqual(stats["blocks_cached"], 64) - - @unittest.skipIf(is_pypy, "images are not collected") - def test_clear_cache_stats(self): - Image.core.reset_stats() - Image.core.clear_cache() - Image.core.set_blocks_max(128) - Image.core.set_block_size(4096) - Image.new("RGB", (256, 256)) - Image.new("RGB", (256, 256)) - # Keep 16 blocks in cache - Image.core.clear_cache(16) - - stats = Image.core.get_stats() - self.assertGreaterEqual(stats["new_count"], 2) - self.assertGreaterEqual(stats["allocated_blocks"], 64) - self.assertGreaterEqual(stats["reused_blocks"], 64) - self.assertGreaterEqual(stats["freed_blocks"], 48) - self.assertEqual(stats["blocks_cached"], 16) - - def test_large_images(self): - Image.core.reset_stats() - Image.core.set_blocks_max(0) - Image.core.set_block_size(4096) - Image.new("RGB", (2048, 16)) - Image.core.clear_cache() - - stats = Image.core.get_stats() - self.assertGreaterEqual(stats["new_count"], 1) - self.assertGreaterEqual(stats["allocated_blocks"], 16) - self.assertGreaterEqual(stats["reused_blocks"], 0) - self.assertEqual(stats["blocks_cached"], 0) - if not is_pypy: - self.assertGreaterEqual(stats["freed_blocks"], 16) - - -class TestEnvVars(PillowTestCase): - def tearDown(self): - # Restore default values - Image.core.set_alignment(1) - Image.core.set_block_size(1024 * 1024) - Image.core.set_blocks_max(0) - Image.core.clear_cache() - - def test_units(self): - Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"}) - self.assertEqual(Image.core.get_blocks_max(), 2 * 1024) - Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"}) - self.assertEqual(Image.core.get_block_size(), 2 * 1024 * 1024) - - def test_warnings(self): - self.assert_warning( - UserWarning, Image._apply_env_variables, {"PILLOW_ALIGNMENT": "15"} - ) - self.assert_warning( - UserWarning, Image._apply_env_variables, {"PILLOW_BLOCK_SIZE": "1024"} - ) - self.assert_warning( - UserWarning, Image._apply_env_variables, {"PILLOW_BLOCKS_MAX": "wat"} - ) diff --git a/Tests/test_decompression_bomb.py b/Tests/test_decompression_bomb.py deleted file mode 100644 index b3a36fe7870..00000000000 --- a/Tests/test_decompression_bomb.py +++ /dev/null @@ -1,77 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/hopper.ppm" - -ORIGINAL_LIMIT = Image.MAX_IMAGE_PIXELS - - -class TestDecompressionBomb(PillowTestCase): - def tearDown(self): - Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT - - def test_no_warning_small_file(self): - # Implicit assert: no warning. - # A warning would cause a failure. - Image.open(TEST_FILE) - - def test_no_warning_no_limit(self): - # Arrange - # Turn limit off - Image.MAX_IMAGE_PIXELS = None - self.assertIsNone(Image.MAX_IMAGE_PIXELS) - - # Act / Assert - # Implicit assert: no warning. - # A warning would cause a failure. - Image.open(TEST_FILE) - - def test_warning(self): - # Set limit to trigger warning on the test file - Image.MAX_IMAGE_PIXELS = 128 * 128 - 1 - self.assertEqual(Image.MAX_IMAGE_PIXELS, 128 * 128 - 1) - - self.assert_warning(Image.DecompressionBombWarning, Image.open, TEST_FILE) - - def test_exception(self): - # Set limit to trigger exception on the test file - Image.MAX_IMAGE_PIXELS = 64 * 128 - 1 - self.assertEqual(Image.MAX_IMAGE_PIXELS, 64 * 128 - 1) - - self.assertRaises(Image.DecompressionBombError, lambda: Image.open(TEST_FILE)) - - -class TestDecompressionCrop(PillowTestCase): - def setUp(self): - self.src = hopper() - Image.MAX_IMAGE_PIXELS = self.src.height * self.src.width * 4 - 1 - - def tearDown(self): - Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT - - def testEnlargeCrop(self): - # Crops can extend the extents, therefore we should have the - # same decompression bomb warnings on them. - box = (0, 0, self.src.width * 2, self.src.height * 2) - self.assert_warning(Image.DecompressionBombWarning, self.src.crop, box) - - def test_crop_decompression_checks(self): - - im = Image.new("RGB", (100, 100)) - - good_values = ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990)) - - warning_values = ((-160, -160, 99, 99), (160, 160, -99, -99)) - - error_values = ((-99909, -99990, 99999, 99999), (99909, 99990, -99999, -99999)) - - for value in good_values: - self.assertEqual(im.crop(value).size, (9, 9)) - - for value in warning_values: - self.assert_warning(Image.DecompressionBombWarning, im.crop, value) - - for value in error_values: - with self.assertRaises(Image.DecompressionBombError): - im.crop(value) diff --git a/Tests/test_features.py b/Tests/test_features.py deleted file mode 100644 index 64b0302caa5..00000000000 --- a/Tests/test_features.py +++ /dev/null @@ -1,88 +0,0 @@ -from __future__ import unicode_literals - -import io - -from PIL import features - -from .helper import PillowTestCase, unittest - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -class TestFeatures(PillowTestCase): - def test_check(self): - # Check the correctness of the convenience function - for module in features.modules: - self.assertEqual(features.check_module(module), features.check(module)) - for codec in features.codecs: - self.assertEqual(features.check_codec(codec), features.check(codec)) - for feature in features.features: - self.assertEqual(features.check_feature(feature), features.check(feature)) - - @unittest.skipUnless(HAVE_WEBP, "WebP not available") - def test_webp_transparency(self): - self.assertEqual( - features.check("transp_webp"), not _webp.WebPDecoderBuggyAlpha() - ) - self.assertEqual(features.check("transp_webp"), _webp.HAVE_TRANSPARENCY) - - @unittest.skipUnless(HAVE_WEBP, "WebP not available") - def test_webp_mux(self): - self.assertEqual(features.check("webp_mux"), _webp.HAVE_WEBPMUX) - - @unittest.skipUnless(HAVE_WEBP, "WebP not available") - def test_webp_anim(self): - self.assertEqual(features.check("webp_anim"), _webp.HAVE_WEBPANIM) - - def test_check_modules(self): - for feature in features.modules: - self.assertIn(features.check_module(feature), [True, False]) - for feature in features.codecs: - self.assertIn(features.check_codec(feature), [True, False]) - - def test_supported_modules(self): - self.assertIsInstance(features.get_supported_modules(), list) - self.assertIsInstance(features.get_supported_codecs(), list) - self.assertIsInstance(features.get_supported_features(), list) - self.assertIsInstance(features.get_supported(), list) - - def test_unsupported_codec(self): - # Arrange - codec = "unsupported_codec" - # Act / Assert - self.assertRaises(ValueError, features.check_codec, codec) - - def test_unsupported_module(self): - # Arrange - module = "unsupported_module" - # Act / Assert - self.assertRaises(ValueError, features.check_module, module) - - def test_pilinfo(self): - buf = io.StringIO() - features.pilinfo(buf) - out = buf.getvalue() - lines = out.splitlines() - self.assertEqual(lines[0], "-" * 68) - self.assertTrue(lines[1].startswith("Pillow ")) - self.assertEqual(lines[2], "-" * 68) - self.assertTrue(lines[3].startswith("Python modules loaded from ")) - self.assertTrue(lines[4].startswith("Binary modules loaded from ")) - self.assertEqual(lines[5], "-" * 68) - self.assertTrue(lines[6].startswith("Python ")) - jpeg = ( - "\n" - + "-" * 68 - + "\n" - + "JPEG image/jpeg\n" - + "Extensions: .jfif, .jpe, .jpeg, .jpg\n" - + "Features: open, save\n" - + "-" * 68 - + "\n" - ) - self.assertIn(jpeg, out) diff --git a/Tests/test_file_blp.py b/Tests/test_file_blp.py deleted file mode 100644 index 59951a890a9..00000000000 --- a/Tests/test_file_blp.py +++ /dev/null @@ -1,20 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestFileBlp(PillowTestCase): - def test_load_blp2_raw(self): - im = Image.open("Tests/images/blp/blp2_raw.blp") - target = Image.open("Tests/images/blp/blp2_raw.png") - self.assert_image_equal(im, target) - - def test_load_blp2_dxt1(self): - im = Image.open("Tests/images/blp/blp2_dxt1.blp") - target = Image.open("Tests/images/blp/blp2_dxt1.png") - self.assert_image_equal(im, target) - - def test_load_blp2_dxt1a(self): - im = Image.open("Tests/images/blp/blp2_dxt1a.blp") - target = Image.open("Tests/images/blp/blp2_dxt1a.png") - self.assert_image_equal(im, target) diff --git a/Tests/test_file_bmp.py b/Tests/test_file_bmp.py deleted file mode 100644 index 2180835ba52..00000000000 --- a/Tests/test_file_bmp.py +++ /dev/null @@ -1,124 +0,0 @@ -import io - -from PIL import BmpImagePlugin, Image - -from .helper import PillowTestCase, hopper - - -class TestFileBmp(PillowTestCase): - def roundtrip(self, im): - outfile = self.tempfile("temp.bmp") - - im.save(outfile, "BMP") - - reloaded = Image.open(outfile) - reloaded.load() - self.assertEqual(im.mode, reloaded.mode) - self.assertEqual(im.size, reloaded.size) - self.assertEqual(reloaded.format, "BMP") - self.assertEqual(reloaded.get_format_mimetype(), "image/bmp") - - def test_sanity(self): - self.roundtrip(hopper()) - - self.roundtrip(hopper("1")) - self.roundtrip(hopper("L")) - self.roundtrip(hopper("P")) - self.roundtrip(hopper("RGB")) - - def test_invalid_file(self): - with open("Tests/images/flower.jpg", "rb") as fp: - self.assertRaises(SyntaxError, BmpImagePlugin.BmpImageFile, fp) - - def test_save_to_bytes(self): - output = io.BytesIO() - im = hopper() - im.save(output, "BMP") - - output.seek(0) - reloaded = Image.open(output) - - self.assertEqual(im.mode, reloaded.mode) - self.assertEqual(im.size, reloaded.size) - self.assertEqual(reloaded.format, "BMP") - - def test_dpi(self): - dpi = (72, 72) - - output = io.BytesIO() - im = hopper() - im.save(output, "BMP", dpi=dpi) - - output.seek(0) - reloaded = Image.open(output) - - self.assertEqual(reloaded.info["dpi"], dpi) - - def test_save_bmp_with_dpi(self): - # Test for #1301 - # Arrange - outfile = self.tempfile("temp.jpg") - im = Image.open("Tests/images/hopper.bmp") - - # Act - im.save(outfile, "JPEG", dpi=im.info["dpi"]) - - # Assert - reloaded = Image.open(outfile) - reloaded.load() - self.assertEqual(im.info["dpi"], reloaded.info["dpi"]) - self.assertEqual(im.size, reloaded.size) - self.assertEqual(reloaded.format, "JPEG") - - def test_load_dpi_rounding(self): - # Round up - im = Image.open("Tests/images/hopper.bmp") - self.assertEqual(im.info["dpi"], (96, 96)) - - # Round down - im = Image.open("Tests/images/hopper_roundDown.bmp") - self.assertEqual(im.info["dpi"], (72, 72)) - - def test_save_dpi_rounding(self): - outfile = self.tempfile("temp.bmp") - im = Image.open("Tests/images/hopper.bmp") - - im.save(outfile, dpi=(72.2, 72.2)) - reloaded = Image.open(outfile) - self.assertEqual(reloaded.info["dpi"], (72, 72)) - - im.save(outfile, dpi=(72.8, 72.8)) - reloaded = Image.open(outfile) - self.assertEqual(reloaded.info["dpi"], (73, 73)) - - def test_load_dib(self): - # test for #1293, Imagegrab returning Unsupported Bitfields Format - im = Image.open("Tests/images/clipboard.dib") - self.assertEqual(im.format, "DIB") - self.assertEqual(im.get_format_mimetype(), "image/bmp") - - target = Image.open("Tests/images/clipboard_target.png") - self.assert_image_equal(im, target) - - def test_save_dib(self): - outfile = self.tempfile("temp.dib") - - im = Image.open("Tests/images/clipboard.dib") - im.save(outfile) - - reloaded = Image.open(outfile) - self.assertEqual(reloaded.format, "DIB") - self.assertEqual(reloaded.get_format_mimetype(), "image/bmp") - self.assert_image_equal(im, reloaded) - - def test_rgba_bitfields(self): - # This test image has been manually hexedited - # to change the bitfield compression in the header from XBGR to RGBA - im = Image.open("Tests/images/rgb32bf-rgba.bmp") - - # So before the comparing the image, swap the channels - b, g, r = im.split()[1:] - im = Image.merge("RGB", (r, g, b)) - - target = Image.open("Tests/images/bmp/q/rgb32bf-xbgr.bmp") - self.assert_image_equal(im, target) diff --git a/Tests/test_file_bufrstub.py b/Tests/test_file_bufrstub.py deleted file mode 100644 index 37573e3406c..00000000000 --- a/Tests/test_file_bufrstub.py +++ /dev/null @@ -1,42 +0,0 @@ -from PIL import BufrStubImagePlugin, Image - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d" - - -class TestFileBufrStub(PillowTestCase): - def test_open(self): - # Act - im = Image.open(TEST_FILE) - - # Assert - self.assertEqual(im.format, "BUFR") - - # Dummy data from the stub - self.assertEqual(im.mode, "F") - self.assertEqual(im.size, (1, 1)) - - def test_invalid_file(self): - # Arrange - invalid_file = "Tests/images/flower.jpg" - - # Act / Assert - self.assertRaises( - SyntaxError, BufrStubImagePlugin.BufrStubImageFile, invalid_file - ) - - def test_load(self): - # Arrange - im = Image.open(TEST_FILE) - - # Act / Assert: stub cannot load without an implemented handler - self.assertRaises(IOError, im.load) - - def test_save(self): - # Arrange - im = hopper() - tmpfile = self.tempfile("temp.bufr") - - # Act / Assert: stub cannot save without an implemented handler - self.assertRaises(IOError, im.save, tmpfile) diff --git a/Tests/test_file_container.py b/Tests/test_file_container.py deleted file mode 100644 index 5f14001d9a5..00000000000 --- a/Tests/test_file_container.py +++ /dev/null @@ -1,125 +0,0 @@ -from PIL import ContainerIO, Image - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/dummy.container" - - -class TestFileContainer(PillowTestCase): - def test_sanity(self): - dir(Image) - dir(ContainerIO) - - def test_isatty(self): - im = hopper() - container = ContainerIO.ContainerIO(im, 0, 0) - - self.assertFalse(container.isatty()) - - def test_seek_mode_0(self): - # Arrange - mode = 0 - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 22, 100) - - # Act - container.seek(33, mode) - container.seek(33, mode) - - # Assert - self.assertEqual(container.tell(), 33) - - def test_seek_mode_1(self): - # Arrange - mode = 1 - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 22, 100) - - # Act - container.seek(33, mode) - container.seek(33, mode) - - # Assert - self.assertEqual(container.tell(), 66) - - def test_seek_mode_2(self): - # Arrange - mode = 2 - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 22, 100) - - # Act - container.seek(33, mode) - container.seek(33, mode) - - # Assert - self.assertEqual(container.tell(), 100) - - def test_read_n0(self): - # Arrange - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 22, 100) - - # Act - container.seek(81) - data = container.read() - - # Assert - self.assertEqual(data, "7\nThis is line 8\n") - - def test_read_n(self): - # Arrange - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 22, 100) - - # Act - container.seek(81) - data = container.read(3) - - # Assert - self.assertEqual(data, "7\nT") - - def test_read_eof(self): - # Arrange - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 22, 100) - - # Act - container.seek(100) - data = container.read() - - # Assert - self.assertEqual(data, "") - - def test_readline(self): - # Arrange - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 0, 120) - - # Act - data = container.readline() - - # Assert - self.assertEqual(data, "This is line 1\n") - - def test_readlines(self): - # Arrange - expected = [ - "This is line 1\n", - "This is line 2\n", - "This is line 3\n", - "This is line 4\n", - "This is line 5\n", - "This is line 6\n", - "This is line 7\n", - "This is line 8\n", - ] - with open(TEST_FILE) as fh: - container = ContainerIO.ContainerIO(fh, 0, 120) - - # Act - data = container.readlines() - - # Assert - - self.assertEqual(data, expected) diff --git a/Tests/test_file_cur.py b/Tests/test_file_cur.py deleted file mode 100644 index 0b2f7a98ce3..00000000000 --- a/Tests/test_file_cur.py +++ /dev/null @@ -1,29 +0,0 @@ -from PIL import CurImagePlugin, Image - -from .helper import PillowTestCase - -TEST_FILE = "Tests/images/deerstalker.cur" - - -class TestFileCur(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_FILE) - - 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, 0)) - self.assertEqual(im.getpixel((11, 1)), (253, 254, 254, 1)) - self.assertEqual(im.getpixel((16, 16)), (84, 87, 86, 255)) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, CurImagePlugin.CurImageFile, invalid_file) - - no_cursors_file = "Tests/images/no_cursors.cur" - - cur = CurImagePlugin.CurImageFile(TEST_FILE) - cur.fp.close() - with open(no_cursors_file, "rb") as cur.fp: - self.assertRaises(TypeError, cur._open) diff --git a/Tests/test_file_dcx.py b/Tests/test_file_dcx.py deleted file mode 100644 index 4d3690d30c5..00000000000 --- a/Tests/test_file_dcx.py +++ /dev/null @@ -1,65 +0,0 @@ -from PIL import DcxImagePlugin, Image - -from .helper import PillowTestCase, hopper - -# Created with ImageMagick: convert hopper.ppm hopper.dcx -TEST_FILE = "Tests/images/hopper.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 = hopper() - self.assert_image_equal(im, orig) - - def test_unclosed_file(self): - def open(): - im = Image.open(TEST_FILE) - im.load() - - self.assert_warning(None, open) - - def test_invalid_file(self): - with open("Tests/images/flower.jpg", "rb") as fp: - self.assertRaises(SyntaxError, DcxImagePlugin.DcxImageFile, fp) - - def test_tell(self): - # Arrange - im = Image.open(TEST_FILE) - - # Act - frame = im.tell() - - # Assert - self.assertEqual(frame, 0) - - def test_n_frames(self): - im = Image.open(TEST_FILE) - self.assertEqual(im.n_frames, 1) - self.assertFalse(im.is_animated) - - def test_eoferror(self): - im = Image.open(TEST_FILE) - n_frames = im.n_frames - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_seek_too_far(self): - # Arrange - im = Image.open(TEST_FILE) - frame = 999 # too big on purpose - - # Act / Assert - self.assertRaises(EOFError, im.seek, frame) diff --git a/Tests/test_file_dds.py b/Tests/test_file_dds.py deleted file mode 100644 index 498c64f2124..00000000000 --- a/Tests/test_file_dds.py +++ /dev/null @@ -1,142 +0,0 @@ -from io import BytesIO - -from PIL import DdsImagePlugin, Image - -from .helper import PillowTestCase - -TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds" -TEST_FILE_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds" -TEST_FILE_DXT5 = "Tests/images/dxt5-argb-8bbp-interpolatedalpha_MipMaps-1.dds" -TEST_FILE_DX10_BC7 = "Tests/images/bc7-argb-8bpp_MipMaps-1.dds" -TEST_FILE_UNCOMPRESSED_RGB = "Tests/images/uncompressed_rgb.dds" - - -class TestFileDds(PillowTestCase): - """Test DdsImagePlugin""" - - def test_sanity_dxt1(self): - """Check DXT1 images can be opened""" - target = Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) - - im = Image.open(TEST_FILE_DXT1) - im.load() - - self.assertEqual(im.format, "DDS") - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (256, 256)) - - self.assert_image_equal(target.convert("RGBA"), im) - - def test_sanity_dxt5(self): - """Check DXT5 images can be opened""" - - target = Image.open(TEST_FILE_DXT5.replace(".dds", ".png")) - - im = Image.open(TEST_FILE_DXT5) - im.load() - - self.assertEqual(im.format, "DDS") - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (256, 256)) - - self.assert_image_equal(target, im) - - def test_sanity_dxt3(self): - """Check DXT3 images can be opened""" - - target = Image.open(TEST_FILE_DXT3.replace(".dds", ".png")) - - im = Image.open(TEST_FILE_DXT3) - im.load() - - self.assertEqual(im.format, "DDS") - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (256, 256)) - - self.assert_image_equal(target, im) - - def test_dx10_bc7(self): - """Check DX10 images can be opened""" - - target = Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png")) - - im = Image.open(TEST_FILE_DX10_BC7) - im.load() - - self.assertEqual(im.format, "DDS") - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (256, 256)) - - self.assert_image_equal(target, im) - - def test_unimplemented_dxgi_format(self): - self.assertRaises( - NotImplementedError, - Image.open, - "Tests/images/unimplemented_dxgi_format.dds", - ) - - def test_uncompressed_rgb(self): - """Check uncompressed RGB images can be opened""" - - target = Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png")) - - im = Image.open(TEST_FILE_UNCOMPRESSED_RGB) - im.load() - - self.assertEqual(im.format, "DDS") - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (800, 600)) - - self.assert_image_equal(target, im) - - def test__validate_true(self): - """Check valid prefix""" - # Arrange - prefix = b"DDS etc" - - # Act - output = DdsImagePlugin._validate(prefix) - - # Assert - self.assertTrue(output) - - def test__validate_false(self): - """Check invalid prefix""" - # Arrange - prefix = b"something invalid" - - # Act - output = DdsImagePlugin._validate(prefix) - - # Assert - self.assertFalse(output) - - def test_short_header(self): - """ Check a short header""" - with open(TEST_FILE_DXT5, "rb") as f: - img_file = f.read() - - def short_header(): - Image.open(BytesIO(img_file[:119])) - - self.assertRaises(IOError, short_header) - - def test_short_file(self): - """ Check that the appropriate error is thrown for a short file""" - - with open(TEST_FILE_DXT5, "rb") as f: - img_file = f.read() - - def short_file(): - im = Image.open(BytesIO(img_file[:-100])) - im.load() - - self.assertRaises(IOError, short_file) - - def test_unimplemented_pixel_format(self): - self.assertRaises( - NotImplementedError, - Image.open, - "Tests/images/unimplemented_pixel_format.dds", - ) diff --git a/Tests/test_file_eps.py b/Tests/test_file_eps.py deleted file mode 100644 index 3459310dfad..00000000000 --- a/Tests/test_file_eps.py +++ /dev/null @@ -1,254 +0,0 @@ -import io - -from PIL import EpsImagePlugin, Image - -from .helper import PillowTestCase, hopper, unittest - -HAS_GHOSTSCRIPT = EpsImagePlugin.has_ghostscript() - -# Our two EPS test files (they are identical except for their bounding boxes) -file1 = "Tests/images/zero_bb.eps" -file2 = "Tests/images/non_zero_bb.eps" - -# Due to palletization, we'll need to convert these to RGB after load -file1_compare = "Tests/images/zero_bb.png" -file1_compare_scale2 = "Tests/images/zero_bb_scale2.png" - -file2_compare = "Tests/images/non_zero_bb.png" -file2_compare_scale2 = "Tests/images/non_zero_bb_scale2.png" - -# EPS test files with binary preview -file3 = "Tests/images/binary_preview_map.eps" - - -class TestFileEps(PillowTestCase): - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_sanity(self): - # Regular scale - image1 = Image.open(file1) - image1.load() - self.assertEqual(image1.mode, "RGB") - self.assertEqual(image1.size, (460, 352)) - self.assertEqual(image1.format, "EPS") - - image2 = Image.open(file2) - image2.load() - self.assertEqual(image2.mode, "RGB") - self.assertEqual(image2.size, (360, 252)) - self.assertEqual(image2.format, "EPS") - - # Double scale - image1_scale2 = Image.open(file1) - image1_scale2.load(scale=2) - self.assertEqual(image1_scale2.mode, "RGB") - self.assertEqual(image1_scale2.size, (920, 704)) - self.assertEqual(image1_scale2.format, "EPS") - - image2_scale2 = Image.open(file2) - image2_scale2.load(scale=2) - self.assertEqual(image2_scale2.mode, "RGB") - self.assertEqual(image2_scale2.size, (720, 504)) - self.assertEqual(image2_scale2.format, "EPS") - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, EpsImagePlugin.EpsImageFile, invalid_file) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_cmyk(self): - cmyk_image = Image.open("Tests/images/pil_sample_cmyk.eps") - - self.assertEqual(cmyk_image.mode, "CMYK") - self.assertEqual(cmyk_image.size, (100, 100)) - self.assertEqual(cmyk_image.format, "EPS") - - cmyk_image.load() - self.assertEqual(cmyk_image.mode, "RGB") - - if "jpeg_decoder" in dir(Image.core): - target = Image.open("Tests/images/pil_sample_rgb.jpg") - self.assert_image_similar(cmyk_image, target, 10) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_showpage(self): - # See https://github.com/python-pillow/Pillow/issues/2615 - plot_image = Image.open("Tests/images/reqd_showpage.eps") - target = Image.open("Tests/images/reqd_showpage.png") - - # should not crash/hang - plot_image.load() - # fonts could be slightly different - self.assert_image_similar(plot_image, target, 6) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_file_object(self): - # issue 479 - image1 = Image.open(file1) - with open(self.tempfile("temp_file.eps"), "wb") as fh: - image1.save(fh, "EPS") - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_iobase_object(self): - # issue 479 - image1 = Image.open(file1) - with io.open(self.tempfile("temp_iobase.eps"), "wb") as fh: - image1.save(fh, "EPS") - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_bytesio_object(self): - with open(file1, "rb") as f: - img_bytes = io.BytesIO(f.read()) - - img = Image.open(img_bytes) - img.load() - - image1_scale1_compare = Image.open(file1_compare).convert("RGB") - image1_scale1_compare.load() - self.assert_image_similar(img, image1_scale1_compare, 5) - - def test_image_mode_not_supported(self): - im = hopper("RGBA") - tmpfile = self.tempfile("temp.eps") - self.assertRaises(ValueError, im.save, tmpfile) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_render_scale1(self): - # We need png support for these render test - codecs = dir(Image.core) - if "zip_encoder" not in codecs or "zip_decoder" not in codecs: - self.skipTest("zip/deflate support not available") - - # Zero bounding box - image1_scale1 = Image.open(file1) - image1_scale1.load() - image1_scale1_compare = Image.open(file1_compare).convert("RGB") - image1_scale1_compare.load() - self.assert_image_similar(image1_scale1, image1_scale1_compare, 5) - - # Non-Zero bounding box - image2_scale1 = Image.open(file2) - image2_scale1.load() - image2_scale1_compare = Image.open(file2_compare).convert("RGB") - image2_scale1_compare.load() - self.assert_image_similar(image2_scale1, image2_scale1_compare, 10) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_render_scale2(self): - # We need png support for these render test - codecs = dir(Image.core) - if "zip_encoder" not in codecs or "zip_decoder" not in codecs: - self.skipTest("zip/deflate support not available") - - # Zero bounding box - image1_scale2 = Image.open(file1) - image1_scale2.load(scale=2) - image1_scale2_compare = Image.open(file1_compare_scale2).convert("RGB") - image1_scale2_compare.load() - self.assert_image_similar(image1_scale2, image1_scale2_compare, 5) - - # Non-Zero bounding box - image2_scale2 = Image.open(file2) - image2_scale2.load(scale=2) - image2_scale2_compare = Image.open(file2_compare_scale2).convert("RGB") - image2_scale2_compare.load() - self.assert_image_similar(image2_scale2, image2_scale2_compare, 10) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_resize(self): - # Arrange - image1 = Image.open(file1) - image2 = Image.open(file2) - image3 = Image.open("Tests/images/illu10_preview.eps") - new_size = (100, 100) - - # Act - image1 = image1.resize(new_size) - image2 = image2.resize(new_size) - image3 = image3.resize(new_size) - - # Assert - self.assertEqual(image1.size, new_size) - self.assertEqual(image2.size, new_size) - self.assertEqual(image3.size, new_size) - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_thumbnail(self): - # Issue #619 - # Arrange - image1 = Image.open(file1) - image2 = Image.open(file2) - new_size = (100, 100) - - # Act - image1.thumbnail(new_size) - image2.thumbnail(new_size) - - # Assert - self.assertEqual(max(image1.size), max(new_size)) - self.assertEqual(max(image2.size), max(new_size)) - - def test_read_binary_preview(self): - # Issue 302 - # open image with binary preview - Image.open(file3) - - def _test_readline(self, t, ending): - ending = "Failure with line ending: %s" % ( - "".join("%s" % ord(s) for s in ending) - ) - self.assertEqual(t.readline().strip("\r\n"), "something", ending) - self.assertEqual(t.readline().strip("\r\n"), "else", ending) - self.assertEqual(t.readline().strip("\r\n"), "baz", ending) - self.assertEqual(t.readline().strip("\r\n"), "bif", ending) - - def _test_readline_io_psfile(self, test_string, ending): - f = io.BytesIO(test_string.encode("latin-1")) - t = EpsImagePlugin.PSFile(f) - self._test_readline(t, ending) - - def _test_readline_file_psfile(self, test_string, ending): - f = self.tempfile("temp.txt") - with open(f, "wb") as w: - w.write(test_string.encode("latin-1")) - - with open(f, "rb") as r: - t = EpsImagePlugin.PSFile(r) - self._test_readline(t, ending) - - def test_readline(self): - # check all the freaking line endings possible from the spec - # test_string = u'something\r\nelse\n\rbaz\rbif\n' - line_endings = ["\r\n", "\n", "\n\r", "\r"] - strings = ["something", "else", "baz", "bif"] - - for ending in line_endings: - s = ending.join(strings) - self._test_readline_io_psfile(s, ending) - self._test_readline_file_psfile(s, ending) - - def test_open_eps(self): - # https://github.com/python-pillow/Pillow/issues/1104 - # Arrange - FILES = [ - "Tests/images/illu10_no_preview.eps", - "Tests/images/illu10_preview.eps", - "Tests/images/illuCS6_no_preview.eps", - "Tests/images/illuCS6_preview.eps", - ] - - # Act / Assert - for filename in FILES: - img = Image.open(filename) - self.assertEqual(img.mode, "RGB") - - @unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available") - def test_emptyline(self): - # Test file includes an empty line in the header data - emptyline_file = "Tests/images/zero_bb_emptyline.eps" - - image = Image.open(emptyline_file) - image.load() - self.assertEqual(image.mode, "RGB") - self.assertEqual(image.size, (460, 352)) - self.assertEqual(image.format, "EPS") diff --git a/Tests/test_file_fitsstub.py b/Tests/test_file_fitsstub.py deleted file mode 100644 index 0221bab9934..00000000000 --- a/Tests/test_file_fitsstub.py +++ /dev/null @@ -1,46 +0,0 @@ -from PIL import FitsStubImagePlugin, Image - -from .helper import PillowTestCase - -TEST_FILE = "Tests/images/hopper.fits" - - -class TestFileFitsStub(PillowTestCase): - def test_open(self): - # Act - im = Image.open(TEST_FILE) - - # Assert - self.assertEqual(im.format, "FITS") - - # Dummy data from the stub - self.assertEqual(im.mode, "F") - self.assertEqual(im.size, (1, 1)) - - def test_invalid_file(self): - # Arrange - invalid_file = "Tests/images/flower.jpg" - - # Act / Assert - self.assertRaises( - SyntaxError, FitsStubImagePlugin.FITSStubImageFile, invalid_file - ) - - def test_load(self): - # Arrange - im = Image.open(TEST_FILE) - - # Act / Assert: stub cannot load without an implemented handler - self.assertRaises(IOError, im.load) - - def test_save(self): - # Arrange - im = Image.open(TEST_FILE) - dummy_fp = None - dummy_filename = "dummy.filename" - - # Act / Assert: stub cannot save without an implemented handler - self.assertRaises(IOError, im.save, dummy_filename) - self.assertRaises( - IOError, FitsStubImagePlugin._save, im, dummy_fp, dummy_filename - ) diff --git a/Tests/test_file_fli.py b/Tests/test_file_fli.py deleted file mode 100644 index ad3e84a5bbe..00000000000 --- a/Tests/test_file_fli.py +++ /dev/null @@ -1,98 +0,0 @@ -from PIL import FliImagePlugin, Image - -from .helper import PillowTestCase - -# created as an export of a palette image from Gimp2.6 -# save as...-> hopper.fli, default options. -static_test_file = "Tests/images/hopper.fli" - -# From https://samples.libav.org/fli-flc/ -animated_test_file = "Tests/images/a.fli" - - -class TestFileFli(PillowTestCase): - def test_sanity(self): - im = Image.open(static_test_file) - im.load() - self.assertEqual(im.mode, "P") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "FLI") - self.assertFalse(im.is_animated) - - im = Image.open(animated_test_file) - self.assertEqual(im.mode, "P") - self.assertEqual(im.size, (320, 200)) - self.assertEqual(im.format, "FLI") - self.assertEqual(im.info["duration"], 71) - self.assertTrue(im.is_animated) - - def test_unclosed_file(self): - def open(): - im = Image.open(static_test_file) - im.load() - - self.assert_warning(None, open) - - def test_tell(self): - # Arrange - im = Image.open(static_test_file) - - # Act - frame = im.tell() - - # Assert - self.assertEqual(frame, 0) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, FliImagePlugin.FliImageFile, invalid_file) - - def test_n_frames(self): - im = Image.open(static_test_file) - self.assertEqual(im.n_frames, 1) - self.assertFalse(im.is_animated) - - im = Image.open(animated_test_file) - self.assertEqual(im.n_frames, 384) - self.assertTrue(im.is_animated) - - def test_eoferror(self): - im = Image.open(animated_test_file) - n_frames = im.n_frames - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_seek_tell(self): - im = Image.open(animated_test_file) - - layer_number = im.tell() - self.assertEqual(layer_number, 0) - - im.seek(0) - layer_number = im.tell() - self.assertEqual(layer_number, 0) - - im.seek(1) - layer_number = im.tell() - self.assertEqual(layer_number, 1) - - im.seek(2) - layer_number = im.tell() - self.assertEqual(layer_number, 2) - - im.seek(1) - layer_number = im.tell() - self.assertEqual(layer_number, 1) - - def test_seek(self): - im = Image.open(animated_test_file) - im.seek(50) - - expected = Image.open("Tests/images/a_fli.png") - self.assert_image_equal(im, expected) diff --git a/Tests/test_file_fpx.py b/Tests/test_file_fpx.py deleted file mode 100644 index 68412c8caa0..00000000000 --- a/Tests/test_file_fpx.py +++ /dev/null @@ -1,20 +0,0 @@ -from .helper import PillowTestCase, unittest - -try: - from PIL import FpxImagePlugin -except ImportError: - olefile_installed = False -else: - olefile_installed = True - - -@unittest.skipUnless(olefile_installed, "olefile package not installed") -class TestFileFpx(PillowTestCase): - def test_invalid_file(self): - # Test an invalid OLE file - invalid_file = "Tests/images/flower.jpg" - self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, invalid_file) - - # Test a valid OLE file, but not an FPX file - ole_file = "Tests/images/test-ole-file.doc" - self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file) diff --git a/Tests/test_file_ftex.py b/Tests/test_file_ftex.py deleted file mode 100644 index 7d30042ca0c..00000000000 --- a/Tests/test_file_ftex.py +++ /dev/null @@ -1,16 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestFileFtex(PillowTestCase): - def test_load_raw(self): - im = Image.open("Tests/images/ftex_uncompressed.ftu") - target = Image.open("Tests/images/ftex_uncompressed.png") - - self.assert_image_equal(im, target) - - def test_load_dxt1(self): - im = Image.open("Tests/images/ftex_dxt1.ftc") - target = Image.open("Tests/images/ftex_dxt1.png") - self.assert_image_similar(im, target.convert("RGBA"), 15) diff --git a/Tests/test_file_gbr.py b/Tests/test_file_gbr.py deleted file mode 100644 index 659179a4e12..00000000000 --- a/Tests/test_file_gbr.py +++ /dev/null @@ -1,17 +0,0 @@ -from PIL import GbrImagePlugin, Image - -from .helper import PillowTestCase - - -class TestFileGbr(PillowTestCase): - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, GbrImagePlugin.GbrImageFile, invalid_file) - - def test_gbr_file(self): - im = Image.open("Tests/images/gbr.gbr") - - target = Image.open("Tests/images/gbr.png") - - self.assert_image_equal(target, im) diff --git a/Tests/test_file_gd.py b/Tests/test_file_gd.py deleted file mode 100644 index 6467d1e9281..00000000000 --- a/Tests/test_file_gd.py +++ /dev/null @@ -1,20 +0,0 @@ -from PIL import GdImageFile - -from .helper import PillowTestCase - -TEST_GD_FILE = "Tests/images/hopper.gd" - - -class TestFileGd(PillowTestCase): - def test_sanity(self): - im = GdImageFile.open(TEST_GD_FILE) - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "GD") - - def test_bad_mode(self): - self.assertRaises(ValueError, GdImageFile.open, TEST_GD_FILE, "bad mode") - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(IOError, GdImageFile.open, invalid_file) diff --git a/Tests/test_file_gif.py b/Tests/test_file_gif.py deleted file mode 100644 index 2ba370c3f94..00000000000 --- a/Tests/test_file_gif.py +++ /dev/null @@ -1,752 +0,0 @@ -from io import BytesIO - -from PIL import GifImagePlugin, Image, ImageDraw, ImagePalette - -from .helper import PillowTestCase, hopper, netpbm_available, unittest - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - -codecs = dir(Image.core) - -# sample gif stream -TEST_GIF = "Tests/images/hopper.gif" - -with open(TEST_GIF, "rb") as f: - data = f.read() - - -class TestFileGif(PillowTestCase): - def setUp(self): - if "gif_encoder" not in codecs or "gif_decoder" not in codecs: - self.skipTest("gif support not available") # can this happen? - - def test_sanity(self): - im = Image.open(TEST_GIF) - im.load() - self.assertEqual(im.mode, "P") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "GIF") - self.assertEqual(im.info["version"], b"GIF89a") - - def test_unclosed_file(self): - def open(): - im = Image.open(TEST_GIF) - im.load() - - self.assert_warning(None, open) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, GifImagePlugin.GifImageFile, invalid_file) - - def test_optimize(self): - def test_grayscale(optimize): - im = Image.new("L", (1, 1), 0) - filename = BytesIO() - im.save(filename, "GIF", optimize=optimize) - return len(filename.getvalue()) - - def test_bilevel(optimize): - im = Image.new("1", (1, 1), 0) - test_file = BytesIO() - im.save(test_file, "GIF", optimize=optimize) - return len(test_file.getvalue()) - - self.assertEqual(test_grayscale(0), 800) - self.assertEqual(test_grayscale(1), 44) - self.assertEqual(test_bilevel(0), 800) - self.assertEqual(test_bilevel(1), 800) - - def test_optimize_correctness(self): - # 256 color Palette image, posterize to > 128 and < 128 levels - # Size bigger and smaller than 512x512 - # Check the palette for number of colors allocated. - # Check for correctness after conversion back to RGB - def check(colors, size, expected_palette_length): - # make an image with empty colors in the start of the palette range - im = Image.frombytes( - "P", - (colors, colors), - bytes(bytearray(range(256 - colors, 256)) * colors), - ) - im = im.resize((size, size)) - outfile = BytesIO() - im.save(outfile, "GIF") - outfile.seek(0) - reloaded = Image.open(outfile) - - # check palette length - palette_length = max(i + 1 for i, v in enumerate(reloaded.histogram()) if v) - self.assertEqual(expected_palette_length, palette_length) - - self.assert_image_equal(im.convert("RGB"), reloaded.convert("RGB")) - - # These do optimize the palette - check(128, 511, 128) - check(64, 511, 64) - check(4, 511, 4) - - # These don't optimize the palette - check(128, 513, 256) - check(64, 513, 256) - check(4, 513, 256) - - # other limits that don't optimize the palette - check(129, 511, 256) - check(255, 511, 256) - check(256, 511, 256) - - def test_optimize_full_l(self): - im = Image.frombytes("L", (16, 16), bytes(bytearray(range(256)))) - test_file = BytesIO() - im.save(test_file, "GIF", optimize=True) - self.assertEqual(im.mode, "L") - - def test_roundtrip(self): - out = self.tempfile("temp.gif") - im = hopper() - im.save(out) - reread = Image.open(out) - - self.assert_image_similar(reread.convert("RGB"), im, 50) - - def test_roundtrip2(self): - # see https://github.com/python-pillow/Pillow/issues/403 - out = self.tempfile("temp.gif") - im = Image.open(TEST_GIF) - im2 = im.copy() - im2.save(out) - reread = Image.open(out) - - self.assert_image_similar(reread.convert("RGB"), hopper(), 50) - - def test_roundtrip_save_all(self): - # Single frame image - out = self.tempfile("temp.gif") - im = hopper() - im.save(out, save_all=True) - reread = Image.open(out) - - self.assert_image_similar(reread.convert("RGB"), im, 50) - - # Multiframe image - im = Image.open("Tests/images/dispose_bgnd.gif") - - out = self.tempfile("temp.gif") - im.save(out, save_all=True) - reread = Image.open(out) - - self.assertEqual(reread.n_frames, 5) - - def test_headers_saving_for_animated_gifs(self): - important_headers = ["background", "version", "duration", "loop"] - # Multiframe image - im = Image.open("Tests/images/dispose_bgnd.gif") - - info = im.info.copy() - - out = self.tempfile("temp.gif") - im.save(out, save_all=True) - reread = Image.open(out) - - for header in important_headers: - self.assertEqual(info[header], reread.info[header]) - - def test_palette_handling(self): - # see https://github.com/python-pillow/Pillow/issues/513 - - im = Image.open(TEST_GIF) - im = im.convert("RGB") - - im = im.resize((100, 100), Image.LANCZOS) - im2 = im.convert("P", palette=Image.ADAPTIVE, colors=256) - - f = self.tempfile("temp.gif") - im2.save(f, optimize=True) - - reloaded = Image.open(f) - - self.assert_image_similar(im, reloaded.convert("RGB"), 10) - - def test_palette_434(self): - # see https://github.com/python-pillow/Pillow/issues/434 - - def roundtrip(im, *args, **kwargs): - out = self.tempfile("temp.gif") - im.copy().save(out, *args, **kwargs) - reloaded = Image.open(out) - - return reloaded - - orig = "Tests/images/test.colors.gif" - im = Image.open(orig) - - self.assert_image_similar(im, roundtrip(im), 1) - self.assert_image_similar(im, roundtrip(im, optimize=True), 1) - - im = im.convert("RGB") - # check automatic P conversion - reloaded = roundtrip(im).convert("RGB") - self.assert_image_equal(im, reloaded) - - @unittest.skipUnless(netpbm_available(), "netpbm not available") - def test_save_netpbm_bmp_mode(self): - img = Image.open(TEST_GIF).convert("RGB") - - tempfile = self.tempfile("temp.gif") - GifImagePlugin._save_netpbm(img, 0, tempfile) - self.assert_image_similar(img, Image.open(tempfile).convert("RGB"), 0) - - @unittest.skipUnless(netpbm_available(), "netpbm not available") - def test_save_netpbm_l_mode(self): - img = Image.open(TEST_GIF).convert("L") - - tempfile = self.tempfile("temp.gif") - GifImagePlugin._save_netpbm(img, 0, tempfile) - self.assert_image_similar(img, Image.open(tempfile).convert("L"), 0) - - def test_seek(self): - img = Image.open("Tests/images/dispose_none.gif") - framecount = 0 - try: - while True: - framecount += 1 - img.seek(img.tell() + 1) - except EOFError: - self.assertEqual(framecount, 5) - - def test_seek_info(self): - im = Image.open("Tests/images/iss634.gif") - info = im.info.copy() - - im.seek(1) - im.seek(0) - - self.assertEqual(im.info, info) - - def test_seek_rewind(self): - im = Image.open("Tests/images/iss634.gif") - im.seek(2) - im.seek(1) - - expected = Image.open("Tests/images/iss634.gif") - expected.seek(1) - self.assert_image_equal(im, expected) - - def test_n_frames(self): - for path, n_frames in [[TEST_GIF, 1], ["Tests/images/iss634.gif", 42]]: - # Test is_animated before n_frames - im = Image.open(path) - self.assertEqual(im.is_animated, n_frames != 1) - - # Test is_animated after n_frames - im = Image.open(path) - self.assertEqual(im.n_frames, n_frames) - self.assertEqual(im.is_animated, n_frames != 1) - - def test_eoferror(self): - im = Image.open(TEST_GIF) - n_frames = im.n_frames - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_dispose_none(self): - img = Image.open("Tests/images/dispose_none.gif") - try: - while True: - img.seek(img.tell() + 1) - self.assertEqual(img.disposal_method, 1) - except EOFError: - pass - - def test_dispose_background(self): - img = Image.open("Tests/images/dispose_bgnd.gif") - try: - while True: - img.seek(img.tell() + 1) - self.assertEqual(img.disposal_method, 2) - except EOFError: - pass - - def test_dispose_previous(self): - img = Image.open("Tests/images/dispose_prev.gif") - try: - while True: - img.seek(img.tell() + 1) - self.assertEqual(img.disposal_method, 3) - except EOFError: - pass - - def test_save_dispose(self): - out = self.tempfile("temp.gif") - im_list = [ - Image.new("L", (100, 100), "#000"), - Image.new("L", (100, 100), "#111"), - Image.new("L", (100, 100), "#222"), - ] - for method in range(0, 4): - im_list[0].save( - out, save_all=True, append_images=im_list[1:], disposal=method - ) - img = Image.open(out) - for _ in range(2): - img.seek(img.tell() + 1) - self.assertEqual(img.disposal_method, method) - - # check per frame disposal - im_list[0].save( - out, - save_all=True, - append_images=im_list[1:], - disposal=tuple(range(len(im_list))), - ) - - img = Image.open(out) - - for i in range(2): - img.seek(img.tell() + 1) - self.assertEqual(img.disposal_method, i + 1) - - def test_dispose2_palette(self): - out = self.tempfile("temp.gif") - - # 4 backgrounds: White, Grey, Black, Red - circles = [(255, 255, 255), (153, 153, 153), (0, 0, 0), (255, 0, 0)] - - im_list = [] - for circle in circles: - img = Image.new("RGB", (100, 100), (255, 0, 0)) - - # Red circle in center of each frame - d = ImageDraw.Draw(img) - d.ellipse([(40, 40), (60, 60)], fill=circle) - - im_list.append(img) - - im_list[0].save(out, save_all=True, append_images=im_list[1:], disposal=2) - - img = Image.open(out) - - for i, circle in enumerate(circles): - img.seek(i) - rgb_img = img.convert("RGB") - - # Check top left pixel matches background - self.assertEqual(rgb_img.getpixel((0, 0)), (255, 0, 0)) - - # Center remains red every frame - self.assertEqual(rgb_img.getpixel((50, 50)), circle) - - def test_dispose2_diff(self): - out = self.tempfile("temp.gif") - - # 4 frames: red/blue, red/red, blue/blue, red/blue - circles = [ - ((255, 0, 0, 255), (0, 0, 255, 255)), - ((255, 0, 0, 255), (255, 0, 0, 255)), - ((0, 0, 255, 255), (0, 0, 255, 255)), - ((255, 0, 0, 255), (0, 0, 255, 255)), - ] - - im_list = [] - for i in range(len(circles)): - # Transparent BG - img = Image.new("RGBA", (100, 100), (255, 255, 255, 0)) - - # Two circles per frame - d = ImageDraw.Draw(img) - d.ellipse([(0, 30), (40, 70)], fill=circles[i][0]) - d.ellipse([(60, 30), (100, 70)], fill=circles[i][1]) - - im_list.append(img) - - im_list[0].save( - out, save_all=True, append_images=im_list[1:], disposal=2, transparency=0 - ) - - img = Image.open(out) - - for i, colours in enumerate(circles): - img.seek(i) - rgb_img = img.convert("RGBA") - - # Check left circle is correct colour - self.assertEqual(rgb_img.getpixel((20, 50)), colours[0]) - - # Check right circle is correct colour - self.assertEqual(rgb_img.getpixel((80, 50)), colours[1]) - - # Check BG is correct colour - self.assertEqual(rgb_img.getpixel((1, 1)), (255, 255, 255, 0)) - - def test_dispose2_background(self): - out = self.tempfile("temp.gif") - - im_list = [] - - im = Image.new("P", (100, 100)) - d = ImageDraw.Draw(im) - d.rectangle([(50, 0), (100, 100)], fill="#f00") - d.rectangle([(0, 0), (50, 100)], fill="#0f0") - im_list.append(im) - - im = Image.new("P", (100, 100)) - d = ImageDraw.Draw(im) - d.rectangle([(0, 0), (100, 50)], fill="#f00") - d.rectangle([(0, 50), (100, 100)], fill="#0f0") - im_list.append(im) - - im_list[0].save( - out, save_all=True, append_images=im_list[1:], disposal=[0, 2], background=1 - ) - - im = Image.open(out) - im.seek(1) - self.assertEqual(im.getpixel((0, 0)), 0) - - def test_iss634(self): - img = Image.open("Tests/images/iss634.gif") - # seek to the second frame - img.seek(img.tell() + 1) - # all transparent pixels should be replaced with the color from the - # first frame - self.assertEqual(img.histogram()[img.info["transparency"]], 0) - - def test_duration(self): - duration = 1000 - - out = self.tempfile("temp.gif") - im = Image.new("L", (100, 100), "#000") - - # Check that the argument has priority over the info settings - im.info["duration"] = 100 - im.save(out, duration=duration) - - reread = Image.open(out) - self.assertEqual(reread.info["duration"], duration) - - def test_multiple_duration(self): - duration_list = [1000, 2000, 3000] - - out = self.tempfile("temp.gif") - im_list = [ - Image.new("L", (100, 100), "#000"), - Image.new("L", (100, 100), "#111"), - Image.new("L", (100, 100), "#222"), - ] - - # duration as list - im_list[0].save( - out, save_all=True, append_images=im_list[1:], duration=duration_list - ) - reread = Image.open(out) - - for duration in duration_list: - self.assertEqual(reread.info["duration"], duration) - try: - reread.seek(reread.tell() + 1) - except EOFError: - pass - - # duration as tuple - im_list[0].save( - out, save_all=True, append_images=im_list[1:], duration=tuple(duration_list) - ) - reread = Image.open(out) - - for duration in duration_list: - self.assertEqual(reread.info["duration"], duration) - try: - reread.seek(reread.tell() + 1) - except EOFError: - pass - - def test_identical_frames(self): - duration_list = [1000, 1500, 2000, 4000] - - out = self.tempfile("temp.gif") - im_list = [ - Image.new("L", (100, 100), "#000"), - Image.new("L", (100, 100), "#000"), - Image.new("L", (100, 100), "#000"), - Image.new("L", (100, 100), "#111"), - ] - - # duration as list - im_list[0].save( - out, save_all=True, append_images=im_list[1:], duration=duration_list - ) - reread = Image.open(out) - - # Assert that the first three frames were combined - self.assertEqual(reread.n_frames, 2) - - # Assert that the new duration is the total of the identical frames - self.assertEqual(reread.info["duration"], 4500) - - def test_number_of_loops(self): - number_of_loops = 2 - - out = self.tempfile("temp.gif") - im = Image.new("L", (100, 100), "#000") - im.save(out, loop=number_of_loops) - reread = Image.open(out) - - self.assertEqual(reread.info["loop"], number_of_loops) - - def test_background(self): - out = self.tempfile("temp.gif") - im = Image.new("L", (100, 100), "#000") - im.info["background"] = 1 - im.save(out) - reread = Image.open(out) - - self.assertEqual(reread.info["background"], im.info["background"]) - - if HAVE_WEBP and _webp.HAVE_WEBPANIM: - im = Image.open("Tests/images/hopper.webp") - self.assertIsInstance(im.info["background"], tuple) - im.save(out) - - def test_comment(self): - im = Image.open(TEST_GIF) - self.assertEqual(im.info["comment"], b"File written by Adobe Photoshop\xa8 4.0") - - out = self.tempfile("temp.gif") - im = Image.new("L", (100, 100), "#000") - im.info["comment"] = b"Test comment text" - im.save(out) - reread = Image.open(out) - - self.assertEqual(reread.info["comment"], im.info["comment"]) - - def test_comment_over_255(self): - out = self.tempfile("temp.gif") - im = Image.new("L", (100, 100), "#000") - comment = b"Test comment text" - while len(comment) < 256: - comment += comment - im.info["comment"] = comment - im.save(out) - reread = Image.open(out) - - self.assertEqual(reread.info["comment"], comment) - - def test_zero_comment_subblocks(self): - im = Image.open("Tests/images/hopper_zero_comment_subblocks.gif") - expected = Image.open(TEST_GIF) - self.assert_image_equal(im, expected) - - def test_version(self): - out = self.tempfile("temp.gif") - - def assertVersionAfterSave(im, version): - im.save(out) - reread = Image.open(out) - self.assertEqual(reread.info["version"], version) - - # Test that GIF87a is used by default - im = Image.new("L", (100, 100), "#000") - assertVersionAfterSave(im, b"GIF87a") - - # Test setting the version to 89a - im = Image.new("L", (100, 100), "#000") - im.info["version"] = b"89a" - assertVersionAfterSave(im, b"GIF89a") - - # Test that adding a GIF89a feature changes the version - im.info["transparency"] = 1 - assertVersionAfterSave(im, b"GIF89a") - - # Test that a GIF87a image is also saved in that format - im = Image.open("Tests/images/test.colors.gif") - assertVersionAfterSave(im, b"GIF87a") - - # Test that a GIF89a image is also saved in that format - im.info["version"] = b"GIF89a" - assertVersionAfterSave(im, b"GIF87a") - - def test_append_images(self): - out = self.tempfile("temp.gif") - - # Test appending single frame images - im = Image.new("RGB", (100, 100), "#f00") - ims = [Image.new("RGB", (100, 100), color) for color in ["#0f0", "#00f"]] - im.copy().save(out, save_all=True, append_images=ims) - - reread = Image.open(out) - self.assertEqual(reread.n_frames, 3) - - # Tests appending using a generator - def imGenerator(ims): - for im in ims: - yield im - - im.save(out, save_all=True, append_images=imGenerator(ims)) - - reread = Image.open(out) - self.assertEqual(reread.n_frames, 3) - - # Tests appending single and multiple frame images - im = Image.open("Tests/images/dispose_none.gif") - ims = [Image.open("Tests/images/dispose_prev.gif")] - im.save(out, save_all=True, append_images=ims) - - reread = Image.open(out) - self.assertEqual(reread.n_frames, 10) - - def test_transparent_optimize(self): - # from issue #2195, if the transparent color is incorrectly - # optimized out, gif loses transparency - # Need a palette that isn't using the 0 color, and one - # that's > 128 items where the transparent color is actually - # the top palette entry to trigger the bug. - - data = bytes(bytearray(range(1, 254))) - palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3) - - im = Image.new("L", (253, 1)) - im.frombytes(data) - im.putpalette(palette) - - out = self.tempfile("temp.gif") - im.save(out, transparency=253) - reloaded = Image.open(out) - - self.assertEqual(reloaded.info["transparency"], 253) - - def test_rgb_transparency(self): - out = self.tempfile("temp.gif") - - # Single frame - im = Image.new("RGB", (1, 1)) - im.info["transparency"] = (255, 0, 0) - self.assert_warning(UserWarning, im.save, out) - - reloaded = Image.open(out) - self.assertNotIn("transparency", reloaded.info) - - # Multiple frames - im = Image.new("RGB", (1, 1)) - im.info["transparency"] = b"" - ims = [Image.new("RGB", (1, 1))] - self.assert_warning(UserWarning, im.save, out, save_all=True, append_images=ims) - - reloaded = Image.open(out) - self.assertNotIn("transparency", reloaded.info) - - def test_bbox(self): - out = self.tempfile("temp.gif") - - im = Image.new("RGB", (100, 100), "#fff") - ims = [Image.new("RGB", (100, 100), "#000")] - im.save(out, save_all=True, append_images=ims) - - reread = Image.open(out) - self.assertEqual(reread.n_frames, 2) - - def test_palette_save_L(self): - # generate an L mode image with a separate palette - - im = hopper("P") - im_l = Image.frombytes("L", im.size, im.tobytes()) - palette = bytes(bytearray(im.getpalette())) - - out = self.tempfile("temp.gif") - im_l.save(out, palette=palette) - - reloaded = Image.open(out) - - self.assert_image_equal(reloaded.convert("RGB"), im.convert("RGB")) - - def test_palette_save_P(self): - # pass in a different palette, then construct what the image - # would look like. - # Forcing a non-straight grayscale palette. - - im = hopper("P") - palette = bytes(bytearray([255 - i // 3 for i in range(768)])) - - out = self.tempfile("temp.gif") - im.save(out, palette=palette) - - reloaded = Image.open(out) - im.putpalette(palette) - self.assert_image_equal(reloaded, im) - - def test_palette_save_ImagePalette(self): - # pass in a different palette, as an ImagePalette.ImagePalette - # effectively the same as test_palette_save_P - - im = hopper("P") - palette = ImagePalette.ImagePalette("RGB", list(range(256))[::-1] * 3) - - out = self.tempfile("temp.gif") - im.save(out, palette=palette) - - reloaded = Image.open(out) - im.putpalette(palette) - self.assert_image_equal(reloaded, im) - - def test_save_I(self): - # Test saving something that would trigger the auto-convert to 'L' - - im = hopper("I") - - out = self.tempfile("temp.gif") - im.save(out) - - reloaded = Image.open(out) - self.assert_image_equal(reloaded.convert("L"), im.convert("L")) - - def test_getdata(self): - # test getheader/getdata against legacy values - # Create a 'P' image with holes in the palette - im = Image._wedge().resize((16, 16)) - im.putpalette(ImagePalette.ImagePalette("RGB")) - im.info = {"background": 0} - - passed_palette = bytes(bytearray([255 - i // 3 for i in range(768)])) - - GifImagePlugin._FORCE_OPTIMIZE = True - try: - h = GifImagePlugin.getheader(im, passed_palette) - d = GifImagePlugin.getdata(im) - - import pickle - - # Enable to get target values on pre-refactor version - # with open('Tests/images/gif_header_data.pkl', 'wb') as f: - # pickle.dump((h, d), f, 1) - with open("Tests/images/gif_header_data.pkl", "rb") as f: - (h_target, d_target) = pickle.load(f) - - self.assertEqual(h, h_target) - self.assertEqual(d, d_target) - finally: - GifImagePlugin._FORCE_OPTIMIZE = False - - def test_lzw_bits(self): - # see https://github.com/python-pillow/Pillow/issues/2811 - im = Image.open("Tests/images/issue_2811.gif") - - self.assertEqual(im.tile[0][3][0], 11) # LZW bits - # codec error prepatch - im.load() - - def test_extents(self): - im = Image.open("Tests/images/test_extents.gif") - self.assertEqual(im.size, (100, 100)) - im.seek(1) - self.assertEqual(im.size, (150, 150)) diff --git a/Tests/test_file_gimpgradient.py b/Tests/test_file_gimpgradient.py deleted file mode 100644 index bafee79a3e5..00000000000 --- a/Tests/test_file_gimpgradient.py +++ /dev/null @@ -1,122 +0,0 @@ -from PIL import GimpGradientFile - -from .helper import PillowTestCase - - -class TestImage(PillowTestCase): - def test_linear_pos_le_middle(self): - # Arrange - middle = 0.5 - pos = 0.25 - - # Act - ret = GimpGradientFile.linear(middle, pos) - - # Assert - self.assertEqual(ret, 0.25) - - def test_linear_pos_le_small_middle(self): - # Arrange - middle = 1e-11 - pos = 1e-12 - - # Act - ret = GimpGradientFile.linear(middle, pos) - - # Assert - self.assertEqual(ret, 0.0) - - def test_linear_pos_gt_middle(self): - # Arrange - middle = 0.5 - pos = 0.75 - - # Act - ret = GimpGradientFile.linear(middle, pos) - - # Assert - self.assertEqual(ret, 0.75) - - def test_linear_pos_gt_small_middle(self): - # Arrange - middle = 1 - 1e-11 - pos = 1 - 1e-12 - - # Act - ret = GimpGradientFile.linear(middle, pos) - - # Assert - self.assertEqual(ret, 1.0) - - def test_curved(self): - # Arrange - middle = 0.5 - pos = 0.75 - - # Act - ret = GimpGradientFile.curved(middle, pos) - - # Assert - self.assertEqual(ret, 0.75) - - def test_sine(self): - # Arrange - middle = 0.5 - pos = 0.75 - - # Act - ret = GimpGradientFile.sine(middle, pos) - - # Assert - self.assertEqual(ret, 0.8535533905932737) - - def test_sphere_increasing(self): - # Arrange - middle = 0.5 - pos = 0.75 - - # Act - ret = GimpGradientFile.sphere_increasing(middle, pos) - - # Assert - self.assertAlmostEqual(ret, 0.9682458365518543) - - def test_sphere_decreasing(self): - # Arrange - middle = 0.5 - pos = 0.75 - - # Act - ret = GimpGradientFile.sphere_decreasing(middle, pos) - - # Assert - self.assertEqual(ret, 0.3385621722338523) - - def test_load_via_imagepalette(self): - # Arrange - from PIL import ImagePalette - - test_file = "Tests/images/gimp_gradient.ggr" - - # Act - palette = ImagePalette.load(test_file) - - # Assert - # load returns raw palette information - self.assertEqual(len(palette[0]), 1024) - self.assertEqual(palette[1], "RGBA") - - def test_load_1_3_via_imagepalette(self): - # Arrange - from PIL import ImagePalette - - # GIMP 1.3 gradient files contain a name field - test_file = "Tests/images/gimp_gradient_with_name.ggr" - - # Act - palette = ImagePalette.load(test_file) - - # Assert - # load returns raw palette information - self.assertEqual(len(palette[0]), 1024) - self.assertEqual(palette[1], "RGBA") diff --git a/Tests/test_file_gimppalette.py b/Tests/test_file_gimppalette.py deleted file mode 100644 index a1677f0cb17..00000000000 --- a/Tests/test_file_gimppalette.py +++ /dev/null @@ -1,29 +0,0 @@ -from PIL.GimpPaletteFile import GimpPaletteFile - -from .helper import PillowTestCase - - -class TestImage(PillowTestCase): - def test_sanity(self): - with open("Tests/images/test.gpl", "rb") as fp: - GimpPaletteFile(fp) - - with open("Tests/images/hopper.jpg", "rb") as fp: - self.assertRaises(SyntaxError, GimpPaletteFile, fp) - - with open("Tests/images/bad_palette_file.gpl", "rb") as fp: - self.assertRaises(SyntaxError, GimpPaletteFile, fp) - - with open("Tests/images/bad_palette_entry.gpl", "rb") as fp: - self.assertRaises(ValueError, GimpPaletteFile, fp) - - def test_get_palette(self): - # Arrange - with open("Tests/images/custom_gimp_palette.gpl", "rb") as fp: - palette_file = GimpPaletteFile(fp) - - # Act - palette, mode = palette_file.getpalette() - - # Assert - self.assertEqual(mode, "RGB") diff --git a/Tests/test_file_gribstub.py b/Tests/test_file_gribstub.py deleted file mode 100644 index d322e1c70fa..00000000000 --- a/Tests/test_file_gribstub.py +++ /dev/null @@ -1,42 +0,0 @@ -from PIL import GribStubImagePlugin, Image - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/WAlaska.wind.7days.grb" - - -class TestFileGribStub(PillowTestCase): - def test_open(self): - # Act - im = Image.open(TEST_FILE) - - # Assert - self.assertEqual(im.format, "GRIB") - - # Dummy data from the stub - self.assertEqual(im.mode, "F") - self.assertEqual(im.size, (1, 1)) - - def test_invalid_file(self): - # Arrange - invalid_file = "Tests/images/flower.jpg" - - # Act / Assert - self.assertRaises( - SyntaxError, GribStubImagePlugin.GribStubImageFile, invalid_file - ) - - def test_load(self): - # Arrange - im = Image.open(TEST_FILE) - - # Act / Assert: stub cannot load without an implemented handler - self.assertRaises(IOError, im.load) - - def test_save(self): - # Arrange - im = hopper() - tmpfile = self.tempfile("temp.grib") - - # Act / Assert: stub cannot save without an implemented handler - self.assertRaises(IOError, im.save, tmpfile) diff --git a/Tests/test_file_hdf5stub.py b/Tests/test_file_hdf5stub.py deleted file mode 100644 index c300bae2066..00000000000 --- a/Tests/test_file_hdf5stub.py +++ /dev/null @@ -1,46 +0,0 @@ -from PIL import Hdf5StubImagePlugin, Image - -from .helper import PillowTestCase - -TEST_FILE = "Tests/images/hdf5.h5" - - -class TestFileHdf5Stub(PillowTestCase): - def test_open(self): - # Act - im = Image.open(TEST_FILE) - - # Assert - self.assertEqual(im.format, "HDF5") - - # Dummy data from the stub - self.assertEqual(im.mode, "F") - self.assertEqual(im.size, (1, 1)) - - def test_invalid_file(self): - # Arrange - invalid_file = "Tests/images/flower.jpg" - - # Act / Assert - self.assertRaises( - SyntaxError, Hdf5StubImagePlugin.HDF5StubImageFile, invalid_file - ) - - def test_load(self): - # Arrange - im = Image.open(TEST_FILE) - - # Act / Assert: stub cannot load without an implemented handler - self.assertRaises(IOError, im.load) - - def test_save(self): - # Arrange - im = Image.open(TEST_FILE) - dummy_fp = None - dummy_filename = "dummy.filename" - - # Act / Assert: stub cannot save without an implemented handler - self.assertRaises(IOError, im.save, dummy_filename) - self.assertRaises( - IOError, Hdf5StubImagePlugin._save, im, dummy_fp, dummy_filename - ) diff --git a/Tests/test_file_icns.py b/Tests/test_file_icns.py deleted file mode 100644 index 2e33e0ae52c..00000000000 --- a/Tests/test_file_icns.py +++ /dev/null @@ -1,120 +0,0 @@ -import io -import sys - -from PIL import IcnsImagePlugin, Image - -from .helper import PillowTestCase, unittest - -# sample icon file -TEST_FILE = "Tests/images/pillow.icns" - -enable_jpeg2k = hasattr(Image.core, "jp2klib_version") - - -class TestFileIcns(PillowTestCase): - def test_sanity(self): - # Loading this icon by default should result in the largest size - # (512x512@2x) being loaded - im = Image.open(TEST_FILE) - - # Assert that there is no unclosed file warning - self.assert_warning(None, im.load) - - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (1024, 1024)) - self.assertEqual(im.format, "ICNS") - - @unittest.skipIf(sys.platform != "darwin", "requires macOS") - def test_save(self): - im = Image.open(TEST_FILE) - - temp_file = self.tempfile("temp.icns") - im.save(temp_file) - - reread = Image.open(temp_file) - - self.assertEqual(reread.mode, "RGBA") - self.assertEqual(reread.size, (1024, 1024)) - self.assertEqual(reread.format, "ICNS") - - @unittest.skipIf(sys.platform != "darwin", "requires macOS") - def test_save_append_images(self): - im = Image.open(TEST_FILE) - - temp_file = self.tempfile("temp.icns") - provided_im = Image.new("RGBA", (32, 32), (255, 0, 0, 128)) - im.save(temp_file, append_images=[provided_im]) - - reread = Image.open(temp_file) - self.assert_image_similar(reread, im, 1) - - reread = Image.open(temp_file) - reread.size = (16, 16, 2) - reread.load() - self.assert_image_equal(reread, provided_im) - - def test_sizes(self): - # Check that we can load all of the sizes, and that the final pixel - # dimensions are as expected - im = Image.open(TEST_FILE) - for w, h, r in im.info["sizes"]: - wr = w * r - hr = h * r - im.size = (w, h, r) - im.load() - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (wr, hr)) - - # Check that we cannot load an incorrect size - with self.assertRaises(ValueError): - im.size = (1, 1) - - def test_older_icon(self): - # This icon was made with Icon Composer rather than iconutil; it still - # uses PNG rather than JP2, however (since it was made on 10.9). - im = Image.open("Tests/images/pillow2.icns") - for w, h, r in im.info["sizes"]: - wr = w * r - hr = h * r - im2 = Image.open("Tests/images/pillow2.icns") - im2.size = (w, h, r) - im2.load() - self.assertEqual(im2.mode, "RGBA") - self.assertEqual(im2.size, (wr, hr)) - - def test_jp2_icon(self): - # This icon was made by using Uli Kusterer's oldiconutil to replace - # the PNG images with JPEG 2000 ones. The advantage of doing this is - # that OS X 10.5 supports JPEG 2000 but not PNG; some commercial - # software therefore does just this. - - # (oldiconutil is here: https://github.com/uliwitness/oldiconutil) - - if not enable_jpeg2k: - return - - im = Image.open("Tests/images/pillow3.icns") - for w, h, r in im.info["sizes"]: - wr = w * r - hr = h * r - im2 = Image.open("Tests/images/pillow3.icns") - im2.size = (w, h, r) - im2.load() - self.assertEqual(im2.mode, "RGBA") - self.assertEqual(im2.size, (wr, hr)) - - def test_getimage(self): - with open(TEST_FILE, "rb") as fp: - icns_file = IcnsImagePlugin.IcnsFile(fp) - - im = icns_file.getimage() - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (1024, 1024)) - - im = icns_file.getimage((512, 512)) - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (512, 512)) - - def test_not_an_icns_file(self): - with io.BytesIO(b"invalid\n") as fp: - self.assertRaises(SyntaxError, IcnsImagePlugin.IcnsFile, fp) diff --git a/Tests/test_file_ico.py b/Tests/test_file_ico.py deleted file mode 100644 index 8a01e417f38..00000000000 --- a/Tests/test_file_ico.py +++ /dev/null @@ -1,103 +0,0 @@ -import io - -from PIL import IcoImagePlugin, Image, ImageDraw - -from .helper import PillowTestCase, hopper - -TEST_ICO_FILE = "Tests/images/hopper.ico" - - -class TestFileIco(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_ICO_FILE) - im.load() - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (16, 16)) - self.assertEqual(im.format, "ICO") - self.assertEqual(im.get_format_mimetype(), "image/x-icon") - - def test_invalid_file(self): - with open("Tests/images/flower.jpg", "rb") as fp: - self.assertRaises(SyntaxError, IcoImagePlugin.IcoImageFile, fp) - - def test_save_to_bytes(self): - output = io.BytesIO() - im = hopper() - im.save(output, "ico", sizes=[(32, 32), (64, 64)]) - - # the default image - output.seek(0) - reloaded = Image.open(output) - self.assertEqual(reloaded.info["sizes"], {(32, 32), (64, 64)}) - - self.assertEqual(im.mode, reloaded.mode) - self.assertEqual((64, 64), reloaded.size) - self.assertEqual(reloaded.format, "ICO") - self.assert_image_equal(reloaded, hopper().resize((64, 64), Image.LANCZOS)) - - # the other one - output.seek(0) - reloaded = Image.open(output) - reloaded.size = (32, 32) - - self.assertEqual(im.mode, reloaded.mode) - self.assertEqual((32, 32), reloaded.size) - self.assertEqual(reloaded.format, "ICO") - self.assert_image_equal(reloaded, hopper().resize((32, 32), Image.LANCZOS)) - - def test_incorrect_size(self): - im = Image.open(TEST_ICO_FILE) - with self.assertRaises(ValueError): - im.size = (1, 1) - - def test_save_256x256(self): - """Issue #2264 https://github.com/python-pillow/Pillow/issues/2264""" - # Arrange - im = Image.open("Tests/images/hopper_256x256.ico") - outfile = self.tempfile("temp_saved_hopper_256x256.ico") - - # Act - im.save(outfile) - im_saved = Image.open(outfile) - - # Assert - self.assertEqual(im_saved.size, (256, 256)) - - def test_only_save_relevant_sizes(self): - """Issue #2266 https://github.com/python-pillow/Pillow/issues/2266 - Should save in 16x16, 24x24, 32x32, 48x48 sizes - and not in 16x16, 24x24, 32x32, 48x48, 48x48, 48x48, 48x48 sizes - """ - # Arrange - im = Image.open("Tests/images/python.ico") # 16x16, 32x32, 48x48 - outfile = self.tempfile("temp_saved_python.ico") - - # Act - im.save(outfile) - im_saved = Image.open(outfile) - - # Assert - self.assertEqual( - im_saved.info["sizes"], {(16, 16), (24, 24), (32, 32), (48, 48)} - ) - - def test_unexpected_size(self): - # This image has been manually hexedited to state that it is 16x32 - # while the image within is still 16x16 - im = self.assert_warning( - UserWarning, Image.open, "Tests/images/hopper_unexpected.ico" - ) - self.assertEqual(im.size, (16, 16)) - - def test_draw_reloaded(self): - im = Image.open(TEST_ICO_FILE) - outfile = self.tempfile("temp_saved_hopper_draw.ico") - - draw = ImageDraw.Draw(im) - draw.line((0, 0) + im.size, "#f00") - im.save(outfile) - - im = Image.open(outfile) - im.save("Tests/images/hopper_draw.ico") - reloaded = Image.open("Tests/images/hopper_draw.ico") - self.assert_image_equal(im, reloaded) diff --git a/Tests/test_file_im.py b/Tests/test_file_im.py deleted file mode 100644 index 90e26efd519..00000000000 --- a/Tests/test_file_im.py +++ /dev/null @@ -1,70 +0,0 @@ -from PIL import Image, ImImagePlugin - -from .helper import PillowTestCase, hopper - -# sample im -TEST_IM = "Tests/images/hopper.im" - - -class TestFileIm(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_IM) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "IM") - - def test_unclosed_file(self): - def open(): - im = Image.open(TEST_IM) - im.load() - - self.assert_warning(None, open) - - def test_tell(self): - # Arrange - im = Image.open(TEST_IM) - - # Act - frame = im.tell() - - # Assert - self.assertEqual(frame, 0) - - def test_n_frames(self): - im = Image.open(TEST_IM) - self.assertEqual(im.n_frames, 1) - self.assertFalse(im.is_animated) - - def test_eoferror(self): - im = Image.open(TEST_IM) - n_frames = im.n_frames - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_roundtrip(self): - for mode in ["RGB", "P", "PA"]: - out = self.tempfile("temp.im") - im = hopper(mode) - im.save(out) - reread = Image.open(out) - - self.assert_image_equal(reread, im) - - def test_save_unsupported_mode(self): - out = self.tempfile("temp.im") - im = hopper("HSV") - self.assertRaises(ValueError, im.save, out) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, ImImagePlugin.ImImageFile, invalid_file) - - def test_number(self): - self.assertEqual(1.2, ImImagePlugin.number("1.2")) diff --git a/Tests/test_file_iptc.py b/Tests/test_file_iptc.py deleted file mode 100644 index 800563af1bb..00000000000 --- a/Tests/test_file_iptc.py +++ /dev/null @@ -1,71 +0,0 @@ -from PIL import Image, IptcImagePlugin - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/iptc.jpg" - - -class TestFileIptc(PillowTestCase): - def test_getiptcinfo_jpg_none(self): - # Arrange - im = hopper() - - # Act - iptc = IptcImagePlugin.getiptcinfo(im) - - # Assert - self.assertIsNone(iptc) - - def test_getiptcinfo_jpg_found(self): - # Arrange - im = Image.open(TEST_FILE) - - # Act - iptc = IptcImagePlugin.getiptcinfo(im) - - # Assert - self.assertIsInstance(iptc, dict) - self.assertEqual(iptc[(2, 90)], b"Budapest") - self.assertEqual(iptc[(2, 101)], b"Hungary") - - def test_getiptcinfo_tiff_none(self): - # Arrange - im = Image.open("Tests/images/hopper.tif") - - # Act - iptc = IptcImagePlugin.getiptcinfo(im) - - # Assert - self.assertIsNone(iptc) - - def test_i(self): - # Arrange - c = b"a" - - # Act - ret = IptcImagePlugin.i(c) - - # Assert - self.assertEqual(ret, 97) - - def test_dump(self): - # Arrange - c = b"abc" - # Temporarily redirect stdout - try: - from cStringIO import StringIO - except ImportError: - from io import StringIO - import sys - - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - - # Act - IptcImagePlugin.dump(c) - - # Reset stdout - sys.stdout = old_stdout - - # Assert - self.assertEqual(mystdout.getvalue(), "61 62 63 \n") diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py deleted file mode 100644 index e0cb7528e89..00000000000 --- a/Tests/test_file_jpeg.py +++ /dev/null @@ -1,672 +0,0 @@ -import os -import sys -from io import BytesIO - -from PIL import Image, ImageFile, JpegImagePlugin - -from .helper import PillowTestCase, cjpeg_available, djpeg_available, hopper, unittest - -codecs = dir(Image.core) - -TEST_FILE = "Tests/images/hopper.jpg" - - -class TestFileJpeg(PillowTestCase): - def setUp(self): - if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: - self.skipTest("jpeg support not available") - - def roundtrip(self, im, **options): - out = BytesIO() - im.save(out, "JPEG", **options) - test_bytes = out.tell() - out.seek(0) - im = Image.open(out) - im.bytes = test_bytes # for testing only - return im - - def gen_random_image(self, size, mode="RGB"): - """ Generates a very hard to compress file - :param size: tuple - :param mode: optional image mode - - """ - return Image.frombytes(mode, size, os.urandom(size[0] * size[1] * len(mode))) - - def test_sanity(self): - - # internal version number - self.assertRegex(Image.core.jpeglib_version, r"\d+\.\d+$") - - im = Image.open(TEST_FILE) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "JPEG") - self.assertEqual(im.get_format_mimetype(), "image/jpeg") - - def test_app(self): - # Test APP/COM reader (@PIL135) - im = Image.open(TEST_FILE) - self.assertEqual( - im.applist[0], ("APP0", b"JFIF\x00\x01\x01\x01\x00`\x00`\x00\x00") - ) - self.assertEqual( - im.applist[1], ("COM", b"File written by Adobe Photoshop\xa8 4.0\x00") - ) - self.assertEqual(len(im.applist), 2) - - def test_cmyk(self): - # Test CMYK handling. Thanks to Tim and Charlie for test data, - # Michael for getting me to look one more time. - f = "Tests/images/pil_sample_cmyk.jpg" - im = Image.open(f) - # the source image has red pixels in the upper left corner. - c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))] - self.assertEqual(c, 0.0) - self.assertGreater(m, 0.8) - self.assertGreater(y, 0.8) - self.assertEqual(k, 0.0) - # the opposite corner is black - c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0] - 1, im.size[1] - 1))] - self.assertGreater(k, 0.9) - # roundtrip, and check again - im = self.roundtrip(im) - c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))] - self.assertEqual(c, 0.0) - self.assertGreater(m, 0.8) - self.assertGreater(y, 0.8) - self.assertEqual(k, 0.0) - c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0] - 1, im.size[1] - 1))] - self.assertGreater(k, 0.9) - - def test_dpi(self): - def test(xdpi, ydpi=None): - im = Image.open(TEST_FILE) - im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi)) - return im.info.get("dpi") - - self.assertEqual(test(72), (72, 72)) - self.assertEqual(test(300), (300, 300)) - self.assertEqual(test(100, 200), (100, 200)) - self.assertIsNone(test(0)) # square pixels - - def test_icc(self): - # Test ICC support - im1 = Image.open("Tests/images/rgb.jpg") - icc_profile = im1.info["icc_profile"] - self.assertEqual(len(icc_profile), 3144) - # Roundtrip via physical file. - f = self.tempfile("temp.jpg") - im1.save(f, icc_profile=icc_profile) - im2 = Image.open(f) - self.assertEqual(im2.info.get("icc_profile"), icc_profile) - # Roundtrip via memory buffer. - im1 = self.roundtrip(hopper()) - im2 = self.roundtrip(hopper(), icc_profile=icc_profile) - self.assert_image_equal(im1, im2) - self.assertFalse(im1.info.get("icc_profile")) - self.assertTrue(im2.info.get("icc_profile")) - - def test_icc_big(self): - # Make sure that the "extra" support handles large blocks - def test(n): - # The ICC APP marker can store 65519 bytes per marker, so - # using a 4-byte test code should allow us to detect out of - # order issues. - icc_profile = (b"Test" * int(n / 4 + 1))[:n] - self.assertEqual(len(icc_profile), n) # sanity - im1 = self.roundtrip(hopper(), icc_profile=icc_profile) - self.assertEqual(im1.info.get("icc_profile"), icc_profile or None) - - test(0) - test(1) - test(3) - test(4) - test(5) - test(65533 - 14) # full JPEG marker block - test(65533 - 14 + 1) # full block plus one byte - test(ImageFile.MAXBLOCK) # full buffer block - test(ImageFile.MAXBLOCK + 1) # full buffer block plus one byte - test(ImageFile.MAXBLOCK * 4 + 3) # large block - - def test_large_icc_meta(self): - # https://github.com/python-pillow/Pillow/issues/148 - # Sometimes the meta data on the icc_profile block is bigger than - # Image.MAXBLOCK or the image size. - im = Image.open("Tests/images/icc_profile_big.jpg") - f = self.tempfile("temp.jpg") - icc_profile = im.info["icc_profile"] - # Should not raise IOError for image with icc larger than image size. - im.save( - f, - format="JPEG", - progressive=True, - quality=95, - icc_profile=icc_profile, - optimize=True, - ) - - def test_optimize(self): - im1 = self.roundtrip(hopper()) - im2 = self.roundtrip(hopper(), optimize=0) - im3 = self.roundtrip(hopper(), optimize=1) - self.assert_image_equal(im1, im2) - self.assert_image_equal(im1, im3) - self.assertGreaterEqual(im1.bytes, im2.bytes) - self.assertGreaterEqual(im1.bytes, im3.bytes) - - def test_optimize_large_buffer(self): - # https://github.com/python-pillow/Pillow/issues/148 - f = self.tempfile("temp.jpg") - # this requires ~ 1.5x Image.MAXBLOCK - im = Image.new("RGB", (4096, 4096), 0xFF3333) - im.save(f, format="JPEG", optimize=True) - - def test_progressive(self): - im1 = self.roundtrip(hopper()) - im2 = self.roundtrip(hopper(), progressive=False) - im3 = self.roundtrip(hopper(), progressive=True) - self.assertFalse(im1.info.get("progressive")) - self.assertFalse(im2.info.get("progressive")) - self.assertTrue(im3.info.get("progressive")) - - self.assert_image_equal(im1, im3) - self.assertGreaterEqual(im1.bytes, im3.bytes) - - def test_progressive_large_buffer(self): - f = self.tempfile("temp.jpg") - # this requires ~ 1.5x Image.MAXBLOCK - im = Image.new("RGB", (4096, 4096), 0xFF3333) - im.save(f, format="JPEG", progressive=True) - - def test_progressive_large_buffer_highest_quality(self): - f = self.tempfile("temp.jpg") - im = self.gen_random_image((255, 255)) - # this requires more bytes than pixels in the image - im.save(f, format="JPEG", progressive=True, quality=100) - - def test_progressive_cmyk_buffer(self): - # Issue 2272, quality 90 cmyk image is tripping the large buffer bug. - f = BytesIO() - im = self.gen_random_image((256, 256), "CMYK") - im.save(f, format="JPEG", progressive=True, quality=94) - - def test_large_exif(self): - # https://github.com/python-pillow/Pillow/issues/148 - f = self.tempfile("temp.jpg") - im = hopper() - im.save(f, "JPEG", quality=90, exif=b"1" * 65532) - - def test_exif_typeerror(self): - im = Image.open("Tests/images/exif_typeerror.jpg") - # Should not raise a TypeError - im._getexif() - - def test_exif_gps(self): - # Arrange - im = Image.open("Tests/images/exif_gps.jpg") - gps_index = 34853 - expected_exif_gps = { - 0: b"\x00\x00\x00\x01", - 2: (4294967295, 1), - 5: b"\x01", - 30: 65535, - 29: "1999:99:99 99:99:99", - } - - # Act - exif = im._getexif() - - # Assert - self.assertEqual(exif[gps_index], expected_exif_gps) - - def test_exif_rollback(self): - # rolling back exif support in 3.1 to pre-3.0 formatting. - # expected from 2.9, with b/u qualifiers switched for 3.2 compatibility - # this test passes on 2.9 and 3.1, but not 3.0 - expected_exif = { - 34867: 4294967295, - 258: (24, 24, 24), - 36867: "2099:09:29 10:10:10", - 34853: { - 0: b"\x00\x00\x00\x01", - 2: (4294967295, 1), - 5: b"\x01", - 30: 65535, - 29: "1999:99:99 99:99:99", - }, - 296: 65535, - 34665: 185, - 41994: 65535, - 514: 4294967295, - 271: "Make", - 272: "XXX-XXX", - 305: "PIL", - 42034: ((1, 1), (1, 1), (1, 1), (1, 1)), - 42035: "LensMake", - 34856: b"\xaa\xaa\xaa\xaa\xaa\xaa", - 282: (4294967295, 1), - 33434: (4294967295, 1), - } - - im = Image.open("Tests/images/exif_gps.jpg") - exif = im._getexif() - - for tag, value in expected_exif.items(): - self.assertEqual(value, exif[tag]) - - def test_exif_gps_typeerror(self): - im = Image.open("Tests/images/exif_gps_typeerror.jpg") - - # Should not raise a TypeError - im._getexif() - - def test_progressive_compat(self): - im1 = self.roundtrip(hopper()) - self.assertFalse(im1.info.get("progressive")) - self.assertFalse(im1.info.get("progression")) - - im2 = self.roundtrip(hopper(), progressive=0) - im3 = self.roundtrip(hopper(), progression=0) # compatibility - self.assertFalse(im2.info.get("progressive")) - self.assertFalse(im2.info.get("progression")) - self.assertFalse(im3.info.get("progressive")) - self.assertFalse(im3.info.get("progression")) - - im2 = self.roundtrip(hopper(), progressive=1) - im3 = self.roundtrip(hopper(), progression=1) # compatibility - self.assert_image_equal(im1, im2) - self.assert_image_equal(im1, im3) - self.assertTrue(im2.info.get("progressive")) - self.assertTrue(im2.info.get("progression")) - self.assertTrue(im3.info.get("progressive")) - self.assertTrue(im3.info.get("progression")) - - def test_quality(self): - im1 = self.roundtrip(hopper()) - im2 = self.roundtrip(hopper(), quality=50) - self.assert_image(im1, im2.mode, im2.size) - self.assertGreaterEqual(im1.bytes, im2.bytes) - - def test_smooth(self): - im1 = self.roundtrip(hopper()) - im2 = self.roundtrip(hopper(), smooth=100) - self.assert_image(im1, im2.mode, im2.size) - - def test_subsampling(self): - def getsampling(im): - layer = im.layer - return layer[0][1:3] + layer[1][1:3] + layer[2][1:3] - - # experimental API - im = self.roundtrip(hopper(), subsampling=-1) # default - self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling=0) # 4:4:4 - self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling=1) # 4:2:2 - self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling=2) # 4:2:0 - self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling=3) # default (undefined) - self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1)) - - im = self.roundtrip(hopper(), subsampling="4:4:4") - self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling="4:2:2") - self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling="4:2:0") - self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1)) - im = self.roundtrip(hopper(), subsampling="4:1:1") - self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1)) - - self.assertRaises(TypeError, self.roundtrip, hopper(), subsampling="1:1:1") - - def test_exif(self): - im = Image.open("Tests/images/pil_sample_rgb.jpg") - info = im._getexif() - self.assertEqual(info[305], "Adobe Photoshop CS Macintosh") - - def test_mp(self): - im = Image.open("Tests/images/pil_sample_rgb.jpg") - self.assertIsNone(im._getmp()) - - def test_quality_keep(self): - # RGB - im = Image.open("Tests/images/hopper.jpg") - f = self.tempfile("temp.jpg") - im.save(f, quality="keep") - # Grayscale - im = Image.open("Tests/images/hopper_gray.jpg") - f = self.tempfile("temp.jpg") - im.save(f, quality="keep") - # CMYK - im = Image.open("Tests/images/pil_sample_cmyk.jpg") - f = self.tempfile("temp.jpg") - im.save(f, quality="keep") - - def test_junk_jpeg_header(self): - # https://github.com/python-pillow/Pillow/issues/630 - filename = "Tests/images/junk_jpeg_header.jpg" - Image.open(filename) - - def test_ff00_jpeg_header(self): - filename = "Tests/images/jpeg_ff00_header.jpg" - Image.open(filename) - - def test_truncated_jpeg_should_read_all_the_data(self): - filename = "Tests/images/truncated_jpeg.jpg" - ImageFile.LOAD_TRUNCATED_IMAGES = True - im = Image.open(filename) - im.load() - ImageFile.LOAD_TRUNCATED_IMAGES = False - self.assertIsNotNone(im.getbbox()) - - def test_truncated_jpeg_throws_IOError(self): - filename = "Tests/images/truncated_jpeg.jpg" - im = Image.open(filename) - - with self.assertRaises(IOError): - im.load() - - def _n_qtables_helper(self, n, test_file): - im = Image.open(test_file) - f = self.tempfile("temp.jpg") - im.save(f, qtables=[[n] * 64] * n) - im = Image.open(f) - self.assertEqual(len(im.quantization), n) - reloaded = self.roundtrip(im, qtables="keep") - self.assertEqual(im.quantization, reloaded.quantization) - - def test_qtables(self): - im = Image.open("Tests/images/hopper.jpg") - qtables = im.quantization - reloaded = self.roundtrip(im, qtables=qtables, subsampling=0) - self.assertEqual(im.quantization, reloaded.quantization) - self.assert_image_similar(im, self.roundtrip(im, qtables="web_low"), 30) - self.assert_image_similar(im, self.roundtrip(im, qtables="web_high"), 30) - self.assert_image_similar(im, self.roundtrip(im, qtables="keep"), 30) - - # valid bounds for baseline qtable - bounds_qtable = [int(s) for s in ("255 1 " * 32).split(None)] - self.roundtrip(im, qtables=[bounds_qtable]) - - # values from wizard.txt in jpeg9-a src package. - standard_l_qtable = [ - int(s) - for s in """ - 16 11 10 16 24 40 51 61 - 12 12 14 19 26 58 60 55 - 14 13 16 24 40 57 69 56 - 14 17 22 29 51 87 80 62 - 18 22 37 56 68 109 103 77 - 24 35 55 64 81 104 113 92 - 49 64 78 87 103 121 120 101 - 72 92 95 98 112 100 103 99 - """.split( - None - ) - ] - - standard_chrominance_qtable = [ - int(s) - for s in """ - 17 18 24 47 99 99 99 99 - 18 21 26 66 99 99 99 99 - 24 26 56 99 99 99 99 99 - 47 66 99 99 99 99 99 99 - 99 99 99 99 99 99 99 99 - 99 99 99 99 99 99 99 99 - 99 99 99 99 99 99 99 99 - 99 99 99 99 99 99 99 99 - """.split( - None - ) - ] - # list of qtable lists - self.assert_image_similar( - im, - self.roundtrip( - im, qtables=[standard_l_qtable, standard_chrominance_qtable] - ), - 30, - ) - - # tuple of qtable lists - self.assert_image_similar( - im, - self.roundtrip( - im, qtables=(standard_l_qtable, standard_chrominance_qtable) - ), - 30, - ) - - # dict of qtable lists - self.assert_image_similar( - im, - self.roundtrip( - im, qtables={0: standard_l_qtable, 1: standard_chrominance_qtable} - ), - 30, - ) - - self._n_qtables_helper(1, "Tests/images/hopper_gray.jpg") - self._n_qtables_helper(1, "Tests/images/pil_sample_rgb.jpg") - self._n_qtables_helper(2, "Tests/images/pil_sample_rgb.jpg") - self._n_qtables_helper(3, "Tests/images/pil_sample_rgb.jpg") - self._n_qtables_helper(1, "Tests/images/pil_sample_cmyk.jpg") - self._n_qtables_helper(2, "Tests/images/pil_sample_cmyk.jpg") - self._n_qtables_helper(3, "Tests/images/pil_sample_cmyk.jpg") - self._n_qtables_helper(4, "Tests/images/pil_sample_cmyk.jpg") - - # not a sequence - self.assertRaises(ValueError, self.roundtrip, im, qtables="a") - # sequence wrong length - self.assertRaises(ValueError, self.roundtrip, im, qtables=[]) - # sequence wrong length - self.assertRaises(ValueError, self.roundtrip, im, qtables=[1, 2, 3, 4, 5]) - - # qtable entry not a sequence - self.assertRaises(ValueError, self.roundtrip, im, qtables=[1]) - # qtable entry has wrong number of items - self.assertRaises(ValueError, self.roundtrip, im, qtables=[[1, 2, 3, 4]]) - - @unittest.skipUnless(djpeg_available(), "djpeg not available") - def test_load_djpeg(self): - img = Image.open(TEST_FILE) - img.load_djpeg() - self.assert_image_similar(img, Image.open(TEST_FILE), 0) - - @unittest.skipUnless(cjpeg_available(), "cjpeg not available") - def test_save_cjpeg(self): - img = Image.open(TEST_FILE) - - tempfile = self.tempfile("temp.jpg") - JpegImagePlugin._save_cjpeg(img, 0, tempfile) - # Default save quality is 75%, so a tiny bit of difference is alright - self.assert_image_similar(img, Image.open(tempfile), 17) - - def test_no_duplicate_0x1001_tag(self): - # Arrange - from PIL import ExifTags - - tag_ids = {v: k for k, v in ExifTags.TAGS.items()} - - # Assert - self.assertEqual(tag_ids["RelatedImageWidth"], 0x1001) - self.assertEqual(tag_ids["RelatedImageLength"], 0x1002) - - def test_MAXBLOCK_scaling(self): - im = self.gen_random_image((512, 512)) - f = self.tempfile("temp.jpeg") - im.save(f, quality=100, optimize=True) - - reloaded = Image.open(f) - - # none of these should crash - reloaded.save(f, quality="keep") - reloaded.save(f, quality="keep", progressive=True) - reloaded.save(f, quality="keep", optimize=True) - - def test_bad_mpo_header(self): - """ Treat unknown MPO as JPEG """ - # Arrange - - # Act - # Shouldn't raise error - fn = "Tests/images/sugarshack_bad_mpo_header.jpg" - im = self.assert_warning(UserWarning, Image.open, fn) - - # Assert - self.assertEqual(im.format, "JPEG") - - def test_save_correct_modes(self): - out = BytesIO() - for mode in ["1", "L", "RGB", "RGBX", "CMYK", "YCbCr"]: - img = Image.new(mode, (20, 20)) - img.save(out, "JPEG") - - def test_save_wrong_modes(self): - # ref https://github.com/python-pillow/Pillow/issues/2005 - out = BytesIO() - for mode in ["LA", "La", "RGBA", "RGBa", "P"]: - img = Image.new(mode, (20, 20)) - self.assertRaises(IOError, img.save, out, "JPEG") - - def test_save_tiff_with_dpi(self): - # Arrange - outfile = self.tempfile("temp.tif") - im = Image.open("Tests/images/hopper.tif") - - # Act - im.save(outfile, "JPEG", dpi=im.info["dpi"]) - - # Assert - reloaded = Image.open(outfile) - reloaded.load() - self.assertEqual(im.info["dpi"], reloaded.info["dpi"]) - - def test_load_dpi_rounding(self): - # Round up - im = Image.open("Tests/images/iptc_roundUp.jpg") - self.assertEqual(im.info["dpi"], (44, 44)) - - # Round down - im = Image.open("Tests/images/iptc_roundDown.jpg") - self.assertEqual(im.info["dpi"], (2, 2)) - - def test_save_dpi_rounding(self): - outfile = self.tempfile("temp.jpg") - im = Image.open("Tests/images/hopper.jpg") - - im.save(outfile, dpi=(72.2, 72.2)) - reloaded = Image.open(outfile) - self.assertEqual(reloaded.info["dpi"], (72, 72)) - - im.save(outfile, dpi=(72.8, 72.8)) - reloaded = Image.open(outfile) - self.assertEqual(reloaded.info["dpi"], (73, 73)) - - def test_dpi_tuple_from_exif(self): - # Arrange - # This Photoshop CC 2017 image has DPI in EXIF not metadata - # EXIF XResolution is (2000000, 10000) - im = Image.open("Tests/images/photoshop-200dpi.jpg") - - # Act / Assert - self.assertEqual(im.info.get("dpi"), (200, 200)) - - def test_dpi_int_from_exif(self): - # Arrange - # This image has DPI in EXIF not metadata - # EXIF XResolution is 72 - im = Image.open("Tests/images/exif-72dpi-int.jpg") - - # Act / Assert - self.assertEqual(im.info.get("dpi"), (72, 72)) - - def test_dpi_from_dpcm_exif(self): - # Arrange - # This is photoshop-200dpi.jpg with EXIF resolution unit set to cm: - # exiftool -exif:ResolutionUnit=cm photoshop-200dpi.jpg - im = Image.open("Tests/images/exif-200dpcm.jpg") - - # Act / Assert - self.assertEqual(im.info.get("dpi"), (508, 508)) - - def test_dpi_exif_zero_division(self): - # Arrange - # This is photoshop-200dpi.jpg with EXIF resolution set to 0/0: - # exiftool -XResolution=0/0 -YResolution=0/0 photoshop-200dpi.jpg - im = Image.open("Tests/images/exif-dpi-zerodivision.jpg") - - # Act / Assert - # This should return the default, and not raise a ZeroDivisionError - self.assertEqual(im.info.get("dpi"), (72, 72)) - - def test_no_dpi_in_exif(self): - # Arrange - # This is photoshop-200dpi.jpg with resolution removed from EXIF: - # exiftool "-*resolution*"= photoshop-200dpi.jpg - im = Image.open("Tests/images/no-dpi-in-exif.jpg") - - # Act / Assert - # "When the image resolution is unknown, 72 [dpi] is designated." - # http://www.exiv2.org/tags.html - self.assertEqual(im.info.get("dpi"), (72, 72)) - - def test_invalid_exif(self): - # This is no-dpi-in-exif with the tiff header of the exif block - # hexedited from MM * to FF FF FF FF - im = Image.open("Tests/images/invalid-exif.jpg") - - # This should return the default, and not a SyntaxError or - # OSError for unidentified image. - self.assertEqual(im.info.get("dpi"), (72, 72)) - - def test_ifd_offset_exif(self): - # Arrange - # This image has been manually hexedited to have an IFD offset of 10, - # in contrast to normal 8 - im = Image.open("Tests/images/exif-ifd-offset.jpg") - - # Act / Assert - self.assertEqual(im._getexif()[306], "2017:03:13 23:03:09") - - def test_photoshop(self): - im = Image.open("Tests/images/photoshop-200dpi.jpg") - self.assertEqual( - im.info["photoshop"][0x03ED], - { - "XResolution": 200.0, - "DisplayedUnitsX": 1, - "YResolution": 200.0, - "DisplayedUnitsY": 1, - }, - ) - - # This image does not contain a Photoshop header string - im = Image.open("Tests/images/app13.jpg") - self.assertNotIn("photoshop", im.info) - - -@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") -class TestFileCloseW32(PillowTestCase): - def setUp(self): - if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: - self.skipTest("jpeg support not available") - - def test_fd_leak(self): - tmpfile = self.tempfile("temp.jpg") - - with Image.open("Tests/images/hopper.jpg") as im: - im.save(tmpfile) - - im = Image.open(tmpfile) - fp = im.fp - self.assertFalse(fp.closed) - self.assertRaises(WindowsError, os.remove, tmpfile) - im.load() - self.assertTrue(fp.closed) - # this should not fail, as load should have closed the file. - os.remove(tmpfile) diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py deleted file mode 100644 index 7643cfebf78..00000000000 --- a/Tests/test_file_jpeg2k.py +++ /dev/null @@ -1,206 +0,0 @@ -from io import BytesIO - -from PIL import Image, Jpeg2KImagePlugin - -from .helper import PillowTestCase - -codecs = dir(Image.core) - -test_card = Image.open("Tests/images/test-card.png") -test_card.load() - -# OpenJPEG 2.0.0 outputs this debugging message sometimes; we should -# ignore it---it doesn't represent a test failure. -# 'Not enough memory to handle tile data' - - -class TestFileJpeg2k(PillowTestCase): - def setUp(self): - if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs: - self.skipTest("JPEG 2000 support not available") - - def roundtrip(self, im, **options): - out = BytesIO() - im.save(out, "JPEG2000", **options) - test_bytes = out.tell() - out.seek(0) - im = Image.open(out) - im.bytes = test_bytes # for testing only - im.load() - return im - - def test_sanity(self): - # Internal version number - self.assertRegex(Image.core.jp2klib_version, r"\d+\.\d+\.\d+$") - - im = Image.open("Tests/images/test-card-lossless.jp2") - px = im.load() - self.assertEqual(px[0, 0], (0, 0, 0)) - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (640, 480)) - self.assertEqual(im.format, "JPEG2000") - self.assertEqual(im.get_format_mimetype(), "image/jp2") - - def test_jpf(self): - im = Image.open("Tests/images/balloon.jpf") - self.assertEqual(im.format, "JPEG2000") - self.assertEqual(im.get_format_mimetype(), "image/jpx") - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, Jpeg2KImagePlugin.Jpeg2KImageFile, invalid_file) - - def test_bytesio(self): - with open("Tests/images/test-card-lossless.jp2", "rb") as f: - data = BytesIO(f.read()) - im = Image.open(data) - im.load() - self.assert_image_similar(im, test_card, 1.0e-3) - - # These two test pre-written JPEG 2000 files that were not written with - # PIL (they were made using Adobe Photoshop) - - def test_lossless(self): - im = Image.open("Tests/images/test-card-lossless.jp2") - im.load() - outfile = self.tempfile("temp_test-card.png") - im.save(outfile) - self.assert_image_similar(im, test_card, 1.0e-3) - - def test_lossy_tiled(self): - im = Image.open("Tests/images/test-card-lossy-tiled.jp2") - im.load() - self.assert_image_similar(im, test_card, 2.0) - - def test_lossless_rt(self): - im = self.roundtrip(test_card) - self.assert_image_equal(im, test_card) - - def test_lossy_rt(self): - im = self.roundtrip(test_card, quality_layers=[20]) - self.assert_image_similar(im, test_card, 2.0) - - def test_tiled_rt(self): - im = self.roundtrip(test_card, tile_size=(128, 128)) - self.assert_image_equal(im, test_card) - - def test_tiled_offset_rt(self): - im = self.roundtrip( - test_card, tile_size=(128, 128), tile_offset=(0, 0), offset=(32, 32) - ) - self.assert_image_equal(im, test_card) - - def test_irreversible_rt(self): - im = self.roundtrip(test_card, irreversible=True, quality_layers=[20]) - self.assert_image_similar(im, test_card, 2.0) - - def test_prog_qual_rt(self): - im = self.roundtrip(test_card, quality_layers=[60, 40, 20], progression="LRCP") - self.assert_image_similar(im, test_card, 2.0) - - def test_prog_res_rt(self): - im = self.roundtrip(test_card, num_resolutions=8, progression="RLCP") - self.assert_image_equal(im, test_card) - - def test_reduce(self): - im = Image.open("Tests/images/test-card-lossless.jp2") - im.reduce = 2 - im.load() - self.assertEqual(im.size, (160, 120)) - - def test_layers_type(self): - outfile = self.tempfile("temp_layers.jp2") - for quality_layers in [[100, 50, 10], (100, 50, 10), None]: - test_card.save(outfile, quality_layers=quality_layers) - - for quality_layers in ["quality_layers", ("100", "50", "10")]: - self.assertRaises( - ValueError, test_card.save, outfile, quality_layers=quality_layers - ) - - def test_layers(self): - out = BytesIO() - test_card.save( - out, "JPEG2000", quality_layers=[100, 50, 10], progression="LRCP" - ) - out.seek(0) - - im = Image.open(out) - im.layers = 1 - im.load() - self.assert_image_similar(im, test_card, 13) - - out.seek(0) - im = Image.open(out) - im.layers = 3 - im.load() - self.assert_image_similar(im, test_card, 0.4) - - def test_rgba(self): - # Arrange - j2k = Image.open("Tests/images/rgb_trns_ycbc.j2k") - jp2 = Image.open("Tests/images/rgb_trns_ycbc.jp2") - - # Act - j2k.load() - jp2.load() - - # Assert - self.assertEqual(j2k.mode, "RGBA") - self.assertEqual(jp2.mode, "RGBA") - - def test_16bit_monochrome_has_correct_mode(self): - - j2k = Image.open("Tests/images/16bit.cropped.j2k") - jp2 = Image.open("Tests/images/16bit.cropped.jp2") - - j2k.load() - jp2.load() - - self.assertEqual(j2k.mode, "I;16") - self.assertEqual(jp2.mode, "I;16") - - def test_16bit_monochrome_jp2_like_tiff(self): - - tiff_16bit = Image.open("Tests/images/16bit.cropped.tif") - jp2 = Image.open("Tests/images/16bit.cropped.jp2") - self.assert_image_similar(jp2, tiff_16bit, 1e-3) - - def test_16bit_monochrome_j2k_like_tiff(self): - - tiff_16bit = Image.open("Tests/images/16bit.cropped.tif") - j2k = Image.open("Tests/images/16bit.cropped.j2k") - self.assert_image_similar(j2k, tiff_16bit, 1e-3) - - def test_16bit_j2k_roundtrips(self): - - j2k = Image.open("Tests/images/16bit.cropped.j2k") - im = self.roundtrip(j2k) - self.assert_image_equal(im, j2k) - - def test_16bit_jp2_roundtrips(self): - - jp2 = Image.open("Tests/images/16bit.cropped.jp2") - im = self.roundtrip(jp2) - self.assert_image_equal(im, jp2) - - def test_unbound_local(self): - # prepatch, a malformed jp2 file could cause an UnboundLocalError - # exception. - with self.assertRaises(IOError): - Image.open("Tests/images/unbound_variable.jp2") - - def test_parser_feed(self): - # Arrange - from PIL import ImageFile - - with open("Tests/images/test-card-lossless.jp2", "rb") as f: - data = f.read() - - # Act - p = ImageFile.Parser() - p.feed(data) - - # Assert - self.assertEqual(p.image.size, (640, 480)) diff --git a/Tests/test_file_libtiff.py b/Tests/test_file_libtiff.py deleted file mode 100644 index bc5003f5fc2..00000000000 --- a/Tests/test_file_libtiff.py +++ /dev/null @@ -1,820 +0,0 @@ -from __future__ import print_function - -import distutils.version -import io -import itertools -import logging -import os -from collections import namedtuple -from ctypes import c_float - -from PIL import Image, TiffImagePlugin, TiffTags, features -from PIL._util import py3 - -from .helper import PillowTestCase, hopper - -logger = logging.getLogger(__name__) - - -class LibTiffTestCase(PillowTestCase): - def setUp(self): - if not features.check("libtiff"): - self.skipTest("tiff support not available") - - def _assert_noerr(self, im): - """Helper tests that assert basic sanity about the g4 tiff reading""" - # 1 bit - self.assertEqual(im.mode, "1") - - # Does the data actually load - im.load() - im.getdata() - - try: - self.assertEqual(im._compression, "group4") - except AttributeError: - print("No _compression") - print(dir(im)) - - # can we write it back out, in a different form. - out = self.tempfile("temp.png") - im.save(out) - - out_bytes = io.BytesIO() - im.save(out_bytes, format="tiff", compression="group4") - - -class TestFileLibTiff(LibTiffTestCase): - def test_g4_tiff(self): - """Test the ordinary file path load path""" - - test_file = "Tests/images/hopper_g4_500.tif" - im = Image.open(test_file) - - self.assertEqual(im.size, (500, 500)) - self._assert_noerr(im) - - def test_g4_large(self): - test_file = "Tests/images/pport_g4.tif" - im = Image.open(test_file) - self._assert_noerr(im) - - def test_g4_tiff_file(self): - """Testing the string load path""" - - test_file = "Tests/images/hopper_g4_500.tif" - with open(test_file, "rb") as f: - im = Image.open(f) - - self.assertEqual(im.size, (500, 500)) - self._assert_noerr(im) - - def test_g4_tiff_bytesio(self): - """Testing the stringio loading code path""" - test_file = "Tests/images/hopper_g4_500.tif" - s = io.BytesIO() - with open(test_file, "rb") as f: - s.write(f.read()) - s.seek(0) - im = Image.open(s) - - self.assertEqual(im.size, (500, 500)) - self._assert_noerr(im) - - def test_g4_eq_png(self): - """ Checking that we're actually getting the data that we expect""" - png = Image.open("Tests/images/hopper_bw_500.png") - g4 = Image.open("Tests/images/hopper_g4_500.tif") - - self.assert_image_equal(g4, png) - - # see https://github.com/python-pillow/Pillow/issues/279 - def test_g4_fillorder_eq_png(self): - """ Checking that we're actually getting the data that we expect""" - png = Image.open("Tests/images/g4-fillorder-test.png") - g4 = Image.open("Tests/images/g4-fillorder-test.tif") - - self.assert_image_equal(g4, png) - - def test_g4_write(self): - """Checking to see that the saved image is the same as what we wrote""" - test_file = "Tests/images/hopper_g4_500.tif" - orig = Image.open(test_file) - - out = self.tempfile("temp.tif") - rot = orig.transpose(Image.ROTATE_90) - self.assertEqual(rot.size, (500, 500)) - rot.save(out) - - reread = Image.open(out) - self.assertEqual(reread.size, (500, 500)) - self._assert_noerr(reread) - self.assert_image_equal(reread, rot) - self.assertEqual(reread.info["compression"], "group4") - - self.assertEqual(reread.info["compression"], orig.info["compression"]) - - self.assertNotEqual(orig.tobytes(), reread.tobytes()) - - def test_adobe_deflate_tiff(self): - test_file = "Tests/images/tiff_adobe_deflate.tif" - im = Image.open(test_file) - - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (278, 374)) - self.assertEqual(im.tile[0][:3], ("libtiff", (0, 0, 278, 374), 0)) - im.load() - - self.assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png") - - def test_write_metadata(self): - """ Test metadata writing through libtiff """ - for legacy_api in [False, True]: - img = Image.open("Tests/images/hopper_g4.tif") - f = self.tempfile("temp.tiff") - - img.save(f, tiffinfo=img.tag) - - if legacy_api: - original = img.tag.named() - else: - original = img.tag_v2.named() - - # PhotometricInterpretation is set from SAVE_INFO, - # not the original image. - ignored = [ - "StripByteCounts", - "RowsPerStrip", - "PageNumber", - "PhotometricInterpretation", - ] - - loaded = Image.open(f) - if legacy_api: - reloaded = loaded.tag.named() - else: - reloaded = loaded.tag_v2.named() - - for tag, value in itertools.chain(reloaded.items(), original.items()): - if tag not in ignored: - val = original[tag] - if tag.endswith("Resolution"): - if legacy_api: - self.assertEqual( - c_float(val[0][0] / val[0][1]).value, - c_float(value[0][0] / value[0][1]).value, - msg="%s didn't roundtrip" % tag, - ) - else: - self.assertEqual( - c_float(val).value, - c_float(value).value, - msg="%s didn't roundtrip" % tag, - ) - else: - self.assertEqual(val, value, msg="%s didn't roundtrip" % tag) - - # https://github.com/python-pillow/Pillow/issues/1561 - requested_fields = ["StripByteCounts", "RowsPerStrip", "StripOffsets"] - for field in requested_fields: - self.assertIn(field, reloaded, "%s not in metadata" % field) - - def test_additional_metadata(self): - # these should not crash. Seriously dummy data, most of it doesn't make - # any sense, so we're running up against limits where we're asking - # libtiff to do stupid things. - - # Get the list of the ones that we should be able to write - - core_items = { - tag: info - for tag, info in ((s, TiffTags.lookup(s)) for s in TiffTags.LIBTIFF_CORE) - if info.type is not None - } - - # Exclude ones that have special meaning - # that we're already testing them - im = Image.open("Tests/images/hopper_g4.tif") - for tag in im.tag_v2: - try: - del core_items[tag] - except KeyError: - pass - - # Type codes: - # 2: "ascii", - # 3: "short", - # 4: "long", - # 5: "rational", - # 12: "double", - # Type: dummy value - values = { - 2: "test", - 3: 1, - 4: 2 ** 20, - 5: TiffImagePlugin.IFDRational(100, 1), - 12: 1.05, - } - - new_ifd = TiffImagePlugin.ImageFileDirectory_v2() - for tag, info in core_items.items(): - if info.length == 1: - new_ifd[tag] = values[info.type] - if info.length == 0: - new_ifd[tag] = tuple(values[info.type] for _ in range(3)) - else: - new_ifd[tag] = tuple(values[info.type] for _ in range(info.length)) - - # Extra samples really doesn't make sense in this application. - del new_ifd[338] - - out = self.tempfile("temp.tif") - TiffImagePlugin.WRITE_LIBTIFF = True - - im.save(out, tiffinfo=new_ifd) - - TiffImagePlugin.WRITE_LIBTIFF = False - - def test_custom_metadata(self): - tc = namedtuple("test_case", "value,type,supported_by_default") - custom = { - 37000 + k: v - for k, v in enumerate( - [ - tc(4, TiffTags.SHORT, True), - tc(123456789, TiffTags.LONG, True), - tc(-4, TiffTags.SIGNED_BYTE, False), - tc(-4, TiffTags.SIGNED_SHORT, False), - tc(-123456789, TiffTags.SIGNED_LONG, False), - tc(TiffImagePlugin.IFDRational(4, 7), TiffTags.RATIONAL, True), - tc(4.25, TiffTags.FLOAT, True), - tc(4.25, TiffTags.DOUBLE, True), - tc("custom tag value", TiffTags.ASCII, True), - tc(u"custom tag value", TiffTags.ASCII, True), - tc(b"custom tag value", TiffTags.BYTE, True), - tc((4, 5, 6), TiffTags.SHORT, True), - tc((123456789, 9, 34, 234, 219387, 92432323), TiffTags.LONG, True), - tc((-4, 9, 10), TiffTags.SIGNED_BYTE, False), - tc((-4, 5, 6), TiffTags.SIGNED_SHORT, False), - tc( - (-123456789, 9, 34, 234, 219387, -92432323), - TiffTags.SIGNED_LONG, - False, - ), - tc((4.25, 5.25), TiffTags.FLOAT, True), - tc((4.25, 5.25), TiffTags.DOUBLE, True), - # array of TIFF_BYTE requires bytes instead of tuple for backwards - # compatibility - tc(bytes([4]), TiffTags.BYTE, True), - tc(bytes((4, 9, 10)), TiffTags.BYTE, True), - ] - ) - } - - libtiff_version = TiffImagePlugin._libtiff_version() - - libtiffs = [False] - if distutils.version.StrictVersion( - libtiff_version - ) >= distutils.version.StrictVersion("4.0"): - libtiffs.append(True) - - for libtiff in libtiffs: - TiffImagePlugin.WRITE_LIBTIFF = libtiff - - def check_tags(tiffinfo): - im = hopper() - - out = self.tempfile("temp.tif") - im.save(out, tiffinfo=tiffinfo) - - reloaded = Image.open(out) - for tag, value in tiffinfo.items(): - reloaded_value = reloaded.tag_v2[tag] - if ( - isinstance(reloaded_value, TiffImagePlugin.IFDRational) - and libtiff - ): - # libtiff does not support real RATIONALS - self.assertAlmostEqual(float(reloaded_value), float(value)) - continue - - if libtiff and isinstance(value, bytes): - value = value.decode() - - self.assertEqual(reloaded_value, value) - - # Test with types - ifd = TiffImagePlugin.ImageFileDirectory_v2() - for tag, tagdata in custom.items(): - ifd[tag] = tagdata.value - ifd.tagtype[tag] = tagdata.type - check_tags(ifd) - - # Test without types. This only works for some types, int for example are - # always encoded as LONG and not SIGNED_LONG. - check_tags( - { - tag: tagdata.value - for tag, tagdata in custom.items() - if tagdata.supported_by_default - } - ) - TiffImagePlugin.WRITE_LIBTIFF = False - - def test_int_dpi(self): - # issue #1765 - im = hopper("RGB") - out = self.tempfile("temp.tif") - TiffImagePlugin.WRITE_LIBTIFF = True - im.save(out, dpi=(72, 72)) - TiffImagePlugin.WRITE_LIBTIFF = False - reloaded = Image.open(out) - self.assertEqual(reloaded.info["dpi"], (72.0, 72.0)) - - def test_g3_compression(self): - i = Image.open("Tests/images/hopper_g4_500.tif") - out = self.tempfile("temp.tif") - i.save(out, compression="group3") - - reread = Image.open(out) - self.assertEqual(reread.info["compression"], "group3") - self.assert_image_equal(reread, i) - - def test_little_endian(self): - im = Image.open("Tests/images/16bit.deflate.tif") - self.assertEqual(im.getpixel((0, 0)), 480) - self.assertEqual(im.mode, "I;16") - - b = im.tobytes() - # Bytes are in image native order (little endian) - if py3: - self.assertEqual(b[0], ord(b"\xe0")) - self.assertEqual(b[1], ord(b"\x01")) - else: - self.assertEqual(b[0], b"\xe0") - self.assertEqual(b[1], b"\x01") - - out = self.tempfile("temp.tif") - # out = "temp.le.tif" - im.save(out) - reread = Image.open(out) - - self.assertEqual(reread.info["compression"], im.info["compression"]) - self.assertEqual(reread.getpixel((0, 0)), 480) - # UNDONE - libtiff defaults to writing in native endian, so - # on big endian, we'll get back mode = 'I;16B' here. - - def test_big_endian(self): - im = Image.open("Tests/images/16bit.MM.deflate.tif") - - self.assertEqual(im.getpixel((0, 0)), 480) - self.assertEqual(im.mode, "I;16B") - - b = im.tobytes() - - # Bytes are in image native order (big endian) - if py3: - self.assertEqual(b[0], ord(b"\x01")) - self.assertEqual(b[1], ord(b"\xe0")) - else: - self.assertEqual(b[0], b"\x01") - self.assertEqual(b[1], b"\xe0") - - out = self.tempfile("temp.tif") - im.save(out) - reread = Image.open(out) - - self.assertEqual(reread.info["compression"], im.info["compression"]) - self.assertEqual(reread.getpixel((0, 0)), 480) - - def test_g4_string_info(self): - """Tests String data in info directory""" - test_file = "Tests/images/hopper_g4_500.tif" - orig = Image.open(test_file) - - out = self.tempfile("temp.tif") - - orig.tag[269] = "temp.tif" - orig.save(out) - - reread = Image.open(out) - self.assertEqual("temp.tif", reread.tag_v2[269]) - self.assertEqual("temp.tif", reread.tag[269][0]) - - def test_12bit_rawmode(self): - """ Are we generating the same interpretation - of the image as Imagemagick is? """ - TiffImagePlugin.READ_LIBTIFF = True - im = Image.open("Tests/images/12bit.cropped.tif") - im.load() - TiffImagePlugin.READ_LIBTIFF = False - # to make the target -- - # convert 12bit.cropped.tif -depth 16 tmp.tif - # convert tmp.tif -evaluate RightShift 4 12in16bit2.tif - # imagemagick will auto scale so that a 12bit FFF is 16bit FFF0, - # so we need to unshift so that the integer values are the same. - - self.assert_image_equal_tofile(im, "Tests/images/12in16bit.tif") - - def test_blur(self): - # test case from irc, how to do blur on b/w image - # and save to compressed tif. - from PIL import ImageFilter - - out = self.tempfile("temp.tif") - im = Image.open("Tests/images/pport_g4.tif") - im = im.convert("L") - - im = im.filter(ImageFilter.GaussianBlur(4)) - im.save(out, compression="tiff_adobe_deflate") - - im2 = Image.open(out) - im2.load() - - self.assert_image_equal(im, im2) - - def test_compressions(self): - # Test various tiff compressions and assert similar image content but reduced - # file sizes. - im = hopper("RGB") - out = self.tempfile("temp.tif") - im.save(out) - size_raw = os.path.getsize(out) - - for compression in ("packbits", "tiff_lzw"): - im.save(out, compression=compression) - size_compressed = os.path.getsize(out) - im2 = Image.open(out) - self.assert_image_equal(im, im2) - - im.save(out, compression="jpeg") - size_jpeg = os.path.getsize(out) - im2 = Image.open(out) - self.assert_image_similar(im, im2, 30) - - im.save(out, compression="jpeg", quality=30) - size_jpeg_30 = os.path.getsize(out) - im3 = Image.open(out) - self.assert_image_similar(im2, im3, 30) - - self.assertGreater(size_raw, size_compressed) - self.assertGreater(size_compressed, size_jpeg) - self.assertGreater(size_jpeg, size_jpeg_30) - - def test_quality(self): - im = hopper("RGB") - out = self.tempfile("temp.tif") - - self.assertRaises(ValueError, im.save, out, compression="tiff_lzw", quality=50) - self.assertRaises(ValueError, im.save, out, compression="jpeg", quality=-1) - self.assertRaises(ValueError, im.save, out, compression="jpeg", quality=101) - self.assertRaises(ValueError, im.save, out, compression="jpeg", quality="good") - im.save(out, compression="jpeg", quality=0) - im.save(out, compression="jpeg", quality=100) - - def test_cmyk_save(self): - im = hopper("CMYK") - out = self.tempfile("temp.tif") - - im.save(out, compression="tiff_adobe_deflate") - im2 = Image.open(out) - self.assert_image_equal(im, im2) - - def xtest_bw_compression_w_rgb(self): - """ This test passes, but when running all tests causes a failure due - to output on stderr from the error thrown by libtiff. We need to - capture that but not now""" - - im = hopper("RGB") - out = self.tempfile("temp.tif") - - self.assertRaises(IOError, im.save, out, compression="tiff_ccitt") - self.assertRaises(IOError, im.save, out, compression="group3") - self.assertRaises(IOError, im.save, out, compression="group4") - - def test_fp_leak(self): - im = Image.open("Tests/images/hopper_g4_500.tif") - fn = im.fp.fileno() - - os.fstat(fn) - im.load() # this should close it. - self.assertRaises(OSError, os.fstat, fn) - im = None # this should force even more closed. - self.assertRaises(OSError, os.fstat, fn) - self.assertRaises(OSError, os.close, fn) - - def test_multipage(self): - # issue #862 - TiffImagePlugin.READ_LIBTIFF = True - im = Image.open("Tests/images/multipage.tiff") - # file is a multipage tiff, 10x10 green, 10x10 red, 20x20 blue - - im.seek(0) - self.assertEqual(im.size, (10, 10)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (0, 128, 0)) - self.assertTrue(im.tag.next) - - im.seek(1) - self.assertEqual(im.size, (10, 10)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (255, 0, 0)) - self.assertTrue(im.tag.next) - - im.seek(2) - self.assertFalse(im.tag.next) - self.assertEqual(im.size, (20, 20)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (0, 0, 255)) - - TiffImagePlugin.READ_LIBTIFF = False - - def test_multipage_nframes(self): - # issue #862 - TiffImagePlugin.READ_LIBTIFF = True - im = Image.open("Tests/images/multipage.tiff") - frames = im.n_frames - self.assertEqual(frames, 3) - for _ in range(frames): - im.seek(0) - # Should not raise ValueError: I/O operation on closed file - im.load() - - TiffImagePlugin.READ_LIBTIFF = False - - def test__next(self): - TiffImagePlugin.READ_LIBTIFF = True - im = Image.open("Tests/images/hopper.tif") - self.assertFalse(im.tag.next) - im.load() - self.assertFalse(im.tag.next) - - def test_4bit(self): - # Arrange - test_file = "Tests/images/hopper_gray_4bpp.tif" - original = hopper("L") - - # Act - TiffImagePlugin.READ_LIBTIFF = True - im = Image.open(test_file) - TiffImagePlugin.READ_LIBTIFF = False - - # Assert - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.mode, "L") - self.assert_image_similar(im, original, 7.3) - - def test_gray_semibyte_per_pixel(self): - test_files = ( - ( - 24.8, # epsilon - ( # group - "Tests/images/tiff_gray_2_4_bpp/hopper2.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper2I.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper2R.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif", - ), - ), - ( - 7.3, # epsilon - ( # group - "Tests/images/tiff_gray_2_4_bpp/hopper4.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper4I.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper4R.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif", - ), - ), - ) - original = hopper("L") - for epsilon, group in test_files: - im = Image.open(group[0]) - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.mode, "L") - self.assert_image_similar(im, original, epsilon) - for file in group[1:]: - im2 = Image.open(file) - self.assertEqual(im2.size, (128, 128)) - self.assertEqual(im2.mode, "L") - self.assert_image_equal(im, im2) - - def test_save_bytesio(self): - # PR 1011 - # Test TIFF saving to io.BytesIO() object. - - TiffImagePlugin.WRITE_LIBTIFF = True - TiffImagePlugin.READ_LIBTIFF = True - - # Generate test image - pilim = hopper() - - def save_bytesio(compression=None): - - buffer_io = io.BytesIO() - pilim.save(buffer_io, format="tiff", compression=compression) - buffer_io.seek(0) - - pilim_load = Image.open(buffer_io) - self.assert_image_similar(pilim, pilim_load, 0) - - save_bytesio() - save_bytesio("raw") - save_bytesio("packbits") - save_bytesio("tiff_lzw") - - TiffImagePlugin.WRITE_LIBTIFF = False - TiffImagePlugin.READ_LIBTIFF = False - - def test_crashing_metadata(self): - # issue 1597 - im = Image.open("Tests/images/rdf.tif") - out = self.tempfile("temp.tif") - - TiffImagePlugin.WRITE_LIBTIFF = True - # this shouldn't crash - im.save(out, format="TIFF") - TiffImagePlugin.WRITE_LIBTIFF = False - - def test_page_number_x_0(self): - # Issue 973 - # Test TIFF with tag 297 (Page Number) having value of 0 0. - # The first number is the current page number. - # The second is the total number of pages, zero means not available. - outfile = self.tempfile("temp.tif") - # Created by printing a page in Chrome to PDF, then: - # /usr/bin/gs -q -sDEVICE=tiffg3 -sOutputFile=total-pages-zero.tif - # -dNOPAUSE /tmp/test.pdf -c quit - infile = "Tests/images/total-pages-zero.tif" - im = Image.open(infile) - # Should not divide by zero - im.save(outfile) - - def test_fd_duplication(self): - # https://github.com/python-pillow/Pillow/issues/1651 - - tmpfile = self.tempfile("temp.tif") - with open(tmpfile, "wb") as f: - with open("Tests/images/g4-multi.tiff", "rb") as src: - f.write(src.read()) - - im = Image.open(tmpfile) - im.n_frames - im.close() - # Should not raise PermissionError. - os.remove(tmpfile) - - def test_read_icc(self): - with Image.open("Tests/images/hopper.iccprofile.tif") as img: - icc = img.info.get("icc_profile") - self.assertIsNotNone(icc) - TiffImagePlugin.READ_LIBTIFF = True - with Image.open("Tests/images/hopper.iccprofile.tif") as img: - icc_libtiff = img.info.get("icc_profile") - self.assertIsNotNone(icc_libtiff) - TiffImagePlugin.READ_LIBTIFF = False - self.assertEqual(icc, icc_libtiff) - - def test_multipage_compression(self): - im = Image.open("Tests/images/compression.tif") - - im.seek(0) - self.assertEqual(im._compression, "tiff_ccitt") - self.assertEqual(im.size, (10, 10)) - - im.seek(1) - self.assertEqual(im._compression, "packbits") - self.assertEqual(im.size, (10, 10)) - im.load() - - im.seek(0) - self.assertEqual(im._compression, "tiff_ccitt") - self.assertEqual(im.size, (10, 10)) - im.load() - - def test_save_tiff_with_jpegtables(self): - # Arrange - outfile = self.tempfile("temp.tif") - - # Created with ImageMagick: convert hopper.jpg hopper_jpg.tif - # Contains JPEGTables (347) tag - infile = "Tests/images/hopper_jpg.tif" - im = Image.open(infile) - - # Act / Assert - # Should not raise UnicodeDecodeError or anything else - im.save(outfile) - - def test_16bit_RGB_tiff(self): - im = Image.open("Tests/images/tiff_16bit_RGB.tiff") - - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (100, 40)) - self.assertEqual( - im.tile, - [ - ( - "libtiff", - (0, 0, 100, 40), - 0, - ("RGB;16N", "tiff_adobe_deflate", False, 8), - ) - ], - ) - im.load() - - self.assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGB_target.png") - - def test_16bit_RGBa_tiff(self): - im = Image.open("Tests/images/tiff_16bit_RGBa.tiff") - - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (100, 40)) - self.assertEqual( - im.tile, - [("libtiff", (0, 0, 100, 40), 0, ("RGBa;16N", "tiff_lzw", False, 38236))], - ) - im.load() - - self.assert_image_equal_tofile(im, "Tests/images/tiff_16bit_RGBa_target.png") - - def test_gimp_tiff(self): - # Read TIFF JPEG images from GIMP [@PIL168] - - codecs = dir(Image.core) - if "jpeg_decoder" not in codecs: - self.skipTest("jpeg support not available") - - filename = "Tests/images/pil168.tif" - im = Image.open(filename) - - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (256, 256)) - self.assertEqual( - im.tile, [("libtiff", (0, 0, 256, 256), 0, ("RGB", "jpeg", False, 5122))] - ) - im.load() - - self.assert_image_equal_tofile(im, "Tests/images/pil168.png") - - def test_sampleformat(self): - # https://github.com/python-pillow/Pillow/issues/1466 - im = Image.open("Tests/images/copyleft.tiff") - self.assertEqual(im.mode, "RGB") - - self.assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB") - - def test_lzw(self): - im = Image.open("Tests/images/hopper_lzw.tif") - - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "TIFF") - im2 = hopper() - self.assert_image_similar(im, im2, 5) - - def test_strip_cmyk_jpeg(self): - infile = "Tests/images/tiff_strip_cmyk_jpeg.tif" - im = Image.open(infile) - - self.assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5) - - def test_strip_cmyk_16l_jpeg(self): - infile = "Tests/images/tiff_strip_cmyk_16l_jpeg.tif" - im = Image.open(infile) - - self.assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5) - - def test_strip_ycbcr_jpeg_2x2_sampling(self): - infile = "Tests/images/tiff_strip_ycbcr_jpeg_2x2_sampling.tif" - im = Image.open(infile) - - self.assert_image_similar_tofile(im, "Tests/images/flower.jpg", 0.5) - - def test_strip_ycbcr_jpeg_1x1_sampling(self): - infile = "Tests/images/tiff_strip_ycbcr_jpeg_1x1_sampling.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile(im, "Tests/images/flower2.jpg") - - def test_tiled_cmyk_jpeg(self): - infile = "Tests/images/tiff_tiled_cmyk_jpeg.tif" - im = Image.open(infile) - - self.assert_image_similar_tofile(im, "Tests/images/pil_sample_cmyk.jpg", 0.5) - - def test_tiled_ycbcr_jpeg_1x1_sampling(self): - infile = "Tests/images/tiff_tiled_ycbcr_jpeg_1x1_sampling.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile(im, "Tests/images/flower2.jpg") - - def test_tiled_ycbcr_jpeg_2x2_sampling(self): - infile = "Tests/images/tiff_tiled_ycbcr_jpeg_2x2_sampling.tif" - im = Image.open(infile) - - self.assert_image_similar_tofile(im, "Tests/images/flower.jpg", 0.5) - - def test_old_style_jpeg(self): - infile = "Tests/images/old-style-jpeg-compression.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile( - im, "Tests/images/old-style-jpeg-compression.png" - ) diff --git a/Tests/test_file_libtiff_small.py b/Tests/test_file_libtiff_small.py deleted file mode 100644 index 0db37c7ea95..00000000000 --- a/Tests/test_file_libtiff_small.py +++ /dev/null @@ -1,47 +0,0 @@ -from PIL import Image - -from .test_file_libtiff import LibTiffTestCase - - -class TestFileLibTiffSmall(LibTiffTestCase): - - """ The small lena image was failing on open in the libtiff - decoder because the file pointer was set to the wrong place - by a spurious seek. It wasn't failing with the byteio method. - - It was fixed by forcing an lseek to the beginning of the - file just before reading in libtiff. These tests remain - to ensure that it stays fixed. """ - - def test_g4_hopper_file(self): - """Testing the open file load path""" - - test_file = "Tests/images/hopper_g4.tif" - with open(test_file, "rb") as f: - im = Image.open(f) - - self.assertEqual(im.size, (128, 128)) - self._assert_noerr(im) - - def test_g4_hopper_bytesio(self): - """Testing the bytesio loading code path""" - from io import BytesIO - - test_file = "Tests/images/hopper_g4.tif" - s = BytesIO() - with open(test_file, "rb") as f: - s.write(f.read()) - s.seek(0) - im = Image.open(s) - - self.assertEqual(im.size, (128, 128)) - self._assert_noerr(im) - - def test_g4_hopper(self): - """The 128x128 lena image failed for some reason.""" - - test_file = "Tests/images/hopper_g4.tif" - im = Image.open(test_file) - - self.assertEqual(im.size, (128, 128)) - self._assert_noerr(im) diff --git a/Tests/test_file_mcidas.py b/Tests/test_file_mcidas.py deleted file mode 100644 index acc4ddb9191..00000000000 --- a/Tests/test_file_mcidas.py +++ /dev/null @@ -1,28 +0,0 @@ -from PIL import Image, McIdasImagePlugin - -from .helper import PillowTestCase - - -class TestFileMcIdas(PillowTestCase): - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, McIdasImagePlugin.McIdasImageFile, invalid_file) - - def test_valid_file(self): - # Arrange - # https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8 - # https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/ - test_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.ara" - saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png" - - # Act - im = Image.open(test_file) - im.load() - - # Assert - self.assertEqual(im.format, "MCIDAS") - self.assertEqual(im.mode, "I") - self.assertEqual(im.size, (1800, 400)) - im2 = Image.open(saved_file) - self.assert_image_equal(im, im2) diff --git a/Tests/test_file_mic.py b/Tests/test_file_mic.py deleted file mode 100644 index 5ec110c80b0..00000000000 --- a/Tests/test_file_mic.py +++ /dev/null @@ -1,63 +0,0 @@ -from PIL import Image, ImagePalette, features - -from .helper import PillowTestCase, hopper, unittest - -try: - from PIL import MicImagePlugin -except ImportError: - olefile_installed = False -else: - olefile_installed = True - -TEST_FILE = "Tests/images/hopper.mic" - - -@unittest.skipUnless(olefile_installed, "olefile package not installed") -@unittest.skipUnless(features.check("libtiff"), "libtiff not installed") -class TestFileMic(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_FILE) - im.load() - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "MIC") - - # Adjust for the gamma of 2.2 encoded into the file - lut = ImagePalette.make_gamma_lut(1 / 2.2) - im = Image.merge("RGBA", [chan.point(lut) for chan in im.split()]) - - im2 = hopper("RGBA") - self.assert_image_similar(im, im2, 10) - - def test_n_frames(self): - im = Image.open(TEST_FILE) - - self.assertEqual(im.n_frames, 1) - - def test_is_animated(self): - im = Image.open(TEST_FILE) - - self.assertFalse(im.is_animated) - - def test_tell(self): - im = Image.open(TEST_FILE) - - self.assertEqual(im.tell(), 0) - - def test_seek(self): - im = Image.open(TEST_FILE) - - im.seek(0) - self.assertEqual(im.tell(), 0) - - self.assertRaises(EOFError, im.seek, 99) - self.assertEqual(im.tell(), 0) - - def test_invalid_file(self): - # Test an invalid OLE file - invalid_file = "Tests/images/flower.jpg" - self.assertRaises(SyntaxError, MicImagePlugin.MicImageFile, invalid_file) - - # Test a valid OLE file, but not a MIC file - ole_file = "Tests/images/test-ole-file.doc" - self.assertRaises(SyntaxError, MicImagePlugin.MicImageFile, ole_file) diff --git a/Tests/test_file_mpo.py b/Tests/test_file_mpo.py deleted file mode 100644 index 82ecf64574f..00000000000 --- a/Tests/test_file_mpo.py +++ /dev/null @@ -1,174 +0,0 @@ -from io import BytesIO - -from PIL import Image - -from .helper import PillowTestCase - -test_files = ["Tests/images/sugarshack.mpo", "Tests/images/frozenpond.mpo"] - - -class TestFileMpo(PillowTestCase): - def setUp(self): - codecs = dir(Image.core) - if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: - self.skipTest("jpeg support not available") - - def frame_roundtrip(self, im, **options): - # Note that for now, there is no MPO saving functionality - out = BytesIO() - im.save(out, "MPO", **options) - test_bytes = out.tell() - out.seek(0) - im = Image.open(out) - im.bytes = test_bytes # for testing only - return im - - def test_sanity(self): - for test_file in test_files: - im = Image.open(test_file) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (640, 480)) - self.assertEqual(im.format, "MPO") - - def test_unclosed_file(self): - def open(): - im = Image.open(test_files[0]) - im.load() - - self.assert_warning(None, open) - - def test_app(self): - for test_file in test_files: - # Test APP/COM reader (@PIL135) - im = Image.open(test_file) - self.assertEqual(im.applist[0][0], "APP1") - self.assertEqual(im.applist[1][0], "APP2") - self.assertEqual( - im.applist[1][1][:16], b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00" - ) - self.assertEqual(len(im.applist), 2) - - def test_exif(self): - for test_file in test_files: - im = Image.open(test_file) - info = im._getexif() - self.assertEqual(info[272], "Nintendo 3DS") - self.assertEqual(info[296], 2) - self.assertEqual(info[34665], 188) - - def test_frame_size(self): - # This image has been hexedited to contain a different size - # in the EXIF data of the second frame - im = Image.open("Tests/images/sugarshack_frame_size.mpo") - self.assertEqual(im.size, (640, 480)) - - im.seek(1) - self.assertEqual(im.size, (680, 480)) - - def test_parallax(self): - # Nintendo - im = Image.open("Tests/images/sugarshack.mpo") - exif = im.getexif() - self.assertEqual(exif.get_ifd(0x927C)[0x1101]["Parallax"], -44.798187255859375) - - # Fujifilm - im = Image.open("Tests/images/fujifilm.mpo") - im.seek(1) - exif = im.getexif() - self.assertEqual(exif.get_ifd(0x927C)[0xB211], -3.125) - - def test_mp(self): - for test_file in test_files: - im = Image.open(test_file) - mpinfo = im._getmp() - self.assertEqual(mpinfo[45056], b"0100") - self.assertEqual(mpinfo[45057], 2) - - def test_mp_offset(self): - # This image has been manually hexedited to have an IFD offset of 10 - # in APP2 data, in contrast to normal 8 - im = Image.open("Tests/images/sugarshack_ifd_offset.mpo") - mpinfo = im._getmp() - self.assertEqual(mpinfo[45056], b"0100") - self.assertEqual(mpinfo[45057], 2) - - def test_mp_attribute(self): - for test_file in test_files: - im = Image.open(test_file) - mpinfo = im._getmp() - frameNumber = 0 - for mpentry in mpinfo[45058]: - mpattr = mpentry["Attribute"] - if frameNumber: - self.assertFalse(mpattr["RepresentativeImageFlag"]) - else: - self.assertTrue(mpattr["RepresentativeImageFlag"]) - self.assertFalse(mpattr["DependentParentImageFlag"]) - self.assertFalse(mpattr["DependentChildImageFlag"]) - self.assertEqual(mpattr["ImageDataFormat"], "JPEG") - self.assertEqual(mpattr["MPType"], "Multi-Frame Image: (Disparity)") - self.assertEqual(mpattr["Reserved"], 0) - frameNumber += 1 - - def test_seek(self): - for test_file in test_files: - im = Image.open(test_file) - self.assertEqual(im.tell(), 0) - # prior to first image raises an error, both blatant and borderline - self.assertRaises(EOFError, im.seek, -1) - self.assertRaises(EOFError, im.seek, -523) - # after the final image raises an error, - # both blatant and borderline - self.assertRaises(EOFError, im.seek, 2) - self.assertRaises(EOFError, im.seek, 523) - # bad calls shouldn't change the frame - self.assertEqual(im.tell(), 0) - # this one will work - im.seek(1) - self.assertEqual(im.tell(), 1) - # and this one, too - im.seek(0) - self.assertEqual(im.tell(), 0) - - def test_n_frames(self): - im = Image.open("Tests/images/sugarshack.mpo") - self.assertEqual(im.n_frames, 2) - self.assertTrue(im.is_animated) - - def test_eoferror(self): - im = Image.open("Tests/images/sugarshack.mpo") - n_frames = im.n_frames - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_image_grab(self): - for test_file in test_files: - im = Image.open(test_file) - self.assertEqual(im.tell(), 0) - im0 = im.tobytes() - im.seek(1) - self.assertEqual(im.tell(), 1) - im1 = im.tobytes() - im.seek(0) - self.assertEqual(im.tell(), 0) - im02 = im.tobytes() - self.assertEqual(im0, im02) - self.assertNotEqual(im0, im1) - - def test_save(self): - # Note that only individual frames can be saved at present - for test_file in test_files: - im = Image.open(test_file) - self.assertEqual(im.tell(), 0) - jpg0 = self.frame_roundtrip(im) - self.assert_image_similar(im, jpg0, 30) - im.seek(1) - self.assertEqual(im.tell(), 1) - jpg1 = self.frame_roundtrip(im) - self.assert_image_similar(im, jpg1, 30) diff --git a/Tests/test_file_msp.py b/Tests/test_file_msp.py deleted file mode 100644 index 5d512047b93..00000000000 --- a/Tests/test_file_msp.py +++ /dev/null @@ -1,78 +0,0 @@ -import os - -from PIL import Image, MspImagePlugin - -from .helper import PillowTestCase, hopper, unittest - -TEST_FILE = "Tests/images/hopper.msp" -EXTRA_DIR = "Tests/images/picins" -YA_EXTRA_DIR = "Tests/images/msp" - - -class TestFileMsp(PillowTestCase): - def test_sanity(self): - test_file = self.tempfile("temp.msp") - - hopper("1").save(test_file) - - im = Image.open(test_file) - im.load() - self.assertEqual(im.mode, "1") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "MSP") - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, MspImagePlugin.MspImageFile, invalid_file) - - def test_bad_checksum(self): - # Arrange - # This was created by forcing Pillow to save with checksum=0 - bad_checksum = "Tests/images/hopper_bad_checksum.msp" - - # Act / Assert - self.assertRaises(SyntaxError, MspImagePlugin.MspImageFile, bad_checksum) - - def test_open_windows_v1(self): - # Arrange - # Act - im = Image.open(TEST_FILE) - - # Assert - self.assert_image_equal(im, hopper("1")) - self.assertIsInstance(im, MspImagePlugin.MspImageFile) - - def _assert_file_image_equal(self, source_path, target_path): - with Image.open(source_path) as im: - target = Image.open(target_path) - self.assert_image_equal(im, target) - - @unittest.skipIf(not os.path.exists(EXTRA_DIR), "Extra image files not installed") - def test_open_windows_v2(self): - - files = ( - os.path.join(EXTRA_DIR, f) - for f in os.listdir(EXTRA_DIR) - if os.path.splitext(f)[1] == ".msp" - ) - for path in files: - self._assert_file_image_equal(path, path.replace(".msp", ".png")) - - @unittest.skipIf( - not os.path.exists(YA_EXTRA_DIR), "Even More Extra image files not installed" - ) - def test_msp_v2(self): - for f in os.listdir(YA_EXTRA_DIR): - if ".MSP" not in f: - continue - path = os.path.join(YA_EXTRA_DIR, f) - self._assert_file_image_equal(path, path.replace(".MSP", ".png")) - - def test_cannot_save_wrong_mode(self): - # Arrange - im = hopper() - filename = self.tempfile("temp.msp") - - # Act/Assert - self.assertRaises(IOError, im.save, filename) diff --git a/Tests/test_file_palm.py b/Tests/test_file_palm.py deleted file mode 100644 index fbfd8966152..00000000000 --- a/Tests/test_file_palm.py +++ /dev/null @@ -1,61 +0,0 @@ -import os.path - -from .helper import PillowTestCase, hopper, imagemagick_available - - -class TestFilePalm(PillowTestCase): - _roundtrip = imagemagick_available() - - def helper_save_as_palm(self, mode): - # Arrange - im = hopper(mode) - outfile = self.tempfile("temp_" + mode + ".palm") - - # Act - im.save(outfile) - - # Assert - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - - def roundtrip(self, mode): - if not self._roundtrip: - return - - im = hopper(mode) - outfile = self.tempfile("temp.palm") - - im.save(outfile) - converted = self.open_withImagemagick(outfile) - self.assert_image_equal(converted, im) - - def test_monochrome(self): - # Arrange - mode = "1" - - # Act / Assert - self.helper_save_as_palm(mode) - self.roundtrip(mode) - - def test_p_mode(self): - # Arrange - mode = "P" - - # Act / Assert - self.helper_save_as_palm(mode) - self.skipKnownBadTest("Palm P image is wrong") - self.roundtrip(mode) - - def test_l_ioerror(self): - # Arrange - mode = "L" - - # Act / Assert - self.assertRaises(IOError, self.helper_save_as_palm, mode) - - def test_rgb_ioerror(self): - # Arrange - mode = "RGB" - - # Act / Assert - self.assertRaises(IOError, self.helper_save_as_palm, mode) diff --git a/Tests/test_file_pcd.py b/Tests/test_file_pcd.py deleted file mode 100644 index b23328ba537..00000000000 --- a/Tests/test_file_pcd.py +++ /dev/null @@ -1,18 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestFilePcd(PillowTestCase): - def test_load_raw(self): - im = Image.open("Tests/images/hopper.pcd") - im.load() # should not segfault. - - # Note that this image was created with a resized hopper - # image, which was then converted to pcd with imagemagick - # and the colors are wonky in Pillow. It's unclear if this - # is a pillow or a convert issue, as other images not generated - # from convert look find on pillow and not imagemagick. - - # target = hopper().resize((768,512)) - # self.assert_image_similar(im, target, 10) diff --git a/Tests/test_file_pcx.py b/Tests/test_file_pcx.py deleted file mode 100644 index eb2c7d6112b..00000000000 --- a/Tests/test_file_pcx.py +++ /dev/null @@ -1,129 +0,0 @@ -from PIL import Image, ImageFile, PcxImagePlugin - -from .helper import PillowTestCase, hopper - - -class TestFilePcx(PillowTestCase): - def _roundtrip(self, im): - f = self.tempfile("temp.pcx") - im.save(f) - im2 = Image.open(f) - - self.assertEqual(im2.mode, im.mode) - self.assertEqual(im2.size, im.size) - self.assertEqual(im2.format, "PCX") - self.assertEqual(im2.get_format_mimetype(), "image/x-pcx") - self.assert_image_equal(im2, im) - - def test_sanity(self): - for mode in ("1", "L", "P", "RGB"): - self._roundtrip(hopper(mode)) - - # Test an unsupported mode - f = self.tempfile("temp.pcx") - im = hopper("RGBA") - self.assertRaises(ValueError, im.save, f) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, PcxImagePlugin.PcxImageFile, invalid_file) - - def test_odd(self): - # see issue #523, odd sized images should have a stride that's even. - # not that imagemagick or gimp write pcx that way. - # we were not handling properly. - for mode in ("1", "L", "P", "RGB"): - # larger, odd sized images are better here to ensure that - # we handle interrupted scan lines properly. - self._roundtrip(hopper(mode).resize((511, 511))) - - def test_pil184(self): - # Check reading of files where xmin/xmax is not zero. - - test_file = "Tests/images/pil184.pcx" - im = Image.open(test_file) - - self.assertEqual(im.size, (447, 144)) - self.assertEqual(im.tile[0][1], (0, 0, 447, 144)) - - # Make sure all pixels are either 0 or 255. - self.assertEqual(im.histogram()[0] + im.histogram()[255], 447 * 144) - - def test_1px_width(self): - im = Image.new("L", (1, 256)) - px = im.load() - for y in range(256): - px[0, y] = y - self._roundtrip(im) - - def test_large_count(self): - im = Image.new("L", (256, 1)) - px = im.load() - for x in range(256): - px[x, 0] = x // 67 * 67 - self._roundtrip(im) - - def _test_buffer_overflow(self, im, size=1024): - _last = ImageFile.MAXBLOCK - ImageFile.MAXBLOCK = size - try: - self._roundtrip(im) - finally: - ImageFile.MAXBLOCK = _last - - def test_break_in_count_overflow(self): - im = Image.new("L", (256, 5)) - px = im.load() - for y in range(4): - for x in range(256): - px[x, y] = x % 128 - self._test_buffer_overflow(im) - - def test_break_one_in_loop(self): - im = Image.new("L", (256, 5)) - px = im.load() - for y in range(5): - for x in range(256): - px[x, y] = x % 128 - self._test_buffer_overflow(im) - - def test_break_many_in_loop(self): - im = Image.new("L", (256, 5)) - px = im.load() - for y in range(4): - for x in range(256): - px[x, y] = x % 128 - for x in range(8): - px[x, 4] = 16 - self._test_buffer_overflow(im) - - def test_break_one_at_end(self): - im = Image.new("L", (256, 5)) - px = im.load() - for y in range(5): - for x in range(256): - px[x, y] = x % 128 - px[0, 3] = 128 + 64 - self._test_buffer_overflow(im) - - def test_break_many_at_end(self): - im = Image.new("L", (256, 5)) - px = im.load() - for y in range(5): - for x in range(256): - px[x, y] = x % 128 - for x in range(4): - px[x * 2, 3] = 128 + 64 - px[x + 256 - 4, 3] = 0 - self._test_buffer_overflow(im) - - def test_break_padding(self): - im = Image.new("L", (257, 5)) - px = im.load() - for y in range(5): - for x in range(257): - px[x, y] = x % 128 - for x in range(5): - px[x, 3] = 0 - self._test_buffer_overflow(im) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py deleted file mode 100644 index 25c2f6bf6a6..00000000000 --- a/Tests/test_file_pdf.py +++ /dev/null @@ -1,279 +0,0 @@ -import io -import os -import os.path -import tempfile -import time - -from PIL import Image, PdfParser - -from .helper import PillowTestCase, hopper - - -class TestFilePdf(PillowTestCase): - def helper_save_as_pdf(self, mode, **kwargs): - # Arrange - im = hopper(mode) - outfile = self.tempfile("temp_" + mode + ".pdf") - - # Act - im.save(outfile, **kwargs) - - # Assert - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - with PdfParser.PdfParser(outfile) as pdf: - if kwargs.get("append_images", False) or kwargs.get("append", False): - self.assertGreater(len(pdf.pages), 1) - else: - self.assertGreater(len(pdf.pages), 0) - with open(outfile, "rb") as fp: - contents = fp.read() - size = tuple( - int(d) - for d in contents.split(b"/MediaBox [ 0 0 ")[1].split(b"]")[0].split() - ) - self.assertEqual(im.size, size) - - return outfile - - def test_monochrome(self): - # Arrange - mode = "1" - - # Act / Assert - self.helper_save_as_pdf(mode) - - def test_greyscale(self): - # Arrange - mode = "L" - - # Act / Assert - self.helper_save_as_pdf(mode) - - def test_rgb(self): - # Arrange - mode = "RGB" - - # Act / Assert - self.helper_save_as_pdf(mode) - - def test_p_mode(self): - # Arrange - mode = "P" - - # Act / Assert - self.helper_save_as_pdf(mode) - - def test_cmyk_mode(self): - # Arrange - mode = "CMYK" - - # Act / Assert - self.helper_save_as_pdf(mode) - - def test_unsupported_mode(self): - im = hopper("LA") - outfile = self.tempfile("temp_LA.pdf") - - self.assertRaises(ValueError, im.save, outfile) - - def test_save_all(self): - # Single frame image - self.helper_save_as_pdf("RGB", save_all=True) - - # Multiframe image - im = Image.open("Tests/images/dispose_bgnd.gif") - - outfile = self.tempfile("temp.pdf") - im.save(outfile, save_all=True) - - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - - # Append images - ims = [hopper()] - im.copy().save(outfile, save_all=True, append_images=ims) - - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - - # Test appending using a generator - def imGenerator(ims): - for im in ims: - yield im - - im.save(outfile, save_all=True, append_images=imGenerator(ims)) - - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - - # Append JPEG images - jpeg = Image.open("Tests/images/flower.jpg") - jpeg.save(outfile, save_all=True, append_images=[jpeg.copy()]) - - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - - def test_multiframe_normal_save(self): - # Test saving a multiframe image without save_all - im = Image.open("Tests/images/dispose_bgnd.gif") - - outfile = self.tempfile("temp.pdf") - im.save(outfile) - - self.assertTrue(os.path.isfile(outfile)) - self.assertGreater(os.path.getsize(outfile), 0) - - def test_pdf_open(self): - # fail on a buffer full of null bytes - self.assertRaises( - PdfParser.PdfFormatError, PdfParser.PdfParser, buf=bytearray(65536) - ) - - # make an empty PDF object - with PdfParser.PdfParser() as empty_pdf: - self.assertEqual(len(empty_pdf.pages), 0) - self.assertEqual(len(empty_pdf.info), 0) - self.assertFalse(empty_pdf.should_close_buf) - self.assertFalse(empty_pdf.should_close_file) - - # make a PDF file - pdf_filename = self.helper_save_as_pdf("RGB") - - # open the PDF file - with PdfParser.PdfParser(filename=pdf_filename) as hopper_pdf: - self.assertEqual(len(hopper_pdf.pages), 1) - self.assertTrue(hopper_pdf.should_close_buf) - self.assertTrue(hopper_pdf.should_close_file) - - # read a PDF file from a buffer with a non-zero offset - with open(pdf_filename, "rb") as f: - content = b"xyzzy" + f.read() - with PdfParser.PdfParser(buf=content, start_offset=5) as hopper_pdf: - self.assertEqual(len(hopper_pdf.pages), 1) - self.assertFalse(hopper_pdf.should_close_buf) - self.assertFalse(hopper_pdf.should_close_file) - - # read a PDF file from an already open file - with open(pdf_filename, "rb") as f: - with PdfParser.PdfParser(f=f) as hopper_pdf: - self.assertEqual(len(hopper_pdf.pages), 1) - self.assertTrue(hopper_pdf.should_close_buf) - self.assertFalse(hopper_pdf.should_close_file) - - def test_pdf_append_fails_on_nonexistent_file(self): - im = hopper("RGB") - temp_dir = tempfile.mkdtemp() - try: - self.assertRaises( - IOError, im.save, os.path.join(temp_dir, "nonexistent.pdf"), append=True - ) - finally: - os.rmdir(temp_dir) - - def check_pdf_pages_consistency(self, pdf): - pages_info = pdf.read_indirect(pdf.pages_ref) - self.assertNotIn(b"Parent", pages_info) - self.assertIn(b"Kids", pages_info) - kids_not_used = pages_info[b"Kids"] - for page_ref in pdf.pages: - while True: - if page_ref in kids_not_used: - kids_not_used.remove(page_ref) - page_info = pdf.read_indirect(page_ref) - self.assertIn(b"Parent", page_info) - page_ref = page_info[b"Parent"] - if page_ref == pdf.pages_ref: - break - self.assertEqual(pdf.pages_ref, page_info[b"Parent"]) - self.assertEqual(kids_not_used, []) - - def test_pdf_append(self): - # make a PDF file - pdf_filename = self.helper_save_as_pdf("RGB", producer="PdfParser") - - # open it, check pages and info - with PdfParser.PdfParser(pdf_filename, mode="r+b") as pdf: - self.assertEqual(len(pdf.pages), 1) - self.assertEqual(len(pdf.info), 4) - self.assertEqual( - pdf.info.Title, os.path.splitext(os.path.basename(pdf_filename))[0] - ) - self.assertEqual(pdf.info.Producer, "PdfParser") - self.assertIn(b"CreationDate", pdf.info) - self.assertIn(b"ModDate", pdf.info) - self.check_pdf_pages_consistency(pdf) - - # append some info - pdf.info.Title = "abc" - pdf.info.Author = "def" - pdf.info.Subject = u"ghi\uABCD" - pdf.info.Keywords = "qw)e\\r(ty" - pdf.info.Creator = "hopper()" - pdf.start_writing() - pdf.write_xref_and_trailer() - - # open it again, check pages and info again - with PdfParser.PdfParser(pdf_filename) as pdf: - self.assertEqual(len(pdf.pages), 1) - self.assertEqual(len(pdf.info), 8) - self.assertEqual(pdf.info.Title, "abc") - self.assertIn(b"CreationDate", pdf.info) - self.assertIn(b"ModDate", pdf.info) - self.check_pdf_pages_consistency(pdf) - - # append two images - mode_CMYK = hopper("CMYK") - mode_P = hopper("P") - mode_CMYK.save(pdf_filename, append=True, save_all=True, append_images=[mode_P]) - - # open the PDF again, check pages and info again - with PdfParser.PdfParser(pdf_filename) as pdf: - self.assertEqual(len(pdf.pages), 3) - self.assertEqual(len(pdf.info), 8) - self.assertEqual(PdfParser.decode_text(pdf.info[b"Title"]), "abc") - self.assertEqual(pdf.info.Title, "abc") - self.assertEqual(pdf.info.Producer, "PdfParser") - self.assertEqual(pdf.info.Keywords, "qw)e\\r(ty") - self.assertEqual(pdf.info.Subject, u"ghi\uABCD") - self.assertIn(b"CreationDate", pdf.info) - self.assertIn(b"ModDate", pdf.info) - self.check_pdf_pages_consistency(pdf) - - def test_pdf_info(self): - # make a PDF file - pdf_filename = self.helper_save_as_pdf( - "RGB", - title="title", - author="author", - subject="subject", - keywords="keywords", - creator="creator", - producer="producer", - creationDate=time.strptime("2000", "%Y"), - modDate=time.strptime("2001", "%Y"), - ) - - # open it, check pages and info - with PdfParser.PdfParser(pdf_filename) as pdf: - self.assertEqual(len(pdf.info), 8) - self.assertEqual(pdf.info.Title, "title") - self.assertEqual(pdf.info.Author, "author") - self.assertEqual(pdf.info.Subject, "subject") - self.assertEqual(pdf.info.Keywords, "keywords") - self.assertEqual(pdf.info.Creator, "creator") - self.assertEqual(pdf.info.Producer, "producer") - self.assertEqual(pdf.info.CreationDate, time.strptime("2000", "%Y")) - self.assertEqual(pdf.info.ModDate, time.strptime("2001", "%Y")) - self.check_pdf_pages_consistency(pdf) - - def test_pdf_append_to_bytesio(self): - im = hopper("RGB") - f = io.BytesIO() - im.save(f, format="PDF") - initial_size = len(f.getvalue()) - self.assertGreater(initial_size, 0) - im = hopper("P") - f = io.BytesIO(f.getvalue()) - im.save(f, format="PDF", append=True) - self.assertGreater(len(f.getvalue()), initial_size) diff --git a/Tests/test_file_pixar.py b/Tests/test_file_pixar.py deleted file mode 100644 index c744932d437..00000000000 --- a/Tests/test_file_pixar.py +++ /dev/null @@ -1,23 +0,0 @@ -from PIL import Image, PixarImagePlugin - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/hopper.pxr" - - -class TestFilePixar(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_FILE) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "PIXAR") - self.assertIsNone(im.get_format_mimetype()) - - im2 = hopper() - self.assert_image_similar(im, im2, 4.8) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, PixarImagePlugin.PixarImageFile, invalid_file) diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py deleted file mode 100644 index 6d76a6caa7c..00000000000 --- a/Tests/test_file_png.py +++ /dev/null @@ -1,677 +0,0 @@ -import sys -import zlib -from io import BytesIO - -from PIL import Image, ImageFile, PngImagePlugin -from PIL._util import py3 - -from .helper import PillowLeakTestCase, PillowTestCase, hopper, unittest - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - -codecs = dir(Image.core) - - -# sample png stream - -TEST_PNG_FILE = "Tests/images/hopper.png" - -# stuff to create inline PNG images - -MAGIC = PngImagePlugin._MAGIC - - -def chunk(cid, *data): - test_file = BytesIO() - PngImagePlugin.putchunk(*(test_file, cid) + data) - return test_file.getvalue() - - -o32 = PngImagePlugin.o32 - -IHDR = chunk(b"IHDR", o32(1), o32(1), b"\x08\x02", b"\0\0\0") -IDAT = chunk(b"IDAT") -IEND = chunk(b"IEND") - -HEAD = MAGIC + IHDR -TAIL = IDAT + IEND - - -def load(data): - return Image.open(BytesIO(data)) - - -def roundtrip(im, **options): - out = BytesIO() - im.save(out, "PNG", **options) - out.seek(0) - return Image.open(out) - - -class TestFilePng(PillowTestCase): - def setUp(self): - if "zip_encoder" not in codecs or "zip_decoder" not in codecs: - self.skipTest("zip/deflate support not available") - - def get_chunks(self, filename): - chunks = [] - with open(filename, "rb") as fp: - fp.read(8) - with PngImagePlugin.PngStream(fp) as png: - while True: - cid, pos, length = png.read() - chunks.append(cid) - try: - s = png.call(cid, pos, length) - except EOFError: - break - png.crc(cid, s) - return chunks - - def test_sanity(self): - - # internal version number - self.assertRegex(Image.core.zlib_version, r"\d+\.\d+\.\d+(\.\d+)?$") - - test_file = self.tempfile("temp.png") - - hopper("RGB").save(test_file) - - im = Image.open(test_file) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "PNG") - self.assertEqual(im.get_format_mimetype(), "image/png") - - for mode in ["1", "L", "P", "RGB", "I", "I;16"]: - im = hopper(mode) - im.save(test_file) - reloaded = Image.open(test_file) - if mode == "I;16": - reloaded = reloaded.convert(mode) - self.assert_image_equal(reloaded, im) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, PngImagePlugin.PngImageFile, invalid_file) - - def test_broken(self): - # Check reading of totally broken files. In this case, the test - # file was checked into Subversion as a text file. - - test_file = "Tests/images/broken.png" - self.assertRaises(IOError, Image.open, test_file) - - def test_bad_text(self): - # Make sure PIL can read malformed tEXt chunks (@PIL152) - - im = load(HEAD + chunk(b"tEXt") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"tEXt", b"spam") + TAIL) - self.assertEqual(im.info, {"spam": ""}) - - im = load(HEAD + chunk(b"tEXt", b"spam\0") + TAIL) - self.assertEqual(im.info, {"spam": ""}) - - im = load(HEAD + chunk(b"tEXt", b"spam\0egg") + TAIL) - self.assertEqual(im.info, {"spam": "egg"}) - - im = load(HEAD + chunk(b"tEXt", b"spam\0egg\0") + TAIL) - self.assertEqual(im.info, {"spam": "egg\x00"}) - - def test_bad_ztxt(self): - # Test reading malformed zTXt chunks (python-pillow/Pillow#318) - - im = load(HEAD + chunk(b"zTXt") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"zTXt", b"spam") + TAIL) - self.assertEqual(im.info, {"spam": ""}) - - im = load(HEAD + chunk(b"zTXt", b"spam\0") + TAIL) - self.assertEqual(im.info, {"spam": ""}) - - im = load(HEAD + chunk(b"zTXt", b"spam\0\0") + TAIL) - self.assertEqual(im.info, {"spam": ""}) - - im = load(HEAD + chunk(b"zTXt", b"spam\0\0" + zlib.compress(b"egg")[:1]) + TAIL) - self.assertEqual(im.info, {"spam": ""}) - - im = load(HEAD + chunk(b"zTXt", b"spam\0\0" + zlib.compress(b"egg")) + TAIL) - self.assertEqual(im.info, {"spam": "egg"}) - - def test_bad_itxt(self): - - im = load(HEAD + chunk(b"iTXt") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"iTXt", b"spam") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"iTXt", b"spam\0") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"iTXt", b"spam\0\x02") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"iTXt", b"spam\0\0\0foo\0") + TAIL) - self.assertEqual(im.info, {}) - - im = load(HEAD + chunk(b"iTXt", b"spam\0\0\0en\0Spam\0egg") + TAIL) - self.assertEqual(im.info, {"spam": "egg"}) - self.assertEqual(im.info["spam"].lang, "en") - self.assertEqual(im.info["spam"].tkey, "Spam") - - im = load( - HEAD - + chunk(b"iTXt", b"spam\0\1\0en\0Spam\0" + zlib.compress(b"egg")[:1]) - + TAIL - ) - self.assertEqual(im.info, {"spam": ""}) - - im = load( - HEAD - + chunk(b"iTXt", b"spam\0\1\1en\0Spam\0" + zlib.compress(b"egg")) - + TAIL - ) - self.assertEqual(im.info, {}) - - im = load( - HEAD - + chunk(b"iTXt", b"spam\0\1\0en\0Spam\0" + zlib.compress(b"egg")) - + TAIL - ) - self.assertEqual(im.info, {"spam": "egg"}) - self.assertEqual(im.info["spam"].lang, "en") - self.assertEqual(im.info["spam"].tkey, "Spam") - - def test_interlace(self): - - test_file = "Tests/images/pil123p.png" - im = Image.open(test_file) - - self.assert_image(im, "P", (162, 150)) - self.assertTrue(im.info.get("interlace")) - - im.load() - - test_file = "Tests/images/pil123rgba.png" - im = Image.open(test_file) - - self.assert_image(im, "RGBA", (162, 150)) - self.assertTrue(im.info.get("interlace")) - - im.load() - - def test_load_transparent_p(self): - test_file = "Tests/images/pil123p.png" - im = Image.open(test_file) - - self.assert_image(im, "P", (162, 150)) - im = im.convert("RGBA") - self.assert_image(im, "RGBA", (162, 150)) - - # image has 124 unique alpha values - self.assertEqual(len(im.getchannel("A").getcolors()), 124) - - def test_load_transparent_rgb(self): - test_file = "Tests/images/rgb_trns.png" - im = Image.open(test_file) - self.assertEqual(im.info["transparency"], (0, 255, 52)) - - self.assert_image(im, "RGB", (64, 64)) - im = im.convert("RGBA") - self.assert_image(im, "RGBA", (64, 64)) - - # image has 876 transparent pixels - self.assertEqual(im.getchannel("A").getcolors()[0][0], 876) - - def test_save_p_transparent_palette(self): - in_file = "Tests/images/pil123p.png" - im = Image.open(in_file) - - # 'transparency' contains a byte string with the opacity for - # each palette entry - self.assertEqual(len(im.info["transparency"]), 256) - - test_file = self.tempfile("temp.png") - im.save(test_file) - - # check if saved image contains same transparency - im = Image.open(test_file) - self.assertEqual(len(im.info["transparency"]), 256) - - self.assert_image(im, "P", (162, 150)) - im = im.convert("RGBA") - self.assert_image(im, "RGBA", (162, 150)) - - # image has 124 unique alpha values - self.assertEqual(len(im.getchannel("A").getcolors()), 124) - - def test_save_p_single_transparency(self): - in_file = "Tests/images/p_trns_single.png" - im = Image.open(in_file) - - # pixel value 164 is full transparent - self.assertEqual(im.info["transparency"], 164) - self.assertEqual(im.getpixel((31, 31)), 164) - - test_file = self.tempfile("temp.png") - im.save(test_file) - - # check if saved image contains same transparency - im = Image.open(test_file) - self.assertEqual(im.info["transparency"], 164) - self.assertEqual(im.getpixel((31, 31)), 164) - self.assert_image(im, "P", (64, 64)) - im = im.convert("RGBA") - self.assert_image(im, "RGBA", (64, 64)) - - self.assertEqual(im.getpixel((31, 31)), (0, 255, 52, 0)) - - # image has 876 transparent pixels - self.assertEqual(im.getchannel("A").getcolors()[0][0], 876) - - def test_save_p_transparent_black(self): - # check if solid black image with full transparency - # is supported (check for #1838) - im = Image.new("RGBA", (10, 10), (0, 0, 0, 0)) - self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))]) - - im = im.convert("P") - test_file = self.tempfile("temp.png") - im.save(test_file) - - # check if saved image contains same transparency - im = Image.open(test_file) - self.assertEqual(len(im.info["transparency"]), 256) - self.assert_image(im, "P", (10, 10)) - im = im.convert("RGBA") - self.assert_image(im, "RGBA", (10, 10)) - self.assertEqual(im.getcolors(), [(100, (0, 0, 0, 0))]) - - def test_save_greyscale_transparency(self): - for mode, num_transparent in {"1": 1994, "L": 559, "I": 559}.items(): - in_file = "Tests/images/" + mode.lower() + "_trns.png" - im = Image.open(in_file) - self.assertEqual(im.mode, mode) - self.assertEqual(im.info["transparency"], 255) - - im_rgba = im.convert("RGBA") - self.assertEqual(im_rgba.getchannel("A").getcolors()[0][0], num_transparent) - - test_file = self.tempfile("temp.png") - im.save(test_file) - - test_im = Image.open(test_file) - self.assertEqual(test_im.mode, mode) - self.assertEqual(test_im.info["transparency"], 255) - self.assert_image_equal(im, test_im) - - test_im_rgba = test_im.convert("RGBA") - self.assertEqual( - test_im_rgba.getchannel("A").getcolors()[0][0], num_transparent - ) - - def test_save_rgb_single_transparency(self): - in_file = "Tests/images/caption_6_33_22.png" - im = Image.open(in_file) - - test_file = self.tempfile("temp.png") - im.save(test_file) - - def test_load_verify(self): - # Check open/load/verify exception (@PIL150) - - im = Image.open(TEST_PNG_FILE) - - # Assert that there is no unclosed file warning - self.assert_warning(None, im.verify) - - im = Image.open(TEST_PNG_FILE) - im.load() - self.assertRaises(RuntimeError, im.verify) - - def test_verify_struct_error(self): - # Check open/load/verify exception (#1755) - - # offsets to test, -10: breaks in i32() in read. (IOError) - # -13: breaks in crc, txt chunk. - # -14: malformed chunk - - for offset in (-10, -13, -14): - with open(TEST_PNG_FILE, "rb") as f: - test_file = f.read()[:offset] - - im = Image.open(BytesIO(test_file)) - self.assertIsNotNone(im.fp) - self.assertRaises((IOError, SyntaxError), im.verify) - - def test_verify_ignores_crc_error(self): - # check ignores crc errors in ancillary chunks - - chunk_data = chunk(b"tEXt", b"spam") - broken_crc_chunk_data = chunk_data[:-1] + b"q" # break CRC - - image_data = HEAD + broken_crc_chunk_data + TAIL - self.assertRaises(SyntaxError, PngImagePlugin.PngImageFile, BytesIO(image_data)) - - ImageFile.LOAD_TRUNCATED_IMAGES = True - try: - im = load(image_data) - self.assertIsNotNone(im) - finally: - ImageFile.LOAD_TRUNCATED_IMAGES = False - - def test_verify_not_ignores_crc_error_in_required_chunk(self): - # check does not ignore crc errors in required chunks - - image_data = MAGIC + IHDR[:-1] + b"q" + TAIL - - ImageFile.LOAD_TRUNCATED_IMAGES = True - try: - self.assertRaises( - SyntaxError, PngImagePlugin.PngImageFile, BytesIO(image_data) - ) - finally: - ImageFile.LOAD_TRUNCATED_IMAGES = False - - def test_roundtrip_dpi(self): - # Check dpi roundtripping - - im = Image.open(TEST_PNG_FILE) - - im = roundtrip(im, dpi=(100, 100)) - self.assertEqual(im.info["dpi"], (100, 100)) - - def test_load_dpi_rounding(self): - # Round up - im = Image.open(TEST_PNG_FILE) - self.assertEqual(im.info["dpi"], (96, 96)) - - # Round down - im = Image.open("Tests/images/icc_profile_none.png") - self.assertEqual(im.info["dpi"], (72, 72)) - - def test_save_dpi_rounding(self): - im = Image.open(TEST_PNG_FILE) - - im = roundtrip(im, dpi=(72.2, 72.2)) - self.assertEqual(im.info["dpi"], (72, 72)) - - im = roundtrip(im, dpi=(72.8, 72.8)) - self.assertEqual(im.info["dpi"], (73, 73)) - - def test_roundtrip_text(self): - # Check text roundtripping - - im = Image.open(TEST_PNG_FILE) - - info = PngImagePlugin.PngInfo() - info.add_text("TXT", "VALUE") - info.add_text("ZIP", "VALUE", zip=True) - - im = roundtrip(im, pnginfo=info) - self.assertEqual(im.info, {"TXT": "VALUE", "ZIP": "VALUE"}) - self.assertEqual(im.text, {"TXT": "VALUE", "ZIP": "VALUE"}) - - def test_roundtrip_itxt(self): - # Check iTXt roundtripping - - im = Image.new("RGB", (32, 32)) - info = PngImagePlugin.PngInfo() - info.add_itxt("spam", "Eggs", "en", "Spam") - info.add_text("eggs", PngImagePlugin.iTXt("Spam", "en", "Eggs"), zip=True) - - im = roundtrip(im, pnginfo=info) - self.assertEqual(im.info, {"spam": "Eggs", "eggs": "Spam"}) - self.assertEqual(im.text, {"spam": "Eggs", "eggs": "Spam"}) - self.assertEqual(im.text["spam"].lang, "en") - self.assertEqual(im.text["spam"].tkey, "Spam") - self.assertEqual(im.text["eggs"].lang, "en") - self.assertEqual(im.text["eggs"].tkey, "Eggs") - - def test_nonunicode_text(self): - # Check so that non-Unicode text is saved as a tEXt rather than iTXt - - im = Image.new("RGB", (32, 32)) - info = PngImagePlugin.PngInfo() - info.add_text("Text", "Ascii") - im = roundtrip(im, pnginfo=info) - self.assertIsInstance(im.info["Text"], str) - - def test_unicode_text(self): - # Check preservation of non-ASCII characters on Python 3 - # This cannot really be meaningfully tested on Python 2, - # since it didn't preserve charsets to begin with. - - def rt_text(value): - im = Image.new("RGB", (32, 32)) - info = PngImagePlugin.PngInfo() - info.add_text("Text", value) - im = roundtrip(im, pnginfo=info) - self.assertEqual(im.info, {"Text": value}) - - if py3: - rt_text(" Aa" + chr(0xA0) + chr(0xC4) + chr(0xFF)) # Latin1 - rt_text(chr(0x400) + chr(0x472) + chr(0x4FF)) # Cyrillic - # CJK: - rt_text(chr(0x4E00) + chr(0x66F0) + chr(0x9FBA) + chr(0x3042) + chr(0xAC00)) - rt_text("A" + chr(0xC4) + chr(0x472) + chr(0x3042)) # Combined - - def test_scary(self): - # Check reading of evil PNG file. For information, see: - # http://scary.beasts.org/security/CESA-2004-001.txt - # The first byte is removed from pngtest_bad.png - # to avoid classification as malware. - - with open("Tests/images/pngtest_bad.png.bin", "rb") as fd: - data = b"\x89" + fd.read() - - pngfile = BytesIO(data) - self.assertRaises(IOError, Image.open, pngfile) - - def test_trns_rgb(self): - # Check writing and reading of tRNS chunks for RGB images. - # Independent file sample provided by Sebastian Spaeth. - - test_file = "Tests/images/caption_6_33_22.png" - im = Image.open(test_file) - self.assertEqual(im.info["transparency"], (248, 248, 248)) - - # check saving transparency by default - im = roundtrip(im) - self.assertEqual(im.info["transparency"], (248, 248, 248)) - - im = roundtrip(im, transparency=(0, 1, 2)) - self.assertEqual(im.info["transparency"], (0, 1, 2)) - - def test_trns_p(self): - # Check writing a transparency of 0, issue #528 - im = hopper("P") - im.info["transparency"] = 0 - - f = self.tempfile("temp.png") - im.save(f) - - im2 = Image.open(f) - self.assertIn("transparency", im2.info) - - self.assert_image_equal(im2.convert("RGBA"), im.convert("RGBA")) - - def test_trns_null(self): - # Check reading images with null tRNS value, issue #1239 - test_file = "Tests/images/tRNS_null_1x1.png" - im = Image.open(test_file) - - self.assertEqual(im.info["transparency"], 0) - - def test_save_icc_profile(self): - im = Image.open("Tests/images/icc_profile_none.png") - self.assertIsNone(im.info["icc_profile"]) - - with_icc = Image.open("Tests/images/icc_profile.png") - expected_icc = with_icc.info["icc_profile"] - - im = roundtrip(im, icc_profile=expected_icc) - self.assertEqual(im.info["icc_profile"], expected_icc) - - def test_discard_icc_profile(self): - im = Image.open("Tests/images/icc_profile.png") - - im = roundtrip(im, icc_profile=None) - self.assertNotIn("icc_profile", im.info) - - def test_roundtrip_icc_profile(self): - im = Image.open("Tests/images/icc_profile.png") - expected_icc = im.info["icc_profile"] - - im = roundtrip(im) - self.assertEqual(im.info["icc_profile"], expected_icc) - - def test_roundtrip_no_icc_profile(self): - im = Image.open("Tests/images/icc_profile_none.png") - self.assertIsNone(im.info["icc_profile"]) - - im = roundtrip(im) - self.assertNotIn("icc_profile", im.info) - - def test_repr_png(self): - im = hopper() - - repr_png = Image.open(BytesIO(im._repr_png_())) - self.assertEqual(repr_png.format, "PNG") - self.assert_image_equal(im, repr_png) - - def test_chunk_order(self): - im = Image.open("Tests/images/icc_profile.png") - test_file = self.tempfile("temp.png") - im.convert("P").save(test_file, dpi=(100, 100)) - - chunks = self.get_chunks(test_file) - - # https://www.w3.org/TR/PNG/#5ChunkOrdering - # IHDR - shall be first - self.assertEqual(chunks.index(b"IHDR"), 0) - # PLTE - before first IDAT - self.assertLess(chunks.index(b"PLTE"), chunks.index(b"IDAT")) - # iCCP - before PLTE and IDAT - self.assertLess(chunks.index(b"iCCP"), chunks.index(b"PLTE")) - self.assertLess(chunks.index(b"iCCP"), chunks.index(b"IDAT")) - # tRNS - after PLTE, before IDAT - self.assertGreater(chunks.index(b"tRNS"), chunks.index(b"PLTE")) - self.assertLess(chunks.index(b"tRNS"), chunks.index(b"IDAT")) - # pHYs - before IDAT - self.assertLess(chunks.index(b"pHYs"), chunks.index(b"IDAT")) - - def test_getchunks(self): - im = hopper() - - chunks = PngImagePlugin.getchunks(im) - self.assertEqual(len(chunks), 3) - - def test_textual_chunks_after_idat(self): - im = Image.open("Tests/images/hopper.png") - self.assertIn("comment", im.text.keys()) - for k, v in { - "date:create": "2014-09-04T09:37:08+03:00", - "date:modify": "2014-09-04T09:37:08+03:00", - }.items(): - self.assertEqual(im.text[k], v) - - # Raises a SyntaxError in load_end - im = Image.open("Tests/images/broken_data_stream.png") - with self.assertRaises(IOError): - self.assertIsInstance(im.text, dict) - - # Raises a UnicodeDecodeError in load_end - im = Image.open("Tests/images/truncated_image.png") - # The file is truncated - self.assertRaises(IOError, lambda: im.text) - ImageFile.LOAD_TRUNCATED_IMAGES = True - self.assertIsInstance(im.text, dict) - ImageFile.LOAD_TRUNCATED_IMAGES = False - - # Raises an EOFError in load_end - im = Image.open("Tests/images/hopper_idat_after_image_end.png") - self.assertEqual(im.text, {"TXT": "VALUE", "ZIP": "VALUE"}) - - def test_exif(self): - im = Image.open("Tests/images/exif.png") - exif = im._getexif() - self.assertEqual(exif[274], 1) - - def test_exif_save(self): - im = Image.open("Tests/images/exif.png") - - test_file = self.tempfile("temp.png") - im.save(test_file) - - reloaded = Image.open(test_file) - exif = reloaded._getexif() - self.assertEqual(exif[274], 1) - - def test_exif_from_jpg(self): - im = Image.open("Tests/images/pil_sample_rgb.jpg") - - test_file = self.tempfile("temp.png") - im.save(test_file) - - reloaded = Image.open(test_file) - exif = reloaded._getexif() - self.assertEqual(exif[305], "Adobe Photoshop CS Macintosh") - - def test_exif_argument(self): - im = Image.open(TEST_PNG_FILE) - - test_file = self.tempfile("temp.png") - im.save(test_file, exif=b"exifstring") - - reloaded = Image.open(test_file) - self.assertEqual(reloaded.info["exif"], b"Exif\x00\x00exifstring") - - @unittest.skipUnless( - HAVE_WEBP and _webp.HAVE_WEBPANIM, "WebP support not installed with animation" - ) - def test_apng(self): - im = Image.open("Tests/images/iss634.apng") - self.assertEqual(im.get_format_mimetype(), "image/apng") - - # This also tests reading unknown PNG chunks (fcTL and fdAT) in load_end - expected = Image.open("Tests/images/iss634.webp") - self.assert_image_similar(im, expected, 0.23) - - -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") -class TestTruncatedPngPLeaks(PillowLeakTestCase): - mem_limit = 2 * 1024 # max increase in K - iterations = 100 # Leak is 56k/iteration, this will leak 5.6megs - - def setUp(self): - if "zip_encoder" not in codecs or "zip_decoder" not in codecs: - self.skipTest("zip/deflate support not available") - - def test_leak_load(self): - with open("Tests/images/hopper.png", "rb") as f: - DATA = BytesIO(f.read(16 * 1024)) - - ImageFile.LOAD_TRUNCATED_IMAGES = True - with Image.open(DATA) as im: - im.load() - - def core(): - with Image.open(DATA) as im: - im.load() - - try: - self._test_leak(core) - finally: - ImageFile.LOAD_TRUNCATED_IMAGES = False diff --git a/Tests/test_file_ppm.py b/Tests/test_file_ppm.py deleted file mode 100644 index 5d2a0bc69e8..00000000000 --- a/Tests/test_file_ppm.py +++ /dev/null @@ -1,75 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - -# sample ppm stream -test_file = "Tests/images/hopper.ppm" - - -class TestFilePpm(PillowTestCase): - def test_sanity(self): - im = Image.open(test_file) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "PPM") - self.assertEqual(im.get_format_mimetype(), "image/x-portable-pixmap") - - def test_16bit_pgm(self): - im = Image.open("Tests/images/16_bit_binary.pgm") - im.load() - self.assertEqual(im.mode, "I") - self.assertEqual(im.size, (20, 100)) - self.assertEqual(im.get_format_mimetype(), "image/x-portable-graymap") - - tgt = Image.open("Tests/images/16_bit_binary_pgm.png") - self.assert_image_equal(im, tgt) - - def test_16bit_pgm_write(self): - im = Image.open("Tests/images/16_bit_binary.pgm") - im.load() - - f = self.tempfile("temp.pgm") - im.save(f, "PPM") - - reloaded = Image.open(f) - self.assert_image_equal(im, reloaded) - - def test_pnm(self): - im = Image.open("Tests/images/hopper.pnm") - self.assert_image_similar(im, hopper(), 0.0001) - - f = self.tempfile("temp.pnm") - im.save(f) - - reloaded = Image.open(f) - self.assert_image_equal(im, reloaded) - - def test_truncated_file(self): - path = self.tempfile("temp.pgm") - with open(path, "w") as f: - f.write("P6") - - self.assertRaises(ValueError, Image.open, path) - - def test_neg_ppm(self): - # Storage.c accepted negative values for xsize, ysize. the - # internal open_ppm function didn't check for sanity but it - # has been removed. The default opener doesn't accept negative - # sizes. - - with self.assertRaises(IOError): - Image.open("Tests/images/negative_size.ppm") - - def test_mimetypes(self): - path = self.tempfile("temp.pgm") - - with open(path, "w") as f: - f.write("P4\n128 128\n255") - im = Image.open(path) - self.assertEqual(im.get_format_mimetype(), "image/x-portable-bitmap") - - with open(path, "w") as f: - f.write("PyCMYK\n128 128\n255") - im = Image.open(path) - self.assertEqual(im.get_format_mimetype(), "image/x-portable-anymap") diff --git a/Tests/test_file_psd.py b/Tests/test_file_psd.py deleted file mode 100644 index f55ee1dcbb6..00000000000 --- a/Tests/test_file_psd.py +++ /dev/null @@ -1,89 +0,0 @@ -from PIL import Image, PsdImagePlugin - -from .helper import PillowTestCase, hopper - -test_file = "Tests/images/hopper.psd" - - -class TestImagePsd(PillowTestCase): - def test_sanity(self): - im = Image.open(test_file) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "PSD") - - im2 = hopper() - self.assert_image_similar(im, im2, 4.8) - - def test_unclosed_file(self): - def open(): - im = Image.open(test_file) - im.load() - - self.assert_warning(None, open) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, PsdImagePlugin.PsdImageFile, invalid_file) - - def test_n_frames(self): - im = Image.open("Tests/images/hopper_merged.psd") - self.assertEqual(im.n_frames, 1) - self.assertFalse(im.is_animated) - - im = Image.open(test_file) - self.assertEqual(im.n_frames, 2) - self.assertTrue(im.is_animated) - - def test_eoferror(self): - im = Image.open(test_file) - # PSD seek index starts at 1 rather than 0 - n_frames = im.n_frames + 1 - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_seek_tell(self): - im = Image.open(test_file) - - layer_number = im.tell() - self.assertEqual(layer_number, 1) - - self.assertRaises(EOFError, im.seek, 0) - - im.seek(1) - layer_number = im.tell() - self.assertEqual(layer_number, 1) - - im.seek(2) - layer_number = im.tell() - self.assertEqual(layer_number, 2) - - def test_seek_eoferror(self): - im = Image.open(test_file) - - self.assertRaises(EOFError, im.seek, -1) - - def test_open_after_exclusive_load(self): - im = Image.open(test_file) - im.load() - im.seek(im.tell() + 1) - im.load() - - def test_icc_profile(self): - im = Image.open(test_file) - self.assertIn("icc_profile", im.info) - - icc_profile = im.info["icc_profile"] - self.assertEqual(len(icc_profile), 3144) - - def test_no_icc_profile(self): - im = Image.open("Tests/images/hopper_merged.psd") - - self.assertNotIn("icc_profile", im.info) diff --git a/Tests/test_file_sgi.py b/Tests/test_file_sgi.py deleted file mode 100644 index ff3aea1d57b..00000000000 --- a/Tests/test_file_sgi.py +++ /dev/null @@ -1,89 +0,0 @@ -from PIL import Image, SgiImagePlugin - -from .helper import PillowTestCase, hopper - - -class TestFileSgi(PillowTestCase): - def test_rgb(self): - # Created with ImageMagick then renamed: - # convert hopper.ppm -compress None sgi:hopper.rgb - test_file = "Tests/images/hopper.rgb" - - im = Image.open(test_file) - self.assert_image_equal(im, hopper()) - self.assertEqual(im.get_format_mimetype(), "image/rgb") - - def test_rgb16(self): - test_file = "Tests/images/hopper16.rgb" - - im = Image.open(test_file) - self.assert_image_equal(im, hopper()) - - def test_l(self): - # Created with ImageMagick - # convert hopper.ppm -monochrome -compress None sgi:hopper.bw - test_file = "Tests/images/hopper.bw" - - im = Image.open(test_file) - self.assert_image_similar(im, hopper("L"), 2) - self.assertEqual(im.get_format_mimetype(), "image/sgi") - - def test_rgba(self): - # Created with ImageMagick: - # convert transparent.png -compress None transparent.sgi - test_file = "Tests/images/transparent.sgi" - - im = Image.open(test_file) - target = Image.open("Tests/images/transparent.png") - self.assert_image_equal(im, target) - self.assertEqual(im.get_format_mimetype(), "image/sgi") - - def test_rle(self): - # Created with ImageMagick: - # convert hopper.ppm hopper.sgi - test_file = "Tests/images/hopper.sgi" - - im = Image.open(test_file) - target = Image.open("Tests/images/hopper.rgb") - self.assert_image_equal(im, target) - - def test_rle16(self): - test_file = "Tests/images/tv16.sgi" - - im = Image.open(test_file) - target = Image.open("Tests/images/tv.rgb") - self.assert_image_equal(im, target) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(ValueError, SgiImagePlugin.SgiImageFile, invalid_file) - - def test_write(self): - def roundtrip(img): - out = self.tempfile("temp.sgi") - img.save(out, format="sgi") - reloaded = Image.open(out) - self.assert_image_equal(img, reloaded) - - for mode in ("L", "RGB", "RGBA"): - roundtrip(hopper(mode)) - - # Test 1 dimension for an L mode image - roundtrip(Image.new("L", (10, 1))) - - def test_write16(self): - test_file = "Tests/images/hopper16.rgb" - - im = Image.open(test_file) - out = self.tempfile("temp.sgi") - im.save(out, format="sgi", bpc=2) - - reloaded = Image.open(out) - self.assert_image_equal(im, reloaded) - - def test_unsupported_mode(self): - im = hopper("LA") - out = self.tempfile("temp.sgi") - - self.assertRaises(ValueError, im.save, out, format="sgi") diff --git a/Tests/test_file_spider.py b/Tests/test_file_spider.py deleted file mode 100644 index 8a1eb66372e..00000000000 --- a/Tests/test_file_spider.py +++ /dev/null @@ -1,119 +0,0 @@ -import tempfile - -from PIL import Image, ImageSequence, SpiderImagePlugin - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/hopper.spider" - - -class TestImageSpider(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_FILE) - im.load() - self.assertEqual(im.mode, "F") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "SPIDER") - - def test_unclosed_file(self): - def open(): - im = Image.open(TEST_FILE) - im.load() - - self.assert_warning(None, open) - - def test_save(self): - # Arrange - temp = self.tempfile("temp.spider") - im = hopper() - - # Act - im.save(temp, "SPIDER") - - # Assert - im2 = Image.open(temp) - self.assertEqual(im2.mode, "F") - self.assertEqual(im2.size, (128, 128)) - self.assertEqual(im2.format, "SPIDER") - - def test_tempfile(self): - # Arrange - im = hopper() - - # Act - with tempfile.TemporaryFile() as fp: - im.save(fp, "SPIDER") - - # Assert - fp.seek(0) - reloaded = Image.open(fp) - self.assertEqual(reloaded.mode, "F") - self.assertEqual(reloaded.size, (128, 128)) - self.assertEqual(reloaded.format, "SPIDER") - - def test_isSpiderImage(self): - 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_n_frames(self): - im = Image.open(TEST_FILE) - self.assertEqual(im.n_frames, 1) - self.assertFalse(im.is_animated) - - def test_loadImageSeries(self): - # Arrange - not_spider_file = "Tests/images/hopper.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.assertIsNone(img_list) - - def test_isInt_not_a_number(self): - # Arrange - not_a_number = "a" - - # Act - ret = SpiderImagePlugin.isInt(not_a_number) - - # Assert - self.assertEqual(ret, 0) - - def test_invalid_file(self): - invalid_file = "Tests/images/invalid.spider" - - self.assertRaises(IOError, Image.open, invalid_file) - - def test_nonstack_file(self): - im = Image.open(TEST_FILE) - - self.assertRaises(EOFError, im.seek, 0) - - def test_nonstack_dos(self): - im = Image.open(TEST_FILE) - for i, frame in enumerate(ImageSequence.Iterator(im)): - if i > 1: - self.fail("Non-stack DOS file test failed") diff --git a/Tests/test_file_sun.py b/Tests/test_file_sun.py deleted file mode 100644 index 84d59e0c737..00000000000 --- a/Tests/test_file_sun.py +++ /dev/null @@ -1,46 +0,0 @@ -import os - -from PIL import Image, SunImagePlugin - -from .helper import PillowTestCase, hopper, unittest - -EXTRA_DIR = "Tests/images/sunraster" - - -class TestFileSun(PillowTestCase): - def test_sanity(self): - # Arrange - # Created with ImageMagick: convert hopper.jpg hopper.ras - test_file = "Tests/images/hopper.ras" - - # Act - im = Image.open(test_file) - - # Assert - self.assertEqual(im.size, (128, 128)) - - self.assert_image_similar(im, hopper(), 5) # visually verified - - invalid_file = "Tests/images/flower.jpg" - self.assertRaises(SyntaxError, SunImagePlugin.SunImageFile, invalid_file) - - def test_im1(self): - im = Image.open("Tests/images/sunraster.im1") - target = Image.open("Tests/images/sunraster.im1.png") - self.assert_image_equal(im, target) - - @unittest.skipIf(not os.path.exists(EXTRA_DIR), "Extra image files not installed") - def test_others(self): - files = ( - os.path.join(EXTRA_DIR, f) - for f in os.listdir(EXTRA_DIR) - if os.path.splitext(f)[1] in (".sun", ".SUN", ".ras") - ) - for path in files: - with Image.open(path) as im: - im.load() - self.assertIsInstance(im, SunImagePlugin.SunImageFile) - target_path = "%s.png" % os.path.splitext(path)[0] - # im.save(target_file) - with Image.open(target_path) as target: - self.assert_image_equal(im, target) diff --git a/Tests/test_file_tar.py b/Tests/test_file_tar.py deleted file mode 100644 index c4666a65ab7..00000000000 --- a/Tests/test_file_tar.py +++ /dev/null @@ -1,35 +0,0 @@ -from PIL import Image, TarIO - -from .helper import PillowTestCase - -codecs = dir(Image.core) - -# Sample tar archive -TEST_TAR_FILE = "Tests/images/hopper.tar" - - -class TestFileTar(PillowTestCase): - def setUp(self): - if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs: - self.skipTest("neither jpeg nor zip support available") - - def test_sanity(self): - for codec, test_path, format in [ - ["zip_decoder", "hopper.png", "PNG"], - ["jpeg_decoder", "hopper.jpg", "JPEG"], - ]: - if codec in codecs: - tar = TarIO.TarIO(TEST_TAR_FILE, test_path) - im = Image.open(tar) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, format) - - def test_close(self): - tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") - tar.close() - - def test_contextmanager(self): - with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"): - pass diff --git a/Tests/test_file_tga.py b/Tests/test_file_tga.py deleted file mode 100644 index abbebe0ebe5..00000000000 --- a/Tests/test_file_tga.py +++ /dev/null @@ -1,200 +0,0 @@ -import os -from glob import glob -from itertools import product - -from PIL import Image - -from .helper import PillowTestCase - -_TGA_DIR = os.path.join("Tests", "images", "tga") -_TGA_DIR_COMMON = os.path.join(_TGA_DIR, "common") - - -class TestFileTga(PillowTestCase): - - _MODES = ("L", "LA", "P", "RGB", "RGBA") - _ORIGINS = ("tl", "bl") - - _ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1} - - def test_sanity(self): - for mode in self._MODES: - png_paths = glob( - os.path.join(_TGA_DIR_COMMON, "*x*_{}.png".format(mode.lower())) - ) - - for png_path in png_paths: - reference_im = Image.open(png_path) - self.assertEqual(reference_im.mode, mode) - - path_no_ext = os.path.splitext(png_path)[0] - for origin, rle in product(self._ORIGINS, (True, False)): - tga_path = "{}_{}_{}.tga".format( - path_no_ext, origin, "rle" if rle else "raw" - ) - - original_im = Image.open(tga_path) - self.assertEqual(original_im.format, "TGA") - self.assertEqual(original_im.get_format_mimetype(), "image/x-tga") - if rle: - self.assertEqual(original_im.info["compression"], "tga_rle") - self.assertEqual( - original_im.info["orientation"], - self._ORIGIN_TO_ORIENTATION[origin], - ) - if mode == "P": - self.assertEqual( - original_im.getpalette(), reference_im.getpalette() - ) - - self.assert_image_equal(original_im, reference_im) - - # Generate a new test name every time so the - # test will not fail with permission error - # on Windows. - out = self.tempfile("temp.tga") - - original_im.save(out, rle=rle) - saved_im = Image.open(out) - if rle: - self.assertEqual( - saved_im.info["compression"], - original_im.info["compression"], - ) - self.assertEqual( - saved_im.info["orientation"], original_im.info["orientation"] - ) - if mode == "P": - self.assertEqual( - saved_im.getpalette(), original_im.getpalette() - ) - - self.assert_image_equal(saved_im, original_im) - - def test_id_field(self): - # tga file with id field - test_file = "Tests/images/tga_id_field.tga" - - # Act - im = Image.open(test_file) - - # Assert - self.assertEqual(im.size, (100, 100)) - - def test_id_field_rle(self): - # tga file with id field - test_file = "Tests/images/rgb32rle.tga" - - # Act - im = Image.open(test_file) - - # Assert - self.assertEqual(im.size, (199, 199)) - - def test_save(self): - test_file = "Tests/images/tga_id_field.tga" - im = Image.open(test_file) - - out = self.tempfile("temp.tga") - - # Save - im.save(out) - test_im = Image.open(out) - self.assertEqual(test_im.size, (100, 100)) - self.assertEqual(test_im.info["id_section"], im.info["id_section"]) - - # RGBA save - im.convert("RGBA").save(out) - test_im = Image.open(out) - self.assertEqual(test_im.size, (100, 100)) - - def test_save_id_section(self): - test_file = "Tests/images/rgb32rle.tga" - im = Image.open(test_file) - - out = self.tempfile("temp.tga") - - # Check there is no id section - im.save(out) - test_im = Image.open(out) - self.assertNotIn("id_section", test_im.info) - - # Save with custom id section - im.save(out, id_section=b"Test content") - test_im = Image.open(out) - self.assertEqual(test_im.info["id_section"], b"Test content") - - # Save with custom id section greater than 255 characters - id_section = b"Test content" * 25 - self.assert_warning(UserWarning, lambda: im.save(out, id_section=id_section)) - test_im = Image.open(out) - self.assertEqual(test_im.info["id_section"], id_section[:255]) - - test_file = "Tests/images/tga_id_field.tga" - im = Image.open(test_file) - - # Save with no id section - im.save(out, id_section="") - test_im = Image.open(out) - self.assertNotIn("id_section", test_im.info) - - def test_save_orientation(self): - test_file = "Tests/images/rgb32rle.tga" - im = Image.open(test_file) - self.assertEqual(im.info["orientation"], -1) - - out = self.tempfile("temp.tga") - - im.save(out, orientation=1) - test_im = Image.open(out) - self.assertEqual(test_im.info["orientation"], 1) - - def test_save_rle(self): - test_file = "Tests/images/rgb32rle.tga" - im = Image.open(test_file) - self.assertEqual(im.info["compression"], "tga_rle") - - out = self.tempfile("temp.tga") - - # Save - im.save(out) - test_im = Image.open(out) - self.assertEqual(test_im.size, (199, 199)) - self.assertEqual(test_im.info["compression"], "tga_rle") - - # Save without compression - im.save(out, compression=None) - test_im = Image.open(out) - self.assertNotIn("compression", test_im.info) - - # RGBA save - im.convert("RGBA").save(out) - test_im = Image.open(out) - self.assertEqual(test_im.size, (199, 199)) - - test_file = "Tests/images/tga_id_field.tga" - im = Image.open(test_file) - self.assertNotIn("compression", im.info) - - # Save with compression - im.save(out, compression="tga_rle") - test_im = Image.open(out) - self.assertEqual(test_im.info["compression"], "tga_rle") - - def test_save_l_transparency(self): - # There are 559 transparent pixels in la.tga. - num_transparent = 559 - - in_file = "Tests/images/la.tga" - im = Image.open(in_file) - self.assertEqual(im.mode, "LA") - self.assertEqual(im.getchannel("A").getcolors()[0][0], num_transparent) - - out = self.tempfile("temp.tga") - im.save(out) - - test_im = Image.open(out) - self.assertEqual(test_im.mode, "LA") - self.assertEqual(test_im.getchannel("A").getcolors()[0][0], num_transparent) - - self.assert_image_equal(im, test_im) diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py deleted file mode 100644 index c3f55150c63..00000000000 --- a/Tests/test_file_tiff.py +++ /dev/null @@ -1,637 +0,0 @@ -import logging -import sys -from io import BytesIO - -from PIL import Image, TiffImagePlugin, features -from PIL._util import py3 -from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION - -from .helper import PillowTestCase, hopper, unittest - -logger = logging.getLogger(__name__) - - -class TestFileTiff(PillowTestCase): - def test_sanity(self): - - filename = self.tempfile("temp.tif") - - hopper("RGB").save(filename) - - im = Image.open(filename) - im.load() - self.assertEqual(im.mode, "RGB") - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.format, "TIFF") - - hopper("1").save(filename) - Image.open(filename) - - hopper("L").save(filename) - Image.open(filename) - - hopper("P").save(filename) - Image.open(filename) - - hopper("RGB").save(filename) - Image.open(filename) - - hopper("I").save(filename) - Image.open(filename) - - def test_unclosed_file(self): - def open(): - im = Image.open("Tests/images/multipage.tiff") - im.load() - - self.assert_warning(None, open) - - def test_mac_tiff(self): - # Read RGBa images from macOS [@PIL136] - - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (55, 43)) - self.assertEqual(im.tile, [("raw", (0, 0, 55, 43), 8, ("RGBa", 0, 1))]) - im.load() - - self.assert_image_similar_tofile(im, "Tests/images/pil136.png", 1) - - def test_wrong_bits_per_sample(self): - im = Image.open("Tests/images/tiff_wrong_bits_per_sample.tiff") - - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.size, (52, 53)) - self.assertEqual(im.tile, [("raw", (0, 0, 52, 53), 160, ("RGBA", 0, 1))]) - im.load() - - def test_set_legacy_api(self): - ifd = TiffImagePlugin.ImageFileDirectory_v2() - with self.assertRaises(Exception) as e: - ifd.legacy_api = None - self.assertEqual(str(e.exception), "Not allowing setting of legacy api") - - def test_size(self): - filename = "Tests/images/pil168.tif" - im = Image.open(filename) - - def set_size(): - im.size = (256, 256) - - self.assert_warning(DeprecationWarning, set_size) - - def test_xyres_tiff(self): - filename = "Tests/images/pil168.tif" - im = Image.open(filename) - - # legacy api - self.assertIsInstance(im.tag[X_RESOLUTION][0], tuple) - self.assertIsInstance(im.tag[Y_RESOLUTION][0], tuple) - - # v2 api - self.assertIsInstance(im.tag_v2[X_RESOLUTION], TiffImagePlugin.IFDRational) - self.assertIsInstance(im.tag_v2[Y_RESOLUTION], TiffImagePlugin.IFDRational) - - self.assertEqual(im.info["dpi"], (72.0, 72.0)) - - def test_xyres_fallback_tiff(self): - filename = "Tests/images/compression.tif" - im = Image.open(filename) - - # v2 api - self.assertIsInstance(im.tag_v2[X_RESOLUTION], TiffImagePlugin.IFDRational) - self.assertIsInstance(im.tag_v2[Y_RESOLUTION], TiffImagePlugin.IFDRational) - self.assertRaises(KeyError, lambda: im.tag_v2[RESOLUTION_UNIT]) - - # Legacy. - self.assertEqual(im.info["resolution"], (100.0, 100.0)) - # Fallback "inch". - self.assertEqual(im.info["dpi"], (100.0, 100.0)) - - def test_int_resolution(self): - filename = "Tests/images/pil168.tif" - im = Image.open(filename) - - # Try to read a file where X,Y_RESOLUTION are ints - im.tag_v2[X_RESOLUTION] = 71 - im.tag_v2[Y_RESOLUTION] = 71 - im._setup() - self.assertEqual(im.info["dpi"], (71.0, 71.0)) - - def test_load_dpi_rounding(self): - for resolutionUnit, dpi in ((None, (72, 73)), (2, (72, 73)), (3, (183, 185))): - im = Image.open( - "Tests/images/hopper_roundDown_" + str(resolutionUnit) + ".tif" - ) - self.assertEqual(im.tag_v2.get(RESOLUTION_UNIT), resolutionUnit) - self.assertEqual(im.info["dpi"], (dpi[0], dpi[0])) - - im = Image.open( - "Tests/images/hopper_roundUp_" + str(resolutionUnit) + ".tif" - ) - self.assertEqual(im.tag_v2.get(RESOLUTION_UNIT), resolutionUnit) - self.assertEqual(im.info["dpi"], (dpi[1], dpi[1])) - - def test_save_dpi_rounding(self): - outfile = self.tempfile("temp.tif") - im = Image.open("Tests/images/hopper.tif") - - for dpi in (72.2, 72.8): - im.save(outfile, dpi=(dpi, dpi)) - - reloaded = Image.open(outfile) - reloaded.load() - self.assertEqual((round(dpi), round(dpi)), reloaded.info["dpi"]) - - def test_save_setting_missing_resolution(self): - b = BytesIO() - Image.open("Tests/images/10ct_32bit_128.tiff").save( - b, format="tiff", resolution=123.45 - ) - im = Image.open(b) - self.assertEqual(float(im.tag_v2[X_RESOLUTION]), 123.45) - self.assertEqual(float(im.tag_v2[Y_RESOLUTION]), 123.45) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, TiffImagePlugin.TiffImageFile, invalid_file) - - TiffImagePlugin.PREFIXES.append(b"\xff\xd8\xff\xe0") - self.assertRaises(SyntaxError, TiffImagePlugin.TiffImageFile, invalid_file) - TiffImagePlugin.PREFIXES.pop() - - def test_bad_exif(self): - i = Image.open("Tests/images/hopper_bad_exif.jpg") - # Should not raise struct.error. - self.assert_warning(UserWarning, i._getexif) - - def test_save_rgba(self): - im = hopper("RGBA") - outfile = self.tempfile("temp.tif") - im.save(outfile) - - def test_save_unsupported_mode(self): - im = hopper("HSV") - outfile = self.tempfile("temp.tif") - self.assertRaises(IOError, im.save, outfile) - - def test_little_endian(self): - im = Image.open("Tests/images/16bit.cropped.tif") - self.assertEqual(im.getpixel((0, 0)), 480) - self.assertEqual(im.mode, "I;16") - - b = im.tobytes() - # Bytes are in image native order (little endian) - if py3: - self.assertEqual(b[0], ord(b"\xe0")) - self.assertEqual(b[1], ord(b"\x01")) - else: - self.assertEqual(b[0], b"\xe0") - self.assertEqual(b[1], b"\x01") - - def test_big_endian(self): - im = Image.open("Tests/images/16bit.MM.cropped.tif") - self.assertEqual(im.getpixel((0, 0)), 480) - self.assertEqual(im.mode, "I;16B") - - b = im.tobytes() - - # Bytes are in image native order (big endian) - if py3: - self.assertEqual(b[0], ord(b"\x01")) - self.assertEqual(b[1], ord(b"\xe0")) - else: - self.assertEqual(b[0], b"\x01") - self.assertEqual(b[1], b"\xe0") - - def test_16bit_s(self): - im = Image.open("Tests/images/16bit.s.tif") - im.load() - self.assertEqual(im.mode, "I") - self.assertEqual(im.getpixel((0, 0)), 32767) - self.assertEqual(im.getpixel((0, 1)), 0) - - def test_12bit_rawmode(self): - """ Are we generating the same interpretation - of the image as Imagemagick is? """ - - im = Image.open("Tests/images/12bit.cropped.tif") - - # to make the target -- - # convert 12bit.cropped.tif -depth 16 tmp.tif - # convert tmp.tif -evaluate RightShift 4 12in16bit2.tif - # imagemagick will auto scale so that a 12bit FFF is 16bit FFF0, - # so we need to unshift so that the integer values are the same. - - self.assert_image_equal_tofile(im, "Tests/images/12in16bit.tif") - - def test_32bit_float(self): - # Issue 614, specific 32-bit float format - path = "Tests/images/10ct_32bit_128.tiff" - im = Image.open(path) - im.load() - - self.assertEqual(im.getpixel((0, 0)), -0.4526388943195343) - self.assertEqual(im.getextrema(), (-3.140936851501465, 3.140684127807617)) - - def test_unknown_pixel_mode(self): - self.assertRaises( - IOError, Image.open, "Tests/images/hopper_unknown_pixel_mode.tif" - ) - - def test_n_frames(self): - for path, n_frames in [ - ["Tests/images/multipage-lastframe.tif", 1], - ["Tests/images/multipage.tiff", 3], - ]: - im = Image.open(path) - self.assertEqual(im.n_frames, n_frames) - self.assertEqual(im.is_animated, n_frames != 1) - - def test_eoferror(self): - im = Image.open("Tests/images/multipage-lastframe.tif") - n_frames = im.n_frames - - # Test seeking past the last frame - self.assertRaises(EOFError, im.seek, n_frames) - self.assertLess(im.tell(), n_frames) - - # Test that seeking to the last frame does not raise an error - im.seek(n_frames - 1) - - def test_multipage(self): - # issue #862 - im = Image.open("Tests/images/multipage.tiff") - # file is a multipage tiff: 10x10 green, 10x10 red, 20x20 blue - - im.seek(0) - self.assertEqual(im.size, (10, 10)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (0, 128, 0)) - - im.seek(1) - im.load() - self.assertEqual(im.size, (10, 10)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (255, 0, 0)) - - im.seek(0) - im.load() - self.assertEqual(im.size, (10, 10)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (0, 128, 0)) - - im.seek(2) - im.load() - self.assertEqual(im.size, (20, 20)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (0, 0, 255)) - - def test_multipage_last_frame(self): - im = Image.open("Tests/images/multipage-lastframe.tif") - im.load() - self.assertEqual(im.size, (20, 20)) - self.assertEqual(im.convert("RGB").getpixel((0, 0)), (0, 0, 255)) - - def test___str__(self): - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - - # Act - ret = str(im.ifd) - - # Assert - self.assertIsInstance(ret, str) - - def test_dict(self): - # Arrange - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - - # v2 interface - v2_tags = { - 256: 55, - 257: 43, - 258: (8, 8, 8, 8), - 259: 1, - 262: 2, - 296: 2, - 273: (8,), - 338: (1,), - 277: 4, - 279: (9460,), - 282: 72.0, - 283: 72.0, - 284: 1, - } - self.assertEqual(dict(im.tag_v2), v2_tags) - - # legacy interface - legacy_tags = { - 256: (55,), - 257: (43,), - 258: (8, 8, 8, 8), - 259: (1,), - 262: (2,), - 296: (2,), - 273: (8,), - 338: (1,), - 277: (4,), - 279: (9460,), - 282: ((720000, 10000),), - 283: ((720000, 10000),), - 284: (1,), - } - self.assertEqual(dict(im.tag), legacy_tags) - - def test__delitem__(self): - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - len_before = len(dict(im.ifd)) - del im.ifd[256] - len_after = len(dict(im.ifd)) - self.assertEqual(len_before, len_after + 1) - - def test_load_byte(self): - for legacy_api in [False, True]: - ifd = TiffImagePlugin.ImageFileDirectory_v2() - data = b"abc" - ret = ifd.load_byte(data, legacy_api) - self.assertEqual(ret, b"abc") - - def test_load_string(self): - ifd = TiffImagePlugin.ImageFileDirectory_v2() - data = b"abc\0" - ret = ifd.load_string(data, False) - self.assertEqual(ret, "abc") - - def test_load_float(self): - ifd = TiffImagePlugin.ImageFileDirectory_v2() - data = b"abcdabcd" - ret = ifd.load_float(data, False) - self.assertEqual(ret, (1.6777999408082104e22, 1.6777999408082104e22)) - - def test_load_double(self): - ifd = TiffImagePlugin.ImageFileDirectory_v2() - data = b"abcdefghabcdefgh" - ret = ifd.load_double(data, False) - self.assertEqual(ret, (8.540883223036124e194, 8.540883223036124e194)) - - def test_seek(self): - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - im.seek(0) - self.assertEqual(im.tell(), 0) - - def test_seek_eof(self): - filename = "Tests/images/pil136.tiff" - im = Image.open(filename) - self.assertEqual(im.tell(), 0) - self.assertRaises(EOFError, im.seek, -1) - self.assertRaises(EOFError, im.seek, 1) - - def test__limit_rational_int(self): - from PIL.TiffImagePlugin import _limit_rational - - value = 34 - ret = _limit_rational(value, 65536) - self.assertEqual(ret, (34, 1)) - - def test__limit_rational_float(self): - from PIL.TiffImagePlugin import _limit_rational - - value = 22.3 - ret = _limit_rational(value, 65536) - self.assertEqual(ret, (223, 10)) - - def test_4bit(self): - test_file = "Tests/images/hopper_gray_4bpp.tif" - original = hopper("L") - im = Image.open(test_file) - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.mode, "L") - self.assert_image_similar(im, original, 7.3) - - def test_gray_semibyte_per_pixel(self): - test_files = ( - ( - 24.8, # epsilon - ( # group - "Tests/images/tiff_gray_2_4_bpp/hopper2.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper2I.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper2R.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper2IR.tif", - ), - ), - ( - 7.3, # epsilon - ( # group - "Tests/images/tiff_gray_2_4_bpp/hopper4.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper4I.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper4R.tif", - "Tests/images/tiff_gray_2_4_bpp/hopper4IR.tif", - ), - ), - ) - original = hopper("L") - for epsilon, group in test_files: - im = Image.open(group[0]) - self.assertEqual(im.size, (128, 128)) - self.assertEqual(im.mode, "L") - self.assert_image_similar(im, original, epsilon) - for file in group[1:]: - im2 = Image.open(file) - self.assertEqual(im2.size, (128, 128)) - self.assertEqual(im2.mode, "L") - self.assert_image_equal(im, im2) - - def test_with_underscores(self): - kwargs = {"resolution_unit": "inch", "x_resolution": 72, "y_resolution": 36} - filename = self.tempfile("temp.tif") - hopper("RGB").save(filename, **kwargs) - im = Image.open(filename) - - # legacy interface - self.assertEqual(im.tag[X_RESOLUTION][0][0], 72) - self.assertEqual(im.tag[Y_RESOLUTION][0][0], 36) - - # v2 interface - self.assertEqual(im.tag_v2[X_RESOLUTION], 72) - self.assertEqual(im.tag_v2[Y_RESOLUTION], 36) - - def test_roundtrip_tiff_uint16(self): - # Test an image of all '0' values - pixel_value = 0x1234 - infile = "Tests/images/uint16_1_4660.tif" - im = Image.open(infile) - self.assertEqual(im.getpixel((0, 0)), pixel_value) - - tmpfile = self.tempfile("temp.tif") - im.save(tmpfile) - - reloaded = Image.open(tmpfile) - - self.assert_image_equal(im, reloaded) - - def test_strip_raw(self): - infile = "Tests/images/tiff_strip_raw.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png") - - def test_strip_planar_raw(self): - # gdal_translate -of GTiff -co INTERLEAVE=BAND \ - # tiff_strip_raw.tif tiff_strip_planar_raw.tiff - infile = "Tests/images/tiff_strip_planar_raw.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png") - - def test_strip_planar_raw_with_overviews(self): - # gdaladdo tiff_strip_planar_raw2.tif 2 4 8 16 - infile = "Tests/images/tiff_strip_planar_raw_with_overviews.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png") - - def test_tiled_planar_raw(self): - # gdal_translate -of GTiff -co TILED=YES -co BLOCKXSIZE=32 \ - # -co BLOCKYSIZE=32 -co INTERLEAVE=BAND \ - # tiff_tiled_raw.tif tiff_tiled_planar_raw.tiff - infile = "Tests/images/tiff_tiled_planar_raw.tif" - im = Image.open(infile) - - self.assert_image_equal_tofile(im, "Tests/images/tiff_adobe_deflate.png") - - def test_palette(self): - for mode in ["P", "PA"]: - outfile = self.tempfile("temp.tif") - - im = hopper(mode) - im.save(outfile) - - reloaded = Image.open(outfile) - self.assert_image_equal(im.convert("RGB"), reloaded.convert("RGB")) - - def test_tiff_save_all(self): - import io - import os - - mp = io.BytesIO() - with Image.open("Tests/images/multipage.tiff") as im: - im.save(mp, format="tiff", save_all=True) - - mp.seek(0, os.SEEK_SET) - with Image.open(mp) as im: - self.assertEqual(im.n_frames, 3) - - # Test appending images - mp = io.BytesIO() - im = Image.new("RGB", (100, 100), "#f00") - ims = [Image.new("RGB", (100, 100), color) for color in ["#0f0", "#00f"]] - im.copy().save(mp, format="TIFF", save_all=True, append_images=ims) - - mp.seek(0, os.SEEK_SET) - reread = Image.open(mp) - self.assertEqual(reread.n_frames, 3) - - # Test appending using a generator - def imGenerator(ims): - for im in ims: - yield im - - mp = io.BytesIO() - im.save(mp, format="TIFF", save_all=True, append_images=imGenerator(ims)) - - mp.seek(0, os.SEEK_SET) - reread = Image.open(mp) - self.assertEqual(reread.n_frames, 3) - - def test_saving_icc_profile(self): - # Tests saving TIFF with icc_profile set. - # At the time of writing this will only work for non-compressed tiffs - # as libtiff does not support embedded ICC profiles, - # ImageFile._save(..) however does. - im = Image.new("RGB", (1, 1)) - im.info["icc_profile"] = "Dummy value" - - # Try save-load round trip to make sure both handle icc_profile. - tmpfile = self.tempfile("temp.tif") - im.save(tmpfile, "TIFF", compression="raw") - reloaded = Image.open(tmpfile) - - self.assertEqual(b"Dummy value", reloaded.info["icc_profile"]) - - def test_close_on_load_exclusive(self): - # similar to test_fd_leak, but runs on unixlike os - tmpfile = self.tempfile("temp.tif") - - with Image.open("Tests/images/uint16_1_4660.tif") as im: - im.save(tmpfile) - - im = Image.open(tmpfile) - fp = im.fp - self.assertFalse(fp.closed) - im.load() - self.assertTrue(fp.closed) - - def test_close_on_load_nonexclusive(self): - tmpfile = self.tempfile("temp.tif") - - with Image.open("Tests/images/uint16_1_4660.tif") as im: - im.save(tmpfile) - - with open(tmpfile, "rb") as f: - im = Image.open(f) - fp = im.fp - self.assertFalse(fp.closed) - im.load() - self.assertFalse(fp.closed) - - @unittest.skipUnless(features.check("libtiff"), "libtiff not installed") - def test_sampleformat_not_corrupted(self): - # Assert that a TIFF image with SampleFormat=UINT tag is not corrupted - # when saving to a new file. - # Pillow 6.0 fails with "OSError: cannot identify image file". - import base64 - - tiff = BytesIO( - base64.b64decode( - b"SUkqAAgAAAAPAP4ABAABAAAAAAAAAAABBAABAAAAAQAAAAEBBAABAAAAAQAA" - b"AAIBAwADAAAAwgAAAAMBAwABAAAACAAAAAYBAwABAAAAAgAAABEBBAABAAAA" - b"4AAAABUBAwABAAAAAwAAABYBBAABAAAAAQAAABcBBAABAAAACwAAABoBBQAB" - b"AAAAyAAAABsBBQABAAAA0AAAABwBAwABAAAAAQAAACgBAwABAAAAAQAAAFMB" - b"AwADAAAA2AAAAAAAAAAIAAgACAABAAAAAQAAAAEAAAABAAAAAQABAAEAAAB4" - b"nGNgYAAAAAMAAQ==" - ) - ) - out = BytesIO() - with Image.open(tiff) as im: - im.save(out, format="tiff") - out.seek(0) - with Image.open(out) as im: - im.load() - - -@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") -class TestFileTiffW32(PillowTestCase): - def test_fd_leak(self): - tmpfile = self.tempfile("temp.tif") - import os - - # this is an mmaped file. - with Image.open("Tests/images/uint16_1_4660.tif") as im: - im.save(tmpfile) - - im = Image.open(tmpfile) - fp = im.fp - self.assertFalse(fp.closed) - self.assertRaises(WindowsError, os.remove, tmpfile) - im.load() - self.assertTrue(fp.closed) - - # this closes the mmap - im.close() - - # this should not fail, as load should have closed the file pointer, - # and close should have closed the mmap - os.remove(tmpfile) diff --git a/Tests/test_file_tiff_metadata.py b/Tests/test_file_tiff_metadata.py deleted file mode 100644 index 8761e431eec..00000000000 --- a/Tests/test_file_tiff_metadata.py +++ /dev/null @@ -1,256 +0,0 @@ -import io -import struct - -from PIL import Image, TiffImagePlugin, TiffTags -from PIL.TiffImagePlugin import IFDRational, _limit_rational - -from .helper import PillowTestCase, hopper - -tag_ids = {info.name: info.value for info in TiffTags.TAGS_V2.values()} - - -class TestFileTiffMetadata(PillowTestCase): - def test_rt_metadata(self): - """ Test writing arbitrary metadata into the tiff image directory - Use case is ImageJ private tags, one numeric, one arbitrary - data. https://github.com/python-pillow/Pillow/issues/291 - """ - - img = hopper() - - # Behaviour change: re #1416 - # Pre ifd rewrite, ImageJMetaData was being written as a string(2), - # Post ifd rewrite, it's defined as arbitrary bytes(7). It should - # roundtrip with the actual bytes, rather than stripped text - # of the premerge tests. - # - # For text items, we still have to decode('ascii','replace') because - # the tiff file format can't take 8 bit bytes in that field. - - basetextdata = "This is some arbitrary metadata for a text field" - bindata = basetextdata.encode("ascii") + b" \xff" - textdata = basetextdata + " " + chr(255) - reloaded_textdata = basetextdata + " ?" - floatdata = 12.345 - doubledata = 67.89 - info = TiffImagePlugin.ImageFileDirectory() - - ImageJMetaData = tag_ids["ImageJMetaData"] - ImageJMetaDataByteCounts = tag_ids["ImageJMetaDataByteCounts"] - ImageDescription = tag_ids["ImageDescription"] - - info[ImageJMetaDataByteCounts] = len(bindata) - info[ImageJMetaData] = bindata - info[tag_ids["RollAngle"]] = floatdata - info.tagtype[tag_ids["RollAngle"]] = 11 - info[tag_ids["YawAngle"]] = doubledata - info.tagtype[tag_ids["YawAngle"]] = 12 - - info[ImageDescription] = textdata - - f = self.tempfile("temp.tif") - - img.save(f, tiffinfo=info) - - loaded = Image.open(f) - - self.assertEqual(loaded.tag[ImageJMetaDataByteCounts], (len(bindata),)) - self.assertEqual(loaded.tag_v2[ImageJMetaDataByteCounts], (len(bindata),)) - - self.assertEqual(loaded.tag[ImageJMetaData], bindata) - self.assertEqual(loaded.tag_v2[ImageJMetaData], bindata) - - self.assertEqual(loaded.tag[ImageDescription], (reloaded_textdata,)) - self.assertEqual(loaded.tag_v2[ImageDescription], reloaded_textdata) - - loaded_float = loaded.tag[tag_ids["RollAngle"]][0] - self.assertAlmostEqual(loaded_float, floatdata, places=5) - loaded_double = loaded.tag[tag_ids["YawAngle"]][0] - self.assertAlmostEqual(loaded_double, doubledata) - - # check with 2 element ImageJMetaDataByteCounts, issue #2006 - - info[ImageJMetaDataByteCounts] = (8, len(bindata) - 8) - img.save(f, tiffinfo=info) - loaded = Image.open(f) - - self.assertEqual(loaded.tag[ImageJMetaDataByteCounts], (8, len(bindata) - 8)) - self.assertEqual(loaded.tag_v2[ImageJMetaDataByteCounts], (8, len(bindata) - 8)) - - def test_read_metadata(self): - img = Image.open("Tests/images/hopper_g4.tif") - - self.assertEqual( - { - "YResolution": IFDRational(4294967295, 113653537), - "PlanarConfiguration": 1, - "BitsPerSample": (1,), - "ImageLength": 128, - "Compression": 4, - "FillOrder": 1, - "RowsPerStrip": 128, - "ResolutionUnit": 3, - "PhotometricInterpretation": 0, - "PageNumber": (0, 1), - "XResolution": IFDRational(4294967295, 113653537), - "ImageWidth": 128, - "Orientation": 1, - "StripByteCounts": (1968,), - "SamplesPerPixel": 1, - "StripOffsets": (8,), - }, - img.tag_v2.named(), - ) - - self.assertEqual( - { - "YResolution": ((4294967295, 113653537),), - "PlanarConfiguration": (1,), - "BitsPerSample": (1,), - "ImageLength": (128,), - "Compression": (4,), - "FillOrder": (1,), - "RowsPerStrip": (128,), - "ResolutionUnit": (3,), - "PhotometricInterpretation": (0,), - "PageNumber": (0, 1), - "XResolution": ((4294967295, 113653537),), - "ImageWidth": (128,), - "Orientation": (1,), - "StripByteCounts": (1968,), - "SamplesPerPixel": (1,), - "StripOffsets": (8,), - }, - img.tag.named(), - ) - - def test_write_metadata(self): - """ Test metadata writing through the python code """ - img = Image.open("Tests/images/hopper.tif") - - f = self.tempfile("temp.tiff") - img.save(f, tiffinfo=img.tag) - - loaded = Image.open(f) - - original = img.tag_v2.named() - reloaded = loaded.tag_v2.named() - - for k, v in original.items(): - if isinstance(v, IFDRational): - original[k] = IFDRational(*_limit_rational(v, 2 ** 31)) - elif isinstance(v, tuple) and isinstance(v[0], IFDRational): - original[k] = tuple( - IFDRational(*_limit_rational(elt, 2 ** 31)) for elt in v - ) - - ignored = ["StripByteCounts", "RowsPerStrip", "PageNumber", "StripOffsets"] - - for tag, value in reloaded.items(): - if tag in ignored: - continue - if isinstance(original[tag], tuple) and isinstance( - original[tag][0], IFDRational - ): - # Need to compare element by element in the tuple, - # not comparing tuples of object references - self.assert_deep_equal( - original[tag], - value, - "%s didn't roundtrip, %s, %s" % (tag, original[tag], value), - ) - else: - self.assertEqual( - original[tag], - value, - "%s didn't roundtrip, %s, %s" % (tag, original[tag], value), - ) - - for tag, value in original.items(): - if tag not in ignored: - self.assertEqual(value, reloaded[tag], "%s didn't roundtrip" % tag) - - def test_no_duplicate_50741_tag(self): - self.assertEqual(tag_ids["MakerNoteSafety"], 50741) - self.assertEqual(tag_ids["BestQualityScale"], 50780) - - def test_empty_metadata(self): - f = io.BytesIO(b"II*\x00\x08\x00\x00\x00") - head = f.read(8) - info = TiffImagePlugin.ImageFileDirectory(head) - # Should not raise struct.error. - self.assert_warning(UserWarning, info.load, f) - - def test_iccprofile(self): - # https://github.com/python-pillow/Pillow/issues/1462 - im = Image.open("Tests/images/hopper.iccprofile.tif") - out = self.tempfile("temp.tiff") - - im.save(out) - reloaded = Image.open(out) - self.assertNotIsInstance(im.info["icc_profile"], tuple) - self.assertEqual(im.info["icc_profile"], reloaded.info["icc_profile"]) - - def test_iccprofile_binary(self): - # https://github.com/python-pillow/Pillow/issues/1526 - # We should be able to load this, - # but probably won't be able to save it. - - im = Image.open("Tests/images/hopper.iccprofile_binary.tif") - self.assertEqual(im.tag_v2.tagtype[34675], 1) - self.assertTrue(im.info["icc_profile"]) - - def test_iccprofile_save_png(self): - im = Image.open("Tests/images/hopper.iccprofile.tif") - outfile = self.tempfile("temp.png") - im.save(outfile) - - def test_iccprofile_binary_save_png(self): - im = Image.open("Tests/images/hopper.iccprofile_binary.tif") - outfile = self.tempfile("temp.png") - im.save(outfile) - - def test_exif_div_zero(self): - im = hopper() - info = TiffImagePlugin.ImageFileDirectory_v2() - info[41988] = TiffImagePlugin.IFDRational(0, 0) - - out = self.tempfile("temp.tiff") - im.save(out, tiffinfo=info, compression="raw") - - reloaded = Image.open(out) - self.assertEqual(0, reloaded.tag_v2[41988].numerator) - self.assertEqual(0, reloaded.tag_v2[41988].denominator) - - def test_expty_values(self): - data = io.BytesIO( - b"II*\x00\x08\x00\x00\x00\x03\x00\x1a\x01\x05\x00\x00\x00\x00\x00" - b"\x00\x00\x00\x00\x1b\x01\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00" - b"\x98\x82\x02\x00\x07\x00\x00\x002\x00\x00\x00\x00\x00\x00\x00a " - b"text\x00\x00" - ) - head = data.read(8) - info = TiffImagePlugin.ImageFileDirectory_v2(head) - info.load(data) - # Should not raise ValueError. - info = dict(info) - self.assertIn(33432, info) - - def test_PhotoshopInfo(self): - im = Image.open("Tests/images/issue_2278.tif") - - self.assertIsInstance(im.tag_v2[34377], bytes) - out = self.tempfile("temp.tiff") - im.save(out) - reloaded = Image.open(out) - self.assertIsInstance(reloaded.tag_v2[34377], bytes) - - def test_too_many_entries(self): - ifd = TiffImagePlugin.ImageFileDirectory_v2() - - # 277: ("SamplesPerPixel", SHORT, 1), - ifd._tagdata[277] = struct.pack("hh", 4, 4) - ifd.tagtype[277] = TiffTags.SHORT - - # Should not raise ValueError. - self.assert_warning(UserWarning, lambda: ifd[277]) diff --git a/Tests/test_file_wal.py b/Tests/test_file_wal.py deleted file mode 100644 index 74c238fc1c6..00000000000 --- a/Tests/test_file_wal.py +++ /dev/null @@ -1,18 +0,0 @@ -from PIL import WalImageFile - -from .helper import PillowTestCase - - -class TestFileWal(PillowTestCase): - def test_open(self): - # Arrange - TEST_FILE = "Tests/images/hopper.wal" - - # Act - im = WalImageFile.open(TEST_FILE) - - # Assert - self.assertEqual(im.format, "WAL") - self.assertEqual(im.format_description, "Quake2 Texture") - self.assertEqual(im.mode, "P") - self.assertEqual(im.size, (128, 128)) diff --git a/Tests/test_file_webp.py b/Tests/test_file_webp.py deleted file mode 100644 index 4d44f47b65c..00000000000 --- a/Tests/test_file_webp.py +++ /dev/null @@ -1,177 +0,0 @@ -from PIL import Image, WebPImagePlugin - -from .helper import PillowTestCase, hopper, unittest - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -class TestUnsupportedWebp(PillowTestCase): - def test_unsupported(self): - if HAVE_WEBP: - WebPImagePlugin.SUPPORTED = False - - file_path = "Tests/images/hopper.webp" - self.assert_warning( - UserWarning, lambda: self.assertRaises(IOError, Image.open, file_path) - ) - - if HAVE_WEBP: - WebPImagePlugin.SUPPORTED = True - - -@unittest.skipIf(not HAVE_WEBP, "WebP support not installed") -class TestFileWebp(PillowTestCase): - def setUp(self): - self.rgb_mode = "RGB" - - def test_version(self): - _webp.WebPDecoderVersion() - _webp.WebPDecoderBuggyAlpha() - - def test_read_rgb(self): - """ - Can we read a RGB mode WebP file without error? - Does it have the bits we expect? - """ - - image = Image.open("Tests/images/hopper.webp") - - self.assertEqual(image.mode, self.rgb_mode) - self.assertEqual(image.size, (128, 128)) - self.assertEqual(image.format, "WEBP") - image.load() - image.getdata() - - # generated with: - # dwebp -ppm ../../Tests/images/hopper.webp -o hopper_webp_bits.ppm - self.assert_image_similar_tofile( - image, "Tests/images/hopper_webp_bits.ppm", 1.0 - ) - - def test_write_rgb(self): - """ - Can we write a RGB mode file to webp without error. - Does it have the bits we expect? - """ - - temp_file = self.tempfile("temp.webp") - - hopper(self.rgb_mode).save(temp_file) - image = Image.open(temp_file) - - self.assertEqual(image.mode, self.rgb_mode) - self.assertEqual(image.size, (128, 128)) - self.assertEqual(image.format, "WEBP") - image.load() - image.getdata() - - # generated with: dwebp -ppm temp.webp -o hopper_webp_write.ppm - self.assert_image_similar_tofile( - image, "Tests/images/hopper_webp_write.ppm", 12.0 - ) - - # This test asserts that the images are similar. If the average pixel - # difference between the two images is less than the epsilon value, - # then we're going to accept that it's a reasonable lossy version of - # the image. The old lena images for WebP are showing ~16 on - # Ubuntu, the jpegs are showing ~18. - target = hopper(self.rgb_mode) - self.assert_image_similar(image, target, 12.0) - - def test_write_unsupported_mode_L(self): - """ - Saving a black-and-white file to WebP format should work, and be - similar to the original file. - """ - - temp_file = self.tempfile("temp.webp") - hopper("L").save(temp_file) - image = Image.open(temp_file) - - self.assertEqual(image.mode, self.rgb_mode) - self.assertEqual(image.size, (128, 128)) - self.assertEqual(image.format, "WEBP") - - image.load() - image.getdata() - target = hopper("L").convert(self.rgb_mode) - - self.assert_image_similar(image, target, 10.0) - - def test_write_unsupported_mode_P(self): - """ - Saving a palette-based file to WebP format should work, and be - similar to the original file. - """ - - temp_file = self.tempfile("temp.webp") - hopper("P").save(temp_file) - image = Image.open(temp_file) - - self.assertEqual(image.mode, self.rgb_mode) - self.assertEqual(image.size, (128, 128)) - self.assertEqual(image.format, "WEBP") - - image.load() - image.getdata() - target = hopper("P").convert(self.rgb_mode) - - self.assert_image_similar(image, target, 50.0) - - def test_WebPEncode_with_invalid_args(self): - """ - Calling encoder functions with no arguments should result in an error. - """ - - if _webp.HAVE_WEBPANIM: - self.assertRaises(TypeError, _webp.WebPAnimEncoder) - self.assertRaises(TypeError, _webp.WebPEncode) - - def test_WebPDecode_with_invalid_args(self): - """ - Calling decoder functions with no arguments should result in an error. - """ - - if _webp.HAVE_WEBPANIM: - self.assertRaises(TypeError, _webp.WebPAnimDecoder) - self.assertRaises(TypeError, _webp.WebPDecode) - - def test_no_resource_warning(self): - file_path = "Tests/images/hopper.webp" - image = Image.open(file_path) - - temp_file = self.tempfile("temp.webp") - self.assert_warning(None, image.save, temp_file) - - def test_file_pointer_could_be_reused(self): - file_path = "Tests/images/hopper.webp" - with open(file_path, "rb") as blob: - Image.open(blob).load() - Image.open(blob).load() - - @unittest.skipUnless( - HAVE_WEBP and _webp.HAVE_WEBPANIM, "WebP save all not available" - ) - def test_background_from_gif(self): - im = Image.open("Tests/images/chi.gif") - original_value = im.convert("RGB").getpixel((1, 1)) - - # Save as WEBP - out_webp = self.tempfile("temp.webp") - im.save(out_webp, save_all=True) - - # Save as GIF - out_gif = self.tempfile("temp.gif") - Image.open(out_webp).save(out_gif) - - reread = Image.open(out_gif) - reread_value = reread.convert("RGB").getpixel((1, 1)) - difference = sum( - [abs(original_value[i] - reread_value[i]) for i in range(0, 3)] - ) - self.assertLess(difference, 5) diff --git a/Tests/test_file_webp_alpha.py b/Tests/test_file_webp_alpha.py deleted file mode 100644 index f2f10d7b72e..00000000000 --- a/Tests/test_file_webp_alpha.py +++ /dev/null @@ -1,117 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper, unittest - -try: - from PIL import _webp -except ImportError: - _webp = None - - -@unittest.skipIf(_webp is None, "WebP support not installed") -class TestFileWebpAlpha(PillowTestCase): - def setUp(self): - if _webp.WebPDecoderBuggyAlpha(self): - self.skipTest( - "Buggy early version of WebP installed, not testing transparency" - ) - - def test_read_rgba(self): - """ - Can we read an RGBA mode file without error? - Does it have the bits we expect? - """ - - # Generated with `cwebp transparent.png -o transparent.webp` - file_path = "Tests/images/transparent.webp" - image = Image.open(file_path) - - self.assertEqual(image.mode, "RGBA") - self.assertEqual(image.size, (200, 150)) - self.assertEqual(image.format, "WEBP") - image.load() - image.getdata() - - image.tobytes() - - target = Image.open("Tests/images/transparent.png") - self.assert_image_similar(image, target, 20.0) - - def test_write_lossless_rgb(self): - """ - Can we write an RGBA mode file with lossless compression without - error? Does it have the bits we expect? - """ - - temp_file = self.tempfile("temp.webp") - # temp_file = "temp.webp" - - pil_image = hopper("RGBA") - - mask = Image.new("RGBA", (64, 64), (128, 128, 128, 128)) - # Add some partially transparent bits: - pil_image.paste(mask, (0, 0), mask) - - pil_image.save(temp_file, lossless=True) - - image = Image.open(temp_file) - image.load() - - self.assertEqual(image.mode, "RGBA") - self.assertEqual(image.size, pil_image.size) - self.assertEqual(image.format, "WEBP") - image.load() - image.getdata() - - self.assert_image_equal(image, pil_image) - - def test_write_rgba(self): - """ - Can we write a RGBA mode file to webp without error. - Does it have the bits we expect? - """ - - temp_file = self.tempfile("temp.webp") - - pil_image = Image.new("RGBA", (10, 10), (255, 0, 0, 20)) - pil_image.save(temp_file) - - if _webp.WebPDecoderBuggyAlpha(self): - return - - image = Image.open(temp_file) - image.load() - - self.assertEqual(image.mode, "RGBA") - self.assertEqual(image.size, (10, 10)) - self.assertEqual(image.format, "WEBP") - image.load() - image.getdata() - - # early versions of webp are known to produce higher deviations: - # deal with it - if _webp.WebPDecoderVersion(self) <= 0x201: - self.assert_image_similar(image, pil_image, 3.0) - else: - self.assert_image_similar(image, pil_image, 1.0) - - def test_write_unsupported_mode_PA(self): - """ - Saving a palette-based file with transparency to WebP format - should work, and be similar to the original file. - """ - - temp_file = self.tempfile("temp.webp") - file_path = "Tests/images/transparent.gif" - Image.open(file_path).save(temp_file) - image = Image.open(temp_file) - - self.assertEqual(image.mode, "RGBA") - self.assertEqual(image.size, (200, 150)) - self.assertEqual(image.format, "WEBP") - - image.load() - image.getdata() - target = Image.open(file_path).convert("RGBA") - - self.assert_image_similar(image, target, 25.0) diff --git a/Tests/test_file_webp_animated.py b/Tests/test_file_webp_animated.py deleted file mode 100644 index dec74d0d044..00000000000 --- a/Tests/test_file_webp_animated.py +++ /dev/null @@ -1,165 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -class TestFileWebpAnimation(PillowTestCase): - def setUp(self): - if not HAVE_WEBP: - self.skipTest("WebP support not installed") - return - - if not _webp.HAVE_WEBPANIM: - self.skipTest( - "WebP library does not contain animation support, " - "not testing animation" - ) - - def test_n_frames(self): - """ - Ensure that WebP format sets n_frames and is_animated - attributes correctly. - """ - - im = Image.open("Tests/images/hopper.webp") - self.assertEqual(im.n_frames, 1) - self.assertFalse(im.is_animated) - - im = Image.open("Tests/images/iss634.webp") - self.assertEqual(im.n_frames, 42) - self.assertTrue(im.is_animated) - - def test_write_animation_L(self): - """ - Convert an animated GIF to animated WebP, then compare the - frame count, and first and last frames to ensure they're - visually similar. - """ - - orig = Image.open("Tests/images/iss634.gif") - self.assertGreater(orig.n_frames, 1) - - temp_file = self.tempfile("temp.webp") - orig.save(temp_file, save_all=True) - im = Image.open(temp_file) - self.assertEqual(im.n_frames, orig.n_frames) - - # Compare first and last frames to the original animated GIF - orig.load() - im.load() - self.assert_image_similar(im, orig.convert("RGBA"), 25.0) - orig.seek(orig.n_frames - 1) - im.seek(im.n_frames - 1) - orig.load() - im.load() - self.assert_image_similar(im, orig.convert("RGBA"), 25.0) - - def test_write_animation_RGB(self): - """ - Write an animated WebP from RGB frames, and ensure the frames - are visually similar to the originals. - """ - - def check(temp_file): - im = Image.open(temp_file) - self.assertEqual(im.n_frames, 2) - - # Compare first frame to original - im.load() - self.assert_image_equal(im, frame1.convert("RGBA")) - - # Compare second frame to original - im.seek(1) - im.load() - self.assert_image_equal(im, frame2.convert("RGBA")) - - frame1 = Image.open("Tests/images/anim_frame1.webp") - frame2 = Image.open("Tests/images/anim_frame2.webp") - - temp_file1 = self.tempfile("temp.webp") - frame1.copy().save( - temp_file1, save_all=True, append_images=[frame2], lossless=True - ) - check(temp_file1) - - # Tests appending using a generator - def imGenerator(ims): - for im in ims: - yield im - - temp_file2 = self.tempfile("temp_generator.webp") - frame1.copy().save( - temp_file2, - save_all=True, - append_images=imGenerator([frame2]), - lossless=True, - ) - check(temp_file2) - - def test_timestamp_and_duration(self): - """ - Try passing a list of durations, and make sure the encoded - timestamps and durations are correct. - """ - - durations = [0, 10, 20, 30, 40] - temp_file = self.tempfile("temp.webp") - frame1 = Image.open("Tests/images/anim_frame1.webp") - frame2 = Image.open("Tests/images/anim_frame2.webp") - frame1.save( - temp_file, - save_all=True, - append_images=[frame2, frame1, frame2, frame1], - duration=durations, - ) - - im = Image.open(temp_file) - self.assertEqual(im.n_frames, 5) - self.assertTrue(im.is_animated) - - # Check that timestamps and durations match original values specified - ts = 0 - for frame in range(im.n_frames): - im.seek(frame) - im.load() - self.assertEqual(im.info["duration"], durations[frame]) - self.assertEqual(im.info["timestamp"], ts) - ts += durations[frame] - - def test_seeking(self): - """ - Create an animated WebP file, and then try seeking through - frames in reverse-order, verifying the timestamps and durations - are correct. - """ - - dur = 33 - temp_file = self.tempfile("temp.webp") - frame1 = Image.open("Tests/images/anim_frame1.webp") - frame2 = Image.open("Tests/images/anim_frame2.webp") - frame1.save( - temp_file, - save_all=True, - append_images=[frame2, frame1, frame2, frame1], - duration=dur, - ) - - im = Image.open(temp_file) - self.assertEqual(im.n_frames, 5) - self.assertTrue(im.is_animated) - - # Traverse frames in reverse, checking timestamps and durations - ts = dur * (im.n_frames - 1) - for frame in reversed(range(im.n_frames)): - im.seek(frame) - im.load() - self.assertEqual(im.info["duration"], dur) - self.assertEqual(im.info["timestamp"], ts) - ts -= dur diff --git a/Tests/test_file_webp_lossless.py b/Tests/test_file_webp_lossless.py deleted file mode 100644 index 2eff4152911..00000000000 --- a/Tests/test_file_webp_lossless.py +++ /dev/null @@ -1,38 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -class TestFileWebpLossless(PillowTestCase): - def setUp(self): - if not HAVE_WEBP: - self.skipTest("WebP support not installed") - return - - if _webp.WebPDecoderVersion() < 0x0200: - self.skipTest("lossless not included") - - self.rgb_mode = "RGB" - - def test_write_lossless_rgb(self): - temp_file = self.tempfile("temp.webp") - - hopper(self.rgb_mode).save(temp_file, lossless=True) - - image = Image.open(temp_file) - image.load() - - self.assertEqual(image.mode, self.rgb_mode) - self.assertEqual(image.size, (128, 128)) - self.assertEqual(image.format, "WEBP") - image.load() - image.getdata() - - self.assert_image_equal(image, hopper(self.rgb_mode)) diff --git a/Tests/test_file_webp_metadata.py b/Tests/test_file_webp_metadata.py deleted file mode 100644 index ae528e3bf16..00000000000 --- a/Tests/test_file_webp_metadata.py +++ /dev/null @@ -1,139 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -class TestFileWebpMetadata(PillowTestCase): - def setUp(self): - if not HAVE_WEBP: - self.skipTest("WebP support not installed") - return - - if not _webp.HAVE_WEBPMUX: - self.skipTest("WebPMux support not installed") - - def test_read_exif_metadata(self): - - file_path = "Tests/images/flower.webp" - image = Image.open(file_path) - - self.assertEqual(image.format, "WEBP") - exif_data = image.info.get("exif", None) - self.assertTrue(exif_data) - - exif = image._getexif() - - # camera make - self.assertEqual(exif[271], "Canon") - - jpeg_image = Image.open("Tests/images/flower.jpg") - expected_exif = jpeg_image.info["exif"] - - self.assertEqual(exif_data, expected_exif) - - def test_write_exif_metadata(self): - from io import BytesIO - - file_path = "Tests/images/flower.jpg" - image = Image.open(file_path) - expected_exif = image.info["exif"] - - test_buffer = BytesIO() - - image.save(test_buffer, "webp", exif=expected_exif) - - test_buffer.seek(0) - webp_image = Image.open(test_buffer) - - webp_exif = webp_image.info.get("exif", None) - self.assertTrue(webp_exif) - if webp_exif: - self.assertEqual(webp_exif, expected_exif, "WebP EXIF didn't match") - - def test_read_icc_profile(self): - - file_path = "Tests/images/flower2.webp" - image = Image.open(file_path) - - self.assertEqual(image.format, "WEBP") - self.assertTrue(image.info.get("icc_profile", None)) - - icc = image.info["icc_profile"] - - jpeg_image = Image.open("Tests/images/flower2.jpg") - expected_icc = jpeg_image.info["icc_profile"] - - self.assertEqual(icc, expected_icc) - - def test_write_icc_metadata(self): - from io import BytesIO - - file_path = "Tests/images/flower2.jpg" - image = Image.open(file_path) - expected_icc_profile = image.info["icc_profile"] - - test_buffer = BytesIO() - - image.save(test_buffer, "webp", icc_profile=expected_icc_profile) - - test_buffer.seek(0) - webp_image = Image.open(test_buffer) - - webp_icc_profile = webp_image.info.get("icc_profile", None) - - self.assertTrue(webp_icc_profile) - if webp_icc_profile: - self.assertEqual( - webp_icc_profile, expected_icc_profile, "Webp ICC didn't match" - ) - - def test_read_no_exif(self): - from io import BytesIO - - file_path = "Tests/images/flower.jpg" - image = Image.open(file_path) - self.assertIn("exif", image.info) - - test_buffer = BytesIO() - - image.save(test_buffer, "webp") - - test_buffer.seek(0) - webp_image = Image.open(test_buffer) - - self.assertFalse(webp_image._getexif()) - - def test_write_animated_metadata(self): - if not _webp.HAVE_WEBPANIM: - self.skipTest("WebP animation support not available") - - iccp_data = "".encode("utf-8") - exif_data = "".encode("utf-8") - xmp_data = "".encode("utf-8") - - temp_file = self.tempfile("temp.webp") - frame1 = Image.open("Tests/images/anim_frame1.webp") - frame2 = Image.open("Tests/images/anim_frame2.webp") - frame1.save( - temp_file, - save_all=True, - append_images=[frame2, frame1, frame2], - icc_profile=iccp_data, - exif=exif_data, - xmp=xmp_data, - ) - - image = Image.open(temp_file) - self.assertIn("icc_profile", image.info) - self.assertIn("exif", image.info) - self.assertIn("xmp", image.info) - self.assertEqual(iccp_data, image.info.get("icc_profile", None)) - self.assertEqual(exif_data, image.info.get("exif", None)) - self.assertEqual(xmp_data, image.info.get("xmp", None)) diff --git a/Tests/test_file_wmf.py b/Tests/test_file_wmf.py deleted file mode 100644 index cea0cec5bd8..00000000000 --- a/Tests/test_file_wmf.py +++ /dev/null @@ -1,61 +0,0 @@ -from PIL import Image, WmfImagePlugin - -from .helper import PillowTestCase, hopper - - -class TestFileWmf(PillowTestCase): - def test_load_raw(self): - - # Test basic EMF open and rendering - im = Image.open("Tests/images/drawing.emf") - if hasattr(Image.core, "drawwmf"): - # Currently, support for WMF/EMF is Windows-only - im.load() - # Compare to reference rendering - imref = Image.open("Tests/images/drawing_emf_ref.png") - imref.load() - self.assert_image_similar(im, imref, 0) - - # Test basic WMF open and rendering - im = Image.open("Tests/images/drawing.wmf") - if hasattr(Image.core, "drawwmf"): - # Currently, support for WMF/EMF is Windows-only - im.load() - # Compare to reference rendering - imref = Image.open("Tests/images/drawing_wmf_ref.png") - imref.load() - self.assert_image_similar(im, imref, 2.0) - - def test_register_handler(self): - class TestHandler: - methodCalled = False - - def save(self, im, fp, filename): - self.methodCalled = True - - handler = TestHandler() - WmfImagePlugin.register_handler(handler) - - im = hopper() - tmpfile = self.tempfile("temp.wmf") - im.save(tmpfile) - self.assertTrue(handler.methodCalled) - - # Restore the state before this test - WmfImagePlugin.register_handler(None) - - def test_load_dpi_rounding(self): - # Round up - im = Image.open("Tests/images/drawing.emf") - self.assertEqual(im.info["dpi"], 1424) - - # Round down - im = Image.open("Tests/images/drawing_roundDown.emf") - self.assertEqual(im.info["dpi"], 1426) - - def test_save(self): - im = hopper() - - for ext in [".wmf", ".emf"]: - tmpfile = self.tempfile("temp" + ext) - self.assertRaises(IOError, im.save, tmpfile) diff --git a/Tests/test_file_xbm.py b/Tests/test_file_xbm.py deleted file mode 100644 index 9693ba05a86..00000000000 --- a/Tests/test_file_xbm.py +++ /dev/null @@ -1,61 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - -PIL151 = b""" -#define basic_width 32 -#define basic_height 32 -static char basic_bits[] = { -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, -0x80, 0xff, 0xff, 0x01, 0x40, 0x00, 0x00, 0x02, -0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x08, -0x10, 0x00, 0x00, 0x08, -0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, -0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x08, -0x20, 0x00, 0x00, 0x04, -0x20, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x02, -0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, -}; -""" - - -class TestFileXbm(PillowTestCase): - def test_pil151(self): - from io import BytesIO - - im = Image.open(BytesIO(PIL151)) - - im.load() - self.assertEqual(im.mode, "1") - self.assertEqual(im.size, (32, 32)) - - def test_open(self): - # Arrange - # Created with `convert hopper.png hopper.xbm` - filename = "Tests/images/hopper.xbm" - - # Act - im = Image.open(filename) - - # Assert - self.assertEqual(im.mode, "1") - self.assertEqual(im.size, (128, 128)) - - def test_open_filename_with_underscore(self): - # Arrange - # Created with `convert hopper.png hopper_underscore.xbm` - filename = "Tests/images/hopper_underscore.xbm" - - # Act - im = Image.open(filename) - - # Assert - self.assertEqual(im.mode, "1") - self.assertEqual(im.size, (128, 128)) diff --git a/Tests/test_file_xpm.py b/Tests/test_file_xpm.py deleted file mode 100644 index a49b7c8dd10..00000000000 --- a/Tests/test_file_xpm.py +++ /dev/null @@ -1,33 +0,0 @@ -from PIL import Image, XpmImagePlugin - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/hopper.xpm" - - -class TestFileXpm(PillowTestCase): - def test_sanity(self): - im = Image.open(TEST_FILE) - im.load() - self.assertEqual(im.mode, "P") - 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"), hopper("RGB"), 60) - - def test_invalid_file(self): - invalid_file = "Tests/images/flower.jpg" - - self.assertRaises(SyntaxError, XpmImagePlugin.XpmImageFile, invalid_file) - - def test_load_read(self): - # Arrange - im = Image.open(TEST_FILE) - dummy_bytes = 1 - - # Act - data = im.load_read(dummy_bytes) - - # Assert - self.assertEqual(len(data), 16384) diff --git a/Tests/test_file_xvthumb.py b/Tests/test_file_xvthumb.py deleted file mode 100644 index f8b6d35314f..00000000000 --- a/Tests/test_file_xvthumb.py +++ /dev/null @@ -1,35 +0,0 @@ -from PIL import Image, XVThumbImagePlugin - -from .helper import PillowTestCase, hopper - -TEST_FILE = "Tests/images/hopper.p7" - - -class TestFileXVThumb(PillowTestCase): - def test_open(self): - # Act - im = Image.open(TEST_FILE) - - # Assert - self.assertEqual(im.format, "XVThumb") - - # Create a Hopper image with a similar XV palette - im_hopper = hopper().quantize(palette=im) - self.assert_image_similar(im, im_hopper, 9) - - def test_unexpected_eof(self): - # Test unexpected EOF reading XV thumbnail file - # Arrange - bad_file = "Tests/images/hopper_bad.p7" - - # Act / Assert - self.assertRaises(SyntaxError, XVThumbImagePlugin.XVThumbImageFile, bad_file) - - def test_invalid_file(self): - # Arrange - invalid_file = "Tests/images/flower.jpg" - - # Act / Assert - self.assertRaises( - SyntaxError, XVThumbImagePlugin.XVThumbImageFile, invalid_file - ) diff --git a/Tests/test_font_bdf.py b/Tests/test_font_bdf.py deleted file mode 100644 index 9b3a342d02f..00000000000 --- a/Tests/test_font_bdf.py +++ /dev/null @@ -1,19 +0,0 @@ -from PIL import BdfFontFile, FontFile - -from .helper import PillowTestCase - -filename = "Tests/images/courB08.bdf" - - -class TestFontBdf(PillowTestCase): - def test_sanity(self): - - with open(filename, "rb") as test_file: - font = BdfFontFile.BdfFontFile(test_file) - - self.assertIsInstance(font, FontFile.FontFile) - self.assertEqual(len([_f for _f in font.glyph if _f]), 190) - - def test_invalid_file(self): - with open("Tests/images/flower.jpg", "rb") as fp: - self.assertRaises(SyntaxError, BdfFontFile.BdfFontFile, fp) diff --git a/Tests/test_font_leaks.py b/Tests/test_font_leaks.py deleted file mode 100644 index 14b36858523..00000000000 --- a/Tests/test_font_leaks.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import division - -import sys - -from PIL import Image, ImageDraw, ImageFont, features - -from .helper import PillowLeakTestCase, unittest - - -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") -class TestTTypeFontLeak(PillowLeakTestCase): - # fails at iteration 3 in master - iterations = 10 - mem_limit = 4096 # k - - def _test_font(self, font): - im = Image.new("RGB", (255, 255), "white") - draw = ImageDraw.ImageDraw(im) - self._test_leak( - lambda: draw.text( - (0, 0), "some text " * 1024, font=font, fill="black" # ~10k - ) - ) - - @unittest.skipIf(not features.check("freetype2"), "Test requires freetype2") - def test_leak(self): - ttype = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 20) - self._test_font(ttype) - - -class TestDefaultFontLeak(TestTTypeFontLeak): - # fails at iteration 37 in master - iterations = 100 - mem_limit = 1024 # k - - def test_leak(self): - default_font = ImageFont.load_default() - self._test_font(default_font) diff --git a/Tests/test_font_pcf.py b/Tests/test_font_pcf.py deleted file mode 100644 index a2b4ef27e8d..00000000000 --- a/Tests/test_font_pcf.py +++ /dev/null @@ -1,79 +0,0 @@ -from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile -from PIL._util import py3 - -from .helper import PillowTestCase - -codecs = dir(Image.core) - -fontname = "Tests/fonts/10x20-ISO8859-1.pcf" - -message = "hello, world" - - -class TestFontPcf(PillowTestCase): - def setUp(self): - if "zip_encoder" not in codecs or "zip_decoder" not in codecs: - self.skipTest("zlib support not available") - - def save_font(self): - with open(fontname, "rb") as test_file: - font = PcfFontFile.PcfFontFile(test_file) - self.assertIsInstance(font, FontFile.FontFile) - # check the number of characters in the font - self.assertEqual(len([_f for _f in font.glyph if _f]), 223) - - tempname = self.tempfile("temp.pil") - self.addCleanup(self.delete_tempfile, tempname[:-4] + ".pbm") - font.save(tempname) - - with Image.open(tempname.replace(".pil", ".pbm")) as loaded: - with Image.open("Tests/fonts/10x20.pbm") as target: - self.assert_image_equal(loaded, target) - - with open(tempname, "rb") as f_loaded: - with open("Tests/fonts/10x20.pil", "rb") as f_target: - self.assertEqual(f_loaded.read(), f_target.read()) - return tempname - - def test_sanity(self): - self.save_font() - - def test_invalid_file(self): - with open("Tests/images/flower.jpg", "rb") as fp: - self.assertRaises(SyntaxError, PcfFontFile.PcfFontFile, fp) - - def test_draw(self): - tempname = self.save_font() - font = ImageFont.load(tempname) - im = Image.new("L", (130, 30), "white") - draw = ImageDraw.Draw(im) - draw.text((0, 0), message, "black", font=font) - with Image.open("Tests/images/test_draw_pbm_target.png") as target: - self.assert_image_similar(im, target, 0) - - def test_textsize(self): - tempname = self.save_font() - font = ImageFont.load(tempname) - for i in range(255): - (dx, dy) = font.getsize(chr(i)) - self.assertEqual(dy, 20) - self.assertIn(dx, (0, 10)) - for l in range(len(message)): - msg = message[: l + 1] - self.assertEqual(font.getsize(msg), (len(msg) * 10, 20)) - - def _test_high_characters(self, message): - tempname = self.save_font() - font = ImageFont.load(tempname) - im = Image.new("L", (750, 30), "white") - draw = ImageDraw.Draw(im) - draw.text((0, 0), message, "black", font=font) - with Image.open("Tests/images/high_ascii_chars.png") as target: - self.assert_image_similar(im, target, 0) - - def test_high_characters(self): - message = "".join(chr(i + 1) for i in range(140, 232)) - self._test_high_characters(message) - # accept bytes instances in Py3. - if py3: - self._test_high_characters(message.encode("latin1")) diff --git a/Tests/test_format_hsv.py b/Tests/test_format_hsv.py deleted file mode 100644 index ce0524e1e22..00000000000 --- a/Tests/test_format_hsv.py +++ /dev/null @@ -1,154 +0,0 @@ -import colorsys -import itertools - -from PIL import Image -from PIL._util import py3 - -from .helper import PillowTestCase, hopper - - -class TestFormatHSV(PillowTestCase): - def int_to_float(self, i): - return float(i) / 255.0 - - def str_to_float(self, i): - return float(ord(i)) / 255.0 - - def tuple_to_ints(self, tp): - x, y, z = tp - return int(x * 255.0), int(y * 255.0), int(z * 255.0) - - def test_sanity(self): - Image.new("HSV", (100, 100)) - - def wedge(self): - w = Image._wedge() - w90 = w.rotate(90) - - (px, h) = w.size - - r = Image.new("L", (px * 3, h)) - g = r.copy() - b = r.copy() - - r.paste(w, (0, 0)) - r.paste(w90, (px, 0)) - - g.paste(w90, (0, 0)) - g.paste(w, (2 * px, 0)) - - b.paste(w, (px, 0)) - b.paste(w90, (2 * px, 0)) - - img = Image.merge("RGB", (r, g, b)) - - return img - - def to_xxx_colorsys(self, im, func, mode): - # convert the hard way using the library colorsys routines. - - (r, g, b) = im.split() - - if py3: - conv_func = self.int_to_float - else: - conv_func = self.str_to_float - - if hasattr(itertools, "izip"): - iter_helper = itertools.izip - else: - iter_helper = itertools.zip_longest - - converted = [ - self.tuple_to_ints(func(conv_func(_r), conv_func(_g), conv_func(_b))) - for (_r, _g, _b) in iter_helper(r.tobytes(), g.tobytes(), b.tobytes()) - ] - - if py3: - new_bytes = b"".join( - bytes(chr(h) + chr(s) + chr(v), "latin-1") for (h, s, v) in converted - ) - else: - new_bytes = b"".join(chr(h) + chr(s) + chr(v) for (h, s, v) in converted) - - hsv = Image.frombytes(mode, r.size, new_bytes) - - return hsv - - def to_hsv_colorsys(self, im): - return self.to_xxx_colorsys(im, colorsys.rgb_to_hsv, "HSV") - - def to_rgb_colorsys(self, im): - return self.to_xxx_colorsys(im, colorsys.hsv_to_rgb, "RGB") - - def test_wedge(self): - src = self.wedge().resize((3 * 32, 32), Image.BILINEAR) - im = src.convert("HSV") - comparable = self.to_hsv_colorsys(src) - - self.assert_image_similar( - im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong" - ) - self.assert_image_similar( - im.getchannel(1), - comparable.getchannel(1), - 1, - "Saturation conversion is wrong", - ) - self.assert_image_similar( - im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong" - ) - - comparable = src - im = im.convert("RGB") - - self.assert_image_similar( - im.getchannel(0), comparable.getchannel(0), 3, "R conversion is wrong" - ) - self.assert_image_similar( - im.getchannel(1), comparable.getchannel(1), 3, "G conversion is wrong" - ) - self.assert_image_similar( - im.getchannel(2), comparable.getchannel(2), 3, "B conversion is wrong" - ) - - def test_convert(self): - im = hopper("RGB").convert("HSV") - comparable = self.to_hsv_colorsys(hopper("RGB")) - - self.assert_image_similar( - im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong" - ) - self.assert_image_similar( - im.getchannel(1), - comparable.getchannel(1), - 1, - "Saturation conversion is wrong", - ) - self.assert_image_similar( - im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong" - ) - - def test_hsv_to_rgb(self): - comparable = self.to_hsv_colorsys(hopper("RGB")) - converted = comparable.convert("RGB") - comparable = self.to_rgb_colorsys(comparable) - - self.assert_image_similar( - converted.getchannel(0), - comparable.getchannel(0), - 3, - "R conversion is wrong", - ) - self.assert_image_similar( - converted.getchannel(1), - comparable.getchannel(1), - 3, - "G conversion is wrong", - ) - self.assert_image_similar( - converted.getchannel(2), - comparable.getchannel(2), - 3, - "B conversion is wrong", - ) diff --git a/Tests/test_format_lab.py b/Tests/test_format_lab.py deleted file mode 100644 index a98c2057901..00000000000 --- a/Tests/test_format_lab.py +++ /dev/null @@ -1,41 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestFormatLab(PillowTestCase): - def test_white(self): - i = Image.open("Tests/images/lab.tif") - - i.load() - - self.assertEqual(i.mode, "LAB") - - self.assertEqual(i.getbands(), ("L", "A", "B")) - - k = i.getpixel((0, 0)) - self.assertEqual(k, (255, 128, 128)) - - L = i.getdata(0) - a = i.getdata(1) - b = i.getdata(2) - - self.assertEqual(list(L), [255] * 100) - self.assertEqual(list(a), [128] * 100) - self.assertEqual(list(b), [128] * 100) - - def test_green(self): - # l= 50 (/100), a = -100 (-128 .. 128) b=0 in PS - # == RGB: 0, 152, 117 - i = Image.open("Tests/images/lab-green.tif") - - k = i.getpixel((0, 0)) - self.assertEqual(k, (128, 28, 128)) - - def test_red(self): - # l= 50 (/100), a = 100 (-128 .. 128) b=0 in PS - # == RGB: 255, 0, 124 - i = Image.open("Tests/images/lab-red.tif") - - k = i.getpixel((0, 0)) - self.assertEqual(k, (128, 228, 128)) diff --git a/Tests/test_image.py b/Tests/test_image.py deleted file mode 100644 index 493b4735acd..00000000000 --- a/Tests/test_image.py +++ /dev/null @@ -1,622 +0,0 @@ -import os -import shutil -import sys - -from PIL import Image -from PIL._util import py3 - -from .helper import PillowTestCase, hopper, unittest - - -class TestImage(PillowTestCase): - def test_image_modes_success(self): - for mode in [ - "1", - "P", - "PA", - "L", - "LA", - "La", - "F", - "I", - "I;16", - "I;16L", - "I;16B", - "I;16N", - "RGB", - "RGBX", - "RGBA", - "RGBa", - "CMYK", - "YCbCr", - "LAB", - "HSV", - ]: - Image.new(mode, (1, 1)) - - def test_image_modes_fail(self): - for mode in [ - "", - "bad", - "very very long", - "BGR;15", - "BGR;16", - "BGR;24", - "BGR;32", - ]: - with self.assertRaises(ValueError) as e: - Image.new(mode, (1, 1)) - self.assertEqual(str(e.exception), "unrecognized image mode") - - def test_sanity(self): - - im = Image.new("L", (100, 100)) - self.assertEqual(repr(im)[:45], "= 3 - wchar_t *whome = Py_DecodeLocale(home, NULL); - Py_SetPythonHome(whome); -#else - Py_SetPythonHome(home); -#endif - - Py_InitializeEx(0); - Py_DECREF(PyImport_ImportModule("PIL.Image")); - Py_Finalize(); - - Py_InitializeEx(0); - Py_DECREF(PyImport_ImportModule("PIL.Image")); - Py_Finalize(); - -#if PY_MAJOR_VERSION >= 3 - PyMem_RawFree(whome); -#endif - - return 0; -} - """ - % sys.prefix.replace("\\", "\\\\") - ) - - compiler = ccompiler.new_compiler() - compiler.add_include_dir(sysconfig.get_python_inc()) - - libdir = sysconfig.get_config_var( - "LIBDIR" - ) or sysconfig.get_python_inc().replace("include", "libs") - print(libdir) - compiler.add_library_dir(libdir) - objects = compiler.compile(["embed_pil.c"]) - compiler.link_executable(objects, "embed_pil") - - env = os.environ.copy() - env["PATH"] = sys.prefix + ";" + env["PATH"] - - # do not display the Windows Error Reporting dialog - ctypes.windll.kernel32.SetErrorMode(0x0002) - - process = subprocess.Popen(["embed_pil.exe"], env=env) - process.communicate() - self.assertEqual(process.returncode, 0) diff --git a/Tests/test_image_array.py b/Tests/test_image_array.py deleted file mode 100644 index 02e5c80f2a0..00000000000 --- a/Tests/test_image_array.py +++ /dev/null @@ -1,54 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - -im = hopper().resize((128, 100)) - - -class TestImageArray(PillowTestCase): - def test_toarray(self): - def test(mode): - ai = im.convert(mode).__array_interface__ - return ai["version"], ai["shape"], ai["typestr"], len(ai["data"]) - - # self.assertEqual(test("1"), (3, (100, 128), '|b1', 1600)) - self.assertEqual(test("L"), (3, (100, 128), "|u1", 12800)) - - # FIXME: wrong? - self.assertEqual(test("I"), (3, (100, 128), Image._ENDIAN + "i4", 51200)) - # FIXME: wrong? - self.assertEqual(test("F"), (3, (100, 128), Image._ENDIAN + "f4", 51200)) - - self.assertEqual(test("LA"), (3, (100, 128, 2), "|u1", 25600)) - self.assertEqual(test("RGB"), (3, (100, 128, 3), "|u1", 38400)) - self.assertEqual(test("RGBA"), (3, (100, 128, 4), "|u1", 51200)) - self.assertEqual(test("RGBX"), (3, (100, 128, 4), "|u1", 51200)) - - def test_fromarray(self): - class Wrapper(object): - """ Class with API matching Image.fromarray """ - - def __init__(self, img, arr_params): - self.img = img - self.__array_interface__ = arr_params - - def tobytes(self): - return self.img.tobytes() - - def test(mode): - i = im.convert(mode) - a = i.__array_interface__ - a["strides"] = 1 # pretend it's non-contiguous - # Make wrapper instance for image, new array interface - wrapped = Wrapper(i, a) - out = Image.fromarray(wrapped) - return out.mode, out.size, list(i.getdata()) == list(out.getdata()) - - # self.assertEqual(test("1"), ("1", (128, 100), True)) - self.assertEqual(test("L"), ("L", (128, 100), True)) - self.assertEqual(test("I"), ("I", (128, 100), True)) - self.assertEqual(test("F"), ("F", (128, 100), True)) - self.assertEqual(test("LA"), ("LA", (128, 100), True)) - self.assertEqual(test("RGB"), ("RGB", (128, 100), True)) - self.assertEqual(test("RGBA"), ("RGBA", (128, 100), True)) - self.assertEqual(test("RGBX"), ("RGBA", (128, 100), True)) diff --git a/Tests/test_image_convert.py b/Tests/test_image_convert.py deleted file mode 100644 index 96ecf8996c9..00000000000 --- a/Tests/test_image_convert.py +++ /dev/null @@ -1,240 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageConvert(PillowTestCase): - def test_sanity(self): - def convert(im, mode): - out = im.convert(mode) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size) - - modes = ( - "1", - "L", - "LA", - "P", - "PA", - "I", - "F", - "RGB", - "RGBA", - "RGBX", - "CMYK", - "YCbCr", - ) - - for mode in modes: - im = hopper(mode) - for mode in modes: - convert(im, mode) - - # Check 0 - im = Image.new(mode, (0, 0)) - for mode in modes: - convert(im, mode) - - def test_default(self): - - im = hopper("P") - self.assert_image(im, "P", im.size) - im = im.convert() - self.assert_image(im, "RGB", im.size) - im = im.convert() - self.assert_image(im, "RGB", im.size) - - # ref https://github.com/python-pillow/Pillow/issues/274 - - def _test_float_conversion(self, im): - orig = im.getpixel((5, 5)) - converted = im.convert("F").getpixel((5, 5)) - self.assertEqual(orig, converted) - - def test_8bit(self): - im = Image.open("Tests/images/hopper.jpg") - self._test_float_conversion(im.convert("L")) - - def test_16bit(self): - im = Image.open("Tests/images/16bit.cropped.tif") - self._test_float_conversion(im) - - def test_16bit_workaround(self): - im = Image.open("Tests/images/16bit.cropped.tif") - self._test_float_conversion(im.convert("I")) - - def test_rgba_p(self): - im = hopper("RGBA") - im.putalpha(hopper("L")) - - converted = im.convert("P") - comparable = converted.convert("RGBA") - - self.assert_image_similar(im, comparable, 20) - - def test_trns_p(self): - im = hopper("P") - im.info["transparency"] = 0 - - f = self.tempfile("temp.png") - - im_l = im.convert("L") - self.assertEqual(im_l.info["transparency"], 0) # undone - im_l.save(f) - - im_rgb = im.convert("RGB") - self.assertEqual(im_rgb.info["transparency"], (0, 0, 0)) # undone - im_rgb.save(f) - - # ref https://github.com/python-pillow/Pillow/issues/664 - - def test_trns_p_rgba(self): - # Arrange - im = hopper("P") - im.info["transparency"] = 128 - - # Act - im_rgba = im.convert("RGBA") - - # Assert - self.assertNotIn("transparency", im_rgba.info) - # https://github.com/python-pillow/Pillow/issues/2702 - self.assertIsNone(im_rgba.palette) - - def test_trns_l(self): - im = hopper("L") - im.info["transparency"] = 128 - - f = self.tempfile("temp.png") - - im_rgb = im.convert("RGB") - self.assertEqual(im_rgb.info["transparency"], (128, 128, 128)) # undone - im_rgb.save(f) - - im_p = im.convert("P") - self.assertIn("transparency", im_p.info) - im_p.save(f) - - im_p = self.assert_warning(UserWarning, im.convert, "P", palette=Image.ADAPTIVE) - self.assertNotIn("transparency", im_p.info) - im_p.save(f) - - def test_trns_RGB(self): - im = hopper("RGB") - im.info["transparency"] = im.getpixel((0, 0)) - - f = self.tempfile("temp.png") - - im_l = im.convert("L") - self.assertEqual(im_l.info["transparency"], im_l.getpixel((0, 0))) # undone - im_l.save(f) - - im_p = im.convert("P") - self.assertIn("transparency", im_p.info) - im_p.save(f) - - im_rgba = im.convert("RGBA") - self.assertNotIn("transparency", im_rgba.info) - im_rgba.save(f) - - im_p = self.assert_warning(UserWarning, im.convert, "P", palette=Image.ADAPTIVE) - self.assertNotIn("transparency", im_p.info) - im_p.save(f) - - def test_gif_with_rgba_palette_to_p(self): - # See https://github.com/python-pillow/Pillow/issues/2433 - im = Image.open("Tests/images/hopper.gif") - im.info["transparency"] = 255 - im.load() - self.assertEqual(im.palette.mode, "RGBA") - im_p = im.convert("P") - - # Should not raise ValueError: unrecognized raw mode - im_p.load() - - def test_p_la(self): - im = hopper("RGBA") - alpha = hopper("L") - im.putalpha(alpha) - - comparable = im.convert("P").convert("LA").getchannel("A") - - self.assert_image_similar(alpha, comparable, 5) - - def test_matrix_illegal_conversion(self): - # Arrange - im = hopper("CMYK") - # fmt: off - matrix = ( - 0.412453, 0.357580, 0.180423, 0, - 0.212671, 0.715160, 0.072169, 0, - 0.019334, 0.119193, 0.950227, 0) - # fmt: on - self.assertNotEqual(im.mode, "RGB") - - # Act / Assert - self.assertRaises(ValueError, im.convert, mode="CMYK", matrix=matrix) - - def test_matrix_wrong_mode(self): - # Arrange - im = hopper("L") - # fmt: off - matrix = ( - 0.412453, 0.357580, 0.180423, 0, - 0.212671, 0.715160, 0.072169, 0, - 0.019334, 0.119193, 0.950227, 0) - # fmt: on - self.assertEqual(im.mode, "L") - - # Act / Assert - self.assertRaises(ValueError, im.convert, mode="L", matrix=matrix) - - def test_matrix_xyz(self): - def matrix_convert(mode): - # Arrange - im = hopper("RGB") - im.info["transparency"] = (255, 0, 0) - # fmt: off - matrix = ( - 0.412453, 0.357580, 0.180423, 0, - 0.212671, 0.715160, 0.072169, 0, - 0.019334, 0.119193, 0.950227, 0) - # fmt: on - self.assertEqual(im.mode, "RGB") - - # Act - # Convert an RGB image to the CIE XYZ colour space - converted_im = im.convert(mode=mode, matrix=matrix) - - # Assert - self.assertEqual(converted_im.mode, mode) - self.assertEqual(converted_im.size, im.size) - target = Image.open("Tests/images/hopper-XYZ.png") - if converted_im.mode == "RGB": - self.assert_image_similar(converted_im, target, 3) - self.assertEqual(converted_im.info["transparency"], (105, 54, 4)) - else: - self.assert_image_similar(converted_im, target.getchannel(0), 1) - self.assertEqual(converted_im.info["transparency"], 105) - - matrix_convert("RGB") - matrix_convert("L") - - def test_matrix_identity(self): - # Arrange - im = hopper("RGB") - # fmt: off - identity_matrix = ( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0) - # fmt: on - self.assertEqual(im.mode, "RGB") - - # Act - # Convert with an identity matrix - converted_im = im.convert(mode="RGB", matrix=identity_matrix) - - # Assert - # No change - self.assert_image_equal(converted_im, im) diff --git a/Tests/test_image_copy.py b/Tests/test_image_copy.py deleted file mode 100644 index 653159e149f..00000000000 --- a/Tests/test_image_copy.py +++ /dev/null @@ -1,41 +0,0 @@ -import copy - -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageCopy(PillowTestCase): - def test_copy(self): - croppedCoordinates = (10, 10, 20, 20) - croppedSize = (10, 10) - for mode in "1", "P", "L", "RGB", "I", "F": - # Internal copy method - im = hopper(mode) - out = im.copy() - self.assertEqual(out.mode, im.mode) - self.assertEqual(out.size, im.size) - - # Python's copy method - im = hopper(mode) - out = copy.copy(im) - self.assertEqual(out.mode, im.mode) - self.assertEqual(out.size, im.size) - - # Internal copy method on a cropped image - im = hopper(mode) - out = im.crop(croppedCoordinates).copy() - self.assertEqual(out.mode, im.mode) - self.assertEqual(out.size, croppedSize) - - # Python's copy method on a cropped image - im = hopper(mode) - out = copy.copy(im.crop(croppedCoordinates)) - self.assertEqual(out.mode, im.mode) - self.assertEqual(out.size, croppedSize) - - def test_copy_zero(self): - im = Image.new("RGB", (0, 0)) - out = im.copy() - self.assertEqual(out.mode, im.mode) - self.assertEqual(out.size, im.size) diff --git a/Tests/test_image_crop.py b/Tests/test_image_crop.py deleted file mode 100644 index 6a604f49462..00000000000 --- a/Tests/test_image_crop.py +++ /dev/null @@ -1,103 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageCrop(PillowTestCase): - def test_crop(self): - def crop(mode): - im = hopper(mode) - self.assert_image_equal(im.crop(), im) - - cropped = im.crop((50, 50, 100, 100)) - self.assertEqual(cropped.mode, mode) - self.assertEqual(cropped.size, (50, 50)) - - for mode in "1", "P", "L", "RGB", "I", "F": - crop(mode) - - def test_wide_crop(self): - def crop(*bbox): - i = im.crop(bbox) - h = i.histogram() - while h and not h[-1]: - del h[-1] - return tuple(h) - - im = Image.new("L", (100, 100), 1) - - self.assertEqual(crop(0, 0, 100, 100), (0, 10000)) - self.assertEqual(crop(25, 25, 75, 75), (0, 2500)) - - # sides - self.assertEqual(crop(-25, 0, 25, 50), (1250, 1250)) - self.assertEqual(crop(0, -25, 50, 25), (1250, 1250)) - self.assertEqual(crop(75, 0, 125, 50), (1250, 1250)) - self.assertEqual(crop(0, 75, 50, 125), (1250, 1250)) - - self.assertEqual(crop(-25, 25, 125, 75), (2500, 5000)) - self.assertEqual(crop(25, -25, 75, 125), (2500, 5000)) - - # corners - self.assertEqual(crop(-25, -25, 25, 25), (1875, 625)) - self.assertEqual(crop(75, -25, 125, 25), (1875, 625)) - self.assertEqual(crop(75, 75, 125, 125), (1875, 625)) - self.assertEqual(crop(-25, 75, 25, 125), (1875, 625)) - - def test_negative_crop(self): - # Check negative crop size (@PIL171) - - im = Image.new("L", (512, 512)) - im = im.crop((400, 400, 200, 200)) - - self.assertEqual(im.size, (0, 0)) - self.assertEqual(len(im.getdata()), 0) - self.assertRaises(IndexError, lambda: im.getdata()[0]) - - def test_crop_float(self): - # Check cropping floats are rounded to nearest integer - # https://github.com/python-pillow/Pillow/issues/1744 - - # Arrange - im = Image.new("RGB", (10, 10)) - self.assertEqual(im.size, (10, 10)) - - # Act - cropped = im.crop((0.9, 1.1, 4.2, 5.8)) - - # Assert - self.assertEqual(cropped.size, (3, 5)) - - def test_crop_crash(self): - # Image.crop crashes prepatch with an access violation - # apparently a use after free on windows, see - # https://github.com/python-pillow/Pillow/issues/1077 - - test_img = "Tests/images/bmp/g/pal8-0.bmp" - extents = (1, 1, 10, 10) - # works prepatch - img = Image.open(test_img) - img2 = img.crop(extents) - img2.load() - - # fail prepatch - img = Image.open(test_img) - img = img.crop(extents) - img.load() - - def test_crop_zero(self): - - im = Image.new("RGB", (0, 0), "white") - - cropped = im.crop((0, 0, 0, 0)) - self.assertEqual(cropped.size, (0, 0)) - - cropped = im.crop((10, 10, 20, 20)) - self.assertEqual(cropped.size, (10, 10)) - self.assertEqual(cropped.getdata()[0], (0, 0, 0)) - - im = Image.new("RGB", (0, 0)) - - cropped = im.crop((10, 10, 20, 20)) - self.assertEqual(cropped.size, (10, 10)) - self.assertEqual(cropped.getdata()[2], (0, 0, 0)) diff --git a/Tests/test_image_draft.py b/Tests/test_image_draft.py deleted file mode 100644 index 5d92ee79792..00000000000 --- a/Tests/test_image_draft.py +++ /dev/null @@ -1,69 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, fromstring, tostring - - -class TestImageDraft(PillowTestCase): - def setUp(self): - codecs = dir(Image.core) - if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: - self.skipTest("jpeg support not available") - - def draft_roundtrip(self, in_mode, in_size, req_mode, req_size): - im = Image.new(in_mode, in_size) - data = tostring(im, "JPEG") - im = fromstring(data) - im.draft(req_mode, req_size) - return im - - def test_size(self): - for in_size, req_size, out_size in [ - ((435, 361), (2048, 2048), (435, 361)), # bigger - ((435, 361), (435, 361), (435, 361)), # same - ((128, 128), (64, 64), (64, 64)), - ((128, 128), (32, 32), (32, 32)), - ((128, 128), (16, 16), (16, 16)), - # large requested width - ((435, 361), (218, 128), (435, 361)), # almost 2x - ((435, 361), (217, 128), (218, 181)), # more than 2x - ((435, 361), (109, 64), (218, 181)), # almost 4x - ((435, 361), (108, 64), (109, 91)), # more than 4x - ((435, 361), (55, 32), (109, 91)), # almost 8x - ((435, 361), (54, 32), (55, 46)), # more than 8x - ((435, 361), (27, 16), (55, 46)), # more than 16x - # and vice versa - ((435, 361), (128, 181), (435, 361)), # almost 2x - ((435, 361), (128, 180), (218, 181)), # more than 2x - ((435, 361), (64, 91), (218, 181)), # almost 4x - ((435, 361), (64, 90), (109, 91)), # more than 4x - ((435, 361), (32, 46), (109, 91)), # almost 8x - ((435, 361), (32, 45), (55, 46)), # more than 8x - ((435, 361), (16, 22), (55, 46)), # more than 16x - ]: - im = self.draft_roundtrip("L", in_size, None, req_size) - im.load() - self.assertEqual(im.size, out_size) - - def test_mode(self): - for in_mode, req_mode, out_mode in [ - ("RGB", "1", "RGB"), - ("RGB", "L", "L"), - ("RGB", "RGB", "RGB"), - ("RGB", "YCbCr", "YCbCr"), - ("L", "1", "L"), - ("L", "L", "L"), - ("L", "RGB", "L"), - ("L", "YCbCr", "L"), - ("CMYK", "1", "CMYK"), - ("CMYK", "L", "CMYK"), - ("CMYK", "RGB", "CMYK"), - ("CMYK", "YCbCr", "CMYK"), - ]: - im = self.draft_roundtrip(in_mode, (64, 64), req_mode, None) - im.load() - self.assertEqual(im.mode, out_mode) - - def test_several_drafts(self): - im = self.draft_roundtrip("L", (128, 128), None, (64, 64)) - im.draft(None, (64, 64)) - im.load() diff --git a/Tests/test_image_entropy.py b/Tests/test_image_entropy.py deleted file mode 100644 index bc792bca6c4..00000000000 --- a/Tests/test_image_entropy.py +++ /dev/null @@ -1,17 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImageEntropy(PillowTestCase): - def test_entropy(self): - def entropy(mode): - return hopper(mode).entropy() - - self.assertAlmostEqual(entropy("1"), 0.9138803254693582) - self.assertAlmostEqual(entropy("L"), 7.06650513081286) - self.assertAlmostEqual(entropy("I"), 7.06650513081286) - self.assertAlmostEqual(entropy("F"), 7.06650513081286) - self.assertAlmostEqual(entropy("P"), 5.0530452472519745) - self.assertAlmostEqual(entropy("RGB"), 8.821286587714319) - self.assertAlmostEqual(entropy("RGBA"), 7.42724306524488) - self.assertAlmostEqual(entropy("CMYK"), 7.4272430652448795) - self.assertAlmostEqual(entropy("YCbCr"), 7.698360534903628) diff --git a/Tests/test_image_filter.py b/Tests/test_image_filter.py deleted file mode 100644 index bbd10e6e59d..00000000000 --- a/Tests/test_image_filter.py +++ /dev/null @@ -1,143 +0,0 @@ -from PIL import Image, ImageFilter - -from .helper import PillowTestCase, hopper - - -class TestImageFilter(PillowTestCase): - def test_sanity(self): - def filter(filter): - for mode in ["L", "RGB", "CMYK"]: - im = hopper(mode) - out = im.filter(filter) - self.assertEqual(out.mode, im.mode) - self.assertEqual(out.size, im.size) - - filter(ImageFilter.BLUR) - filter(ImageFilter.CONTOUR) - filter(ImageFilter.DETAIL) - filter(ImageFilter.EDGE_ENHANCE) - filter(ImageFilter.EDGE_ENHANCE_MORE) - filter(ImageFilter.EMBOSS) - filter(ImageFilter.FIND_EDGES) - filter(ImageFilter.SMOOTH) - filter(ImageFilter.SMOOTH_MORE) - filter(ImageFilter.SHARPEN) - filter(ImageFilter.MaxFilter) - filter(ImageFilter.MedianFilter) - filter(ImageFilter.MinFilter) - filter(ImageFilter.ModeFilter) - filter(ImageFilter.GaussianBlur) - filter(ImageFilter.GaussianBlur(5)) - filter(ImageFilter.BoxBlur(5)) - filter(ImageFilter.UnsharpMask) - filter(ImageFilter.UnsharpMask(10)) - - self.assertRaises(TypeError, filter, "hello") - - def test_crash(self): - - # crashes on small images - im = Image.new("RGB", (1, 1)) - im.filter(ImageFilter.SMOOTH) - - im = Image.new("RGB", (2, 2)) - im.filter(ImageFilter.SMOOTH) - - im = Image.new("RGB", (3, 3)) - im.filter(ImageFilter.SMOOTH) - - def test_modefilter(self): - def modefilter(mode): - im = Image.new(mode, (3, 3), None) - im.putdata(list(range(9))) - # image is: - # 0 1 2 - # 3 4 5 - # 6 7 8 - mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) - im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0]) # mode=0 - mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) - return mod, mod2 - - self.assertEqual(modefilter("1"), (4, 0)) - self.assertEqual(modefilter("L"), (4, 0)) - self.assertEqual(modefilter("P"), (4, 0)) - self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0))) - - def test_rankfilter(self): - def rankfilter(mode): - im = Image.new(mode, (3, 3), None) - im.putdata(list(range(9))) - # image is: - # 0 1 2 - # 3 4 5 - # 6 7 8 - minimum = im.filter(ImageFilter.MinFilter).getpixel((1, 1)) - med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1)) - maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1)) - return minimum, med, maximum - - self.assertEqual(rankfilter("1"), (0, 4, 8)) - self.assertEqual(rankfilter("L"), (0, 4, 8)) - self.assertRaises(ValueError, rankfilter, "P") - self.assertEqual(rankfilter("RGB"), ((0, 0, 0), (4, 0, 0), (8, 0, 0))) - self.assertEqual(rankfilter("I"), (0, 4, 8)) - self.assertEqual(rankfilter("F"), (0.0, 4.0, 8.0)) - - def test_rankfilter_properties(self): - rankfilter = ImageFilter.RankFilter(1, 2) - - self.assertEqual(rankfilter.size, 1) - self.assertEqual(rankfilter.rank, 2) - - def test_builtinfilter_p(self): - builtinFilter = ImageFilter.BuiltinFilter() - - self.assertRaises(ValueError, builtinFilter.filter, hopper("P")) - - def test_kernel_not_enough_coefficients(self): - self.assertRaises(ValueError, lambda: ImageFilter.Kernel((3, 3), (0, 0))) - - def test_consistency_3x3(self): - source = Image.open("Tests/images/hopper.bmp") - reference = Image.open("Tests/images/hopper_emboss.bmp") - kernel = ImageFilter.Kernel( # noqa: E127 - (3, 3), - # fmt: off - (-1, -1, 0, - -1, 0, 1, - 0, 1, 1), - # fmt: on - 0.3, - ) - source = source.split() * 2 - reference = reference.split() * 2 - - for mode in ["L", "LA", "RGB", "CMYK"]: - self.assert_image_equal( - Image.merge(mode, source[: len(mode)]).filter(kernel), - Image.merge(mode, reference[: len(mode)]), - ) - - def test_consistency_5x5(self): - source = Image.open("Tests/images/hopper.bmp") - reference = Image.open("Tests/images/hopper_emboss_more.bmp") - kernel = ImageFilter.Kernel( # noqa: E127 - (5, 5), - # fmt: off - (-1, -1, -1, -1, 0, - -1, -1, -1, 0, 1, - -1, -1, 0, 1, 1, - -1, 0, 1, 1, 1, - 0, 1, 1, 1, 1), - # fmt: on - 0.3, - ) - source = source.split() * 2 - reference = reference.split() * 2 - - for mode in ["L", "LA", "RGB", "CMYK"]: - self.assert_image_equal( - Image.merge(mode, source[: len(mode)]).filter(kernel), - Image.merge(mode, reference[: len(mode)]), - ) diff --git a/Tests/test_image_frombytes.py b/Tests/test_image_frombytes.py deleted file mode 100644 index 21d466d028f..00000000000 --- a/Tests/test_image_frombytes.py +++ /dev/null @@ -1,14 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageFromBytes(PillowTestCase): - def test_sanity(self): - im1 = hopper() - im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes()) - - self.assert_image_equal(im1, im2) - - def test_not_implemented(self): - self.assertRaises(NotImplementedError, Image.fromstring) diff --git a/Tests/test_image_fromqimage.py b/Tests/test_image_fromqimage.py deleted file mode 100644 index d7556a68002..00000000000 --- a/Tests/test_image_fromqimage.py +++ /dev/null @@ -1,44 +0,0 @@ -from PIL import Image, ImageQt - -from .helper import PillowTestCase, hopper -from .test_imageqt import PillowQtTestCase - - -class TestFromQImage(PillowQtTestCase, PillowTestCase): - - files_to_test = [ - hopper(), - Image.open("Tests/images/transparent.png"), - Image.open("Tests/images/7x13.png"), - ] - - def roundtrip(self, expected): - # PIL -> Qt - intermediate = expected.toqimage() - # Qt -> PIL - result = ImageQt.fromqimage(intermediate) - - if intermediate.hasAlphaChannel(): - self.assert_image_equal(result, expected.convert("RGBA")) - else: - self.assert_image_equal(result, expected.convert("RGB")) - - def test_sanity_1(self): - for im in self.files_to_test: - self.roundtrip(im.convert("1")) - - def test_sanity_rgb(self): - for im in self.files_to_test: - self.roundtrip(im.convert("RGB")) - - def test_sanity_rgba(self): - for im in self.files_to_test: - self.roundtrip(im.convert("RGBA")) - - def test_sanity_l(self): - for im in self.files_to_test: - self.roundtrip(im.convert("L")) - - def test_sanity_p(self): - for im in self.files_to_test: - self.roundtrip(im.convert("P")) diff --git a/Tests/test_image_getbands.py b/Tests/test_image_getbands.py deleted file mode 100644 index 785b2ae4204..00000000000 --- a/Tests/test_image_getbands.py +++ /dev/null @@ -1,16 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestImageGetBands(PillowTestCase): - def test_getbands(self): - self.assertEqual(Image.new("1", (1, 1)).getbands(), ("1",)) - self.assertEqual(Image.new("L", (1, 1)).getbands(), ("L",)) - self.assertEqual(Image.new("I", (1, 1)).getbands(), ("I",)) - self.assertEqual(Image.new("F", (1, 1)).getbands(), ("F",)) - self.assertEqual(Image.new("P", (1, 1)).getbands(), ("P",)) - self.assertEqual(Image.new("RGB", (1, 1)).getbands(), ("R", "G", "B")) - self.assertEqual(Image.new("RGBA", (1, 1)).getbands(), ("R", "G", "B", "A")) - self.assertEqual(Image.new("CMYK", (1, 1)).getbands(), ("C", "M", "Y", "K")) - self.assertEqual(Image.new("YCbCr", (1, 1)).getbands(), ("Y", "Cb", "Cr")) diff --git a/Tests/test_image_getbbox.py b/Tests/test_image_getbbox.py deleted file mode 100644 index 2df9f20f1b0..00000000000 --- a/Tests/test_image_getbbox.py +++ /dev/null @@ -1,38 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageGetBbox(PillowTestCase): - def test_sanity(self): - - bbox = hopper().getbbox() - self.assertIsInstance(bbox, tuple) - - def test_bbox(self): - - # 8-bit mode - im = Image.new("L", (100, 100), 0) - self.assertIsNone(im.getbbox()) - - im.paste(255, (10, 25, 90, 75)) - self.assertEqual(im.getbbox(), (10, 25, 90, 75)) - - im.paste(255, (25, 10, 75, 90)) - self.assertEqual(im.getbbox(), (10, 10, 90, 90)) - - im.paste(255, (-10, -10, 110, 110)) - self.assertEqual(im.getbbox(), (0, 0, 100, 100)) - - # 32-bit mode - im = Image.new("RGB", (100, 100), 0) - self.assertIsNone(im.getbbox()) - - im.paste(255, (10, 25, 90, 75)) - self.assertEqual(im.getbbox(), (10, 25, 90, 75)) - - im.paste(255, (25, 10, 75, 90)) - self.assertEqual(im.getbbox(), (10, 10, 90, 90)) - - im.paste(255, (-10, -10, 110, 110)) - self.assertEqual(im.getbbox(), (0, 0, 100, 100)) diff --git a/Tests/test_image_getcolors.py b/Tests/test_image_getcolors.py deleted file mode 100644 index f1abf028725..00000000000 --- a/Tests/test_image_getcolors.py +++ /dev/null @@ -1,67 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImageGetColors(PillowTestCase): - def test_getcolors(self): - def getcolors(mode, limit=None): - im = hopper(mode) - if limit: - colors = im.getcolors(limit) - else: - colors = im.getcolors() - if colors: - return len(colors) - return None - - self.assertEqual(getcolors("1"), 2) - self.assertEqual(getcolors("L"), 255) - self.assertEqual(getcolors("I"), 255) - self.assertEqual(getcolors("F"), 255) - self.assertEqual(getcolors("P"), 90) # fixed palette - self.assertIsNone(getcolors("RGB")) - self.assertIsNone(getcolors("RGBA")) - self.assertIsNone(getcolors("CMYK")) - self.assertIsNone(getcolors("YCbCr")) - - self.assertIsNone(getcolors("L", 128)) - self.assertEqual(getcolors("L", 1024), 255) - - self.assertIsNone(getcolors("RGB", 8192)) - self.assertEqual(getcolors("RGB", 16384), 10100) - self.assertEqual(getcolors("RGB", 100000), 10100) - - self.assertEqual(getcolors("RGBA", 16384), 10100) - self.assertEqual(getcolors("CMYK", 16384), 10100) - self.assertEqual(getcolors("YCbCr", 16384), 9329) - - # -------------------------------------------------------------------- - - def test_pack(self): - # Pack problems for small tables (@PIL209) - - im = hopper().quantize(3).convert("RGB") - - expected = [ - (4039, (172, 166, 181)), - (4385, (124, 113, 134)), - (7960, (31, 20, 33)), - ] - - A = im.getcolors(maxcolors=2) - self.assertIsNone(A) - - A = im.getcolors(maxcolors=3) - A.sort() - self.assertEqual(A, expected) - - A = im.getcolors(maxcolors=4) - A.sort() - self.assertEqual(A, expected) - - A = im.getcolors(maxcolors=8) - A.sort() - self.assertEqual(A, expected) - - A = im.getcolors(maxcolors=16) - A.sort() - self.assertEqual(A, expected) diff --git a/Tests/test_image_getdata.py b/Tests/test_image_getdata.py deleted file mode 100644 index d9bfcc7ddef..00000000000 --- a/Tests/test_image_getdata.py +++ /dev/null @@ -1,27 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImageGetData(PillowTestCase): - def test_sanity(self): - - data = hopper().getdata() - - len(data) - list(data) - - self.assertEqual(data[0], (20, 20, 70)) - - def test_roundtrip(self): - def getdata(mode): - im = hopper(mode).resize((32, 30)) - data = im.getdata() - return data[0], len(data), len(list(data)) - - self.assertEqual(getdata("1"), (0, 960, 960)) - self.assertEqual(getdata("L"), (16, 960, 960)) - self.assertEqual(getdata("I"), (16, 960, 960)) - self.assertEqual(getdata("F"), (16.0, 960, 960)) - self.assertEqual(getdata("RGB"), ((11, 13, 52), 960, 960)) - self.assertEqual(getdata("RGBA"), ((11, 13, 52, 255), 960, 960)) - self.assertEqual(getdata("CMYK"), ((244, 242, 203, 0), 960, 960)) - self.assertEqual(getdata("YCbCr"), ((16, 147, 123), 960, 960)) diff --git a/Tests/test_image_getextrema.py b/Tests/test_image_getextrema.py deleted file mode 100644 index 1944b041c04..00000000000 --- a/Tests/test_image_getextrema.py +++ /dev/null @@ -1,25 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageGetExtrema(PillowTestCase): - def test_extrema(self): - def extrema(mode): - return hopper(mode).getextrema() - - self.assertEqual(extrema("1"), (0, 255)) - self.assertEqual(extrema("L"), (0, 255)) - self.assertEqual(extrema("I"), (0, 255)) - self.assertEqual(extrema("F"), (0, 255)) - self.assertEqual(extrema("P"), (0, 225)) # fixed palette - self.assertEqual(extrema("RGB"), ((0, 255), (0, 255), (0, 255))) - self.assertEqual(extrema("RGBA"), ((0, 255), (0, 255), (0, 255), (255, 255))) - self.assertEqual(extrema("CMYK"), ((0, 255), (0, 255), (0, 255), (0, 0))) - self.assertEqual(extrema("I;16"), (0, 255)) - - def test_true_16(self): - im = Image.open("Tests/images/16_bit_noise.tif") - self.assertEqual(im.mode, "I;16") - extrema = im.getextrema() - self.assertEqual(extrema, (106, 285)) diff --git a/Tests/test_image_getim.py b/Tests/test_image_getim.py deleted file mode 100644 index 3f0c46c46d3..00000000000 --- a/Tests/test_image_getim.py +++ /dev/null @@ -1,14 +0,0 @@ -from PIL._util import py3 - -from .helper import PillowTestCase, hopper - - -class TestImageGetIm(PillowTestCase): - def test_sanity(self): - im = hopper() - type_repr = repr(type(im.getim())) - - if py3: - self.assertIn("PyCapsule", type_repr) - - self.assertIsInstance(im.im.id, int) diff --git a/Tests/test_image_getpalette.py b/Tests/test_image_getpalette.py deleted file mode 100644 index 7beeeff58ff..00000000000 --- a/Tests/test_image_getpalette.py +++ /dev/null @@ -1,20 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImageGetPalette(PillowTestCase): - def test_palette(self): - def palette(mode): - p = hopper(mode).getpalette() - if p: - return p[:10] - return None - - self.assertIsNone(palette("1")) - self.assertIsNone(palette("L")) - self.assertIsNone(palette("I")) - self.assertIsNone(palette("F")) - self.assertEqual(palette("P"), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - self.assertIsNone(palette("RGB")) - self.assertIsNone(palette("RGBA")) - self.assertIsNone(palette("CMYK")) - self.assertIsNone(palette("YCbCr")) diff --git a/Tests/test_image_getprojection.py b/Tests/test_image_getprojection.py deleted file mode 100644 index 3b8bca64f0e..00000000000 --- a/Tests/test_image_getprojection.py +++ /dev/null @@ -1,31 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageGetProjection(PillowTestCase): - def test_sanity(self): - - im = hopper() - - projection = im.getprojection() - - self.assertEqual(len(projection), 2) - self.assertEqual(len(projection[0]), im.size[0]) - self.assertEqual(len(projection[1]), im.size[1]) - - # 8-bit image - im = Image.new("L", (10, 10)) - self.assertEqual(im.getprojection()[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - im.paste(255, (2, 4, 8, 6)) - self.assertEqual(im.getprojection()[0], [0, 0, 1, 1, 1, 1, 1, 1, 0, 0]) - self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0]) - - # 32-bit image - im = Image.new("RGB", (10, 10)) - self.assertEqual(im.getprojection()[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) - im.paste(255, (2, 4, 8, 6)) - self.assertEqual(im.getprojection()[0], [0, 0, 1, 1, 1, 1, 1, 1, 0, 0]) - self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0]) diff --git a/Tests/test_image_histogram.py b/Tests/test_image_histogram.py deleted file mode 100644 index 8d34658b85e..00000000000 --- a/Tests/test_image_histogram.py +++ /dev/null @@ -1,18 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImageHistogram(PillowTestCase): - def test_histogram(self): - def histogram(mode): - h = hopper(mode).histogram() - return len(h), min(h), max(h) - - self.assertEqual(histogram("1"), (256, 0, 10994)) - self.assertEqual(histogram("L"), (256, 0, 638)) - self.assertEqual(histogram("I"), (256, 0, 638)) - self.assertEqual(histogram("F"), (256, 0, 638)) - self.assertEqual(histogram("P"), (256, 0, 1871)) - self.assertEqual(histogram("RGB"), (768, 4, 675)) - self.assertEqual(histogram("RGBA"), (1024, 0, 16384)) - self.assertEqual(histogram("CMYK"), (1024, 0, 16384)) - self.assertEqual(histogram("YCbCr"), (768, 0, 1908)) diff --git a/Tests/test_image_load.py b/Tests/test_image_load.py deleted file mode 100644 index 2770126c41a..00000000000 --- a/Tests/test_image_load.py +++ /dev/null @@ -1,36 +0,0 @@ -import os - -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageLoad(PillowTestCase): - def test_sanity(self): - - im = hopper() - - pix = im.load() - - self.assertEqual(pix[0, 0], (20, 20, 70)) - - def test_close(self): - im = Image.open("Tests/images/hopper.gif") - im.close() - self.assertRaises(ValueError, im.load) - self.assertRaises(ValueError, im.getpixel, (0, 0)) - - def test_contextmanager(self): - fn = None - with Image.open("Tests/images/hopper.gif") as im: - fn = im.fp.fileno() - os.fstat(fn) - - self.assertRaises(OSError, os.fstat, fn) - - def test_contextmanager_non_exclusive_fp(self): - with open("Tests/images/hopper.gif", "rb") as fp: - with Image.open(fp): - pass - - self.assertFalse(fp.closed) diff --git a/Tests/test_image_mode.py b/Tests/test_image_mode.py deleted file mode 100644 index e2395791674..00000000000 --- a/Tests/test_image_mode.py +++ /dev/null @@ -1,72 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageMode(PillowTestCase): - def test_sanity(self): - - im = hopper() - 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(str(m), "1") - self.assertEqual(m.bands, ("1",)) - self.assertEqual(m.basemode, "L") - self.assertEqual(m.basetype, "L") - - for mode in ( - "I;16", - "I;16S", - "I;16L", - "I;16LS", - "I;16B", - "I;16BS", - "I;16N", - "I;16NS", - ): - m = ImageMode.getmode(mode) - self.assertEqual(m.mode, mode) - self.assertEqual(str(m), mode) - self.assertEqual(m.bands, ("I",)) - self.assertEqual(m.basemode, "L") - self.assertEqual(m.basetype, "L") - - m = ImageMode.getmode("RGB") - self.assertEqual(m.mode, "RGB") - self.assertEqual(str(m), "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 = ( - Image.getmodebase(mode), - Image.getmodetype(mode), - Image.getmodebands(mode), - Image.getmodebandnames(mode), - ) - self.assertEqual(signature, result) - - check("1", "L", "L", 1, ("1",)) - check("L", "L", "L", 1, ("L",)) - check("P", "P", "L", 1, ("P",)) - check("I", "L", "I", 1, ("I",)) - check("F", "L", "F", 1, ("F",)) - check("RGB", "RGB", "L", 3, ("R", "G", "B")) - check("RGBA", "RGB", "L", 4, ("R", "G", "B", "A")) - check("RGBX", "RGB", "L", 4, ("R", "G", "B", "X")) - check("RGBX", "RGB", "L", 4, ("R", "G", "B", "X")) - check("CMYK", "RGB", "L", 4, ("C", "M", "Y", "K")) - check("YCbCr", "RGB", "L", 3, ("Y", "Cb", "Cr")) diff --git a/Tests/test_image_paste.py b/Tests/test_image_paste.py deleted file mode 100644 index 3139db664ed..00000000000 --- a/Tests/test_image_paste.py +++ /dev/null @@ -1,298 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, cached_property - - -class TestImagingPaste(PillowTestCase): - masks = {} - size = 128 - - def assert_9points_image(self, im, expected): - expected = [ - point[0] if im.mode == "L" else point[: len(im.mode)] for point in expected - ] - px = im.load() - actual = [ - px[0, 0], - px[self.size // 2, 0], - px[self.size - 1, 0], - px[0, self.size // 2], - px[self.size // 2, self.size // 2], - px[self.size - 1, self.size // 2], - px[0, self.size - 1], - px[self.size // 2, self.size - 1], - px[self.size - 1, self.size - 1], - ] - self.assertEqual(actual, expected) - - def assert_9points_paste(self, im, im2, mask, expected): - im3 = im.copy() - im3.paste(im2, (0, 0), mask) - self.assert_9points_image(im3, expected) - - # Abbreviated syntax - im.paste(im2, mask) - self.assert_9points_image(im, expected) - - @cached_property - def mask_1(self): - mask = Image.new("1", (self.size, self.size)) - px = mask.load() - for y in range(mask.height): - for x in range(mask.width): - px[y, x] = (x + y) % 2 - return mask - - @cached_property - def mask_L(self): - return self.gradient_L.transpose(Image.ROTATE_270) - - @cached_property - def gradient_L(self): - gradient = Image.new("L", (self.size, self.size)) - px = gradient.load() - for y in range(gradient.height): - for x in range(gradient.width): - px[y, x] = (x + y) % 255 - return gradient - - @cached_property - def gradient_RGB(self): - return Image.merge( - "RGB", - [ - self.gradient_L, - self.gradient_L.transpose(Image.ROTATE_90), - self.gradient_L.transpose(Image.ROTATE_180), - ], - ) - - @cached_property - def gradient_RGBA(self): - return Image.merge( - "RGBA", - [ - self.gradient_L, - self.gradient_L.transpose(Image.ROTATE_90), - self.gradient_L.transpose(Image.ROTATE_180), - self.gradient_L.transpose(Image.ROTATE_270), - ], - ) - - @cached_property - def gradient_RGBa(self): - return Image.merge( - "RGBa", - [ - self.gradient_L, - self.gradient_L.transpose(Image.ROTATE_90), - self.gradient_L.transpose(Image.ROTATE_180), - self.gradient_L.transpose(Image.ROTATE_270), - ], - ) - - def test_image_solid(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), "red") - im2 = getattr(self, "gradient_" + mode) - - im.paste(im2, (12, 23)) - - im = im.crop((12, 23, im2.width + 12, im2.height + 23)) - self.assert_image_equal(im, im2) - - def test_image_mask_1(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), "white") - im2 = getattr(self, "gradient_" + mode) - - self.assert_9points_paste( - im, - im2, - self.mask_1, - [ - (255, 255, 255, 255), - (255, 255, 255, 255), - (127, 254, 127, 0), - (255, 255, 255, 255), - (255, 255, 255, 255), - (191, 190, 63, 64), - (127, 0, 127, 254), - (191, 64, 63, 190), - (255, 255, 255, 255), - ], - ) - - def test_image_mask_L(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), "white") - im2 = getattr(self, "gradient_" + mode) - - self.assert_9points_paste( - im, - im2, - self.mask_L, - [ - (128, 191, 255, 191), - (208, 239, 239, 208), - (255, 255, 255, 255), - (112, 111, 206, 207), - (192, 191, 191, 191), - (239, 239, 207, 207), - (128, 1, 128, 254), - (207, 113, 112, 207), - (255, 191, 128, 191), - ], - ) - - def test_image_mask_RGBA(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), "white") - im2 = getattr(self, "gradient_" + mode) - - self.assert_9points_paste( - im, - im2, - self.gradient_RGBA, - [ - (128, 191, 255, 191), - (208, 239, 239, 208), - (255, 255, 255, 255), - (112, 111, 206, 207), - (192, 191, 191, 191), - (239, 239, 207, 207), - (128, 1, 128, 254), - (207, 113, 112, 207), - (255, 191, 128, 191), - ], - ) - - def test_image_mask_RGBa(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), "white") - im2 = getattr(self, "gradient_" + mode) - - self.assert_9points_paste( - im, - im2, - self.gradient_RGBa, - [ - (128, 255, 126, 255), - (0, 127, 126, 255), - (126, 253, 126, 255), - (128, 127, 254, 255), - (0, 255, 254, 255), - (126, 125, 254, 255), - (128, 1, 128, 255), - (0, 129, 128, 255), - (126, 255, 128, 255), - ], - ) - - def test_color_solid(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), "black") - - rect = (12, 23, 128 + 12, 128 + 23) - im.paste("white", rect) - - hist = im.crop(rect).histogram() - while hist: - head, hist = hist[:256], hist[256:] - self.assertEqual(head[255], 128 * 128) - self.assertEqual(sum(head[:255]), 0) - - def test_color_mask_1(self): - for mode in ("RGBA", "RGB", "L"): - im = Image.new(mode, (200, 200), (50, 60, 70, 80)[: len(mode)]) - color = (10, 20, 30, 40)[: len(mode)] - - self.assert_9points_paste( - im, - color, - self.mask_1, - [ - (50, 60, 70, 80), - (50, 60, 70, 80), - (10, 20, 30, 40), - (50, 60, 70, 80), - (50, 60, 70, 80), - (10, 20, 30, 40), - (10, 20, 30, 40), - (10, 20, 30, 40), - (50, 60, 70, 80), - ], - ) - - def test_color_mask_L(self): - for mode in ("RGBA", "RGB", "L"): - im = getattr(self, "gradient_" + mode).copy() - color = "white" - - self.assert_9points_paste( - im, - color, - self.mask_L, - [ - (127, 191, 254, 191), - (111, 207, 206, 110), - (127, 254, 127, 0), - (207, 207, 239, 239), - (191, 191, 190, 191), - (207, 206, 111, 112), - (254, 254, 254, 255), - (239, 206, 206, 238), - (254, 191, 127, 191), - ], - ) - - def test_color_mask_RGBA(self): - for mode in ("RGBA", "RGB", "L"): - im = getattr(self, "gradient_" + mode).copy() - color = "white" - - self.assert_9points_paste( - im, - color, - self.gradient_RGBA, - [ - (127, 191, 254, 191), - (111, 207, 206, 110), - (127, 254, 127, 0), - (207, 207, 239, 239), - (191, 191, 190, 191), - (207, 206, 111, 112), - (254, 254, 254, 255), - (239, 206, 206, 238), - (254, 191, 127, 191), - ], - ) - - def test_color_mask_RGBa(self): - for mode in ("RGBA", "RGB", "L"): - im = getattr(self, "gradient_" + mode).copy() - color = "white" - - self.assert_9points_paste( - im, - color, - self.gradient_RGBa, - [ - (255, 63, 126, 63), - (47, 143, 142, 46), - (126, 253, 126, 255), - (15, 15, 47, 47), - (63, 63, 62, 63), - (142, 141, 46, 47), - (255, 255, 255, 0), - (48, 15, 15, 47), - (126, 63, 255, 63), - ], - ) - - def test_different_sizes(self): - im = Image.new("RGB", (100, 100)) - im2 = Image.new("RGB", (50, 50)) - - im.copy().paste(im2) - im.copy().paste(im2, (0, 0)) diff --git a/Tests/test_image_point.py b/Tests/test_image_point.py deleted file mode 100644 index 56ed4648872..00000000000 --- a/Tests/test_image_point.py +++ /dev/null @@ -1,39 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImagePoint(PillowTestCase): - def test_sanity(self): - im = hopper() - - self.assertRaises(ValueError, im.point, list(range(256))) - im.point(list(range(256)) * 3) - im.point(lambda x: x) - - im = im.convert("I") - self.assertRaises(ValueError, im.point, list(range(256))) - im.point(lambda x: x * 1) - im.point(lambda x: x + 1) - im.point(lambda x: x * 1 + 1) - self.assertRaises(TypeError, im.point, lambda x: x - 1) - self.assertRaises(TypeError, im.point, lambda x: x / 1) - - def test_16bit_lut(self): - """ Tests for 16 bit -> 8 bit lut for converting I->L images - see https://github.com/python-pillow/Pillow/issues/440 - """ - im = hopper("I") - im.point(list(range(256)) * 256, "L") - - def test_f_lut(self): - """ Tests for floating point lut of 8bit gray image """ - im = hopper("L") - lut = [0.5 * float(x) for x in range(256)] - - out = im.point(lut, "F") - - int_lut = [x // 2 for x in range(256)] - self.assert_image_equal(out.convert("L"), im.point(int_lut, "L")) - - def test_f_mode(self): - im = hopper("F") - self.assertRaises(ValueError, im.point, None) diff --git a/Tests/test_image_putalpha.py b/Tests/test_image_putalpha.py deleted file mode 100644 index 6dc802598f7..00000000000 --- a/Tests/test_image_putalpha.py +++ /dev/null @@ -1,52 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestImagePutAlpha(PillowTestCase): - def test_interface(self): - - im = Image.new("RGBA", (1, 1), (1, 2, 3, 0)) - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 0)) - - im = Image.new("RGBA", (1, 1), (1, 2, 3)) - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 255)) - - im.putalpha(Image.new("L", im.size, 4)) - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4)) - - im.putalpha(5) - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 5)) - - def test_promote(self): - - im = Image.new("L", (1, 1), 1) - self.assertEqual(im.getpixel((0, 0)), 1) - - im.putalpha(2) - self.assertEqual(im.mode, "LA") - self.assertEqual(im.getpixel((0, 0)), (1, 2)) - - im = Image.new("P", (1, 1), 1) - self.assertEqual(im.getpixel((0, 0)), 1) - - im.putalpha(2) - self.assertEqual(im.mode, "PA") - self.assertEqual(im.getpixel((0, 0)), (1, 2)) - - im = Image.new("RGB", (1, 1), (1, 2, 3)) - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3)) - - im.putalpha(4) - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4)) - - def test_readonly(self): - - im = Image.new("RGB", (1, 1), (1, 2, 3)) - im.readonly = 1 - - im.putalpha(4) - self.assertFalse(im.readonly) - self.assertEqual(im.mode, "RGBA") - self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4)) diff --git a/Tests/test_image_putdata.py b/Tests/test_image_putdata.py deleted file mode 100644 index a213fbf8841..00000000000 --- a/Tests/test_image_putdata.py +++ /dev/null @@ -1,85 +0,0 @@ -import sys -from array import array - -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImagePutData(PillowTestCase): - def test_sanity(self): - - im1 = hopper() - - data = list(im1.getdata()) - - im2 = Image.new(im1.mode, im1.size, 0) - im2.putdata(data) - - self.assert_image_equal(im1, im2) - - # readonly - im2 = Image.new(im1.mode, im2.size, 0) - im2.readonly = 1 - im2.putdata(data) - - self.assertFalse(im2.readonly) - self.assert_image_equal(im1, im2) - - def test_long_integers(self): - # see bug-200802-systemerror - def put(value): - im = Image.new("RGBA", (1, 1)) - im.putdata([value]) - return im.getpixel((0, 0)) - - self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255)) - self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255)) - self.assertEqual(put(-1), (255, 255, 255, 255)) - self.assertEqual(put(-1), (255, 255, 255, 255)) - if sys.maxsize > 2 ** 32: - self.assertEqual(put(sys.maxsize), (255, 255, 255, 255)) - else: - self.assertEqual(put(sys.maxsize), (255, 255, 255, 127)) - - def test_pypy_performance(self): - im = Image.new("L", (256, 256)) - im.putdata(list(range(256)) * 256) - - def test_mode_i(self): - src = hopper("L") - data = list(src.getdata()) - im = Image.new("I", src.size, 0) - im.putdata(data, 2, 256) - - target = [2 * elt + 256 for elt in data] - self.assertEqual(list(im.getdata()), target) - - def test_mode_F(self): - src = hopper("L") - data = list(src.getdata()) - im = Image.new("F", src.size, 0) - im.putdata(data, 2.0, 256.0) - - target = [2.0 * float(elt) + 256.0 for elt in data] - self.assertEqual(list(im.getdata()), target) - - def test_array_B(self): - # shouldn't segfault - # see https://github.com/python-pillow/Pillow/issues/1008 - - arr = array("B", [0]) * 15000 - im = Image.new("L", (150, 100)) - im.putdata(arr) - - self.assertEqual(len(im.getdata()), len(arr)) - - def test_array_F(self): - # shouldn't segfault - # see https://github.com/python-pillow/Pillow/issues/1008 - - im = Image.new("F", (150, 100)) - arr = array("f", [0.0]) * 15000 - im.putdata(arr) - - self.assertEqual(len(im.getdata()), len(arr)) diff --git a/Tests/test_image_putpalette.py b/Tests/test_image_putpalette.py deleted file mode 100644 index 68cfc4efeb6..00000000000 --- a/Tests/test_image_putpalette.py +++ /dev/null @@ -1,33 +0,0 @@ -from PIL import ImagePalette - -from .helper import PillowTestCase, hopper - - -class TestImagePutPalette(PillowTestCase): - def test_putpalette(self): - def palette(mode): - im = hopper(mode).copy() - im.putpalette(list(range(256)) * 3) - p = im.getpalette() - if p: - return im.mode, p[:10] - return im.mode - - self.assertRaises(ValueError, palette, "1") - for mode in ["L", "LA", "P", "PA"]: - self.assertEqual( - palette(mode), - ("PA" if "A" in mode else "P", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), - ) - self.assertRaises(ValueError, palette, "I") - self.assertRaises(ValueError, palette, "F") - self.assertRaises(ValueError, palette, "RGB") - self.assertRaises(ValueError, palette, "RGBA") - self.assertRaises(ValueError, palette, "YCbCr") - - def test_imagepalette(self): - im = hopper("P") - im.putpalette(ImagePalette.negative()) - im.putpalette(ImagePalette.random()) - im.putpalette(ImagePalette.sepia()) - im.putpalette(ImagePalette.wedge()) diff --git a/Tests/test_image_quantize.py b/Tests/test_image_quantize.py deleted file mode 100644 index 2be5b74fc39..00000000000 --- a/Tests/test_image_quantize.py +++ /dev/null @@ -1,64 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageQuantize(PillowTestCase): - def test_sanity(self): - image = hopper() - converted = image.quantize() - self.assert_image(converted, "P", converted.size) - self.assert_image_similar(converted.convert("RGB"), image, 10) - - image = hopper() - converted = image.quantize(palette=hopper("P")) - self.assert_image(converted, "P", converted.size) - self.assert_image_similar(converted.convert("RGB"), image, 60) - - def test_libimagequant_quantize(self): - image = hopper() - try: - converted = image.quantize(100, Image.LIBIMAGEQUANT) - except ValueError as ex: - if "dependency" in str(ex).lower(): - self.skipTest("libimagequant support not available") - else: - raise - self.assert_image(converted, "P", converted.size) - self.assert_image_similar(converted.convert("RGB"), image, 15) - self.assertEqual(len(converted.getcolors()), 100) - - def test_octree_quantize(self): - image = hopper() - converted = image.quantize(100, Image.FASTOCTREE) - self.assert_image(converted, "P", converted.size) - self.assert_image_similar(converted.convert("RGB"), image, 20) - self.assertEqual(len(converted.getcolors()), 100) - - def test_rgba_quantize(self): - image = hopper("RGBA") - self.assertRaises(ValueError, image.quantize, method=0) - - self.assertEqual(image.quantize().convert().mode, "RGBA") - - def test_quantize(self): - image = Image.open("Tests/images/caption_6_33_22.png").convert("RGB") - converted = image.quantize() - self.assert_image(converted, "P", converted.size) - self.assert_image_similar(converted.convert("RGB"), image, 1) - - def test_quantize_no_dither(self): - image = hopper() - palette = Image.open("Tests/images/caption_6_33_22.png").convert("P") - - converted = image.quantize(dither=0, palette=palette) - self.assert_image(converted, "P", converted.size) - - def test_quantize_dither_diff(self): - image = hopper() - palette = Image.open("Tests/images/caption_6_33_22.png").convert("P") - - dither = image.quantize(dither=1, palette=palette) - nodither = image.quantize(dither=0, palette=palette) - - self.assertNotEqual(dither.tobytes(), nodither.tobytes()) diff --git a/Tests/test_image_resample.py b/Tests/test_image_resample.py deleted file mode 100644 index 7d1dc009db2..00000000000 --- a/Tests/test_image_resample.py +++ /dev/null @@ -1,563 +0,0 @@ -from __future__ import division, print_function - -from contextlib import contextmanager - -from PIL import Image, ImageDraw - -from .helper import PillowTestCase, hopper, unittest - - -class TestImagingResampleVulnerability(PillowTestCase): - # see https://github.com/python-pillow/Pillow/issues/1710 - def test_overflow(self): - im = hopper("L") - xsize = 0x100000008 // 4 - ysize = 1000 # unimportant - with self.assertRaises(MemoryError): - # any resampling filter will do here - im.im.resize((xsize, ysize), Image.BILINEAR) - - def test_invalid_size(self): - im = hopper() - - # Should not crash - im.resize((100, 100)) - - with self.assertRaises(ValueError): - im.resize((-100, 100)) - - with self.assertRaises(ValueError): - im.resize((100, -100)) - - def test_modify_after_resizing(self): - im = hopper("RGB") - # get copy with same size - copy = im.resize(im.size) - # some in-place operation - copy.paste("black", (0, 0, im.width // 2, im.height // 2)) - # image should be different - self.assertNotEqual(im.tobytes(), copy.tobytes()) - - -class TestImagingCoreResampleAccuracy(PillowTestCase): - def make_case(self, mode, size, color): - """Makes a sample image with two dark and two bright squares. - For example: - e0 e0 1f 1f - e0 e0 1f 1f - 1f 1f e0 e0 - 1f 1f e0 e0 - """ - case = Image.new("L", size, 255 - color) - rectangle = ImageDraw.Draw(case).rectangle - rectangle((0, 0, size[0] // 2 - 1, size[1] // 2 - 1), color) - rectangle((size[0] // 2, size[1] // 2, size[0], size[1]), color) - - return Image.merge(mode, [case] * len(mode)) - - def make_sample(self, data, size): - """Restores a sample image from given data string which contains - hex-encoded pixels from the top left fourth of a sample. - """ - data = data.replace(" ", "") - sample = Image.new("L", size) - s_px = sample.load() - w, h = size[0] // 2, size[1] // 2 - for y in range(h): - for x in range(w): - val = int(data[(y * w + x) * 2 : (y * w + x + 1) * 2], 16) - s_px[x, y] = val - s_px[size[0] - x - 1, size[1] - y - 1] = val - s_px[x, size[1] - y - 1] = 255 - val - s_px[size[0] - x - 1, y] = 255 - val - return sample - - def check_case(self, case, sample): - s_px = sample.load() - c_px = case.load() - for y in range(case.size[1]): - for x in range(case.size[0]): - if c_px[x, y] != s_px[x, y]: - message = "\nHave: \n{}\n\nExpected: \n{}".format( - self.serialize_image(case), self.serialize_image(sample) - ) - self.assertEqual(s_px[x, y], c_px[x, y], message) - - def serialize_image(self, image): - s_px = image.load() - return "\n".join( - " ".join("{:02x}".format(s_px[x, y]) for x in range(image.size[0])) - for y in range(image.size[1]) - ) - - def test_reduce_box(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (8, 8), 0xE1) - case = case.resize((4, 4), Image.BOX) - # fmt: off - data = ("e1 e1" - "e1 e1") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (4, 4))) - - def test_reduce_bilinear(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (8, 8), 0xE1) - case = case.resize((4, 4), Image.BILINEAR) - # fmt: off - data = ("e1 c9" - "c9 b7") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (4, 4))) - - def test_reduce_hamming(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (8, 8), 0xE1) - case = case.resize((4, 4), Image.HAMMING) - # fmt: off - data = ("e1 da" - "da d3") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (4, 4))) - - def test_reduce_bicubic(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (12, 12), 0xE1) - case = case.resize((6, 6), Image.BICUBIC) - # fmt: off - data = ("e1 e3 d4" - "e3 e5 d6" - "d4 d6 c9") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (6, 6))) - - def test_reduce_lanczos(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (16, 16), 0xE1) - case = case.resize((8, 8), Image.LANCZOS) - # fmt: off - data = ("e1 e0 e4 d7" - "e0 df e3 d6" - "e4 e3 e7 da" - "d7 d6 d9 ce") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (8, 8))) - - def test_enlarge_box(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (2, 2), 0xE1) - case = case.resize((4, 4), Image.BOX) - # fmt: off - data = ("e1 e1" - "e1 e1") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (4, 4))) - - def test_enlarge_bilinear(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (2, 2), 0xE1) - case = case.resize((4, 4), Image.BILINEAR) - # fmt: off - data = ("e1 b0" - "b0 98") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (4, 4))) - - def test_enlarge_hamming(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (2, 2), 0xE1) - case = case.resize((4, 4), Image.HAMMING) - # fmt: off - data = ("e1 d2" - "d2 c5") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (4, 4))) - - def test_enlarge_bicubic(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (4, 4), 0xE1) - case = case.resize((8, 8), Image.BICUBIC) - # fmt: off - data = ("e1 e5 ee b9" - "e5 e9 f3 bc" - "ee f3 fd c1" - "b9 bc c1 a2") - # fmt: on - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (8, 8))) - - def test_enlarge_lanczos(self): - for mode in ["RGBX", "RGB", "La", "L"]: - case = self.make_case(mode, (6, 6), 0xE1) - case = case.resize((12, 12), Image.LANCZOS) - data = ( - "e1 e0 db ed f5 b8" - "e0 df da ec f3 b7" - "db db d6 e7 ee b5" - "ed ec e6 fb ff bf" - "f5 f4 ee ff ff c4" - "b8 b7 b4 bf c4 a0" - ) - for channel in case.split(): - self.check_case(channel, self.make_sample(data, (12, 12))) - - -class CoreResampleConsistencyTest(PillowTestCase): - def make_case(self, mode, fill): - im = Image.new(mode, (512, 9), fill) - return im.resize((9, 512), Image.LANCZOS), im.load()[0, 0] - - def run_case(self, case): - channel, color = case - px = channel.load() - for x in range(channel.size[0]): - for y in range(channel.size[1]): - if px[x, y] != color: - message = "{} != {} for pixel {}".format(px[x, y], color, (x, y)) - self.assertEqual(px[x, y], color, message) - - def test_8u(self): - im, color = self.make_case("RGB", (0, 64, 255)) - r, g, b = im.split() - self.run_case((r, color[0])) - self.run_case((g, color[1])) - self.run_case((b, color[2])) - self.run_case(self.make_case("L", 12)) - - def test_32i(self): - self.run_case(self.make_case("I", 12)) - self.run_case(self.make_case("I", 0x7FFFFFFF)) - self.run_case(self.make_case("I", -12)) - self.run_case(self.make_case("I", -1 << 31)) - - def test_32f(self): - self.run_case(self.make_case("F", 1)) - self.run_case(self.make_case("F", 3.40282306074e38)) - self.run_case(self.make_case("F", 1.175494e-38)) - self.run_case(self.make_case("F", 1.192093e-07)) - - -class CoreResampleAlphaCorrectTest(PillowTestCase): - def make_levels_case(self, mode): - i = Image.new(mode, (256, 16)) - px = i.load() - for y in range(i.size[1]): - for x in range(i.size[0]): - pix = [x] * len(mode) - pix[-1] = 255 - y * 16 - px[x, y] = tuple(pix) - return i - - def run_levels_case(self, i): - px = i.load() - for y in range(i.size[1]): - used_colors = {px[x, y][0] for x in range(i.size[0])} - self.assertEqual( - 256, - len(used_colors), - "All colors should present in resized image. " - "Only {} on {} line.".format(len(used_colors), y), - ) - - @unittest.skip("current implementation isn't precise enough") - def test_levels_rgba(self): - case = self.make_levels_case("RGBA") - self.run_levels_case(case.resize((512, 32), Image.BOX)) - self.run_levels_case(case.resize((512, 32), Image.BILINEAR)) - self.run_levels_case(case.resize((512, 32), Image.HAMMING)) - self.run_levels_case(case.resize((512, 32), Image.BICUBIC)) - self.run_levels_case(case.resize((512, 32), Image.LANCZOS)) - - @unittest.skip("current implementation isn't precise enough") - def test_levels_la(self): - case = self.make_levels_case("LA") - self.run_levels_case(case.resize((512, 32), Image.BOX)) - self.run_levels_case(case.resize((512, 32), Image.BILINEAR)) - self.run_levels_case(case.resize((512, 32), Image.HAMMING)) - self.run_levels_case(case.resize((512, 32), Image.BICUBIC)) - self.run_levels_case(case.resize((512, 32), Image.LANCZOS)) - - def make_dirty_case(self, mode, clean_pixel, dirty_pixel): - i = Image.new(mode, (64, 64), dirty_pixel) - px = i.load() - xdiv4 = i.size[0] // 4 - ydiv4 = i.size[1] // 4 - for y in range(ydiv4 * 2): - for x in range(xdiv4 * 2): - px[x + xdiv4, y + ydiv4] = clean_pixel - return i - - def run_dirty_case(self, i, clean_pixel): - px = i.load() - for y in range(i.size[1]): - for x in range(i.size[0]): - if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel: - message = "pixel at ({}, {}) is differ:\n{}\n{}".format( - x, y, px[x, y], clean_pixel - ) - self.assertEqual(px[x, y][:3], clean_pixel, message) - - def test_dirty_pixels_rgba(self): - case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0)) - self.run_dirty_case(case.resize((20, 20), Image.BOX), (255, 255, 0)) - self.run_dirty_case(case.resize((20, 20), Image.BILINEAR), (255, 255, 0)) - self.run_dirty_case(case.resize((20, 20), Image.HAMMING), (255, 255, 0)) - self.run_dirty_case(case.resize((20, 20), Image.BICUBIC), (255, 255, 0)) - self.run_dirty_case(case.resize((20, 20), Image.LANCZOS), (255, 255, 0)) - - def test_dirty_pixels_la(self): - case = self.make_dirty_case("LA", (255, 128), (0, 0)) - self.run_dirty_case(case.resize((20, 20), Image.BOX), (255,)) - self.run_dirty_case(case.resize((20, 20), Image.BILINEAR), (255,)) - self.run_dirty_case(case.resize((20, 20), Image.HAMMING), (255,)) - self.run_dirty_case(case.resize((20, 20), Image.BICUBIC), (255,)) - self.run_dirty_case(case.resize((20, 20), Image.LANCZOS), (255,)) - - -class CoreResamplePassesTest(PillowTestCase): - @contextmanager - def count(self, diff): - count = Image.core.get_stats()["new_count"] - yield - self.assertEqual(Image.core.get_stats()["new_count"] - count, diff) - - def test_horizontal(self): - im = hopper("L") - with self.count(1): - im.resize((im.size[0] - 10, im.size[1]), Image.BILINEAR) - - def test_vertical(self): - im = hopper("L") - with self.count(1): - im.resize((im.size[0], im.size[1] - 10), Image.BILINEAR) - - def test_both(self): - im = hopper("L") - with self.count(2): - im.resize((im.size[0] - 10, im.size[1] - 10), Image.BILINEAR) - - def test_box_horizontal(self): - im = hopper("L") - box = (20, 0, im.size[0] - 20, im.size[1]) - with self.count(1): - # the same size, but different box - with_box = im.resize(im.size, Image.BILINEAR, box) - with self.count(2): - cropped = im.crop(box).resize(im.size, Image.BILINEAR) - self.assert_image_similar(with_box, cropped, 0.1) - - def test_box_vertical(self): - im = hopper("L") - box = (0, 20, im.size[0], im.size[1] - 20) - with self.count(1): - # the same size, but different box - with_box = im.resize(im.size, Image.BILINEAR, box) - with self.count(2): - cropped = im.crop(box).resize(im.size, Image.BILINEAR) - self.assert_image_similar(with_box, cropped, 0.1) - - -class CoreResampleCoefficientsTest(PillowTestCase): - def test_reduce(self): - test_color = 254 - - for size in range(400000, 400010, 2): - i = Image.new("L", (size, 1), 0) - draw = ImageDraw.Draw(i) - draw.rectangle((0, 0, i.size[0] // 2 - 1, 0), test_color) - - px = i.resize((5, i.size[1]), Image.BICUBIC).load() - if px[2, 0] != test_color // 2: - self.assertEqual(test_color // 2, px[2, 0]) - - def test_nonzero_coefficients(self): - # regression test for the wrong coefficients calculation - # due to bug https://github.com/python-pillow/Pillow/issues/2161 - im = Image.new("RGBA", (1280, 1280), (0x20, 0x40, 0x60, 0xFF)) - histogram = im.resize((256, 256), Image.BICUBIC).histogram() - - # first channel - self.assertEqual(histogram[0x100 * 0 + 0x20], 0x10000) - # second channel - self.assertEqual(histogram[0x100 * 1 + 0x40], 0x10000) - # third channel - self.assertEqual(histogram[0x100 * 2 + 0x60], 0x10000) - # fourth channel - self.assertEqual(histogram[0x100 * 3 + 0xFF], 0x10000) - - -class CoreResampleBoxTest(PillowTestCase): - def test_wrong_arguments(self): - im = hopper() - for resample in ( - Image.NEAREST, - Image.BOX, - Image.BILINEAR, - Image.HAMMING, - Image.BICUBIC, - Image.LANCZOS, - ): - im.resize((32, 32), resample, (0, 0, im.width, im.height)) - im.resize((32, 32), resample, (20, 20, im.width, im.height)) - im.resize((32, 32), resample, (20, 20, 20, 100)) - im.resize((32, 32), resample, (20, 20, 100, 20)) - - with self.assertRaisesRegex(TypeError, "must be sequence of length 4"): - im.resize((32, 32), resample, (im.width, im.height)) - - with self.assertRaisesRegex(ValueError, "can't be negative"): - im.resize((32, 32), resample, (-20, 20, 100, 100)) - with self.assertRaisesRegex(ValueError, "can't be negative"): - im.resize((32, 32), resample, (20, -20, 100, 100)) - - with self.assertRaisesRegex(ValueError, "can't be empty"): - im.resize((32, 32), resample, (20.1, 20, 20, 100)) - with self.assertRaisesRegex(ValueError, "can't be empty"): - im.resize((32, 32), resample, (20, 20.1, 100, 20)) - with self.assertRaisesRegex(ValueError, "can't be empty"): - im.resize((32, 32), resample, (20.1, 20.1, 20, 20)) - - with self.assertRaisesRegex(ValueError, "can't exceed"): - im.resize((32, 32), resample, (0, 0, im.width + 1, im.height)) - with self.assertRaisesRegex(ValueError, "can't exceed"): - im.resize((32, 32), resample, (0, 0, im.width, im.height + 1)) - - def resize_tiled(self, im, dst_size, xtiles, ytiles): - def split_range(size, tiles): - scale = size / tiles - for i in range(tiles): - yield (int(round(scale * i)), int(round(scale * (i + 1)))) - - tiled = Image.new(im.mode, dst_size) - scale = (im.size[0] / tiled.size[0], im.size[1] / tiled.size[1]) - - for y0, y1 in split_range(dst_size[1], ytiles): - for x0, x1 in split_range(dst_size[0], xtiles): - box = (x0 * scale[0], y0 * scale[1], x1 * scale[0], y1 * scale[1]) - tile = im.resize((x1 - x0, y1 - y0), Image.BICUBIC, box) - tiled.paste(tile, (x0, y0)) - return tiled - - def test_tiles(self): - im = Image.open("Tests/images/flower.jpg") - self.assertEqual(im.size, (480, 360)) - dst_size = (251, 188) - reference = im.resize(dst_size, Image.BICUBIC) - - for tiles in [(1, 1), (3, 3), (9, 7), (100, 100)]: - tiled = self.resize_tiled(im, dst_size, *tiles) - self.assert_image_similar(reference, tiled, 0.01) - - def test_subsample(self): - # This test shows advantages of the subpixel resizing - # after supersampling (e.g. during JPEG decoding). - im = Image.open("Tests/images/flower.jpg") - self.assertEqual(im.size, (480, 360)) - dst_size = (48, 36) - # Reference is cropped image resized to destination - reference = im.crop((0, 0, 473, 353)).resize(dst_size, Image.BICUBIC) - # Image.BOX emulates supersampling (480 / 8 = 60, 360 / 8 = 45) - supersampled = im.resize((60, 45), Image.BOX) - - with_box = supersampled.resize(dst_size, Image.BICUBIC, (0, 0, 59.125, 44.125)) - without_box = supersampled.resize(dst_size, Image.BICUBIC) - - # error with box should be much smaller than without - self.assert_image_similar(reference, with_box, 6) - with self.assertRaisesRegex(AssertionError, r"difference 29\."): - self.assert_image_similar(reference, without_box, 5) - - def test_formats(self): - for resample in [Image.NEAREST, Image.BILINEAR]: - for mode in ["RGB", "L", "RGBA", "LA", "I", ""]: - im = hopper(mode) - box = (20, 20, im.size[0] - 20, im.size[1] - 20) - with_box = im.resize((32, 32), resample, box) - cropped = im.crop(box).resize((32, 32), resample) - self.assert_image_similar(cropped, with_box, 0.4) - - def test_passthrough(self): - # When no resize is required - im = hopper() - - for size, box in [ - ((40, 50), (0, 0, 40, 50)), - ((40, 50), (0, 10, 40, 60)), - ((40, 50), (10, 0, 50, 50)), - ((40, 50), (10, 20, 50, 70)), - ]: - try: - res = im.resize(size, Image.LANCZOS, box) - self.assertEqual(res.size, size) - self.assert_image_equal(res, im.crop(box)) - except AssertionError: - print(">>>", size, box) - raise - - def test_no_passthrough(self): - # When resize is required - im = hopper() - - for size, box in [ - ((40, 50), (0.4, 0.4, 40.4, 50.4)), - ((40, 50), (0.4, 10.4, 40.4, 60.4)), - ((40, 50), (10.4, 0.4, 50.4, 50.4)), - ((40, 50), (10.4, 20.4, 50.4, 70.4)), - ]: - try: - res = im.resize(size, Image.LANCZOS, box) - self.assertEqual(res.size, size) - with self.assertRaisesRegex(AssertionError, r"difference \d"): - # check that the difference at least that much - self.assert_image_similar(res, im.crop(box), 20) - except AssertionError: - print(">>>", size, box) - raise - - def test_skip_horizontal(self): - # Can skip resize for one dimension - im = hopper() - - for flt in [Image.NEAREST, Image.BICUBIC]: - for size, box in [ - ((40, 50), (0, 0, 40, 90)), - ((40, 50), (0, 20, 40, 90)), - ((40, 50), (10, 0, 50, 90)), - ((40, 50), (10, 20, 50, 90)), - ]: - try: - res = im.resize(size, flt, box) - self.assertEqual(res.size, size) - # Borders should be slightly different - self.assert_image_similar(res, im.crop(box).resize(size, flt), 0.4) - except AssertionError: - print(">>>", size, box, flt) - raise - - def test_skip_vertical(self): - # Can skip resize for one dimension - im = hopper() - - for flt in [Image.NEAREST, Image.BICUBIC]: - for size, box in [ - ((40, 50), (0, 0, 90, 50)), - ((40, 50), (20, 0, 90, 50)), - ((40, 50), (0, 10, 90, 60)), - ((40, 50), (20, 10, 90, 60)), - ]: - try: - res = im.resize(size, flt, box) - self.assertEqual(res.size, size) - # Borders should be slightly different - self.assert_image_similar(res, im.crop(box).resize(size, flt), 0.4) - except AssertionError: - print(">>>", size, box, flt) - raise diff --git a/Tests/test_image_resize.py b/Tests/test_image_resize.py deleted file mode 100644 index 7c35be570b7..00000000000 --- a/Tests/test_image_resize.py +++ /dev/null @@ -1,152 +0,0 @@ -""" -Tests for resize functionality. -""" -from itertools import permutations - -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImagingCoreResize(PillowTestCase): - def resize(self, im, size, f): - # Image class independent version of resize. - im.load() - return im._new(im.im.resize(size, f)) - - def test_nearest_mode(self): - for mode in [ - "1", - "P", - "L", - "I", - "F", - "RGB", - "RGBA", - "CMYK", - "YCbCr", - "I;16", - ]: # exotic mode - im = hopper(mode) - r = self.resize(im, (15, 12), Image.NEAREST) - self.assertEqual(r.mode, mode) - self.assertEqual(r.size, (15, 12)) - self.assertEqual(r.im.bands, im.im.bands) - - def test_convolution_modes(self): - self.assertRaises( - ValueError, self.resize, hopper("1"), (15, 12), Image.BILINEAR - ) - self.assertRaises( - ValueError, self.resize, hopper("P"), (15, 12), Image.BILINEAR - ) - self.assertRaises( - ValueError, self.resize, hopper("I;16"), (15, 12), Image.BILINEAR - ) - for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]: - im = hopper(mode) - r = self.resize(im, (15, 12), Image.BILINEAR) - self.assertEqual(r.mode, mode) - self.assertEqual(r.size, (15, 12)) - self.assertEqual(r.im.bands, im.im.bands) - - def test_reduce_filters(self): - for f in [ - Image.NEAREST, - Image.BOX, - Image.BILINEAR, - Image.HAMMING, - Image.BICUBIC, - Image.LANCZOS, - ]: - r = self.resize(hopper("RGB"), (15, 12), f) - self.assertEqual(r.mode, "RGB") - self.assertEqual(r.size, (15, 12)) - - def test_enlarge_filters(self): - for f in [ - Image.NEAREST, - Image.BOX, - Image.BILINEAR, - Image.HAMMING, - Image.BICUBIC, - Image.LANCZOS, - ]: - r = self.resize(hopper("RGB"), (212, 195), f) - self.assertEqual(r.mode, "RGB") - self.assertEqual(r.size, (212, 195)) - - def test_endianness(self): - # Make an image with one colored pixel, in one channel. - # When resized, that channel should be the same as a GS image. - # Other channels should be unaffected. - # The R and A channels should not swap, which is indicative of - # an endianness issues. - - samples = { - "blank": Image.new("L", (2, 2), 0), - "filled": Image.new("L", (2, 2), 255), - "dirty": Image.new("L", (2, 2), 0), - } - samples["dirty"].putpixel((1, 1), 128) - - for f in [ - Image.NEAREST, - Image.BOX, - Image.BILINEAR, - Image.HAMMING, - Image.BICUBIC, - Image.LANCZOS, - ]: - # samples resized with current filter - references = { - name: self.resize(ch, (4, 4), f) for name, ch in samples.items() - } - - for mode, channels_set in [ - ("RGB", ("blank", "filled", "dirty")), - ("RGBA", ("blank", "blank", "filled", "dirty")), - ("LA", ("filled", "dirty")), - ]: - for channels in set(permutations(channels_set)): - # compile image from different channels permutations - im = Image.merge(mode, [samples[ch] for ch in channels]) - resized = self.resize(im, (4, 4), f) - - for i, ch in enumerate(resized.split()): - # check what resized channel in image is the same - # as separately resized channel - self.assert_image_equal(ch, references[channels[i]]) - - def test_enlarge_zero(self): - for f in [ - Image.NEAREST, - Image.BOX, - Image.BILINEAR, - Image.HAMMING, - Image.BICUBIC, - Image.LANCZOS, - ]: - r = self.resize(Image.new("RGB", (0, 0), "white"), (212, 195), f) - self.assertEqual(r.mode, "RGB") - self.assertEqual(r.size, (212, 195)) - self.assertEqual(r.getdata()[0], (0, 0, 0)) - - def test_unknown_filter(self): - self.assertRaises(ValueError, self.resize, hopper(), (10, 10), 9) - - -class TestImageResize(PillowTestCase): - def test_resize(self): - def resize(mode, size): - out = hopper(mode).resize(size) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, size) - - for mode in "1", "P", "L", "RGB", "I", "F": - resize(mode, (112, 103)) - resize(mode, (188, 214)) - - # Test unknown resampling filter - im = hopper() - self.assertRaises(ValueError, im.resize, (10, 10), "unknown") diff --git a/Tests/test_image_rotate.py b/Tests/test_image_rotate.py deleted file mode 100644 index 9c62e7362cb..00000000000 --- a/Tests/test_image_rotate.py +++ /dev/null @@ -1,127 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageRotate(PillowTestCase): - def rotate(self, im, mode, angle, center=None, translate=None): - out = im.rotate(angle, center=center, translate=translate) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size) # default rotate clips output - out = im.rotate(angle, center=center, translate=translate, expand=1) - self.assertEqual(out.mode, mode) - if angle % 180 == 0: - self.assertEqual(out.size, im.size) - elif im.size == (0, 0): - self.assertEqual(out.size, im.size) - else: - self.assertNotEqual(out.size, im.size) - - def test_mode(self): - for mode in ("1", "P", "L", "RGB", "I", "F"): - im = hopper(mode) - self.rotate(im, mode, 45) - - def test_angle(self): - for angle in (0, 90, 180, 270): - im = Image.open("Tests/images/test-card.png") - self.rotate(im, im.mode, angle) - - def test_zero(self): - for angle in (0, 45, 90, 180, 270): - im = Image.new("RGB", (0, 0)) - self.rotate(im, im.mode, angle) - - def test_resample(self): - # Target image creation, inspected by eye. - # >>> im = Image.open('Tests/images/hopper.ppm') - # >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True) - # >>> im.save('Tests/images/hopper_45.png') - - target = Image.open("Tests/images/hopper_45.png") - for (resample, epsilon) in ( - (Image.NEAREST, 10), - (Image.BILINEAR, 5), - (Image.BICUBIC, 0), - ): - im = hopper() - im = im.rotate(45, resample=resample, expand=True) - self.assert_image_similar(im, target, epsilon) - - def test_center_0(self): - im = hopper() - target = Image.open("Tests/images/hopper_45.png") - target_origin = target.size[1] / 2 - target = target.crop((0, target_origin, 128, target_origin + 128)) - - im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC) - - self.assert_image_similar(im, target, 15) - - def test_center_14(self): - im = hopper() - target = Image.open("Tests/images/hopper_45.png") - target_origin = target.size[1] / 2 - 14 - target = target.crop((6, target_origin, 128 + 6, target_origin + 128)) - - im = im.rotate(45, center=(14, 14), resample=Image.BICUBIC) - - self.assert_image_similar(im, target, 10) - - def test_translate(self): - im = hopper() - target = Image.open("Tests/images/hopper_45.png") - target_origin = (target.size[1] / 2 - 64) - 5 - target = target.crop( - (target_origin, target_origin, target_origin + 128, target_origin + 128) - ) - - im = im.rotate(45, translate=(5, 5), resample=Image.BICUBIC) - - self.assert_image_similar(im, target, 1) - - def test_fastpath_center(self): - # if the center is -1,-1 and we rotate by 90<=x<=270 the - # resulting image should be black - for angle in (90, 180, 270): - im = hopper().rotate(angle, center=(-1, -1)) - self.assert_image_equal(im, Image.new("RGB", im.size, "black")) - - def test_fastpath_translate(self): - # if we post-translate by -128 - # resulting image should be black - for angle in (0, 90, 180, 270): - im = hopper().rotate(angle, translate=(-128, -128)) - self.assert_image_equal(im, Image.new("RGB", im.size, "black")) - - def test_center(self): - im = hopper() - self.rotate(im, im.mode, 45, center=(0, 0)) - self.rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0)) - self.rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0)) - - def test_rotate_no_fill(self): - im = Image.new("RGB", (100, 100), "green") - target = Image.open("Tests/images/rotate_45_no_fill.png") - im = im.rotate(45) - self.assert_image_equal(im, target) - - def test_rotate_with_fill(self): - im = Image.new("RGB", (100, 100), "green") - target = Image.open("Tests/images/rotate_45_with_fill.png") - im = im.rotate(45, fillcolor="white") - self.assert_image_equal(im, target) - - def test_alpha_rotate_no_fill(self): - # Alpha images are handled differently internally - im = Image.new("RGBA", (10, 10), "green") - im = im.rotate(45, expand=1) - corner = im.getpixel((0, 0)) - self.assertEqual(corner, (0, 0, 0, 0)) - - def test_alpha_rotate_with_fill(self): - # Alpha images are handled differently internally - im = Image.new("RGBA", (10, 10), "green") - im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255)) - corner = im.getpixel((0, 0)) - self.assertEqual(corner, (255, 0, 0, 255)) diff --git a/Tests/test_image_split.py b/Tests/test_image_split.py deleted file mode 100644 index a19878aaeb1..00000000000 --- a/Tests/test_image_split.py +++ /dev/null @@ -1,64 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageSplit(PillowTestCase): - def test_split(self): - def split(mode): - layers = hopper(mode).split() - return [(i.mode, i.size[0], i.size[1]) for i in layers] - - self.assertEqual(split("1"), [("1", 128, 128)]) - self.assertEqual(split("L"), [("L", 128, 128)]) - self.assertEqual(split("I"), [("I", 128, 128)]) - self.assertEqual(split("F"), [("F", 128, 128)]) - self.assertEqual(split("P"), [("P", 128, 128)]) - self.assertEqual( - split("RGB"), [("L", 128, 128), ("L", 128, 128), ("L", 128, 128)] - ) - self.assertEqual( - split("RGBA"), - [("L", 128, 128), ("L", 128, 128), ("L", 128, 128), ("L", 128, 128)], - ) - self.assertEqual( - split("CMYK"), - [("L", 128, 128), ("L", 128, 128), ("L", 128, 128), ("L", 128, 128)], - ) - self.assertEqual( - split("YCbCr"), [("L", 128, 128), ("L", 128, 128), ("L", 128, 128)] - ) - - def test_split_merge(self): - def split_merge(mode): - return Image.merge(mode, hopper(mode).split()) - - self.assert_image_equal(hopper("1"), split_merge("1")) - self.assert_image_equal(hopper("L"), split_merge("L")) - self.assert_image_equal(hopper("I"), split_merge("I")) - self.assert_image_equal(hopper("F"), split_merge("F")) - self.assert_image_equal(hopper("P"), split_merge("P")) - self.assert_image_equal(hopper("RGB"), split_merge("RGB")) - self.assert_image_equal(hopper("RGBA"), split_merge("RGBA")) - self.assert_image_equal(hopper("CMYK"), split_merge("CMYK")) - self.assert_image_equal(hopper("YCbCr"), split_merge("YCbCr")) - - def test_split_open(self): - codecs = dir(Image.core) - - if "zip_encoder" in codecs: - test_file = self.tempfile("temp.png") - else: - test_file = self.tempfile("temp.pcx") - - def split_open(mode): - hopper(mode).save(test_file) - im = Image.open(test_file) - return len(im.split()) - - self.assertEqual(split_open("1"), 1) - self.assertEqual(split_open("L"), 1) - self.assertEqual(split_open("P"), 1) - self.assertEqual(split_open("RGB"), 3) - if "zip_encoder" in codecs: - self.assertEqual(split_open("RGBA"), 4) diff --git a/Tests/test_image_thumbnail.py b/Tests/test_image_thumbnail.py deleted file mode 100644 index bd7c98c2831..00000000000 --- a/Tests/test_image_thumbnail.py +++ /dev/null @@ -1,49 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestImageThumbnail(PillowTestCase): - def test_sanity(self): - - im = hopper() - im.thumbnail((100, 100)) - - self.assert_image(im, im.mode, (100, 100)) - - def test_aspect(self): - - im = hopper() - im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (100, 100)) - - im = hopper().resize((128, 256)) - im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (50, 100)) - - im = hopper().resize((128, 256)) - im.thumbnail((50, 100)) - self.assert_image(im, im.mode, (50, 100)) - - im = hopper().resize((256, 128)) - im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (100, 50)) - - im = hopper().resize((256, 128)) - im.thumbnail((100, 50)) - self.assert_image(im, im.mode, (100, 50)) - - im = hopper().resize((128, 128)) - im.thumbnail((100, 100)) - self.assert_image(im, im.mode, (100, 100)) - - def test_no_resize(self): - # Check that draft() can resize the image to the destination size - im = Image.open("Tests/images/hopper.jpg") - im.draft(None, (64, 64)) - self.assertEqual(im.size, (64, 64)) - - # Test thumbnail(), where only draft() is necessary to resize the image - im = Image.open("Tests/images/hopper.jpg") - im.thumbnail((64, 64)) - self.assert_image(im, im.mode, (64, 64)) diff --git a/Tests/test_image_tobitmap.py b/Tests/test_image_tobitmap.py deleted file mode 100644 index d7c879a25ba..00000000000 --- a/Tests/test_image_tobitmap.py +++ /dev/null @@ -1,14 +0,0 @@ -from .helper import PillowTestCase, fromstring, hopper - - -class TestImageToBitmap(PillowTestCase): - def test_sanity(self): - - self.assertRaises(ValueError, lambda: hopper().tobitmap()) - - im1 = hopper().convert("1") - - bitmap = im1.tobitmap() - - self.assertIsInstance(bitmap, bytes) - self.assert_image_equal(im1, fromstring(bitmap)) diff --git a/Tests/test_image_tobytes.py b/Tests/test_image_tobytes.py deleted file mode 100644 index d21ef7f6f98..00000000000 --- a/Tests/test_image_tobytes.py +++ /dev/null @@ -1,7 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestImageToBytes(PillowTestCase): - def test_sanity(self): - data = hopper().tobytes() - self.assertIsInstance(data, bytes) diff --git a/Tests/test_image_transform.py b/Tests/test_image_transform.py deleted file mode 100644 index a0e54176a7b..00000000000 --- a/Tests/test_image_transform.py +++ /dev/null @@ -1,286 +0,0 @@ -import math - -from PIL import Image - -from .helper import PillowTestCase, hopper - - -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 = hopper("RGB") - (w, h) = im.size - # fmt: off - transformed = im.transform(im.size, Image.EXTENT, - (0, 0, - w//2, h//2), # ul -> lr - Image.BILINEAR) - # fmt: on - - scaled = im.resize((w * 2, h * 2), Image.BILINEAR).crop((0, 0, w, h)) - - # undone -- precision? - self.assert_image_similar(transformed, scaled, 23) - - def test_quad(self): - # one simple quad transform, equivalent to scale & crop upper left quad - im = hopper("RGB") - (w, h) = im.size - # fmt: off - transformed = im.transform(im.size, Image.QUAD, - (0, 0, 0, h//2, - # ul -> ccw around quad: - w//2, h//2, w//2, 0), - Image.BILINEAR) - # fmt: on - - scaled = im.transform( - (w, h), Image.AFFINE, (0.5, 0, 0, 0, 0.5, 0), Image.BILINEAR - ) - - self.assert_image_equal(transformed, scaled) - - def test_fill(self): - for mode, pixel in [ - ["RGB", (255, 0, 0)], - ["RGBA", (255, 0, 0, 255)], - ["LA", (76, 0)], - ]: - im = hopper(mode) - (w, h) = im.size - transformed = im.transform( - im.size, - Image.EXTENT, - (0, 0, w * 2, h * 2), - Image.BILINEAR, - fillcolor="red", - ) - - self.assertEqual(transformed.getpixel((w - 1, h - 1)), pixel) - - def test_mesh(self): - # this should be a checkerboard of halfsized hoppers in ul, lr - im = hopper("RGBA") - (w, h) = im.size - # fmt: off - transformed = im.transform(im.size, Image.MESH, - [((0, 0, w//2, h//2), # box - (0, 0, 0, h, - w, h, w, 0)), # ul -> ccw around quad - ((w//2, h//2, w, h), # box - (0, 0, 0, h, - w, h, w, 0))], # ul -> ccw around quad - Image.BILINEAR) - # fmt: on - - scaled = im.transform( - (w // 2, h // 2), Image.AFFINE, (2, 0, 0, 0, 2, 0), Image.BILINEAR - ) - - checker = Image.new("RGBA", im.size) - checker.paste(scaled, (0, 0)) - checker.paste(scaled, (w // 2, h // 2)) - - self.assert_image_equal(transformed, checker) - - # now, check to see that the extra area is (0, 0, 0, 0) - blank = Image.new("RGBA", (w // 2, h // 2), (0, 0, 0, 0)) - - self.assert_image_equal(blank, transformed.crop((w // 2, 0, w, h // 2))) - self.assert_image_equal(blank, transformed.crop((0, h // 2, w // 2, h))) - - def _test_alpha_premult(self, op): - # create image with half white, half black, - # with the black half transparent. - # do op, - # there should be no darkness in the white section. - im = Image.new("RGBA", (10, 10), (0, 0, 0, 0)) - im2 = Image.new("RGBA", (5, 10), (255, 255, 255, 255)) - im.paste(im2, (0, 0)) - - im = op(im, (40, 10)) - im_background = Image.new("RGB", (40, 10), (255, 255, 255)) - im_background.paste(im, (0, 0), im) - - hist = im_background.histogram() - self.assertEqual(40 * 10, hist[-1]) - - def test_alpha_premult_resize(self): - def op(im, sz): - return im.resize(sz, Image.BILINEAR) - - self._test_alpha_premult(op) - - def test_alpha_premult_transform(self): - def op(im, sz): - (w, h) = im.size - return im.transform(sz, Image.EXTENT, (0, 0, w, h), Image.BILINEAR) - - self._test_alpha_premult(op) - - def test_blank_fill(self): - # attempting to hit - # https://github.com/python-pillow/Pillow/issues/254 reported - # - # issue is that transforms with transparent overflow area - # contained junk from previous images, especially on systems with - # constrained memory. So, attempt to fill up memory with a - # pattern, free it, and then run the mesh test again. Using a 1Mp - # image with 4 bands, for 4 megs of data allocated, x 64. OMM (64 - # bit 12.04 VM with 512 megs available, this fails with Pillow < - # a0eaf06cc5f62a6fb6de556989ac1014ff3348ea - # - # Running by default, but I'd totally understand not doing it in - # the future - - pattern = [Image.new("RGBA", (1024, 1024), (a, a, a, a)) for a in range(1, 65)] - - # Yeah. Watch some JIT optimize this out. - pattern = None # noqa: F841 - - self.test_mesh() - - def test_missing_method_data(self): - im = hopper() - self.assertRaises(ValueError, im.transform, (100, 100), None) - - def test_unknown_resampling_filter(self): - im = hopper() - (w, h) = im.size - for resample in (Image.BOX, "unknown"): - self.assertRaises( - ValueError, - im.transform, - (100, 100), - Image.EXTENT, - (0, 0, w, h), - resample, - ) - - -class TestImageTransformAffine(PillowTestCase): - transform = Image.AFFINE - - def _test_image(self): - im = hopper("RGB") - return im.crop((10, 20, im.width - 10, im.height - 20)) - - def _test_rotate(self, deg, transpose): - im = self._test_image() - - angle = -math.radians(deg) - matrix = [ - round(math.cos(angle), 15), - round(math.sin(angle), 15), - 0.0, - round(-math.sin(angle), 15), - round(math.cos(angle), 15), - 0.0, - 0, - 0, - ] - matrix[2] = (1 - matrix[0] - matrix[1]) * im.width / 2 - matrix[5] = (1 - matrix[3] - matrix[4]) * im.height / 2 - - if transpose is not None: - transposed = im.transpose(transpose) - else: - transposed = im - - for resample in [Image.NEAREST, Image.BILINEAR, Image.BICUBIC]: - transformed = im.transform( - transposed.size, self.transform, matrix, resample - ) - self.assert_image_equal(transposed, transformed) - - def test_rotate_0_deg(self): - self._test_rotate(0, None) - - def test_rotate_90_deg(self): - self._test_rotate(90, Image.ROTATE_90) - - def test_rotate_180_deg(self): - self._test_rotate(180, Image.ROTATE_180) - - def test_rotate_270_deg(self): - self._test_rotate(270, Image.ROTATE_270) - - def _test_resize(self, scale, epsilonscale): - im = self._test_image() - - size_up = int(round(im.width * scale)), int(round(im.height * scale)) - matrix_up = [1 / scale, 0, 0, 0, 1 / scale, 0, 0, 0] - matrix_down = [scale, 0, 0, 0, scale, 0, 0, 0] - - for resample, epsilon in [ - (Image.NEAREST, 0), - (Image.BILINEAR, 2), - (Image.BICUBIC, 1), - ]: - transformed = im.transform(size_up, self.transform, matrix_up, resample) - transformed = transformed.transform( - im.size, self.transform, matrix_down, resample - ) - self.assert_image_similar(transformed, im, epsilon * epsilonscale) - - def test_resize_1_1x(self): - self._test_resize(1.1, 6.9) - - def test_resize_1_5x(self): - self._test_resize(1.5, 5.5) - - def test_resize_2_0x(self): - self._test_resize(2.0, 5.5) - - def test_resize_2_3x(self): - self._test_resize(2.3, 3.7) - - def test_resize_2_5x(self): - self._test_resize(2.5, 3.7) - - def _test_translate(self, x, y, epsilonscale): - im = self._test_image() - - size_up = int(round(im.width + x)), int(round(im.height + y)) - matrix_up = [1, 0, -x, 0, 1, -y, 0, 0] - matrix_down = [1, 0, x, 0, 1, y, 0, 0] - - for resample, epsilon in [ - (Image.NEAREST, 0), - (Image.BILINEAR, 1.5), - (Image.BICUBIC, 1), - ]: - transformed = im.transform(size_up, self.transform, matrix_up, resample) - transformed = transformed.transform( - im.size, self.transform, matrix_down, resample - ) - self.assert_image_similar(transformed, im, epsilon * epsilonscale) - - def test_translate_0_1(self): - self._test_translate(0.1, 0, 3.7) - - def test_translate_0_6(self): - self._test_translate(0.6, 0, 9.1) - - def test_translate_50(self): - self._test_translate(50, 50, 0) - - -class TestImageTransformPerspective(TestImageTransformAffine): - # Repeat all tests for AFFINE transformations with PERSPECTIVE - transform = Image.PERSPECTIVE diff --git a/Tests/test_image_transpose.py b/Tests/test_image_transpose.py deleted file mode 100644 index f5e8746ee40..00000000000 --- a/Tests/test_image_transpose.py +++ /dev/null @@ -1,159 +0,0 @@ -from PIL.Image import ( - FLIP_LEFT_RIGHT, - FLIP_TOP_BOTTOM, - ROTATE_90, - ROTATE_180, - ROTATE_270, - TRANSPOSE, - TRANSVERSE, -) - -from . import helper -from .helper import PillowTestCase - - -class TestImageTranspose(PillowTestCase): - - hopper = { - mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy() - for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"] - } - - def test_flip_left_right(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(FLIP_LEFT_RIGHT) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, 1))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, y - 2))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, y - 2))) - - for mode in self.hopper: - transpose(mode) - - def test_flip_top_bottom(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(FLIP_TOP_BOTTOM) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y - 2))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((x - 2, y - 2))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((x - 2, 1))) - - for mode in self.hopper: - transpose(mode) - - def test_rotate_90(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(ROTATE_90) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size[::-1]) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, x - 2))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, x - 2))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, 1))) - - for mode in self.hopper: - transpose(mode) - - def test_rotate_180(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(ROTATE_180) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, y - 2))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, y - 2))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, 1))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1))) - - for mode in self.hopper: - transpose(mode) - - def test_rotate_270(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(ROTATE_270) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size[::-1]) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, 1))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, x - 2))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, x - 2))) - - for mode in self.hopper: - transpose(mode) - - def test_transpose(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(TRANSPOSE) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size[::-1]) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, 1))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, x - 2))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, 1))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, x - 2))) - - for mode in self.hopper: - transpose(mode) - - def test_tranverse(self): - def transpose(mode): - im = self.hopper[mode] - out = im.transpose(TRANSVERSE) - self.assertEqual(out.mode, mode) - self.assertEqual(out.size, im.size[::-1]) - - x, y = im.size - self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, x - 2))) - self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, 1))) - self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, x - 2))) - self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1))) - - for mode in self.hopper: - transpose(mode) - - def test_roundtrip(self): - for mode in self.hopper: - im = self.hopper[mode] - - def transpose(first, second): - return im.transpose(first).transpose(second) - - self.assert_image_equal(im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT)) - self.assert_image_equal(im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM)) - self.assert_image_equal(im, transpose(ROTATE_90, ROTATE_270)) - self.assert_image_equal(im, transpose(ROTATE_180, ROTATE_180)) - self.assert_image_equal( - im.transpose(TRANSPOSE), transpose(ROTATE_90, FLIP_TOP_BOTTOM) - ) - self.assert_image_equal( - im.transpose(TRANSPOSE), transpose(ROTATE_270, FLIP_LEFT_RIGHT) - ) - self.assert_image_equal( - im.transpose(TRANSVERSE), transpose(ROTATE_90, FLIP_LEFT_RIGHT) - ) - self.assert_image_equal( - im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM) - ) - self.assert_image_equal( - im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE) - ) diff --git a/Tests/test_imagechops.py b/Tests/test_imagechops.py deleted file mode 100644 index 6f42a28dfd7..00000000000 --- a/Tests/test_imagechops.py +++ /dev/null @@ -1,364 +0,0 @@ -from PIL import Image, ImageChops - -from .helper import PillowTestCase, hopper - -BLACK = (0, 0, 0) -BROWN = (127, 64, 0) -CYAN = (0, 255, 255) -DARK_GREEN = (0, 128, 0) -GREEN = (0, 255, 0) -ORANGE = (255, 128, 0) -WHITE = (255, 255, 255) - -GREY = 128 - - -class TestImageChops(PillowTestCase): - def test_sanity(self): - - im = hopper("L") - - ImageChops.constant(im, 128) - ImageChops.duplicate(im) - ImageChops.invert(im) - ImageChops.lighter(im, im) - ImageChops.darker(im, im) - ImageChops.difference(im, im) - ImageChops.multiply(im, im) - ImageChops.screen(im, im) - - ImageChops.add(im, im) - ImageChops.add(im, im, 2.0) - ImageChops.add(im, im, 2.0, 128) - ImageChops.subtract(im, im) - ImageChops.subtract(im, im, 2.0) - ImageChops.subtract(im, im, 2.0, 128) - - ImageChops.add_modulo(im, im) - ImageChops.subtract_modulo(im, im) - - ImageChops.blend(im, im, 0.5) - ImageChops.composite(im, im, im) - - ImageChops.offset(im, 10) - ImageChops.offset(im, 10, 20) - - def test_add(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png") - im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - - # Act - new = ImageChops.add(im1, im2) - - # Assert - self.assertEqual(new.getbbox(), (25, 25, 76, 76)) - self.assertEqual(new.getpixel((50, 50)), ORANGE) - - def test_add_scale_offset(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png") - im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - - # Act - new = ImageChops.add(im1, im2, scale=2.5, offset=100) - - # Assert - self.assertEqual(new.getbbox(), (0, 0, 100, 100)) - self.assertEqual(new.getpixel((50, 50)), (202, 151, 100)) - - def test_add_clip(self): - # Arrange - im = hopper() - - # Act - new = ImageChops.add(im, im) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (255, 255, 254)) - - def test_add_modulo(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png") - im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - - # Act - new = ImageChops.add_modulo(im1, im2) - - # Assert - self.assertEqual(new.getbbox(), (25, 25, 76, 76)) - self.assertEqual(new.getpixel((50, 50)), ORANGE) - - def test_add_modulo_no_clip(self): - # Arrange - im = hopper() - - # Act - new = ImageChops.add_modulo(im, im) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (224, 76, 254)) - - def test_blend(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png") - im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - - # Act - new = ImageChops.blend(im1, im2, 0.5) - - # Assert - self.assertEqual(new.getbbox(), (25, 25, 76, 76)) - self.assertEqual(new.getpixel((50, 50)), BROWN) - - def test_constant(self): - # Arrange - im = Image.new("RGB", (20, 10)) - - # Act - new = ImageChops.constant(im, GREY) - - # Assert - self.assertEqual(new.size, im.size) - self.assertEqual(new.getpixel((0, 0)), GREY) - self.assertEqual(new.getpixel((19, 9)), GREY) - - def test_darker_image(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_chord_RGB.png") - im2 = Image.open("Tests/images/imagedraw_outline_chord_RGB.png") - - # Act - new = ImageChops.darker(im1, im2) - - # Assert - self.assert_image_equal(new, im2) - - def test_darker_pixel(self): - # Arrange - im1 = hopper() - im2 = Image.open("Tests/images/imagedraw_chord_RGB.png") - - # Act - new = ImageChops.darker(im1, im2) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (240, 166, 0)) - - def test_difference(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_arc_end_le_start.png") - im2 = Image.open("Tests/images/imagedraw_arc_no_loops.png") - - # Act - new = ImageChops.difference(im1, im2) - - # Assert - self.assertEqual(new.getbbox(), (25, 25, 76, 76)) - - def test_difference_pixel(self): - # Arrange - im1 = hopper() - im2 = Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") - - # Act - new = ImageChops.difference(im1, im2) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (240, 166, 128)) - - def test_duplicate(self): - # Arrange - im = hopper() - - # Act - new = ImageChops.duplicate(im) - - # Assert - self.assert_image_equal(new, im) - - def test_invert(self): - # Arrange - im = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - - # Act - new = ImageChops.invert(im) - - # Assert - self.assertEqual(new.getbbox(), (0, 0, 100, 100)) - self.assertEqual(new.getpixel((0, 0)), WHITE) - self.assertEqual(new.getpixel((50, 50)), CYAN) - - def test_lighter_image(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_chord_RGB.png") - im2 = Image.open("Tests/images/imagedraw_outline_chord_RGB.png") - - # Act - new = ImageChops.lighter(im1, im2) - - # Assert - self.assert_image_equal(new, im1) - - def test_lighter_pixel(self): - # Arrange - im1 = hopper() - im2 = Image.open("Tests/images/imagedraw_chord_RGB.png") - - # Act - new = ImageChops.lighter(im1, im2) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (255, 255, 127)) - - def test_multiply_black(self): - """If you multiply an image with a solid black image, - the result is black.""" - # Arrange - im1 = hopper() - black = Image.new("RGB", im1.size, "black") - - # Act - new = ImageChops.multiply(im1, black) - - # Assert - self.assert_image_equal(new, black) - - def test_multiply_green(self): - # Arrange - im = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - green = Image.new("RGB", im.size, "green") - - # Act - new = ImageChops.multiply(im, green) - - # Assert - self.assertEqual(new.getbbox(), (25, 25, 76, 76)) - self.assertEqual(new.getpixel((25, 25)), DARK_GREEN) - self.assertEqual(new.getpixel((50, 50)), BLACK) - - def test_multiply_white(self): - """If you multiply with a solid white image, - the image is unaffected.""" - # Arrange - im1 = hopper() - white = Image.new("RGB", im1.size, "white") - - # Act - new = ImageChops.multiply(im1, white) - - # Assert - self.assert_image_equal(new, im1) - - def test_offset(self): - # Arrange - im = Image.open("Tests/images/imagedraw_ellipse_RGB.png") - xoffset = 45 - yoffset = 20 - - # Act - new = ImageChops.offset(im, xoffset, yoffset) - - # Assert - self.assertEqual(new.getbbox(), (0, 45, 100, 96)) - self.assertEqual(new.getpixel((50, 50)), BLACK) - self.assertEqual(new.getpixel((50 + xoffset, 50 + yoffset)), DARK_GREEN) - - # Test no yoffset - self.assertEqual( - ImageChops.offset(im, xoffset), ImageChops.offset(im, xoffset, xoffset) - ) - - def test_screen(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png") - im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png") - - # Act - new = ImageChops.screen(im1, im2) - - # Assert - self.assertEqual(new.getbbox(), (25, 25, 76, 76)) - self.assertEqual(new.getpixel((50, 50)), ORANGE) - - def test_subtract(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_chord_RGB.png") - im2 = Image.open("Tests/images/imagedraw_outline_chord_RGB.png") - - # Act - new = ImageChops.subtract(im1, im2) - - # Assert - self.assertEqual(new.getbbox(), (25, 50, 76, 76)) - self.assertEqual(new.getpixel((50, 50)), GREEN) - self.assertEqual(new.getpixel((50, 51)), BLACK) - - def test_subtract_scale_offset(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_chord_RGB.png") - im2 = Image.open("Tests/images/imagedraw_outline_chord_RGB.png") - - # Act - new = ImageChops.subtract(im1, im2, scale=2.5, offset=100) - - # Assert - self.assertEqual(new.getbbox(), (0, 0, 100, 100)) - self.assertEqual(new.getpixel((50, 50)), (100, 202, 100)) - - def test_subtract_clip(self): - # Arrange - im1 = hopper() - im2 = Image.open("Tests/images/imagedraw_chord_RGB.png") - - # Act - new = ImageChops.subtract(im1, im2) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (0, 0, 127)) - - def test_subtract_modulo(self): - # Arrange - im1 = Image.open("Tests/images/imagedraw_chord_RGB.png") - im2 = Image.open("Tests/images/imagedraw_outline_chord_RGB.png") - - # Act - new = ImageChops.subtract_modulo(im1, im2) - - # Assert - self.assertEqual(new.getbbox(), (25, 50, 76, 76)) - self.assertEqual(new.getpixel((50, 50)), GREEN) - self.assertEqual(new.getpixel((50, 51)), BLACK) - - def test_subtract_modulo_no_clip(self): - # Arrange - im1 = hopper() - im2 = Image.open("Tests/images/imagedraw_chord_RGB.png") - - # Act - new = ImageChops.subtract_modulo(im1, im2) - - # Assert - self.assertEqual(new.getpixel((50, 50)), (241, 167, 127)) - - def test_logical(self): - def table(op, a, b): - out = [] - for x in (a, b): - imx = Image.new("1", (1, 1), x) - for y in (a, b): - imy = Image.new("1", (1, 1), y) - out.append(op(imx, imy).getpixel((0, 0))) - return tuple(out) - - self.assertEqual(table(ImageChops.logical_and, 0, 1), (0, 0, 0, 255)) - self.assertEqual(table(ImageChops.logical_or, 0, 1), (0, 255, 255, 255)) - self.assertEqual(table(ImageChops.logical_xor, 0, 1), (0, 255, 255, 0)) - - self.assertEqual(table(ImageChops.logical_and, 0, 128), (0, 0, 0, 255)) - self.assertEqual(table(ImageChops.logical_or, 0, 128), (0, 255, 255, 255)) - self.assertEqual(table(ImageChops.logical_xor, 0, 128), (0, 255, 255, 0)) - - self.assertEqual(table(ImageChops.logical_and, 0, 255), (0, 0, 0, 255)) - self.assertEqual(table(ImageChops.logical_or, 0, 255), (0, 255, 255, 255)) - self.assertEqual(table(ImageChops.logical_xor, 0, 255), (0, 255, 255, 0)) diff --git a/Tests/test_imagecms.py b/Tests/test_imagecms.py deleted file mode 100644 index 10465e73977..00000000000 --- a/Tests/test_imagecms.py +++ /dev/null @@ -1,608 +0,0 @@ -import datetime -import os -from io import BytesIO - -from PIL import Image, ImageMode - -from .helper import PillowTestCase, hopper - -try: - from PIL import ImageCms - from PIL.ImageCms import ImageCmsProfile - - ImageCms.core.profile_open -except ImportError: - # Skipped via setUp() - pass - - -SRGB = "Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc" -HAVE_PROFILE = os.path.exists(SRGB) - - -class TestImageCms(PillowTestCase): - def setUp(self): - try: - from PIL import ImageCms - - # need to hit getattr to trigger the delayed import error - ImageCms.core.profile_open - except ImportError as v: - self.skipTest(v) - - def skip_missing(self): - if not HAVE_PROFILE: - self.skipTest("SRGB profile not available") - - def test_sanity(self): - - # basic smoke test. - # this mostly follows the cms_test outline. - - v = ImageCms.versions() # should return four strings - self.assertEqual(v[0], "1.0.0 pil") - self.assertEqual(list(map(type, v)), [str, str, str, str]) - - # internal version number - self.assertRegex(ImageCms.core.littlecms_version, r"\d+\.\d+$") - - self.skip_missing() - i = ImageCms.profileToProfile(hopper(), SRGB, SRGB) - self.assert_image(i, "RGB", (128, 128)) - - i = hopper() - ImageCms.profileToProfile(i, SRGB, SRGB, inPlace=True) - self.assert_image(i, "RGB", (128, 128)) - - t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") - i = ImageCms.applyTransform(hopper(), t) - self.assert_image(i, "RGB", (128, 128)) - - i = hopper() - t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") - ImageCms.applyTransform(hopper(), t, inPlace=True) - self.assert_image(i, "RGB", (128, 128)) - - p = ImageCms.createProfile("sRGB") - o = ImageCms.getOpenProfile(SRGB) - t = ImageCms.buildTransformFromOpenProfiles(p, o, "RGB", "RGB") - i = ImageCms.applyTransform(hopper(), t) - self.assert_image(i, "RGB", (128, 128)) - - t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB") - self.assertEqual(t.inputMode, "RGB") - self.assertEqual(t.outputMode, "RGB") - i = ImageCms.applyTransform(hopper(), t) - self.assert_image(i, "RGB", (128, 128)) - - # test PointTransform convenience API - hopper().point(t) - - def test_name(self): - self.skip_missing() - # get profile information for file - self.assertEqual( - ImageCms.getProfileName(SRGB).strip(), - "IEC 61966-2-1 Default RGB Colour Space - sRGB", - ) - - def test_info(self): - self.skip_missing() - self.assertEqual( - ImageCms.getProfileInfo(SRGB).splitlines(), - [ - "sRGB IEC61966-2-1 black scaled", - "", - "Copyright International Color Consortium, 2009", - "", - ], - ) - - def test_copyright(self): - self.skip_missing() - self.assertEqual( - ImageCms.getProfileCopyright(SRGB).strip(), - "Copyright International Color Consortium, 2009", - ) - - def test_manufacturer(self): - self.skip_missing() - self.assertEqual(ImageCms.getProfileManufacturer(SRGB).strip(), "") - - def test_model(self): - self.skip_missing() - self.assertEqual( - ImageCms.getProfileModel(SRGB).strip(), - "IEC 61966-2-1 Default RGB Colour Space - sRGB", - ) - - def test_description(self): - self.skip_missing() - self.assertEqual( - ImageCms.getProfileDescription(SRGB).strip(), - "sRGB IEC61966-2-1 black scaled", - ) - - def test_intent(self): - self.skip_missing() - self.assertEqual(ImageCms.getDefaultIntent(SRGB), 0) - self.assertEqual( - ImageCms.isIntentSupported( - SRGB, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, ImageCms.DIRECTION_INPUT - ), - 1, - ) - - def test_profile_object(self): - # same, using profile object - p = ImageCms.createProfile("sRGB") - # self.assertEqual(ImageCms.getProfileName(p).strip(), - # 'sRGB built-in - (lcms internal)') - # self.assertEqual(ImageCms.getProfileInfo(p).splitlines(), - # ['sRGB built-in', '', 'WhitePoint : D65 (daylight)', '', '']) - self.assertEqual(ImageCms.getDefaultIntent(p), 0) - self.assertEqual( - ImageCms.isIntentSupported( - p, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, ImageCms.DIRECTION_INPUT - ), - 1, - ) - - def test_extensions(self): - # extensions - - i = Image.open("Tests/images/rgb.jpg") - p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"])) - self.assertEqual( - ImageCms.getProfileName(p).strip(), - "IEC 61966-2.1 Default RGB colour space - sRGB", - ) - - def test_exceptions(self): - # Test mode mismatch - psRGB = ImageCms.createProfile("sRGB") - pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") - self.assertRaises(ValueError, t.apply_in_place, hopper("RGBA")) - - # the procedural pyCMS API uses PyCMSError for all sorts of errors - self.assertRaises( - ImageCms.PyCMSError, ImageCms.profileToProfile, hopper(), "foo", "bar" - ) - self.assertRaises( - ImageCms.PyCMSError, ImageCms.buildTransform, "foo", "bar", "RGB", "RGB" - ) - self.assertRaises(ImageCms.PyCMSError, ImageCms.getProfileName, None) - self.skip_missing() - self.assertRaises( - ImageCms.PyCMSError, ImageCms.isIntentSupported, SRGB, None, None - ) - - def test_display_profile(self): - # try fetching the profile for the current display device - ImageCms.get_display_profile() - - def test_lab_color_profile(self): - ImageCms.createProfile("LAB", 5000) - ImageCms.createProfile("LAB", 6500) - - def test_unsupported_color_space(self): - self.assertRaises(ImageCms.PyCMSError, ImageCms.createProfile, "unsupported") - - def test_invalid_color_temperature(self): - self.assertRaises(ImageCms.PyCMSError, ImageCms.createProfile, "LAB", "invalid") - - def test_simple_lab(self): - i = Image.new("RGB", (10, 10), (128, 128, 128)) - - psRGB = ImageCms.createProfile("sRGB") - pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") - - i_lab = ImageCms.applyTransform(i, t) - - self.assertEqual(i_lab.mode, "LAB") - - k = i_lab.getpixel((0, 0)) - # not a linear luminance map. so L != 128: - self.assertEqual(k, (137, 128, 128)) - - l_data = i_lab.getdata(0) - a_data = i_lab.getdata(1) - b_data = i_lab.getdata(2) - - self.assertEqual(list(l_data), [137] * 100) - self.assertEqual(list(a_data), [128] * 100) - self.assertEqual(list(b_data), [128] * 100) - - def test_lab_color(self): - psRGB = ImageCms.createProfile("sRGB") - pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") - - # Need to add a type mapping for some PIL type to TYPE_Lab_8 in - # findLCMSType, and have that mapping work back to a PIL mode - # (likely RGB). - i = ImageCms.applyTransform(hopper(), t) - self.assert_image(i, "LAB", (128, 128)) - - # i.save('temp.lab.tif') # visually verified vs PS. - - target = Image.open("Tests/images/hopper.Lab.tif") - - self.assert_image_similar(i, target, 3.5) - - def test_lab_srgb(self): - psRGB = ImageCms.createProfile("sRGB") - pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") - - img = Image.open("Tests/images/hopper.Lab.tif") - - img_srgb = ImageCms.applyTransform(img, t) - - # img_srgb.save('temp.srgb.tif') # visually verified vs ps. - - self.assert_image_similar(hopper(), img_srgb, 30) - self.assertTrue(img_srgb.info["icc_profile"]) - - profile = ImageCmsProfile(BytesIO(img_srgb.info["icc_profile"])) - self.assertIn("sRGB", ImageCms.getProfileDescription(profile)) - - def test_lab_roundtrip(self): - # check to see if we're at least internally consistent. - psRGB = ImageCms.createProfile("sRGB") - pLab = ImageCms.createProfile("LAB") - t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") - - t2 = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") - - i = ImageCms.applyTransform(hopper(), t) - - self.assertEqual(i.info["icc_profile"], ImageCmsProfile(pLab).tobytes()) - - out = ImageCms.applyTransform(i, t2) - - self.assert_image_similar(hopper(), out, 2) - - def test_profile_tobytes(self): - i = Image.open("Tests/images/rgb.jpg") - p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"])) - - p2 = ImageCms.getOpenProfile(BytesIO(p.tobytes())) - - # not the same bytes as the original icc_profile, - # but it does roundtrip - self.assertEqual(p.tobytes(), p2.tobytes()) - self.assertEqual(ImageCms.getProfileName(p), ImageCms.getProfileName(p2)) - self.assertEqual( - ImageCms.getProfileDescription(p), ImageCms.getProfileDescription(p2) - ) - - def test_extended_information(self): - self.skip_missing() - o = ImageCms.getOpenProfile(SRGB) - p = o.profile - - def assert_truncated_tuple_equal(tup1, tup2, digits=10): - # Helper function to reduce precision of tuples of floats - # recursively and then check equality. - power = 10 ** digits - - def truncate_tuple(tuple_or_float): - return tuple( - truncate_tuple(val) - if isinstance(val, tuple) - else int(val * power) / power - for val in tuple_or_float - ) - - self.assertEqual(truncate_tuple(tup1), truncate_tuple(tup2)) - - self.assertEqual(p.attributes, 4294967296) - assert_truncated_tuple_equal( - p.blue_colorant, - ( - (0.14306640625, 0.06060791015625, 0.7140960693359375), - (0.1558847490315394, 0.06603820639433387, 0.06060791015625), - ), - ) - assert_truncated_tuple_equal( - p.blue_primary, - ( - (0.14306641366715667, 0.06060790921083026, 0.7140960805782015), - (0.15588475410450106, 0.06603820408959558, 0.06060790921083026), - ), - ) - assert_truncated_tuple_equal( - p.chromatic_adaptation, - ( - ( - (1.04791259765625, 0.0229339599609375, -0.050201416015625), - (0.02960205078125, 0.9904632568359375, -0.0170745849609375), - (-0.009246826171875, 0.0150604248046875, 0.7517852783203125), - ), - ( - (1.0267159024652783, 0.022470062342089134, 0.0229339599609375), - (0.02951378324103937, 0.9875098886387147, 0.9904632568359375), - (-0.012205438066465256, 0.01987915407854985, 0.0150604248046875), - ), - ), - ) - self.assertIsNone(p.chromaticity) - self.assertEqual( - p.clut, - { - 0: (False, False, True), - 1: (False, False, True), - 2: (False, False, True), - 3: (False, False, True), - }, - ) - - self.assertIsNone(p.colorant_table) - self.assertIsNone(p.colorant_table_out) - self.assertIsNone(p.colorimetric_intent) - self.assertEqual(p.connection_space, "XYZ ") - self.assertEqual(p.copyright, "Copyright International Color Consortium, 2009") - self.assertEqual(p.creation_date, datetime.datetime(2009, 2, 27, 21, 36, 31)) - self.assertEqual(p.device_class, "mntr") - assert_truncated_tuple_equal( - p.green_colorant, - ( - (0.3851470947265625, 0.7168731689453125, 0.097076416015625), - (0.32119769927720654, 0.5978443449048152, 0.7168731689453125), - ), - ) - assert_truncated_tuple_equal( - p.green_primary, - ( - (0.3851470888162112, 0.7168731974161346, 0.09707641738998518), - (0.32119768793686687, 0.5978443567149709, 0.7168731974161346), - ), - ) - self.assertEqual(p.header_flags, 0) - self.assertEqual(p.header_manufacturer, "\x00\x00\x00\x00") - self.assertEqual(p.header_model, "\x00\x00\x00\x00") - self.assertEqual( - p.icc_measurement_condition, - { - "backing": (0.0, 0.0, 0.0), - "flare": 0.0, - "geo": "unknown", - "observer": 1, - "illuminant_type": "D65", - }, - ) - self.assertEqual(p.icc_version, 33554432) - self.assertIsNone(p.icc_viewing_condition) - self.assertEqual( - p.intent_supported, - { - 0: (True, True, True), - 1: (True, True, True), - 2: (True, True, True), - 3: (True, True, True), - }, - ) - self.assertTrue(p.is_matrix_shaper) - self.assertEqual(p.luminance, ((0.0, 80.0, 0.0), (0.0, 1.0, 80.0))) - self.assertIsNone(p.manufacturer) - assert_truncated_tuple_equal( - p.media_black_point, - ( - (0.012054443359375, 0.0124969482421875, 0.01031494140625), - (0.34573304157549234, 0.35842450765864337, 0.0124969482421875), - ), - ) - assert_truncated_tuple_equal( - p.media_white_point, - ( - (0.964202880859375, 1.0, 0.8249053955078125), - (0.3457029219802284, 0.3585375327567059, 1.0), - ), - ) - assert_truncated_tuple_equal( - (p.media_white_point_temperature,), (5000.722328847392,) - ) - self.assertEqual(p.model, "IEC 61966-2-1 Default RGB Colour Space - sRGB") - - self.assertIsNone(p.perceptual_rendering_intent_gamut) - - self.assertEqual(p.profile_description, "sRGB IEC61966-2-1 black scaled") - self.assertEqual(p.profile_id, b")\xf8=\xde\xaf\xf2U\xaexB\xfa\xe4\xca\x839\r") - assert_truncated_tuple_equal( - p.red_colorant, - ( - (0.436065673828125, 0.2224884033203125, 0.013916015625), - (0.6484536316398539, 0.3308524880306778, 0.2224884033203125), - ), - ) - assert_truncated_tuple_equal( - p.red_primary, - ( - (0.43606566581047446, 0.22248840582960838, 0.013916015621759925), - (0.6484536250319214, 0.3308524944738204, 0.22248840582960838), - ), - ) - self.assertEqual(p.rendering_intent, 0) - self.assertIsNone(p.saturation_rendering_intent_gamut) - self.assertIsNone(p.screening_description) - self.assertIsNone(p.target) - self.assertEqual(p.technology, "CRT ") - self.assertEqual(p.version, 2.0) - self.assertEqual( - p.viewing_condition, "Reference Viewing Condition in IEC 61966-2-1" - ) - self.assertEqual(p.xcolor_space, "RGB ") - - def test_deprecations(self): - self.skip_missing() - o = ImageCms.getOpenProfile(SRGB) - p = o.profile - - def helper_deprecated(attr, expected): - result = self.assert_warning(DeprecationWarning, getattr, p, attr) - self.assertEqual(result, expected) - - # p.color_space - helper_deprecated("color_space", "RGB") - - # p.pcs - helper_deprecated("pcs", "XYZ") - - # p.product_copyright - helper_deprecated( - "product_copyright", "Copyright International Color Consortium, 2009" - ) - - # p.product_desc - helper_deprecated("product_desc", "sRGB IEC61966-2-1 black scaled") - - # p.product_description - helper_deprecated("product_description", "sRGB IEC61966-2-1 black scaled") - - # p.product_manufacturer - helper_deprecated("product_manufacturer", "") - - # p.product_model - helper_deprecated( - "product_model", "IEC 61966-2-1 Default RGB Colour Space - sRGB" - ) - - def test_profile_typesafety(self): - """ Profile init type safety - - prepatch, these would segfault, postpatch they should emit a typeerror - """ - - with self.assertRaises(TypeError): - ImageCms.ImageCmsProfile(0).tobytes() - with self.assertRaises(TypeError): - ImageCms.ImageCmsProfile(1).tobytes() - - def assert_aux_channel_preserved(self, mode, transform_in_place, preserved_channel): - def create_test_image(): - # set up test image with something interesting in the tested aux channel. - # fmt: off - nine_grid_deltas = [ # noqa: E131 - (-1, -1), (-1, 0), (-1, 1), - (0, -1), (0, 0), (0, 1), - (1, -1), (1, 0), (1, 1), - ] - # fmt: on - chans = [] - bands = ImageMode.getmode(mode).bands - for band_ndx in range(len(bands)): - channel_type = "L" # 8-bit unorm - channel_pattern = hopper(channel_type) - - # paste pattern with varying offsets to avoid correlation - # potentially hiding some bugs (like channels getting mixed). - paste_offset = ( - int(band_ndx / float(len(bands)) * channel_pattern.size[0]), - int(band_ndx / float(len(bands) * 2) * channel_pattern.size[1]), - ) - channel_data = Image.new(channel_type, channel_pattern.size) - for delta in nine_grid_deltas: - channel_data.paste( - channel_pattern, - tuple( - paste_offset[c] + delta[c] * channel_pattern.size[c] - for c in range(2) - ), - ) - chans.append(channel_data) - return Image.merge(mode, chans) - - source_image = create_test_image() - source_image_aux = source_image.getchannel(preserved_channel) - - # create some transform, it doesn't matter which one - source_profile = ImageCms.createProfile("sRGB") - destination_profile = ImageCms.createProfile("sRGB") - t = ImageCms.buildTransform( - source_profile, destination_profile, inMode=mode, outMode=mode - ) - - # apply transform - if transform_in_place: - ImageCms.applyTransform(source_image, t, inPlace=True) - result_image = source_image - else: - result_image = ImageCms.applyTransform(source_image, t, inPlace=False) - result_image_aux = result_image.getchannel(preserved_channel) - - self.assert_image_equal(source_image_aux, result_image_aux) - - def test_preserve_auxiliary_channels_rgba(self): - self.assert_aux_channel_preserved( - mode="RGBA", transform_in_place=False, preserved_channel="A" - ) - - def test_preserve_auxiliary_channels_rgba_in_place(self): - self.assert_aux_channel_preserved( - mode="RGBA", transform_in_place=True, preserved_channel="A" - ) - - def test_preserve_auxiliary_channels_rgbx(self): - self.assert_aux_channel_preserved( - mode="RGBX", transform_in_place=False, preserved_channel="X" - ) - - def test_preserve_auxiliary_channels_rgbx_in_place(self): - self.assert_aux_channel_preserved( - mode="RGBX", transform_in_place=True, preserved_channel="X" - ) - - def test_auxiliary_channels_isolated(self): - # test data in aux channels does not affect non-aux channels - aux_channel_formats = [ - # format, profile, color-only format, source test image - ("RGBA", "sRGB", "RGB", hopper("RGBA")), - ("RGBX", "sRGB", "RGB", hopper("RGBX")), - ("LAB", "LAB", "LAB", Image.open("Tests/images/hopper.Lab.tif")), - ] - for src_format in aux_channel_formats: - for dst_format in aux_channel_formats: - for transform_in_place in [True, False]: - # inplace only if format doesn't change - if transform_in_place and src_format[0] != dst_format[0]: - continue - - # convert with and without AUX data, test colors are equal - source_profile = ImageCms.createProfile(src_format[1]) - destination_profile = ImageCms.createProfile(dst_format[1]) - source_image = src_format[3] - test_transform = ImageCms.buildTransform( - source_profile, - destination_profile, - inMode=src_format[0], - outMode=dst_format[0], - ) - - # test conversion from aux-ful source - if transform_in_place: - test_image = source_image.copy() - ImageCms.applyTransform( - test_image, test_transform, inPlace=True - ) - else: - test_image = ImageCms.applyTransform( - source_image, test_transform, inPlace=False - ) - - # reference conversion from aux-less source - reference_transform = ImageCms.buildTransform( - source_profile, - destination_profile, - inMode=src_format[2], - outMode=dst_format[2], - ) - reference_image = ImageCms.applyTransform( - source_image.convert(src_format[2]), reference_transform - ) - - self.assert_image_equal( - test_image.convert(dst_format[2]), reference_image - ) diff --git a/Tests/test_imagecolor.py b/Tests/test_imagecolor.py deleted file mode 100644 index e4a7b7dfe00..00000000000 --- a/Tests/test_imagecolor.py +++ /dev/null @@ -1,184 +0,0 @@ -from PIL import Image, ImageColor - -from .helper import PillowTestCase - - -class TestImageColor(PillowTestCase): - def test_hash(self): - # short 3 components - self.assertEqual((255, 0, 0), ImageColor.getrgb("#f00")) - self.assertEqual((0, 255, 0), ImageColor.getrgb("#0f0")) - self.assertEqual((0, 0, 255), ImageColor.getrgb("#00f")) - - # short 4 components - self.assertEqual((255, 0, 0, 0), ImageColor.getrgb("#f000")) - self.assertEqual((0, 255, 0, 0), ImageColor.getrgb("#0f00")) - self.assertEqual((0, 0, 255, 0), ImageColor.getrgb("#00f0")) - self.assertEqual((0, 0, 0, 255), ImageColor.getrgb("#000f")) - - # long 3 components - self.assertEqual((222, 0, 0), ImageColor.getrgb("#de0000")) - self.assertEqual((0, 222, 0), ImageColor.getrgb("#00de00")) - self.assertEqual((0, 0, 222), ImageColor.getrgb("#0000de")) - - # long 4 components - self.assertEqual((222, 0, 0, 0), ImageColor.getrgb("#de000000")) - self.assertEqual((0, 222, 0, 0), ImageColor.getrgb("#00de0000")) - self.assertEqual((0, 0, 222, 0), ImageColor.getrgb("#0000de00")) - self.assertEqual((0, 0, 0, 222), ImageColor.getrgb("#000000de")) - - # case insensitivity - self.assertEqual(ImageColor.getrgb("#DEF"), ImageColor.getrgb("#def")) - self.assertEqual(ImageColor.getrgb("#CDEF"), ImageColor.getrgb("#cdef")) - self.assertEqual(ImageColor.getrgb("#DEFDEF"), ImageColor.getrgb("#defdef")) - self.assertEqual(ImageColor.getrgb("#CDEFCDEF"), ImageColor.getrgb("#cdefcdef")) - - # not a number - self.assertRaises(ValueError, ImageColor.getrgb, "#fo0") - self.assertRaises(ValueError, ImageColor.getrgb, "#fo00") - self.assertRaises(ValueError, ImageColor.getrgb, "#fo0000") - self.assertRaises(ValueError, ImageColor.getrgb, "#fo000000") - - # wrong number of components - self.assertRaises(ValueError, ImageColor.getrgb, "#f0000") - self.assertRaises(ValueError, ImageColor.getrgb, "#f000000") - self.assertRaises(ValueError, ImageColor.getrgb, "#f00000000") - self.assertRaises(ValueError, ImageColor.getrgb, "#f000000000") - self.assertRaises(ValueError, ImageColor.getrgb, "#f00000 ") - - def test_colormap(self): - self.assertEqual((0, 0, 0), ImageColor.getrgb("black")) - self.assertEqual((255, 255, 255), ImageColor.getrgb("white")) - self.assertEqual((255, 255, 255), ImageColor.getrgb("WHITE")) - - self.assertRaises(ValueError, ImageColor.getrgb, "black ") - - def test_functions(self): - # rgb numbers - self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb(255,0,0)")) - self.assertEqual((0, 255, 0), ImageColor.getrgb("rgb(0,255,0)")) - self.assertEqual((0, 0, 255), ImageColor.getrgb("rgb(0,0,255)")) - - # percents - self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb(100%,0%,0%)")) - self.assertEqual((0, 255, 0), ImageColor.getrgb("rgb(0%,100%,0%)")) - self.assertEqual((0, 0, 255), ImageColor.getrgb("rgb(0%,0%,100%)")) - - # rgba numbers - self.assertEqual((255, 0, 0, 0), ImageColor.getrgb("rgba(255,0,0,0)")) - self.assertEqual((0, 255, 0, 0), ImageColor.getrgb("rgba(0,255,0,0)")) - self.assertEqual((0, 0, 255, 0), ImageColor.getrgb("rgba(0,0,255,0)")) - self.assertEqual((0, 0, 0, 255), ImageColor.getrgb("rgba(0,0,0,255)")) - - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsl(0,100%,50%)")) - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsl(360,100%,50%)")) - self.assertEqual((0, 255, 255), ImageColor.getrgb("hsl(180,100%,50%)")) - - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsv(0,100%,100%)")) - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsv(360,100%,100%)")) - self.assertEqual((0, 255, 255), ImageColor.getrgb("hsv(180,100%,100%)")) - - # alternate format - self.assertEqual( - ImageColor.getrgb("hsb(0,100%,50%)"), ImageColor.getrgb("hsv(0,100%,50%)") - ) - - # floats - self.assertEqual((254, 3, 3), ImageColor.getrgb("hsl(0.1,99.2%,50.3%)")) - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsl(360.,100.0%,50%)")) - - self.assertEqual((253, 2, 2), ImageColor.getrgb("hsv(0.1,99.2%,99.3%)")) - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsv(360.,100.0%,100%)")) - - # case insensitivity - self.assertEqual( - ImageColor.getrgb("RGB(255,0,0)"), ImageColor.getrgb("rgb(255,0,0)") - ) - self.assertEqual( - ImageColor.getrgb("RGB(100%,0%,0%)"), ImageColor.getrgb("rgb(100%,0%,0%)") - ) - self.assertEqual( - ImageColor.getrgb("RGBA(255,0,0,0)"), ImageColor.getrgb("rgba(255,0,0,0)") - ) - self.assertEqual( - ImageColor.getrgb("HSL(0,100%,50%)"), ImageColor.getrgb("hsl(0,100%,50%)") - ) - self.assertEqual( - ImageColor.getrgb("HSV(0,100%,50%)"), ImageColor.getrgb("hsv(0,100%,50%)") - ) - self.assertEqual( - ImageColor.getrgb("HSB(0,100%,50%)"), ImageColor.getrgb("hsb(0,100%,50%)") - ) - - # space agnosticism - self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb( 255 , 0 , 0 )")) - self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb( 100% , 0% , 0% )")) - self.assertEqual( - (255, 0, 0, 0), ImageColor.getrgb("rgba( 255 , 0 , 0 , 0 )") - ) - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsl( 0 , 100% , 50% )")) - self.assertEqual((255, 0, 0), ImageColor.getrgb("hsv( 0 , 100% , 100% )")) - - # wrong number of components - self.assertRaises(ValueError, ImageColor.getrgb, "rgb(255,0)") - self.assertRaises(ValueError, ImageColor.getrgb, "rgb(255,0,0,0)") - - self.assertRaises(ValueError, ImageColor.getrgb, "rgb(100%,0%)") - self.assertRaises(ValueError, ImageColor.getrgb, "rgb(100%,0%,0)") - self.assertRaises(ValueError, ImageColor.getrgb, "rgb(100%,0%,0 %)") - self.assertRaises(ValueError, ImageColor.getrgb, "rgb(100%,0%,0%,0%)") - - self.assertRaises(ValueError, ImageColor.getrgb, "rgba(255,0,0)") - self.assertRaises(ValueError, ImageColor.getrgb, "rgba(255,0,0,0,0)") - - self.assertRaises(ValueError, ImageColor.getrgb, "hsl(0,100%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsl(0,100%,0%,0%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsl(0%,100%,50%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsl(0,100,50%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsl(0,100%,50)") - - self.assertRaises(ValueError, ImageColor.getrgb, "hsv(0,100%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsv(0,100%,0%,0%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsv(0%,100%,50%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsv(0,100,50%)") - self.assertRaises(ValueError, ImageColor.getrgb, "hsv(0,100%,50)") - - # look for rounding errors (based on code by Tim Hatch) - def test_rounding_errors(self): - - for color in ImageColor.colormap: - expected = Image.new("RGB", (1, 1), color).convert("L").getpixel((0, 0)) - actual = ImageColor.getcolor(color, "L") - self.assertEqual(expected, actual) - - self.assertEqual( - (0, 255, 115), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGB") - ) - Image.new("RGB", (1, 1), "white") - - self.assertEqual((0, 0, 0, 255), ImageColor.getcolor("black", "RGBA")) - self.assertEqual((255, 255, 255, 255), ImageColor.getcolor("white", "RGBA")) - self.assertEqual( - (0, 255, 115, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGBA") - ) - Image.new("RGBA", (1, 1), "white") - - self.assertEqual(0, ImageColor.getcolor("black", "L")) - self.assertEqual(255, ImageColor.getcolor("white", "L")) - self.assertEqual(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "L")) - Image.new("L", (1, 1), "white") - - self.assertEqual(0, ImageColor.getcolor("black", "1")) - self.assertEqual(255, ImageColor.getcolor("white", "1")) - # The following test is wrong, but is current behavior - # The correct result should be 255 due to the mode 1 - self.assertEqual(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1")) - # Correct behavior - # self.assertEqual( - # 255, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1")) - Image.new("1", (1, 1), "white") - - self.assertEqual((0, 255), ImageColor.getcolor("black", "LA")) - self.assertEqual((255, 255), ImageColor.getcolor("white", "LA")) - self.assertEqual((162, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA")) - Image.new("LA", (1, 1), "white") diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index ffe35a4fa4f..5a6d9123e74 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -1,810 +1,11 @@ -import os.path +from PIL import Image, ImageDraw -from PIL import Image, ImageColor, ImageDraw - -from .helper import PillowTestCase, hopper - -BLACK = (0, 0, 0) -WHITE = (255, 255, 255) -GRAY = (190, 190, 190) -DEFAULT_MODE = "RGB" -IMAGES_PATH = os.path.join("Tests", "images", "imagedraw") - -# Image size -W, H = 100, 100 - -# Bounding box points -X0 = int(W / 4) -X1 = int(X0 * 3) -Y0 = int(H / 4) -Y1 = int(X0 * 3) - -# Two kinds of bounding box -BBOX1 = [(X0, Y0), (X1, Y1)] -BBOX2 = [X0, Y0, X1, Y1] - -# Two kinds of coordinate sequences -POINTS1 = [(10, 10), (20, 40), (30, 30)] -POINTS2 = [10, 10, 20, 40, 30, 30] - -KITE_POINTS = [(10, 50), (70, 10), (90, 50), (70, 90), (10, 50)] +from .helper import PillowTestCase class TestImageDraw(PillowTestCase): - def test_sanity(self): - im = hopper("RGB").copy() - - draw = ImageDraw.ImageDraw(im) - draw = ImageDraw.Draw(im) - - draw.ellipse(list(range(4))) - draw.line(list(range(10))) - draw.polygon(list(range(100))) - draw.rectangle(list(range(4))) - - def test_valueerror(self): - im = Image.open("Tests/images/chi.gif") - - draw = ImageDraw.Draw(im) - draw.line((0, 0), fill=(0, 0, 0)) - - def test_mode_mismatch(self): - im = hopper("RGB").copy() - - self.assertRaises(ValueError, ImageDraw.ImageDraw, im, mode="L") - - def helper_arc(self, bbox, start, end): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.arc(bbox, start, end) - - # Assert - self.assert_image_similar(im, Image.open("Tests/images/imagedraw_arc.png"), 1) - - def test_arc1(self): - self.helper_arc(BBOX1, 0, 180) - self.helper_arc(BBOX1, 0.5, 180.4) - - def test_arc2(self): - self.helper_arc(BBOX2, 0, 180) - self.helper_arc(BBOX2, 0.5, 180.4) - - def test_arc_end_le_start(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - start = 270.5 - end = 0 - - # Act - draw.arc(BBOX1, start=start, end=end) - - # Assert - self.assert_image_equal( - im, Image.open("Tests/images/imagedraw_arc_end_le_start.png") - ) - - def test_arc_no_loops(self): - # No need to go in loops - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - start = 5 - end = 370 - - # Act - draw.arc(BBOX1, start=start, end=end) - - # Assert - self.assert_image_similar( - im, Image.open("Tests/images/imagedraw_arc_no_loops.png"), 1 - ) - - def test_arc_width(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_arc_width.png" - - # Act - draw.arc(BBOX1, 10, 260, width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_arc_width_pieslice_large(self): - # Tests an arc with a large enough width that it is a pieslice - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_arc_width_pieslice.png" - - # Act - draw.arc(BBOX1, 10, 260, fill="yellow", width=100) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_arc_width_fill(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_arc_width_fill.png" - - # Act - draw.arc(BBOX1, 10, 260, fill="yellow", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_bitmap(self): - # Arrange - small = Image.open("Tests/images/pil123rgba.png").resize((50, 50)) - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.bitmap((10, 10), small) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_bitmap.png")) - - def helper_chord(self, mode, bbox, start, end): - # Arrange - im = Image.new(mode, (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_chord_{}.png".format(mode) - - # Act - draw.chord(bbox, start, end, fill="red", outline="yellow") - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_chord1(self): - for mode in ["RGB", "L"]: - self.helper_chord(mode, BBOX1, 0, 180) - self.helper_chord(mode, BBOX1, 0.5, 180.4) - - def test_chord2(self): - for mode in ["RGB", "L"]: - self.helper_chord(mode, BBOX2, 0, 180) - self.helper_chord(mode, BBOX2, 0.5, 180.4) - - def test_chord_width(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_chord_width.png" - - # Act - draw.chord(BBOX1, 10, 260, outline="yellow", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_chord_width_fill(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_chord_width_fill.png" - - # Act - draw.chord(BBOX1, 10, 260, fill="red", outline="yellow", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def helper_ellipse(self, mode, bbox): - # Arrange - im = Image.new(mode, (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) - - # Act - draw.ellipse(bbox, fill="green", outline="blue") - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_ellipse1(self): - for mode in ["RGB", "L"]: - self.helper_ellipse(mode, BBOX1) - - def test_ellipse2(self): - for mode in ["RGB", "L"]: - self.helper_ellipse(mode, BBOX2) - - def test_ellipse_edge(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.ellipse(((0, 0), (W - 1, H)), fill="white") - - # Assert - self.assert_image_similar( - im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1 - ) - - def test_ellipse_symmetric(self): - for bbox in [(25, 25, 76, 76), (25, 25, 75, 75)]: - im = Image.new("RGB", (101, 101)) - draw = ImageDraw.Draw(im) - draw.ellipse(bbox, fill="green", outline="blue") - self.assert_image_equal(im, im.transpose(Image.FLIP_LEFT_RIGHT)) - - def test_ellipse_width(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_ellipse_width.png" - - # Act - draw.ellipse(BBOX1, outline="blue", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_ellipse_width_large(self): - # Arrange - im = Image.new("RGB", (500, 500)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_ellipse_width_large.png" - - # Act - draw.ellipse((25, 25, 475, 475), outline="blue", width=75) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_ellipse_width_fill(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_ellipse_width_fill.png" - - # Act - draw.ellipse(BBOX1, fill="green", outline="blue", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def helper_line(self, points): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.line(points, fill="yellow", width=2) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) - - def test_line1(self): - self.helper_line(POINTS1) - - def test_line2(self): - self.helper_line(POINTS2) - - def test_shape1(self): - # Arrange - im = Image.new("RGB", (100, 100), "white") - draw = ImageDraw.Draw(im) - x0, y0 = 5, 5 - x1, y1 = 5, 50 - x2, y2 = 95, 50 - x3, y3 = 95, 5 - - # Act - s = ImageDraw.Outline() - s.move(x0, y0) - s.curve(x1, y1, x2, y2, x3, y3) - s.line(x0, y0) - - draw.shape(s, fill=1) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_shape1.png")) - - def test_shape2(self): - # Arrange - im = Image.new("RGB", (100, 100), "white") + def test_4005(self): + im = Image.new('RGB', (640, 640)) draw = ImageDraw.Draw(im) - x0, y0 = 95, 95 - x1, y1 = 95, 50 - x2, y2 = 5, 50 - x3, y3 = 5, 95 - - # Act - s = ImageDraw.Outline() - s.move(x0, y0) - s.curve(x1, y1, x2, y2, x3, y3) - s.line(x0, y0) - - draw.shape(s, outline="blue") - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_shape2.png")) - - def helper_pieslice(self, bbox, start, end): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.pieslice(bbox, start, end, fill="white", outline="blue") - - # Assert - self.assert_image_similar( - im, Image.open("Tests/images/imagedraw_pieslice.png"), 1 - ) - - def test_pieslice1(self): - self.helper_pieslice(BBOX1, -90, 45) - self.helper_pieslice(BBOX1, -90.5, 45.4) - - def test_pieslice2(self): - self.helper_pieslice(BBOX2, -90, 45) - self.helper_pieslice(BBOX2, -90.5, 45.4) - - def test_pieslice_width(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_pieslice_width.png" - - # Act - draw.pieslice(BBOX1, 10, 260, outline="blue", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_pieslice_width_fill(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_pieslice_width_fill.png" - - # Act - draw.pieslice(BBOX1, 10, 260, fill="white", outline="blue", width=5) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def helper_point(self, points): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.point(points, fill="yellow") - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_point.png")) - - def test_point1(self): - self.helper_point(POINTS1) - - def test_point2(self): - self.helper_point(POINTS2) - - def helper_polygon(self, points): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.polygon(points, fill="red", outline="blue") - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png")) - - def test_polygon1(self): - self.helper_polygon(POINTS1) - - def test_polygon2(self): - self.helper_polygon(POINTS2) - - def test_polygon_kite(self): - # Test drawing lines of different gradients (dx>dy, dy>dx) and - # vertical (dx==0) and horizontal (dy==0) lines - for mode in ["RGB", "L"]: - # Arrange - im = Image.new(mode, (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_polygon_kite_{}.png".format(mode) - - # Act - draw.polygon(KITE_POINTS, fill="blue", outline="yellow") - - # Assert - self.assert_image_equal(im, Image.open(expected)) - - def helper_rectangle(self, bbox): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.rectangle(bbox, fill="black", outline="green") - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png")) - - def test_rectangle1(self): - self.helper_rectangle(BBOX1) - - def test_rectangle2(self): - self.helper_rectangle(BBOX2) - - def test_big_rectangle(self): - # Test drawing a rectangle bigger than the image - # Arrange - im = Image.new("RGB", (W, H)) - bbox = [(-1, -1), (W + 1, H + 1)] - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_big_rectangle.png" - - # Act - draw.rectangle(bbox, fill="orange") - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_rectangle_width(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_rectangle_width.png" - - # Act - draw.rectangle(BBOX1, outline="green", width=5) - - # Assert - self.assert_image_equal(im, Image.open(expected)) - - def test_rectangle_width_fill(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_rectangle_width_fill.png" - - # Act - draw.rectangle(BBOX1, fill="blue", outline="green", width=5) - - # Assert - self.assert_image_equal(im, Image.open(expected)) - - def test_rectangle_I16(self): - # Arrange - im = Image.new("I;16", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw.rectangle(BBOX1, fill="black", outline="green") - - # Assert - self.assert_image_equal( - im.convert("I"), Image.open("Tests/images/imagedraw_rectangle_I.png") - ) - - def test_floodfill(self): - red = ImageColor.getrgb("red") - - for mode, value in [("L", 1), ("RGBA", (255, 0, 0, 0)), ("RGB", red)]: - # Arrange - im = Image.new(mode, (W, H)) - draw = ImageDraw.Draw(im) - draw.rectangle(BBOX2, outline="yellow", fill="green") - centre_point = (int(W / 2), int(H / 2)) - - # Act - ImageDraw.floodfill(im, centre_point, value) - - # Assert - expected = "Tests/images/imagedraw_floodfill_" + mode + ".png" - im_floodfill = Image.open(expected) - self.assert_image_equal(im, im_floodfill) - - # Test that using the same colour does not change the image - ImageDraw.floodfill(im, centre_point, red) - self.assert_image_equal(im, im_floodfill) - - # Test that filling outside the image does not change the image - ImageDraw.floodfill(im, (W, H), red) - self.assert_image_equal(im, im_floodfill) - - # Test filling at the edge of an image - im = Image.new("RGB", (1, 1)) - ImageDraw.floodfill(im, (0, 0), red) - self.assert_image_equal(im, Image.new("RGB", (1, 1), red)) - - def test_floodfill_border(self): - # floodfill() is experimental - - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - draw.rectangle(BBOX2, outline="yellow", fill="green") - centre_point = (int(W / 2), int(H / 2)) - - # Act - ImageDraw.floodfill( - im, - centre_point, - ImageColor.getrgb("red"), - border=ImageColor.getrgb("black"), - ) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png")) - - def test_floodfill_thresh(self): - # floodfill() is experimental - - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - draw.rectangle(BBOX2, outline="darkgreen", fill="green") - centre_point = (int(W / 2), int(H / 2)) - - # Act - ImageDraw.floodfill(im, centre_point, ImageColor.getrgb("red"), thresh=30) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png")) - - def create_base_image_draw( - self, size, mode=DEFAULT_MODE, background1=WHITE, background2=GRAY - ): - img = Image.new(mode, size, background1) - for x in range(0, size[0]): - for y in range(0, size[1]): - if (x + y) % 2 == 0: - img.putpixel((x, y), background2) - return img, ImageDraw.Draw(img) - - def test_square(self): - expected = Image.open(os.path.join(IMAGES_PATH, "square.png")) - expected.load() - img, draw = self.create_base_image_draw((10, 10)) - draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK) - self.assert_image_equal(img, expected, "square as normal polygon failed") - img, draw = self.create_base_image_draw((10, 10)) - draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK) - self.assert_image_equal(img, expected, "square as inverted polygon failed") - img, draw = self.create_base_image_draw((10, 10)) - draw.rectangle((2, 2, 7, 7), BLACK) - self.assert_image_equal(img, expected, "square as normal rectangle failed") - img, draw = self.create_base_image_draw((10, 10)) - draw.rectangle((7, 7, 2, 2), BLACK) - self.assert_image_equal(img, expected, "square as inverted rectangle failed") - - def test_triangle_right(self): - expected = Image.open(os.path.join(IMAGES_PATH, "triangle_right.png")) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK) - self.assert_image_equal(img, expected, "triangle right failed") - - def test_line_horizontal(self): - expected = Image.open( - os.path.join(IMAGES_PATH, "line_horizontal_w2px_normal.png") - ) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 14, 5), BLACK, 2) - self.assert_image_equal( - img, expected, "line straight horizontal normal 2px wide failed" - ) - expected = Image.open( - os.path.join(IMAGES_PATH, "line_horizontal_w2px_inverted.png") - ) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((14, 5, 5, 5), BLACK, 2) - self.assert_image_equal( - img, expected, "line straight horizontal inverted 2px wide failed" - ) - expected = Image.open(os.path.join(IMAGES_PATH, "line_horizontal_w3px.png")) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 14, 5), BLACK, 3) - self.assert_image_equal( - img, expected, "line straight horizontal normal 3px wide failed" - ) - img, draw = self.create_base_image_draw((20, 20)) - draw.line((14, 5, 5, 5), BLACK, 3) - self.assert_image_equal( - img, expected, "line straight horizontal inverted 3px wide failed" - ) - expected = Image.open(os.path.join(IMAGES_PATH, "line_horizontal_w101px.png")) - expected.load() - img, draw = self.create_base_image_draw((200, 110)) - draw.line((5, 55, 195, 55), BLACK, 101) - self.assert_image_equal( - img, expected, "line straight horizontal 101px wide failed" - ) - - def test_line_h_s1_w2(self): - self.skipTest("failing") - expected = Image.open( - os.path.join(IMAGES_PATH, "line_horizontal_slope1px_w2px.png") - ) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 14, 6), BLACK, 2) - self.assert_image_equal( - img, expected, "line horizontal 1px slope 2px wide failed" - ) - - def test_line_vertical(self): - expected = Image.open( - os.path.join(IMAGES_PATH, "line_vertical_w2px_normal.png") - ) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 5, 14), BLACK, 2) - self.assert_image_equal( - img, expected, "line straight vertical normal 2px wide failed" - ) - expected = Image.open( - os.path.join(IMAGES_PATH, "line_vertical_w2px_inverted.png") - ) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 14, 5, 5), BLACK, 2) - self.assert_image_equal( - img, expected, "line straight vertical inverted 2px wide failed" - ) - expected = Image.open(os.path.join(IMAGES_PATH, "line_vertical_w3px.png")) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 5, 14), BLACK, 3) - self.assert_image_equal( - img, expected, "line straight vertical normal 3px wide failed" - ) - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 14, 5, 5), BLACK, 3) - self.assert_image_equal( - img, expected, "line straight vertical inverted 3px wide failed" - ) - expected = Image.open(os.path.join(IMAGES_PATH, "line_vertical_w101px.png")) - expected.load() - img, draw = self.create_base_image_draw((110, 200)) - draw.line((55, 5, 55, 195), BLACK, 101) - self.assert_image_equal( - img, expected, "line straight vertical 101px wide failed" - ) - expected = Image.open( - os.path.join(IMAGES_PATH, "line_vertical_slope1px_w2px.png") - ) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 6, 14), BLACK, 2) - self.assert_image_equal( - img, expected, "line vertical 1px slope 2px wide failed" - ) - - def test_line_oblique_45(self): - expected = Image.open(os.path.join(IMAGES_PATH, "line_oblique_45_w3px_a.png")) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 5, 14, 14), BLACK, 3) - self.assert_image_equal( - img, expected, "line oblique 45 normal 3px wide A failed" - ) - img, draw = self.create_base_image_draw((20, 20)) - draw.line((14, 14, 5, 5), BLACK, 3) - self.assert_image_equal( - img, expected, "line oblique 45 inverted 3px wide A failed" - ) - expected = Image.open(os.path.join(IMAGES_PATH, "line_oblique_45_w3px_b.png")) - expected.load() - img, draw = self.create_base_image_draw((20, 20)) - draw.line((14, 5, 5, 14), BLACK, 3) - self.assert_image_equal( - img, expected, "line oblique 45 normal 3px wide B failed" - ) - img, draw = self.create_base_image_draw((20, 20)) - draw.line((5, 14, 14, 5), BLACK, 3) - self.assert_image_equal( - img, expected, "line oblique 45 inverted 3px wide B failed" - ) - - def test_wide_line_dot(self): - # Test drawing a wide "line" from one point to another just draws - # a single point - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_wide_line_dot.png" - - # Act - draw.line([(50, 50), (50, 50)], width=3) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_line_joint(self): - im = Image.new("RGB", (500, 325)) - draw = ImageDraw.Draw(im) - expected = "Tests/images/imagedraw_line_joint_curve.png" - - # Act - xy = [ - (400, 280), - (380, 280), - (450, 280), - (440, 120), - (350, 200), - (310, 280), - (300, 280), - (250, 280), - (250, 200), - (150, 200), - (150, 260), - (50, 200), - (150, 50), - (250, 100), - ] - draw.line(xy, GRAY, 50, "curve") - - # Assert - self.assert_image_similar(im, Image.open(expected), 3) - - def test_textsize_empty_string(self): - # https://github.com/python-pillow/Pillow/issues/2783 - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw.Draw(im) - - # Act - # Should not cause 'SystemError: returned NULL without setting an error' - draw.textsize("") - draw.textsize("\n") - draw.textsize("test\n") - - def test_same_color_outline(self): - # Prepare shape - x0, y0 = 5, 5 - x1, y1 = 5, 50 - x2, y2 = 95, 50 - x3, y3 = 95, 5 - - s = ImageDraw.Outline() - s.move(x0, y0) - s.curve(x1, y1, x2, y2, x3, y3) - s.line(x0, y0) - - # Begin - for mode in ["RGB", "L"]: - for fill, outline in [["red", None], ["red", "red"], ["red", "#f00"]]: - for operation, args in { - "chord": [BBOX1, 0, 180], - "ellipse": [BBOX1], - "shape": [s], - "pieslice": [BBOX1, -90, 45], - "polygon": [[(18, 30), (85, 30), (60, 72)]], - "rectangle": [BBOX1], - }.items(): - # Arrange - im = Image.new(mode, (W, H)) - draw = ImageDraw.Draw(im) - - # Act - draw_method = getattr(draw, operation) - args += [fill, outline] - draw_method(*args) - - # Assert - expected = "Tests/images/imagedraw_outline_{}_{}.png".format( - operation, mode - ) - self.assert_image_similar(im, Image.open(expected), 1) + draw.arc([0+0/2, 0+0/2, 640.0, 640.0], 72.0, 128.5, fill='#1890ff', width=8) + print('Drew an arc...') diff --git a/Tests/test_imagedraw2.py b/Tests/test_imagedraw2.py deleted file mode 100644 index 9ce472dd07a..00000000000 --- a/Tests/test_imagedraw2.py +++ /dev/null @@ -1,222 +0,0 @@ -import os.path - -from PIL import Image, ImageDraw2, features - -from .helper import PillowTestCase, hopper, unittest - -BLACK = (0, 0, 0) -WHITE = (255, 255, 255) -GRAY = (190, 190, 190) -DEFAULT_MODE = "RGB" -IMAGES_PATH = os.path.join("Tests", "images", "imagedraw") - -# Image size -W, H = 100, 100 - -# Bounding box points -X0 = int(W / 4) -X1 = int(X0 * 3) -Y0 = int(H / 4) -Y1 = int(X0 * 3) - -# Two kinds of bounding box -BBOX1 = [(X0, Y0), (X1, Y1)] -BBOX2 = [X0, Y0, X1, Y1] - -# Two kinds of coordinate sequences -POINTS1 = [(10, 10), (20, 40), (30, 30)] -POINTS2 = [10, 10, 20, 40, 30, 30] - -KITE_POINTS = [(10, 50), (70, 10), (90, 50), (70, 90), (10, 50)] - -HAS_FREETYPE = features.check("freetype2") -FONT_PATH = "Tests/fonts/FreeMono.ttf" - - -class TestImageDraw(PillowTestCase): - def test_sanity(self): - im = hopper("RGB").copy() - - draw = ImageDraw2.Draw(im) - pen = ImageDraw2.Pen("blue", width=7) - draw.line(list(range(10)), pen) - - from PIL import ImageDraw - - draw, handler = ImageDraw.getdraw(im) - pen = ImageDraw2.Pen("blue", width=7) - draw.line(list(range(10)), pen) - - def helper_ellipse(self, mode, bbox): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - pen = ImageDraw2.Pen("blue", width=2) - brush = ImageDraw2.Brush("green") - expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode) - - # Act - draw.ellipse(bbox, pen, brush) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - def test_ellipse1(self): - self.helper_ellipse("RGB", BBOX1) - - def test_ellipse2(self): - self.helper_ellipse("RGB", BBOX2) - - def test_ellipse_edge(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - brush = ImageDraw2.Brush("white") - - # Act - draw.ellipse(((0, 0), (W - 1, H)), brush) - - # Assert - self.assert_image_similar( - im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1 - ) - - def helper_line(self, points): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - pen = ImageDraw2.Pen("yellow", width=2) - - # Act - draw.line(points, pen) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) - - def test_line1_pen(self): - self.helper_line(POINTS1) - - def test_line2_pen(self): - self.helper_line(POINTS2) - - def test_line_pen_as_brush(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - pen = None - brush = ImageDraw2.Pen("yellow", width=2) - - # Act - # Pass in the pen as the brush parameter - draw.line(POINTS1, pen, brush) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) - - def helper_polygon(self, points): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - pen = ImageDraw2.Pen("blue", width=2) - brush = ImageDraw2.Brush("red") - - # Act - draw.polygon(points, pen, brush) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png")) - - def test_polygon1(self): - self.helper_polygon(POINTS1) - - def test_polygon2(self): - self.helper_polygon(POINTS2) - - def helper_rectangle(self, bbox): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - pen = ImageDraw2.Pen("green", width=2) - brush = ImageDraw2.Brush("black") - - # Act - draw.rectangle(bbox, pen, brush) - - # Assert - self.assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png")) - - def test_rectangle1(self): - self.helper_rectangle(BBOX1) - - def test_rectangle2(self): - self.helper_rectangle(BBOX2) - - def test_big_rectangle(self): - # Test drawing a rectangle bigger than the image - # Arrange - im = Image.new("RGB", (W, H)) - bbox = [(-1, -1), (W + 1, H + 1)] - brush = ImageDraw2.Brush("orange") - draw = ImageDraw2.Draw(im) - expected = "Tests/images/imagedraw_big_rectangle.png" - - # Act - draw.rectangle(bbox, brush) - - # Assert - self.assert_image_similar(im, Image.open(expected), 1) - - @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") - def test_text(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - font = ImageDraw2.Font("white", FONT_PATH) - expected = "Tests/images/imagedraw2_text.png" - - # Act - draw.text((5, 5), "ImageDraw2", font) - - # Assert - self.assert_image_similar(im, Image.open(expected), 13) - - @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") - def test_textsize(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - font = ImageDraw2.Font("white", FONT_PATH) - - # Act - size = draw.textsize("ImageDraw2", font) - - # Assert - self.assertEqual(size[1], 12) - - @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") - def test_textsize_empty_string(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - font = ImageDraw2.Font("white", FONT_PATH) - - # Act - # Should not cause 'SystemError: returned NULL without setting an error' - draw.textsize("", font) - draw.textsize("\n", font) - draw.textsize("test\n", font) - - @unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") - def test_flush(self): - # Arrange - im = Image.new("RGB", (W, H)) - draw = ImageDraw2.Draw(im) - font = ImageDraw2.Font("white", FONT_PATH) - - # Act - draw.text((5, 5), "ImageDraw2", font) - im2 = draw.flush() - - # Assert - self.assert_image_equal(im, im2) diff --git a/Tests/test_imageenhance.py b/Tests/test_imageenhance.py deleted file mode 100644 index b2235853a63..00000000000 --- a/Tests/test_imageenhance.py +++ /dev/null @@ -1,54 +0,0 @@ -from PIL import Image, ImageEnhance - -from .helper import PillowTestCase, hopper - - -class TestImageEnhance(PillowTestCase): - def test_sanity(self): - - # FIXME: assert_image - # Implicit asserts no exception: - ImageEnhance.Color(hopper()).enhance(0.5) - ImageEnhance.Contrast(hopper()).enhance(0.5) - ImageEnhance.Brightness(hopper()).enhance(0.5) - ImageEnhance.Sharpness(hopper()).enhance(0.5) - - def test_crash(self): - - # crashes on small images - im = Image.new("RGB", (1, 1)) - ImageEnhance.Sharpness(im).enhance(0.5) - - def _half_transparent_image(self): - # returns an image, half transparent, half solid - im = hopper("RGB") - - transparent = Image.new("L", im.size, 0) - solid = Image.new("L", (im.size[0] // 2, im.size[1]), 255) - transparent.paste(solid, (0, 0)) - im.putalpha(transparent) - - return im - - def _check_alpha(self, im, original, op, amount): - self.assertEqual(im.getbands(), original.getbands()) - self.assert_image_equal( - im.getchannel("A"), - original.getchannel("A"), - "Diff on %s: %s" % (op, amount), - ) - - def test_alpha(self): - # Issue https://github.com/python-pillow/Pillow/issues/899 - # Is alpha preserved through image enhancement? - - original = self._half_transparent_image() - - for op in ["Color", "Brightness", "Contrast", "Sharpness"]: - for amount in [0, 0.5, 1.0]: - self._check_alpha( - getattr(ImageEnhance, op)(original).enhance(amount), - original, - op, - amount, - ) diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py deleted file mode 100644 index 2ca5abe4ca5..00000000000 --- a/Tests/test_imagefile.py +++ /dev/null @@ -1,323 +0,0 @@ -from io import BytesIO - -from PIL import EpsImagePlugin, Image, ImageFile - -from .helper import PillowTestCase, fromstring, hopper, tostring, unittest - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -codecs = dir(Image.core) - -# save original block sizes -MAXBLOCK = ImageFile.MAXBLOCK -SAFEBLOCK = ImageFile.SAFEBLOCK - - -class TestImageFile(PillowTestCase): - def test_parser(self): - def roundtrip(format): - - im = hopper("L").resize((1000, 1000)) - if format in ("MSP", "XBM"): - im = im.convert("1") - - test_file = BytesIO() - - im.copy().save(test_file, format) - - data = test_file.getvalue() - - parser = ImageFile.Parser() - parser.feed(data) - imOut = parser.close() - - return im, imOut - - self.assert_image_equal(*roundtrip("BMP")) - im1, im2 = roundtrip("GIF") - self.assert_image_similar(im1.convert("P"), im2, 1) - self.assert_image_equal(*roundtrip("IM")) - self.assert_image_equal(*roundtrip("MSP")) - if "zip_encoder" in codecs: - try: - # force multiple blocks in PNG driver - ImageFile.MAXBLOCK = 8192 - self.assert_image_equal(*roundtrip("PNG")) - finally: - ImageFile.MAXBLOCK = MAXBLOCK - self.assert_image_equal(*roundtrip("PPM")) - self.assert_image_equal(*roundtrip("TIFF")) - self.assert_image_equal(*roundtrip("XBM")) - self.assert_image_equal(*roundtrip("TGA")) - self.assert_image_equal(*roundtrip("PCX")) - - if EpsImagePlugin.has_ghostscript(): - im1, im2 = roundtrip("EPS") - # This test fails on Ubuntu 12.04, PPC (Bigendian) It - # appears to be a ghostscript 9.05 bug, since the - # ghostscript rendering is wonky and the file is identical - # to that written on ubuntu 12.04 x64 - # md5sum: ba974835ff2d6f3f2fd0053a23521d4a - - # EPS comes back in RGB: - self.assert_image_similar(im1, im2.convert("L"), 20) - - if "jpeg_encoder" in codecs: - im1, im2 = roundtrip("JPEG") # lossy compression - self.assert_image(im1, im2.mode, im2.size) - - self.assertRaises(IOError, roundtrip, "PDF") - - def test_ico(self): - with open("Tests/images/python.ico", "rb") as f: - data = f.read() - with ImageFile.Parser() as p: - p.feed(data) - self.assertEqual((48, 48), p.image.size) - - def test_safeblock(self): - if "zip_encoder" not in codecs: - self.skipTest("PNG (zlib) encoder not available") - - im1 = hopper() - - try: - ImageFile.SAFEBLOCK = 1 - im2 = fromstring(tostring(im1, "PNG")) - finally: - ImageFile.SAFEBLOCK = SAFEBLOCK - - self.assert_image_equal(im1, im2) - - def test_raise_ioerror(self): - self.assertRaises(IOError, ImageFile.raise_ioerror, 1) - - def test_raise_typeerror(self): - with self.assertRaises(TypeError): - parser = ImageFile.Parser() - parser.feed(1) - - def test_truncated_with_errors(self): - if "zip_encoder" not in codecs: - self.skipTest("PNG (zlib) encoder not available") - - im = Image.open("Tests/images/truncated_image.png") - with self.assertRaises(IOError): - im.load() - - def test_truncated_without_errors(self): - if "zip_encoder" not in codecs: - self.skipTest("PNG (zlib) encoder not available") - - im = Image.open("Tests/images/truncated_image.png") - - ImageFile.LOAD_TRUNCATED_IMAGES = True - try: - im.load() - finally: - ImageFile.LOAD_TRUNCATED_IMAGES = False - - def test_broken_datastream_with_errors(self): - if "zip_encoder" not in codecs: - self.skipTest("PNG (zlib) encoder not available") - - im = Image.open("Tests/images/broken_data_stream.png") - with self.assertRaises(IOError): - im.load() - - def test_broken_datastream_without_errors(self): - if "zip_encoder" not in codecs: - self.skipTest("PNG (zlib) encoder not available") - - im = Image.open("Tests/images/broken_data_stream.png") - - ImageFile.LOAD_TRUNCATED_IMAGES = True - try: - im.load() - finally: - ImageFile.LOAD_TRUNCATED_IMAGES = False - - -class MockPyDecoder(ImageFile.PyDecoder): - def decode(self, buffer): - # eof - return -1, 0 - - -xoff, yoff, xsize, ysize = 10, 20, 100, 100 - - -class MockImageFile(ImageFile.ImageFile): - def _open(self): - self.rawmode = "RGBA" - self.mode = "RGBA" - self._size = (200, 200) - self.tile = [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize), 32, None)] - - -class TestPyDecoder(PillowTestCase): - def get_decoder(self): - decoder = MockPyDecoder(None) - - def closure(mode, *args): - decoder.__init__(mode, *args) - return decoder - - Image.register_decoder("MOCK", closure) - return decoder - - def test_setimage(self): - buf = BytesIO(b"\x00" * 255) - - im = MockImageFile(buf) - d = self.get_decoder() - - im.load() - - self.assertEqual(d.state.xoff, xoff) - self.assertEqual(d.state.yoff, yoff) - self.assertEqual(d.state.xsize, xsize) - self.assertEqual(d.state.ysize, ysize) - - self.assertRaises(ValueError, d.set_as_raw, b"\x00") - - def test_extents_none(self): - buf = BytesIO(b"\x00" * 255) - - im = MockImageFile(buf) - im.tile = [("MOCK", None, 32, None)] - d = self.get_decoder() - - im.load() - - self.assertEqual(d.state.xoff, 0) - self.assertEqual(d.state.yoff, 0) - self.assertEqual(d.state.xsize, 200) - self.assertEqual(d.state.ysize, 200) - - def test_negsize(self): - buf = BytesIO(b"\x00" * 255) - - im = MockImageFile(buf) - im.tile = [("MOCK", (xoff, yoff, -10, yoff + ysize), 32, None)] - self.get_decoder() - - self.assertRaises(ValueError, im.load) - - im.tile = [("MOCK", (xoff, yoff, xoff + xsize, -10), 32, None)] - self.assertRaises(ValueError, im.load) - - def test_oversize(self): - buf = BytesIO(b"\x00" * 255) - - im = MockImageFile(buf) - im.tile = [("MOCK", (xoff, yoff, xoff + xsize + 100, yoff + ysize), 32, None)] - self.get_decoder() - - self.assertRaises(ValueError, im.load) - - im.tile = [("MOCK", (xoff, yoff, xoff + xsize, yoff + ysize + 100), 32, None)] - self.assertRaises(ValueError, im.load) - - def test_no_format(self): - buf = BytesIO(b"\x00" * 255) - - im = MockImageFile(buf) - self.assertIsNone(im.format) - self.assertIsNone(im.get_format_mimetype()) - - def test_exif_jpeg(self): - im = Image.open("Tests/images/exif-72dpi-int.jpg") # Little endian - exif = im.getexif() - self.assertNotIn(258, exif) - self.assertIn(40960, exif) - self.assertEqual(exif[40963], 450) - self.assertEqual(exif[11], "gThumb 3.0.1") - - out = self.tempfile("temp.jpg") - exif[258] = 8 - del exif[40960] - exif[40963] = 455 - exif[11] = "Pillow test" - im.save(out, exif=exif) - reloaded = Image.open(out) - reloaded_exif = reloaded.getexif() - self.assertEqual(reloaded_exif[258], 8) - self.assertNotIn(40960, exif) - self.assertEqual(reloaded_exif[40963], 455) - self.assertEqual(exif[11], "Pillow test") - - im = Image.open("Tests/images/no-dpi-in-exif.jpg") # Big endian - exif = im.getexif() - self.assertNotIn(258, exif) - self.assertIn(40962, exif) - self.assertEqual(exif[40963], 200) - self.assertEqual(exif[305], "Adobe Photoshop CC 2017 (Macintosh)") - - out = self.tempfile("temp.jpg") - exif[258] = 8 - del exif[34665] - exif[40963] = 455 - exif[305] = "Pillow test" - im.save(out, exif=exif) - reloaded = Image.open(out) - reloaded_exif = reloaded.getexif() - self.assertEqual(reloaded_exif[258], 8) - self.assertNotIn(40960, exif) - self.assertEqual(reloaded_exif[40963], 455) - self.assertEqual(exif[305], "Pillow test") - - @unittest.skipIf( - not HAVE_WEBP or not _webp.HAVE_WEBPANIM, - "WebP support not installed with animation", - ) - def test_exif_webp(self): - im = Image.open("Tests/images/hopper.webp") - exif = im.getexif() - self.assertEqual(exif, {}) - - out = self.tempfile("temp.webp") - exif[258] = 8 - exif[40963] = 455 - exif[305] = "Pillow test" - - def check_exif(): - reloaded = Image.open(out) - reloaded_exif = reloaded.getexif() - self.assertEqual(reloaded_exif[258], 8) - self.assertEqual(reloaded_exif[40963], 455) - self.assertEqual(exif[305], "Pillow test") - - im.save(out, exif=exif) - check_exif() - im.save(out, exif=exif, save_all=True) - check_exif() - - def test_exif_png(self): - im = Image.open("Tests/images/exif.png") - exif = im.getexif() - self.assertEqual(exif, {274: 1}) - - out = self.tempfile("temp.png") - exif[258] = 8 - del exif[274] - exif[40963] = 455 - exif[305] = "Pillow test" - im.save(out, exif=exif) - - reloaded = Image.open(out) - reloaded_exif = reloaded.getexif() - self.assertEqual(reloaded_exif, {258: 8, 40963: 455, 305: "Pillow test"}) - - def test_exif_interop(self): - im = Image.open("Tests/images/flower.jpg") - exif = im.getexif() - self.assertEqual( - exif.get_ifd(0xA005), {1: "R98", 2: b"0100", 4097: 2272, 4098: 1704} - ) diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py deleted file mode 100644 index 8a23e6339a3..00000000000 --- a/Tests/test_imagefont.py +++ /dev/null @@ -1,738 +0,0 @@ -# -*- coding: utf-8 -*- -import copy -import distutils.version -import os -import re -import shutil -import sys -from io import BytesIO - -from PIL import Image, ImageDraw, ImageFont, features - -from .helper import PillowTestCase, unittest - -FONT_PATH = "Tests/fonts/FreeMono.ttf" -FONT_SIZE = 20 - -TEST_TEXT = "hey you\nyou are awesome\nthis looks awkward" - -HAS_FREETYPE = features.check("freetype2") -HAS_RAQM = features.check("raqm") - - -class SimplePatcher(object): - def __init__(self, parent_obj, attr_name, value): - self._parent_obj = parent_obj - self._attr_name = attr_name - self._saved = None - self._is_saved = False - self._value = value - - def __enter__(self): - # Patch the attr on the object - if hasattr(self._parent_obj, self._attr_name): - self._saved = getattr(self._parent_obj, self._attr_name) - setattr(self._parent_obj, self._attr_name, self._value) - self._is_saved = True - else: - setattr(self._parent_obj, self._attr_name, self._value) - self._is_saved = False - - def __exit__(self, type, value, traceback): - # Restore the original value - if self._is_saved: - setattr(self._parent_obj, self._attr_name, self._saved) - else: - delattr(self._parent_obj, self._attr_name) - - -@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available") -class TestImageFont(PillowTestCase): - LAYOUT_ENGINE = ImageFont.LAYOUT_BASIC - - # Freetype has different metrics depending on the version. - # (and, other things, but first things first) - METRICS = { - (">=2.3", "<2.4"): {"multiline": 30, "textsize": 12, "getters": (13, 16)}, - (">=2.7",): {"multiline": 6.2, "textsize": 2.5, "getters": (12, 16)}, - "Default": {"multiline": 0.5, "textsize": 0.5, "getters": (12, 16)}, - } - - def setUp(self): - freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) - - self.metrics = self.METRICS["Default"] - for conditions, metrics in self.METRICS.items(): - if not isinstance(conditions, tuple): - continue - - for condition in conditions: - version = re.sub("[<=>]", "", condition) - if (condition.startswith(">=") and freetype >= version) or ( - condition.startswith("<") and freetype < version - ): - # Condition was met - continue - - # Condition failed - break - else: - # All conditions were met - self.metrics = metrics - - def get_font(self): - return ImageFont.truetype( - FONT_PATH, FONT_SIZE, layout_engine=self.LAYOUT_ENGINE - ) - - def test_sanity(self): - self.assertRegex(ImageFont.core.freetype2_version, r"\d+\.\d+\.\d+$") - - def test_font_properties(self): - ttf = self.get_font() - self.assertEqual(ttf.path, FONT_PATH) - self.assertEqual(ttf.size, FONT_SIZE) - - ttf_copy = ttf.font_variant() - self.assertEqual(ttf_copy.path, FONT_PATH) - self.assertEqual(ttf_copy.size, FONT_SIZE) - - ttf_copy = ttf.font_variant(size=FONT_SIZE + 1) - self.assertEqual(ttf_copy.size, FONT_SIZE + 1) - - second_font_path = "Tests/fonts/DejaVuSans.ttf" - ttf_copy = ttf.font_variant(font=second_font_path) - self.assertEqual(ttf_copy.path, second_font_path) - - def test_font_with_name(self): - self.get_font() - self._render(FONT_PATH) - - def _font_as_bytes(self): - with open(FONT_PATH, "rb") as f: - font_bytes = BytesIO(f.read()) - return font_bytes - - def test_font_with_filelike(self): - ImageFont.truetype( - self._font_as_bytes(), FONT_SIZE, layout_engine=self.LAYOUT_ENGINE - ) - self._render(self._font_as_bytes()) - # Usage note: making two fonts from the same buffer fails. - # shared_bytes = self._font_as_bytes() - # self._render(shared_bytes) - # self.assertRaises(Exception, _render, shared_bytes) - - def test_font_with_open_file(self): - with open(FONT_PATH, "rb") as f: - self._render(f) - - def test_non_unicode_path(self): - try: - tempfile = self.tempfile("temp_" + chr(128) + ".ttf") - except UnicodeEncodeError: - self.skipTest("Unicode path could not be created") - shutil.copy(FONT_PATH, tempfile) - - ImageFont.truetype(tempfile, FONT_SIZE) - - def test_unavailable_layout_engine(self): - have_raqm = ImageFont.core.HAVE_RAQM - ImageFont.core.HAVE_RAQM = False - - try: - ttf = ImageFont.truetype( - FONT_PATH, FONT_SIZE, layout_engine=ImageFont.LAYOUT_RAQM - ) - finally: - ImageFont.core.HAVE_RAQM = have_raqm - - self.assertEqual(ttf.layout_engine, ImageFont.LAYOUT_BASIC) - - def _render(self, font): - txt = "Hello World!" - ttf = ImageFont.truetype(font, FONT_SIZE, layout_engine=self.LAYOUT_ENGINE) - ttf.getsize(txt) - - img = Image.new("RGB", (256, 64), "white") - d = ImageDraw.Draw(img) - d.text((10, 10), txt, font=ttf, fill="black") - - return img - - def test_render_equal(self): - img_path = self._render(FONT_PATH) - with open(FONT_PATH, "rb") as f: - font_filelike = BytesIO(f.read()) - img_filelike = self._render(font_filelike) - - self.assert_image_equal(img_path, img_filelike) - - def test_textsize_equal(self): - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - ttf = self.get_font() - - txt = "Hello World!" - size = draw.textsize(txt, ttf) - draw.text((10, 10), txt, font=ttf) - draw.rectangle((10, 10, 10 + size[0], 10 + size[1])) - - target = "Tests/images/rectangle_surrounding_text.png" - target_img = Image.open(target) - - # Epsilon ~.5 fails with FreeType 2.7 - self.assert_image_similar(im, target_img, self.metrics["textsize"]) - - def test_render_multiline(self): - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - ttf = self.get_font() - line_spacing = draw.textsize("A", font=ttf)[1] + 4 - lines = TEST_TEXT.split("\n") - y = 0 - for line in lines: - draw.text((0, y), line, font=ttf) - y += line_spacing - - target = "Tests/images/multiline_text.png" - target_img = Image.open(target) - - # some versions of freetype have different horizontal spacing. - # setting a tight epsilon, I'm showing the original test failure - # at epsilon = ~38. - self.assert_image_similar(im, target_img, self.metrics["multiline"]) - - def test_render_multiline_text(self): - ttf = self.get_font() - - # Test that text() correctly connects to multiline_text() - # and that align defaults to left - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), TEST_TEXT, font=ttf) - - target = "Tests/images/multiline_text.png" - target_img = Image.open(target) - - # Epsilon ~.5 fails with FreeType 2.7 - self.assert_image_similar(im, target_img, self.metrics["multiline"]) - - # Test that text() can pass on additional arguments - # to multiline_text() - draw.text( - (0, 0), TEST_TEXT, fill=None, font=ttf, anchor=None, spacing=4, align="left" - ) - draw.text((0, 0), TEST_TEXT, None, ttf, None, 4, "left") - - # Test align center and right - for align, ext in {"center": "_center", "right": "_right"}.items(): - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.multiline_text((0, 0), TEST_TEXT, font=ttf, align=align) - - target = "Tests/images/multiline_text" + ext + ".png" - target_img = Image.open(target) - - # Epsilon ~.5 fails with FreeType 2.7 - self.assert_image_similar(im, target_img, self.metrics["multiline"]) - - def test_unknown_align(self): - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - ttf = self.get_font() - - # Act/Assert - self.assertRaises( - ValueError, - draw.multiline_text, - (0, 0), - TEST_TEXT, - font=ttf, - align="unknown", - ) - - def test_draw_align(self): - im = Image.new("RGB", (300, 100), "white") - draw = ImageDraw.Draw(im) - ttf = self.get_font() - line = "some text" - draw.text((100, 40), line, (0, 0, 0), font=ttf, align="left") - - def test_multiline_size(self): - ttf = self.get_font() - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - - # Test that textsize() correctly connects to multiline_textsize() - self.assertEqual( - draw.textsize(TEST_TEXT, font=ttf), - draw.multiline_textsize(TEST_TEXT, font=ttf), - ) - - # Test that multiline_textsize corresponds to ImageFont.textsize() - # for single line text - self.assertEqual(ttf.getsize("A"), draw.multiline_textsize("A", font=ttf)) - - # Test that textsize() can pass on additional arguments - # to multiline_textsize() - draw.textsize(TEST_TEXT, font=ttf, spacing=4) - draw.textsize(TEST_TEXT, ttf, 4) - - def test_multiline_width(self): - ttf = self.get_font() - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - - self.assertEqual( - draw.textsize("longest line", font=ttf)[0], - draw.multiline_textsize("longest line\nline", font=ttf)[0], - ) - - def test_multiline_spacing(self): - ttf = self.get_font() - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.multiline_text((0, 0), TEST_TEXT, font=ttf, spacing=10) - - target = "Tests/images/multiline_text_spacing.png" - target_img = Image.open(target) - - # Epsilon ~.5 fails with FreeType 2.7 - self.assert_image_similar(im, target_img, self.metrics["multiline"]) - - def test_rotated_transposed_font(self): - img_grey = Image.new("L", (100, 100)) - draw = ImageDraw.Draw(img_grey) - word = "testing" - font = self.get_font() - - orientation = Image.ROTATE_90 - transposed_font = ImageFont.TransposedFont(font, orientation=orientation) - - # Original font - draw.font = font - box_size_a = draw.textsize(word) - - # Rotated font - draw.font = transposed_font - box_size_b = draw.textsize(word) - - # Check (w,h) of box a is (h,w) of box b - self.assertEqual(box_size_a[0], box_size_b[1]) - self.assertEqual(box_size_a[1], box_size_b[0]) - - def test_unrotated_transposed_font(self): - img_grey = Image.new("L", (100, 100)) - draw = ImageDraw.Draw(img_grey) - word = "testing" - font = self.get_font() - - orientation = None - transposed_font = ImageFont.TransposedFont(font, orientation=orientation) - - # Original font - draw.font = font - box_size_a = draw.textsize(word) - - # Rotated font - draw.font = transposed_font - box_size_b = draw.textsize(word) - - # Check boxes a and b are same size - self.assertEqual(box_size_a, box_size_b) - - def test_rotated_transposed_font_get_mask(self): - # Arrange - text = "mask this" - font = self.get_font() - orientation = Image.ROTATE_90 - transposed_font = ImageFont.TransposedFont(font, orientation=orientation) - - # Act - mask = transposed_font.getmask(text) - - # Assert - self.assertEqual(mask.size, (13, 108)) - - def test_unrotated_transposed_font_get_mask(self): - # Arrange - text = "mask this" - font = self.get_font() - orientation = None - transposed_font = ImageFont.TransposedFont(font, orientation=orientation) - - # Act - mask = transposed_font.getmask(text) - - # Assert - self.assertEqual(mask.size, (108, 13)) - - def test_free_type_font_get_name(self): - # Arrange - font = self.get_font() - - # Act - name = font.getname() - - # Assert - self.assertEqual(("FreeMono", "Regular"), name) - - def test_free_type_font_get_metrics(self): - # Arrange - font = self.get_font() - - # Act - ascent, descent = font.getmetrics() - - # Assert - self.assertIsInstance(ascent, int) - self.assertIsInstance(descent, int) - self.assertEqual((ascent, descent), (16, 4)) # too exact check? - - def test_free_type_font_get_offset(self): - # Arrange - font = self.get_font() - text = "offset this" - - # Act - offset = font.getoffset(text) - - # Assert - self.assertEqual(offset, (0, 3)) - - def test_free_type_font_get_mask(self): - # Arrange - font = self.get_font() - text = "mask this" - - # Act - mask = font.getmask(text) - - # Assert - self.assertEqual(mask.size, (108, 13)) - - def test_load_path_not_found(self): - # Arrange - filename = "somefilenamethatdoesntexist.ttf" - - # Act/Assert - self.assertRaises(IOError, ImageFont.load_path, filename) - self.assertRaises(IOError, ImageFont.truetype, filename) - - def test_load_non_font_bytes(self): - with open("Tests/images/hopper.jpg", "rb") as f: - self.assertRaises(IOError, ImageFont.truetype, f) - - def test_default_font(self): - # Arrange - txt = 'This is a "better than nothing" default font.' - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - - target = "Tests/images/default_font.png" - target_img = Image.open(target) - - # Act - default_font = ImageFont.load_default() - draw.text((10, 10), txt, font=default_font) - - # Assert - self.assert_image_equal(im, target_img) - - def test_getsize_empty(self): - # issue #2614 - font = self.get_font() - # should not crash. - self.assertEqual((0, 0), font.getsize("")) - - def test_render_empty(self): - # issue 2666 - font = self.get_font() - im = Image.new(mode="RGB", size=(300, 100)) - target = im.copy() - draw = ImageDraw.Draw(im) - # should not crash here. - draw.text((10, 10), "", font=font) - self.assert_image_equal(im, target) - - def test_unicode_pilfont(self): - # should not segfault, should return UnicodeDecodeError - # issue #2826 - font = ImageFont.load_default() - with self.assertRaises(UnicodeEncodeError): - font.getsize(u"’") - - @unittest.skipIf( - sys.version.startswith("2") or hasattr(sys, "pypy_translation_info"), - "requires CPython 3.3+", - ) - def test_unicode_extended(self): - # issue #3777 - text = u"A\u278A\U0001F12B" - target = "Tests/images/unicode_extended.png" - - ttf = ImageFont.truetype( - "Tests/fonts/NotoSansSymbols-Regular.ttf", - FONT_SIZE, - layout_engine=self.LAYOUT_ENGINE, - ) - img = Image.new("RGB", (100, 60)) - d = ImageDraw.Draw(img) - d.text((10, 10), text, font=ttf) - - self.assert_image_similar_tofile(img, target, self.metrics["multiline"]) - - def _test_fake_loading_font(self, path_to_fake, fontname): - # Make a copy of FreeTypeFont so we can patch the original - free_type_font = copy.deepcopy(ImageFont.FreeTypeFont) - with SimplePatcher(ImageFont, "_FreeTypeFont", free_type_font): - - def loadable_font(filepath, size, index, encoding, *args, **kwargs): - if filepath == path_to_fake: - return ImageFont._FreeTypeFont( - FONT_PATH, size, index, encoding, *args, **kwargs - ) - return ImageFont._FreeTypeFont( - filepath, size, index, encoding, *args, **kwargs - ) - - with SimplePatcher(ImageFont, "FreeTypeFont", loadable_font): - font = ImageFont.truetype(fontname) - # Make sure it's loaded - name = font.getname() - self.assertEqual(("FreeMono", "Regular"), name) - - @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") - def test_find_linux_font(self): - # A lot of mocking here - this is more for hitting code and - # catching syntax like errors - font_directory = "/usr/local/share/fonts" - with SimplePatcher(sys, "platform", "linux"): - patched_env = copy.deepcopy(os.environ) - patched_env["XDG_DATA_DIRS"] = "/usr/share/:/usr/local/share/" - with SimplePatcher(os, "environ", patched_env): - - def fake_walker(path): - if path == font_directory: - return [ - ( - path, - [], - [ - "Arial.ttf", - "Single.otf", - "Duplicate.otf", - "Duplicate.ttf", - ], - ) - ] - return [(path, [], ["some_random_font.ttf"])] - - with SimplePatcher(os, "walk", fake_walker): - # Test that the font loads both with and without the - # extension - self._test_fake_loading_font( - font_directory + "/Arial.ttf", "Arial.ttf" - ) - self._test_fake_loading_font(font_directory + "/Arial.ttf", "Arial") - - # Test that non-ttf fonts can be found without the - # extension - self._test_fake_loading_font( - font_directory + "/Single.otf", "Single" - ) - - # Test that ttf fonts are preferred if the extension is - # not specified - self._test_fake_loading_font( - font_directory + "/Duplicate.ttf", "Duplicate" - ) - - @unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") - def test_find_macos_font(self): - # Like the linux test, more cover hitting code rather than testing - # correctness. - font_directory = "/System/Library/Fonts" - with SimplePatcher(sys, "platform", "darwin"): - - def fake_walker(path): - if path == font_directory: - return [ - ( - path, - [], - [ - "Arial.ttf", - "Single.otf", - "Duplicate.otf", - "Duplicate.ttf", - ], - ) - ] - return [(path, [], ["some_random_font.ttf"])] - - with SimplePatcher(os, "walk", fake_walker): - self._test_fake_loading_font(font_directory + "/Arial.ttf", "Arial.ttf") - self._test_fake_loading_font(font_directory + "/Arial.ttf", "Arial") - self._test_fake_loading_font(font_directory + "/Single.otf", "Single") - self._test_fake_loading_font( - font_directory + "/Duplicate.ttf", "Duplicate" - ) - - def test_imagefont_getters(self): - # Arrange - t = self.get_font() - - # Act / Assert - self.assertEqual(t.getmetrics(), (16, 4)) - self.assertEqual(t.font.ascent, 16) - self.assertEqual(t.font.descent, 4) - self.assertEqual(t.font.height, 20) - self.assertEqual(t.font.x_ppem, 20) - self.assertEqual(t.font.y_ppem, 20) - self.assertEqual(t.font.glyphs, 4177) - self.assertEqual(t.getsize("A"), (12, 16)) - self.assertEqual(t.getsize("AB"), (24, 16)) - self.assertEqual(t.getsize("M"), self.metrics["getters"]) - self.assertEqual(t.getsize("y"), (12, 20)) - self.assertEqual(t.getsize("a"), (12, 16)) - self.assertEqual(t.getsize_multiline("A"), (12, 16)) - self.assertEqual(t.getsize_multiline("AB"), (24, 16)) - self.assertEqual(t.getsize_multiline("a"), (12, 16)) - self.assertEqual(t.getsize_multiline("ABC\n"), (36, 36)) - self.assertEqual(t.getsize_multiline("ABC\nA"), (36, 36)) - self.assertEqual(t.getsize_multiline("ABC\nAaaa"), (48, 36)) - - def test_complex_font_settings(self): - # Arrange - t = self.get_font() - # Act / Assert - if t.layout_engine == ImageFont.LAYOUT_BASIC: - self.assertRaises(KeyError, t.getmask, "абвг", direction="rtl") - self.assertRaises(KeyError, t.getmask, "абвг", features=["-kern"]) - self.assertRaises(KeyError, t.getmask, "абвг", language="sr") - - def test_variation_get(self): - font = self.get_font() - - freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) - if freetype < "2.9.1": - self.assertRaises(NotImplementedError, font.get_variation_names) - self.assertRaises(NotImplementedError, font.get_variation_axes) - return - - self.assertRaises(IOError, font.get_variation_names) - self.assertRaises(IOError, font.get_variation_axes) - - font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf") - self.assertEqual( - font.get_variation_names(), - [ - b"ExtraLight", - b"Light", - b"Regular", - b"Semibold", - b"Bold", - b"Black", - b"Black Medium Contrast", - b"Black High Contrast", - b"Default", - ], - ) - self.assertEqual( - font.get_variation_axes(), - [ - {"name": b"Weight", "minimum": 200, "maximum": 900, "default": 389}, - {"name": b"Contrast", "minimum": 0, "maximum": 100, "default": 0}, - ], - ) - - font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf") - self.assertEqual( - font.get_variation_names(), - [ - b"20", - b"40", - b"60", - b"80", - b"100", - b"120", - b"140", - b"160", - b"180", - b"200", - b"220", - b"240", - b"260", - b"280", - b"300", - b"Regular", - ], - ) - self.assertEqual( - font.get_variation_axes(), - [{"name": b"Size", "minimum": 0, "maximum": 300, "default": 0}], - ) - - def test_variation_set_by_name(self): - font = self.get_font() - - freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) - if freetype < "2.9.1": - self.assertRaises(NotImplementedError, font.set_variation_by_name, "Bold") - return - - self.assertRaises(IOError, font.set_variation_by_name, "Bold") - - def _check_text(font, path, epsilon): - im = Image.new("RGB", (100, 75), "white") - d = ImageDraw.Draw(im) - d.text((10, 10), "Text", font=font, fill="black") - - expected = Image.open(path) - self.assert_image_similar(im, expected, epsilon) - - font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf", 36) - _check_text(font, "Tests/images/variation_adobe.png", 11) - for name in ["Bold", b"Bold"]: - font.set_variation_by_name(name) - _check_text(font, "Tests/images/variation_adobe_name.png", 11) - - font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf", 36) - _check_text(font, "Tests/images/variation_tiny.png", 40) - for name in ["200", b"200"]: - font.set_variation_by_name(name) - _check_text(font, "Tests/images/variation_tiny_name.png", 40) - - def test_variation_set_by_axes(self): - font = self.get_font() - - freetype = distutils.version.StrictVersion(ImageFont.core.freetype2_version) - if freetype < "2.9.1": - self.assertRaises(NotImplementedError, font.set_variation_by_axes, [100]) - return - - self.assertRaises(IOError, font.set_variation_by_axes, [500, 50]) - - def _check_text(font, path, epsilon): - im = Image.new("RGB", (100, 75), "white") - d = ImageDraw.Draw(im) - d.text((10, 10), "Text", font=font, fill="black") - - expected = Image.open(path) - self.assert_image_similar(im, expected, epsilon) - - font = ImageFont.truetype("Tests/fonts/AdobeVFPrototype.ttf", 36) - font.set_variation_by_axes([500, 50]) - _check_text(font, "Tests/images/variation_adobe_axes.png", 5.1) - - font = ImageFont.truetype("Tests/fonts/TINY5x3GX.ttf", 36) - font.set_variation_by_axes([100]) - _check_text(font, "Tests/images/variation_tiny_axes.png", 32.5) - - -@unittest.skipUnless(HAS_RAQM, "Raqm not Available") -class TestImageFont_RaqmLayout(TestImageFont): - LAYOUT_ENGINE = ImageFont.LAYOUT_RAQM diff --git a/Tests/test_imagefont_bitmap.py b/Tests/test_imagefont_bitmap.py deleted file mode 100644 index b7be8f72348..00000000000 --- a/Tests/test_imagefont_bitmap.py +++ /dev/null @@ -1,43 +0,0 @@ -from PIL import Image, ImageDraw, ImageFont - -from .helper import PillowTestCase, unittest - -image_font_installed = True -try: - ImageFont.core.getfont -except ImportError: - image_font_installed = False - - -@unittest.skipIf(not image_font_installed, "image font not installed") -class TestImageFontBitmap(PillowTestCase): - def test_similar(self): - text = "EmbeddedBitmap" - font_outline = ImageFont.truetype(font="Tests/fonts/DejaVuSans.ttf", size=24) - font_bitmap = ImageFont.truetype( - font="Tests/fonts/DejaVuSans-bitmap.ttf", size=24 - ) - size_outline = font_outline.getsize(text) - size_bitmap = font_bitmap.getsize(text) - size_final = ( - max(size_outline[0], size_bitmap[0]), - max(size_outline[1], size_bitmap[1]), - ) - im_bitmap = Image.new("RGB", size_final, (255, 255, 255)) - im_outline = im_bitmap.copy() - draw_bitmap = ImageDraw.Draw(im_bitmap) - draw_outline = ImageDraw.Draw(im_outline) - - # Metrics are different on the bitmap and ttf fonts, - # more so on some platforms and versions of freetype than others. - # Mac has a 1px difference, linux doesn't. - draw_bitmap.text( - (0, size_final[1] - size_bitmap[1]), text, fill=(0, 0, 0), font=font_bitmap - ) - draw_outline.text( - (0, size_final[1] - size_outline[1]), - text, - fill=(0, 0, 0), - font=font_outline, - ) - self.assert_image_similar(im_bitmap, im_outline, 20) diff --git a/Tests/test_imagefontctl.py b/Tests/test_imagefontctl.py deleted file mode 100644 index afd45ce1982..00000000000 --- a/Tests/test_imagefontctl.py +++ /dev/null @@ -1,184 +0,0 @@ -# -*- coding: utf-8 -*- -from PIL import Image, ImageDraw, ImageFont, features - -from .helper import PillowTestCase, unittest - -FONT_SIZE = 20 -FONT_PATH = "Tests/fonts/DejaVuSans.ttf" - - -@unittest.skipUnless(features.check("raqm"), "Raqm Library is not installed.") -class TestImagecomplextext(PillowTestCase): - def test_english(self): - # smoke test, this should not fail - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "TEST", font=ttf, fill=500, direction="ltr") - - def test_complex_text(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "اهلا عمان", font=ttf, fill=500) - - target = "Tests/images/test_text.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_y_offset(self): - ttf = ImageFont.truetype("Tests/fonts/NotoNastaliqUrdu-Regular.ttf", FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "العالم العربي", font=ttf, fill=500) - - target = "Tests/images/test_y_offset.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 1.7) - - def test_complex_unicode_text(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "السلام عليكم", font=ttf, fill=500) - - target = "Tests/images/test_complex_unicode_text.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - ttf = ImageFont.truetype("Tests/fonts/KhmerOSBattambang-Regular.ttf", FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "លោកុប្បត្តិ", font=ttf, fill=500) - - target = "Tests/images/test_complex_unicode_text2.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 2.3) - - def test_text_direction_rtl(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "English عربي", font=ttf, fill=500, direction="rtl") - - target = "Tests/images/test_direction_rtl.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_text_direction_ltr(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "سلطنة عمان Oman", font=ttf, fill=500, direction="ltr") - - target = "Tests/images/test_direction_ltr.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_text_direction_rtl2(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "Oman سلطنة عمان", font=ttf, fill=500, direction="rtl") - - target = "Tests/images/test_direction_ltr.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_text_direction_ttb(self): - ttf = ImageFont.truetype("Tests/fonts/NotoSansJP-Regular.otf", FONT_SIZE) - - im = Image.new(mode="RGB", size=(100, 300)) - draw = ImageDraw.Draw(im) - try: - draw.text((0, 0), "English あい", font=ttf, fill=500, direction="ttb") - except ValueError as ex: - if str(ex) == "libraqm 0.7 or greater required for 'ttb' direction": - self.skipTest("libraqm 0.7 or greater not available") - - target = "Tests/images/test_direction_ttb.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 1.15) - - def test_ligature_features(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "filling", font=ttf, fill=500, features=["-liga"]) - target = "Tests/images/test_ligature_features.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - liga_size = ttf.getsize("fi", features=["-liga"]) - self.assertEqual(liga_size, (13, 19)) - - def test_kerning_features(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "TeToAV", font=ttf, fill=500, features=["-kern"]) - - target = "Tests/images/test_kerning_features.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_arabictext_features(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text( - (0, 0), - "اللغة العربية", - font=ttf, - fill=500, - features=["-fina", "-init", "-medi"], - ) - - target = "Tests/images/test_arabictext_features.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_x_max_and_y_offset(self): - ttf = ImageFont.truetype("Tests/fonts/ArefRuqaa-Regular.ttf", 40) - - im = Image.new(mode="RGB", size=(50, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "لح", font=ttf, fill=500) - - target = "Tests/images/test_x_max_and_y_offset.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) - - def test_language(self): - ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) - - im = Image.new(mode="RGB", size=(300, 100)) - draw = ImageDraw.Draw(im) - draw.text((0, 0), "абвг", font=ttf, fill=500, language="sr") - - target = "Tests/images/test_language.png" - target_img = Image.open(target) - - self.assert_image_similar(im, target_img, 0.5) diff --git a/Tests/test_imagegrab.py b/Tests/test_imagegrab.py deleted file mode 100644 index a29bc019eea..00000000000 --- a/Tests/test_imagegrab.py +++ /dev/null @@ -1,58 +0,0 @@ -import subprocess -import sys - -from .helper import PillowTestCase - -try: - from PIL import ImageGrab - - class TestImageGrab(PillowTestCase): - def test_grab(self): - for im in [ImageGrab.grab(), ImageGrab.grab(include_layered_windows=True)]: - self.assert_image(im, im.mode, im.size) - - def test_grabclipboard(self): - if sys.platform == "darwin": - subprocess.call(["screencapture", "-cx"]) - else: - p = subprocess.Popen( - ["powershell", "-command", "-"], stdin=subprocess.PIPE - ) - p.stdin.write( - b"""[Reflection.Assembly]::LoadWithPartialName("System.Drawing") -[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") -$bmp = New-Object Drawing.Bitmap 200, 200 -[Windows.Forms.Clipboard]::SetImage($bmp)""" - ) - p.communicate() - - im = ImageGrab.grabclipboard() - self.assert_image(im, im.mode, im.size) - - -except ImportError: - - class TestImageGrab(PillowTestCase): - def test_skip(self): - self.skipTest("ImportError") - - -class TestImageGrabImport(PillowTestCase): - def test_import(self): - # Arrange - exception = None - - # Act - try: - from PIL import ImageGrab - - ImageGrab.__name__ # dummy to prevent Pyflakes warning - except Exception as e: - exception = e - - # Assert - if sys.platform in ["win32", "darwin"]: - self.assertIsNone(exception) - else: - self.assertIsInstance(exception, ImportError) - self.assertEqual(str(exception), "ImageGrab is macOS and Windows only") diff --git a/Tests/test_imagemath.py b/Tests/test_imagemath.py deleted file mode 100644 index da41b3a1274..00000000000 --- a/Tests/test_imagemath.py +++ /dev/null @@ -1,178 +0,0 @@ -from __future__ import print_function - -from PIL import Image, ImageMath - -from .helper import PillowTestCase - - -def pixel(im): - if hasattr(im, "im"): - return "%s %r" % (im.mode, im.getpixel((0, 0))) - else: - if isinstance(im, int): - return int(im) # hack to deal with booleans - print(im) - - -A = Image.new("L", (1, 1), 1) -B = Image.new("L", (1, 1), 2) -Z = Image.new("L", (1, 1), 0) # Z for zero -F = Image.new("F", (1, 1), 3) -I = Image.new("I", (1, 1), 4) # noqa: E741 - -A2 = A.resize((2, 2)) -B2 = B.resize((2, 2)) - -images = {"A": A, "B": B, "F": F, "I": I} - - -class TestImageMath(PillowTestCase): - def test_sanity(self): - self.assertEqual(ImageMath.eval("1"), 1) - self.assertEqual(ImageMath.eval("1+A", A=2), 3) - self.assertEqual(pixel(ImageMath.eval("A+B", A=A, B=B)), "I 3") - self.assertEqual(pixel(ImageMath.eval("A+B", images)), "I 3") - self.assertEqual(pixel(ImageMath.eval("float(A)+B", images)), "F 3.0") - self.assertEqual(pixel(ImageMath.eval("int(float(A)+B)", images)), "I 3") - - def test_ops(self): - - self.assertEqual(pixel(ImageMath.eval("-A", images)), "I -1") - self.assertEqual(pixel(ImageMath.eval("+B", images)), "L 2") - - self.assertEqual(pixel(ImageMath.eval("A+B", images)), "I 3") - self.assertEqual(pixel(ImageMath.eval("A-B", images)), "I -1") - self.assertEqual(pixel(ImageMath.eval("A*B", images)), "I 2") - self.assertEqual(pixel(ImageMath.eval("A/B", images)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B**2", images)), "I 4") - self.assertEqual(pixel(ImageMath.eval("B**33", images)), "I 2147483647") - - self.assertEqual(pixel(ImageMath.eval("float(A)+B", images)), "F 3.0") - self.assertEqual(pixel(ImageMath.eval("float(A)-B", images)), "F -1.0") - self.assertEqual(pixel(ImageMath.eval("float(A)*B", images)), "F 2.0") - self.assertEqual(pixel(ImageMath.eval("float(A)/B", images)), "F 0.5") - self.assertEqual(pixel(ImageMath.eval("float(B)**2", images)), "F 4.0") - self.assertEqual( - pixel(ImageMath.eval("float(B)**33", images)), "F 8589934592.0" - ) - - def test_logical(self): - self.assertEqual(pixel(ImageMath.eval("not A", images)), 0) - self.assertEqual(pixel(ImageMath.eval("A and B", images)), "L 2") - self.assertEqual(pixel(ImageMath.eval("A or B", images)), "L 1") - - def test_convert(self): - self.assertEqual(pixel(ImageMath.eval("convert(A+B, 'L')", images)), "L 3") - self.assertEqual(pixel(ImageMath.eval("convert(A+B, '1')", images)), "1 0") - self.assertEqual( - pixel(ImageMath.eval("convert(A+B, 'RGB')", images)), "RGB (3, 3, 3)" - ) - - def test_compare(self): - self.assertEqual(pixel(ImageMath.eval("min(A, B)", images)), "I 1") - self.assertEqual(pixel(ImageMath.eval("max(A, B)", images)), "I 2") - self.assertEqual(pixel(ImageMath.eval("A == 1", images)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A == 2", images)), "I 0") - - def test_one_image_larger(self): - self.assertEqual(pixel(ImageMath.eval("A+B", A=A2, B=B)), "I 3") - self.assertEqual(pixel(ImageMath.eval("A+B", A=A, B=B2)), "I 3") - - def test_abs(self): - self.assertEqual(pixel(ImageMath.eval("abs(A)", A=A)), "I 1") - self.assertEqual(pixel(ImageMath.eval("abs(B)", B=B)), "I 2") - - def test_binary_mod(self): - self.assertEqual(pixel(ImageMath.eval("A%A", A=A)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B%B", B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A%B", A=A, B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("B%A", A=A, B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z%A", A=A, Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z%B", B=B, Z=Z)), "I 0") - - def test_bitwise_invert(self): - self.assertEqual(pixel(ImageMath.eval("~Z", Z=Z)), "I -1") - self.assertEqual(pixel(ImageMath.eval("~A", A=A)), "I -2") - self.assertEqual(pixel(ImageMath.eval("~B", B=B)), "I -3") - - def test_bitwise_and(self): - self.assertEqual(pixel(ImageMath.eval("Z&Z", A=A, Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z&A", A=A, Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A&Z", A=A, Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A&A", A=A, Z=Z)), "I 1") - - def test_bitwise_or(self): - self.assertEqual(pixel(ImageMath.eval("Z|Z", A=A, Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z|A", A=A, Z=Z)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A|Z", A=A, Z=Z)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A|A", A=A, Z=Z)), "I 1") - - def test_bitwise_xor(self): - self.assertEqual(pixel(ImageMath.eval("Z^Z", A=A, Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z^A", A=A, Z=Z)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A^Z", A=A, Z=Z)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A^A", A=A, Z=Z)), "I 0") - - def test_bitwise_leftshift(self): - self.assertEqual(pixel(ImageMath.eval("Z<<0", Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z<<1", Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A<<0", A=A)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A<<1", A=A)), "I 2") - - def test_bitwise_rightshift(self): - self.assertEqual(pixel(ImageMath.eval("Z>>0", Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("Z>>1", Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A>>0", A=A)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A>>1", A=A)), "I 0") - - def test_logical_eq(self): - self.assertEqual(pixel(ImageMath.eval("A==A", A=A)), "I 1") - self.assertEqual(pixel(ImageMath.eval("B==B", B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A==B", A=A, B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B==A", A=A, B=B)), "I 0") - - def test_logical_ne(self): - self.assertEqual(pixel(ImageMath.eval("A!=A", A=A)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B!=B", B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A!=B", A=A, B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("B!=A", A=A, B=B)), "I 1") - - def test_logical_lt(self): - self.assertEqual(pixel(ImageMath.eval("AA", A=A)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B>B", B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("A>B", A=A, B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B>A", A=A, B=B)), "I 1") - - def test_logical_ge(self): - self.assertEqual(pixel(ImageMath.eval("A>=A", A=A)), "I 1") - self.assertEqual(pixel(ImageMath.eval("B>=B", B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("A>=B", A=A, B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("B>=A", A=A, B=B)), "I 1") - - def test_logical_equal(self): - self.assertEqual(pixel(ImageMath.eval("equal(A, A)", A=A)), "I 1") - self.assertEqual(pixel(ImageMath.eval("equal(B, B)", B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("equal(Z, Z)", Z=Z)), "I 1") - self.assertEqual(pixel(ImageMath.eval("equal(A, B)", A=A, B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("equal(B, A)", A=A, B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("equal(A, Z)", A=A, Z=Z)), "I 0") - - def test_logical_not_equal(self): - self.assertEqual(pixel(ImageMath.eval("notequal(A, A)", A=A)), "I 0") - self.assertEqual(pixel(ImageMath.eval("notequal(B, B)", B=B)), "I 0") - self.assertEqual(pixel(ImageMath.eval("notequal(Z, Z)", Z=Z)), "I 0") - self.assertEqual(pixel(ImageMath.eval("notequal(A, B)", A=A, B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("notequal(B, A)", A=A, B=B)), "I 1") - self.assertEqual(pixel(ImageMath.eval("notequal(A, Z)", A=A, Z=Z)), "I 1") diff --git a/Tests/test_imagemorph.py b/Tests/test_imagemorph.py deleted file mode 100644 index 1492872b694..00000000000 --- a/Tests/test_imagemorph.py +++ /dev/null @@ -1,328 +0,0 @@ -# Test the ImageMorphology functionality -from PIL import Image, ImageMorph, _imagingmorph - -from .helper import PillowTestCase, hopper - - -class MorphTests(PillowTestCase): - def setUp(self): - self.A = self.string_to_img( - """ - ....... - ....... - ..111.. - ..111.. - ..111.. - ....... - ....... - """ - ) - - def img_to_string(self, im): - """Turn a (small) binary image into a string representation""" - chars = ".1" - width, height = im.size - return "\n".join( - "".join(chars[im.getpixel((c, r)) > 0] for c in range(width)) - for r in range(height) - ) - - def string_to_img(self, image_string): - """Turn a string image representation into a binary image""" - rows = [s for s in image_string.replace(" ", "").split("\n") if len(s)] - height = len(rows) - width = len(rows[0]) - im = Image.new("L", (width, height)) - for i in range(width): - for j in range(height): - c = rows[j][i] - v = c in "X1" - im.putpixel((i, j), v) - - return im - - def img_string_normalize(self, im): - return self.img_to_string(self.string_to_img(im)) - - def assert_img_equal(self, A, B): - self.assertEqual(self.img_to_string(A), self.img_to_string(B)) - - def assert_img_equal_img_string(self, A, Bstring): - self.assertEqual(self.img_to_string(A), self.img_string_normalize(Bstring)) - - def test_str_to_img(self): - im = Image.open("Tests/images/morph_a.png") - self.assert_image_equal(self.A, im) - - def create_lut(self): - for op in ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge"): - lb = ImageMorph.LutBuilder(op_name=op) - lut = lb.build_lut() - with open("Tests/images/%s.lut" % op, "wb") as f: - f.write(lut) - - # create_lut() - def test_lut(self): - for op in ("corner", "dilation4", "dilation8", "erosion4", "erosion8", "edge"): - lb = ImageMorph.LutBuilder(op_name=op) - self.assertIsNone(lb.get_lut()) - - lut = lb.build_lut() - with open("Tests/images/%s.lut" % op, "rb") as f: - self.assertEqual(lut, bytearray(f.read())) - - def test_no_operator_loaded(self): - mop = ImageMorph.MorphOp() - with self.assertRaises(Exception) as e: - mop.apply(None) - self.assertEqual(str(e.exception), "No operator loaded") - with self.assertRaises(Exception) as e: - mop.match(None) - self.assertEqual(str(e.exception), "No operator loaded") - with self.assertRaises(Exception) as e: - mop.save_lut(None) - self.assertEqual(str(e.exception), "No operator loaded") - - # Test the named patterns - def test_erosion8(self): - # erosion8 - mop = ImageMorph.MorphOp(op_name="erosion8") - count, Aout = mop.apply(self.A) - self.assertEqual(count, 8) - self.assert_img_equal_img_string( - Aout, - """ - ....... - ....... - ....... - ...1... - ....... - ....... - ....... - """, - ) - - def test_dialation8(self): - # dialation8 - mop = ImageMorph.MorphOp(op_name="dilation8") - count, Aout = mop.apply(self.A) - self.assertEqual(count, 16) - self.assert_img_equal_img_string( - Aout, - """ - ....... - .11111. - .11111. - .11111. - .11111. - .11111. - ....... - """, - ) - - def test_erosion4(self): - # erosion4 - mop = ImageMorph.MorphOp(op_name="dilation4") - count, Aout = mop.apply(self.A) - self.assertEqual(count, 12) - self.assert_img_equal_img_string( - Aout, - """ - ....... - ..111.. - .11111. - .11111. - .11111. - ..111.. - ....... - """, - ) - - def test_edge(self): - # edge - mop = ImageMorph.MorphOp(op_name="edge") - count, Aout = mop.apply(self.A) - self.assertEqual(count, 1) - self.assert_img_equal_img_string( - Aout, - """ - ....... - ....... - ..111.. - ..1.1.. - ..111.. - ....... - ....... - """, - ) - - def test_corner(self): - # Create a corner detector pattern - mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "4:(00. 01. ...)->1"]) - count, Aout = mop.apply(self.A) - self.assertEqual(count, 5) - self.assert_img_equal_img_string( - Aout, - """ - ....... - ....... - ..1.1.. - ....... - ..1.1.. - ....... - ....... - """, - ) - - # Test the coordinate counting with the same operator - coords = mop.match(self.A) - self.assertEqual(len(coords), 4) - self.assertEqual(tuple(coords), ((2, 2), (4, 2), (2, 4), (4, 4))) - - coords = mop.get_on_pixels(Aout) - self.assertEqual(len(coords), 4) - self.assertEqual(tuple(coords), ((2, 2), (4, 2), (2, 4), (4, 4))) - - def test_mirroring(self): - # Test 'M' for mirroring - mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "M:(00. 01. ...)->1"]) - count, Aout = mop.apply(self.A) - self.assertEqual(count, 7) - self.assert_img_equal_img_string( - Aout, - """ - ....... - ....... - ..1.1.. - ....... - ....... - ....... - ....... - """, - ) - - def test_negate(self): - # Test 'N' for negate - mop = ImageMorph.MorphOp(patterns=["1:(... ... ...)->0", "N:(00. 01. ...)->1"]) - count, Aout = mop.apply(self.A) - self.assertEqual(count, 8) - self.assert_img_equal_img_string( - Aout, - """ - ....... - ....... - ..1.... - ....... - ....... - ....... - ....... - """, - ) - - def test_non_binary_images(self): - im = hopper("RGB") - mop = ImageMorph.MorphOp(op_name="erosion8") - - with self.assertRaises(Exception) as e: - mop.apply(im) - self.assertEqual( - str(e.exception), "Image must be binary, meaning it must use mode L" - ) - with self.assertRaises(Exception) as e: - mop.match(im) - self.assertEqual( - str(e.exception), "Image must be binary, meaning it must use mode L" - ) - with self.assertRaises(Exception) as e: - mop.get_on_pixels(im) - self.assertEqual( - str(e.exception), "Image must be binary, meaning it must use mode L" - ) - - def test_add_patterns(self): - # Arrange - lb = ImageMorph.LutBuilder(op_name="corner") - self.assertEqual(lb.patterns, ["1:(... ... ...)->0", "4:(00. 01. ...)->1"]) - new_patterns = ["M:(00. 01. ...)->1", "N:(00. 01. ...)->1"] - - # Act - lb.add_patterns(new_patterns) - - # Assert - self.assertEqual( - lb.patterns, - [ - "1:(... ... ...)->0", - "4:(00. 01. ...)->1", - "M:(00. 01. ...)->1", - "N:(00. 01. ...)->1", - ], - ) - - def test_unknown_pattern(self): - self.assertRaises(Exception, ImageMorph.LutBuilder, op_name="unknown") - - def test_pattern_syntax_error(self): - # Arrange - lb = ImageMorph.LutBuilder(op_name="corner") - new_patterns = ["a pattern with a syntax error"] - lb.add_patterns(new_patterns) - - # Act / Assert - with self.assertRaises(Exception) as e: - lb.build_lut() - self.assertEqual( - str(e.exception), 'Syntax error in pattern "a pattern with a syntax error"' - ) - - def test_load_invalid_mrl(self): - # Arrange - invalid_mrl = "Tests/images/hopper.png" - mop = ImageMorph.MorphOp() - - # Act / Assert - with self.assertRaises(Exception) as e: - mop.load_lut(invalid_mrl) - self.assertEqual(str(e.exception), "Wrong size operator file!") - - def test_roundtrip_mrl(self): - # Arrange - tempfile = self.tempfile("temp.mrl") - mop = ImageMorph.MorphOp(op_name="corner") - initial_lut = mop.lut - - # Act - mop.save_lut(tempfile) - mop.load_lut(tempfile) - - # Act / Assert - self.assertEqual(mop.lut, initial_lut) - - def test_set_lut(self): - # Arrange - lb = ImageMorph.LutBuilder(op_name="corner") - lut = lb.build_lut() - mop = ImageMorph.MorphOp() - - # Act - mop.set_lut(lut) - - # Assert - self.assertEqual(mop.lut, lut) - - def test_wrong_mode(self): - lut = ImageMorph.LutBuilder(op_name="corner").build_lut() - imrgb = Image.new("RGB", (10, 10)) - iml = Image.new("L", (10, 10)) - - with self.assertRaises(RuntimeError): - _imagingmorph.apply(bytes(lut), imrgb.im.id, iml.im.id) - - with self.assertRaises(RuntimeError): - _imagingmorph.apply(bytes(lut), iml.im.id, imrgb.im.id) - - with self.assertRaises(RuntimeError): - _imagingmorph.match(bytes(lut), imrgb.im.id) - - # Should not raise - _imagingmorph.match(bytes(lut), iml.im.id) diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py deleted file mode 100644 index 85529a708ec..00000000000 --- a/Tests/test_imageops.py +++ /dev/null @@ -1,277 +0,0 @@ -from PIL import Image, ImageOps - -from .helper import PillowTestCase, hopper - -try: - from PIL import _webp - - HAVE_WEBP = True -except ImportError: - HAVE_WEBP = False - - -class TestImageOps(PillowTestCase): - class Deformer(object): - def getmesh(self, im): - x, y = im.size - return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))] - - deformer = Deformer() - - def test_sanity(self): - - ImageOps.autocontrast(hopper("L")) - ImageOps.autocontrast(hopper("RGB")) - - ImageOps.autocontrast(hopper("L"), cutoff=10) - ImageOps.autocontrast(hopper("L"), ignore=[0, 255]) - - ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255)) - ImageOps.colorize(hopper("L"), "black", "white") - - ImageOps.pad(hopper("L"), (128, 128)) - ImageOps.pad(hopper("RGB"), (128, 128)) - - ImageOps.crop(hopper("L"), 1) - ImageOps.crop(hopper("RGB"), 1) - - ImageOps.deform(hopper("L"), self.deformer) - ImageOps.deform(hopper("RGB"), self.deformer) - - ImageOps.equalize(hopper("L")) - ImageOps.equalize(hopper("RGB")) - - ImageOps.expand(hopper("L"), 1) - ImageOps.expand(hopper("RGB"), 1) - ImageOps.expand(hopper("L"), 2, "blue") - ImageOps.expand(hopper("RGB"), 2, "blue") - - ImageOps.fit(hopper("L"), (128, 128)) - ImageOps.fit(hopper("RGB"), (128, 128)) - - ImageOps.flip(hopper("L")) - ImageOps.flip(hopper("RGB")) - - ImageOps.grayscale(hopper("L")) - ImageOps.grayscale(hopper("RGB")) - - ImageOps.invert(hopper("L")) - ImageOps.invert(hopper("RGB")) - - ImageOps.mirror(hopper("L")) - ImageOps.mirror(hopper("RGB")) - - ImageOps.posterize(hopper("L"), 4) - ImageOps.posterize(hopper("RGB"), 4) - - ImageOps.solarize(hopper("L")) - ImageOps.solarize(hopper("RGB")) - - ImageOps.exif_transpose(hopper("L")) - ImageOps.exif_transpose(hopper("RGB")) - - def test_1pxfit(self): - # Division by zero in equalize if image is 1 pixel high - newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35)) - self.assertEqual(newimg.size, (35, 35)) - - newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35)) - self.assertEqual(newimg.size, (35, 35)) - - newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35)) - self.assertEqual(newimg.size, (35, 35)) - - def test_pad(self): - # Same ratio - im = hopper() - new_size = (im.width * 2, im.height * 2) - new_im = ImageOps.pad(im, new_size) - self.assertEqual(new_im.size, new_size) - - for label, color, new_size in [ - ("h", None, (im.width * 4, im.height * 2)), - ("v", "#f00", (im.width * 2, im.height * 4)), - ]: - for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]): - new_im = ImageOps.pad(im, new_size, color=color, centering=centering) - self.assertEqual(new_im.size, new_size) - - target = Image.open( - "Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg" - ) - self.assert_image_similar(new_im, target, 6) - - def test_pil163(self): - # Division by zero in equalize if < 255 pixels in image (@PIL163) - - i = hopper("RGB").resize((15, 16)) - - ImageOps.equalize(i.convert("L")) - ImageOps.equalize(i.convert("P")) - ImageOps.equalize(i.convert("RGB")) - - def test_scale(self): - # Test the scaling function - i = hopper("L").resize((50, 50)) - - with self.assertRaises(ValueError): - ImageOps.scale(i, -1) - - newimg = ImageOps.scale(i, 1) - self.assertEqual(newimg.size, (50, 50)) - - newimg = ImageOps.scale(i, 2) - self.assertEqual(newimg.size, (100, 100)) - - newimg = ImageOps.scale(i, 0.5) - self.assertEqual(newimg.size, (25, 25)) - - def test_colorize_2color(self): - # Test the colorizing function with 2-color functionality - - # Open test image (256px by 10px, black to white) - im = Image.open("Tests/images/bw_gradient.png") - im = im.convert("L") - - # Create image with original 2-color functionality - im_test = ImageOps.colorize(im, "red", "green") - - # Test output image (2-color) - left = (0, 1) - middle = (127, 1) - right = (255, 1) - self.assert_tuple_approx_equal( - im_test.getpixel(left), - (255, 0, 0), - threshold=1, - msg="black test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(middle), - (127, 63, 0), - threshold=1, - msg="mid test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(right), - (0, 127, 0), - threshold=1, - msg="white test pixel incorrect", - ) - - def test_colorize_2color_offset(self): - # Test the colorizing function with 2-color functionality and offset - - # Open test image (256px by 10px, black to white) - im = Image.open("Tests/images/bw_gradient.png") - im = im.convert("L") - - # Create image with original 2-color functionality with offsets - im_test = ImageOps.colorize( - im, black="red", white="green", blackpoint=50, whitepoint=100 - ) - - # Test output image (2-color) with offsets - left = (25, 1) - middle = (75, 1) - right = (125, 1) - self.assert_tuple_approx_equal( - im_test.getpixel(left), - (255, 0, 0), - threshold=1, - msg="black test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(middle), - (127, 63, 0), - threshold=1, - msg="mid test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(right), - (0, 127, 0), - threshold=1, - msg="white test pixel incorrect", - ) - - def test_colorize_3color_offset(self): - # Test the colorizing function with 3-color functionality and offset - - # Open test image (256px by 10px, black to white) - im = Image.open("Tests/images/bw_gradient.png") - im = im.convert("L") - - # Create image with new three color functionality with offsets - im_test = ImageOps.colorize( - im, - black="red", - white="green", - mid="blue", - blackpoint=50, - whitepoint=200, - midpoint=100, - ) - - # Test output image (3-color) with offsets - left = (25, 1) - left_middle = (75, 1) - middle = (100, 1) - right_middle = (150, 1) - right = (225, 1) - self.assert_tuple_approx_equal( - im_test.getpixel(left), - (255, 0, 0), - threshold=1, - msg="black test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(left_middle), - (127, 0, 127), - threshold=1, - msg="low-mid test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(middle), (0, 0, 255), threshold=1, msg="mid incorrect" - ) - self.assert_tuple_approx_equal( - im_test.getpixel(right_middle), - (0, 63, 127), - threshold=1, - msg="high-mid test pixel incorrect", - ) - self.assert_tuple_approx_equal( - im_test.getpixel(right), - (0, 127, 0), - threshold=1, - msg="white test pixel incorrect", - ) - - def test_exif_transpose(self): - exts = [".jpg"] - if HAVE_WEBP and _webp.HAVE_WEBPANIM: - exts.append(".webp") - for ext in exts: - base_im = Image.open("Tests/images/hopper" + ext) - - orientations = [base_im] - for i in range(2, 9): - im = Image.open("Tests/images/hopper_orientation_" + str(i) + ext) - orientations.append(im) - for i, orientation_im in enumerate(orientations): - for im in [orientation_im, orientation_im.copy()]: # ImageFile # Image - if i == 0: - self.assertNotIn("exif", im.info) - else: - original_exif = im.info["exif"] - transposed_im = ImageOps.exif_transpose(im) - self.assert_image_similar(base_im, transposed_im, 17) - if i == 0: - self.assertNotIn("exif", im.info) - else: - self.assertNotEqual(transposed_im.info["exif"], original_exif) - - self.assertNotIn(0x0112, transposed_im.getexif()) - - # Repeat the operation, to test that it does not keep transposing - transposed_im2 = ImageOps.exif_transpose(transposed_im) - self.assert_image_equal(transposed_im2, transposed_im) diff --git a/Tests/test_imageops_usm.py b/Tests/test_imageops_usm.py deleted file mode 100644 index 8340c5f0dec..00000000000 --- a/Tests/test_imageops_usm.py +++ /dev/null @@ -1,85 +0,0 @@ -from PIL import Image, ImageFilter - -from .helper import PillowTestCase - -im = Image.open("Tests/images/hopper.ppm") -snakes = Image.open("Tests/images/color_snakes.png") - - -class TestImageOpsUsm(PillowTestCase): - def test_filter_api(self): - - test_filter = ImageFilter.GaussianBlur(2.0) - i = im.filter(test_filter) - self.assertEqual(i.mode, "RGB") - self.assertEqual(i.size, (128, 128)) - - test_filter = ImageFilter.UnsharpMask(2.0, 125, 8) - i = im.filter(test_filter) - self.assertEqual(i.mode, "RGB") - self.assertEqual(i.size, (128, 128)) - - def test_usm_formats(self): - - usm = ImageFilter.UnsharpMask - self.assertRaises(ValueError, im.convert("1").filter, usm) - im.convert("L").filter(usm) - self.assertRaises(ValueError, im.convert("I").filter, usm) - self.assertRaises(ValueError, im.convert("F").filter, usm) - im.convert("RGB").filter(usm) - im.convert("RGBA").filter(usm) - im.convert("CMYK").filter(usm) - self.assertRaises(ValueError, im.convert("YCbCr").filter, usm) - - def test_blur_formats(self): - - blur = ImageFilter.GaussianBlur - self.assertRaises(ValueError, im.convert("1").filter, blur) - blur(im.convert("L")) - self.assertRaises(ValueError, im.convert("I").filter, blur) - self.assertRaises(ValueError, im.convert("F").filter, blur) - im.convert("RGB").filter(blur) - im.convert("RGBA").filter(blur) - im.convert("CMYK").filter(blur) - self.assertRaises(ValueError, im.convert("YCbCr").filter, blur) - - def test_usm_accuracy(self): - - src = snakes.convert("RGB") - i = src.filter(ImageFilter.UnsharpMask(5, 1024, 0)) - # Image should not be changed because it have only 0 and 255 levels. - self.assertEqual(i.tobytes(), src.tobytes()) - - def test_blur_accuracy(self): - - i = snakes.filter(ImageFilter.GaussianBlur(0.4)) - # These pixels surrounded with pixels with 255 intensity. - # They must be very close to 255. - for x, y, c in [ - (1, 0, 1), - (2, 0, 1), - (7, 8, 1), - (8, 8, 1), - (2, 9, 1), - (7, 3, 0), - (8, 3, 0), - (5, 8, 0), - (5, 9, 0), - (1, 3, 0), - (4, 3, 2), - (4, 2, 2), - ]: - self.assertGreaterEqual(i.im.getpixel((x, y))[c], 250) - # Fuzzy match. - - def gp(x, y): - return i.im.getpixel((x, y)) - - self.assertTrue(236 <= gp(7, 4)[0] <= 239) - self.assertTrue(236 <= gp(7, 5)[2] <= 239) - self.assertTrue(236 <= gp(7, 6)[2] <= 239) - self.assertTrue(236 <= gp(7, 7)[1] <= 239) - self.assertTrue(236 <= gp(8, 4)[0] <= 239) - self.assertTrue(236 <= gp(8, 5)[2] <= 239) - self.assertTrue(236 <= gp(8, 6)[2] <= 239) - self.assertTrue(236 <= gp(8, 7)[1] <= 239) diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py deleted file mode 100644 index 1297712ef50..00000000000 --- a/Tests/test_imagepalette.py +++ /dev/null @@ -1,136 +0,0 @@ -from PIL import Image, ImagePalette - -from .helper import PillowTestCase - - -class TestImagePalette(PillowTestCase): - def test_sanity(self): - - ImagePalette.ImagePalette("RGB", list(range(256)) * 3) - self.assertRaises( - ValueError, ImagePalette.ImagePalette, "RGB", list(range(256)) * 2 - ) - - def test_getcolor(self): - - palette = ImagePalette.ImagePalette() - - test_map = {} - for i in range(256): - test_map[palette.getcolor((i, i, i))] = i - - self.assertEqual(len(test_map), 256) - self.assertRaises(ValueError, palette.getcolor, (1, 2, 3)) - - # Test unknown color specifier - self.assertRaises(ValueError, palette.getcolor, "unknown") - - def test_file(self): - - palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3) - - f = self.tempfile("temp.lut") - - palette.save(f) - - p = ImagePalette.load(f) - - # load returns raw palette information - self.assertEqual(len(p[0]), 768) - self.assertEqual(p[1], "RGB") - - p = ImagePalette.raw(p[1], p[0]) - self.assertIsInstance(p, ImagePalette.ImagePalette) - self.assertEqual(p.palette, palette.tobytes()) - - def test_make_linear_lut(self): - # Arrange - black = 0 - white = 255 - - # Act - lut = ImagePalette.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 - black = 1 - white = 255 - - # Act - self.assertRaises( - NotImplementedError, ImagePalette.make_linear_lut, black, white - ) - - def test_make_gamma_lut(self): - # Arrange - exp = 5 - - # Act - lut = ImagePalette.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) - - def test_rawmode_valueerrors(self): - # Arrange - palette = ImagePalette.raw("RGB", list(range(256)) * 3) - - # Act / Assert - self.assertRaises(ValueError, palette.tobytes) - self.assertRaises(ValueError, palette.getcolor, (1, 2, 3)) - f = self.tempfile("temp.lut") - self.assertRaises(ValueError, palette.save, f) - - def test_getdata(self): - # Arrange - data_in = list(range(256)) * 3 - palette = ImagePalette.ImagePalette("RGB", data_in) - - # Act - mode, data_out = palette.getdata() - - # Assert - self.assertEqual(mode, "RGB;L") - - def test_rawmode_getdata(self): - # Arrange - data_in = list(range(256)) * 3 - palette = ImagePalette.raw("RGB", data_in) - - # Act - rawmode, data_out = palette.getdata() - - # Assert - self.assertEqual(rawmode, "RGB") - self.assertEqual(data_in, data_out) - - def test_2bit_palette(self): - # issue #2258, 2 bit palettes are corrupted. - outfile = self.tempfile("temp.png") - - rgb = b"\x00" * 2 + b"\x01" * 2 + b"\x02" * 2 - img = Image.frombytes("P", (6, 1), rgb) - img.putpalette(b"\xFF\x00\x00\x00\xFF\x00\x00\x00\xFF") # RGB - img.save(outfile, format="PNG") - - reloaded = Image.open(outfile) - - self.assert_image_equal(img, reloaded) - - def test_invalid_palette(self): - self.assertRaises(IOError, ImagePalette.load, "Tests/images/hopper.jpg") diff --git a/Tests/test_imagepath.py b/Tests/test_imagepath.py deleted file mode 100644 index ed65d47c1ce..00000000000 --- a/Tests/test_imagepath.py +++ /dev/null @@ -1,93 +0,0 @@ -import array -import struct - -from PIL import Image, ImagePath -from PIL._util import py3 - -from .helper import PillowTestCase - - -class TestImagePath(PillowTestCase): - def test_path(self): - - p = ImagePath.Path(list(range(10))) - - # sequence interface - self.assertEqual(len(p), 5) - self.assertEqual(p[0], (0.0, 1.0)) - self.assertEqual(p[-1], (8.0, 9.0)) - self.assertEqual(list(p[:1]), [(0.0, 1.0)]) - with self.assertRaises(TypeError) as cm: - p["foo"] - self.assertEqual(str(cm.exception), "Path indices must be integers, not str") - self.assertEqual( - list(p), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)] - ) - - # method sanity check - self.assertEqual( - p.tolist(), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0), (8.0, 9.0)] - ) - self.assertEqual( - p.tolist(1), [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] - ) - - self.assertEqual(p.getbbox(), (0.0, 1.0, 8.0, 9.0)) - - self.assertEqual(p.compact(5), 2) - self.assertEqual(list(p), [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)]) - - p.transform((1, 0, 1, 0, 1, 1)) - self.assertEqual(list(p), [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)]) - - # alternative constructors - p = ImagePath.Path([0, 1]) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path([0.0, 1.0]) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path([0, 1]) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path([(0, 1)]) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path(p) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path(p.tolist(0)) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path(p.tolist(1)) - self.assertEqual(list(p), [(0.0, 1.0)]) - p = ImagePath.Path(array.array("f", [0, 1])) - self.assertEqual(list(p), [(0.0, 1.0)]) - - arr = array.array("f", [0, 1]) - if hasattr(arr, "tobytes"): - p = ImagePath.Path(arr.tobytes()) - else: - p = ImagePath.Path(arr.tostring()) - self.assertEqual(list(p), [(0.0, 1.0)]) - - def test_overflow_segfault(self): - # Some Pythons fail getting the argument as an integer, and it falls - # through to the sequence. Seeing this on 32-bit Windows. - with self.assertRaises((TypeError, MemoryError)): - # post patch, this fails with a memory error - x = evil() - - # This fails due to the invalid malloc above, - # and segfaults - for i in range(200000): - if py3: - x[i] = b"0" * 16 - else: - x[i] = "0" * 16 - - -class evil: - def __init__(self): - self.corrupt = Image.core.path(0x4000000000000000) - - def __getitem__(self, i): - x = self.corrupt[i] - return struct.pack("dd", x[0], x[1]) - - def __setitem__(self, i, x): - self.corrupt[i] = struct.unpack("dd", x) diff --git a/Tests/test_imageqt.py b/Tests/test_imageqt.py deleted file mode 100644 index dc43e6bc7dc..00000000000 --- a/Tests/test_imageqt.py +++ /dev/null @@ -1,95 +0,0 @@ -import sys -import warnings - -from PIL import ImageQt - -from .helper import PillowTestCase, hopper - -if sys.version_info.major >= 3: - from importlib import reload - -if ImageQt.qt_is_installed: - from PIL.ImageQt import qRgba - - def skip_if_qt_is_not_installed(_): - pass - - -else: - - def skip_if_qt_is_not_installed(test_case): - test_case.skipTest("Qt bindings are not installed") - - -class PillowQtTestCase(object): - def setUp(self): - skip_if_qt_is_not_installed(self) - - def tearDown(self): - pass - - -class PillowQPixmapTestCase(PillowQtTestCase): - def setUp(self): - PillowQtTestCase.setUp(self) - try: - if ImageQt.qt_version == "5": - from PyQt5.QtGui import QGuiApplication - elif ImageQt.qt_version == "4": - from PyQt4.QtGui import QGuiApplication - elif ImageQt.qt_version == "side": - from PySide.QtGui import QGuiApplication - elif ImageQt.qt_version == "side2": - from PySide2.QtGui import QGuiApplication - except ImportError: - self.skipTest("QGuiApplication not installed") - - self.app = QGuiApplication([]) - - def tearDown(self): - PillowQtTestCase.tearDown(self) - self.app.quit() - - -class TestImageQt(PillowQtTestCase, PillowTestCase): - def test_rgb(self): - # from https://doc.qt.io/archives/qt-4.8/qcolor.html - # typedef QRgb - # An ARGB quadruplet on the format #AARRGGBB, - # equivalent to an unsigned int. - if ImageQt.qt_version == "5": - from PyQt5.QtGui import qRgb - elif ImageQt.qt_version == "4": - from PyQt4.QtGui import qRgb - elif ImageQt.qt_version == "side": - from PySide.QtGui import qRgb - elif ImageQt.qt_version == "side2": - from PySide2.QtGui import qRgb - - self.assertEqual(qRgb(0, 0, 0), qRgba(0, 0, 0, 255)) - - def checkrgb(r, g, b): - val = ImageQt.rgb(r, g, b) - val = val % 2 ** 24 # drop the alpha - self.assertEqual(val >> 16, r) - self.assertEqual(((val >> 8) % 2 ** 8), g) - self.assertEqual(val % 2 ** 8, b) - - checkrgb(0, 0, 0) - checkrgb(255, 0, 0) - checkrgb(0, 255, 0) - checkrgb(0, 0, 255) - - def test_image(self): - for mode in ("1", "RGB", "RGBA", "L", "P"): - ImageQt.ImageQt(hopper(mode)) - - def test_deprecated(self): - with warnings.catch_warnings(record=True) as w: - reload(ImageQt) - if ImageQt.qt_version in ["4", "side"]: - self.assertEqual(len(w), 1) - self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) - else: - # No warning. - self.assertEqual(w, []) diff --git a/Tests/test_imagesequence.py b/Tests/test_imagesequence.py deleted file mode 100644 index 1eea839da6c..00000000000 --- a/Tests/test_imagesequence.py +++ /dev/null @@ -1,98 +0,0 @@ -from PIL import Image, ImageSequence, TiffImagePlugin - -from .helper import PillowTestCase, hopper - - -class TestImageSequence(PillowTestCase): - def test_sanity(self): - - test_file = self.tempfile("temp.im") - - im = hopper("RGB") - im.save(test_file) - - seq = ImageSequence.Iterator(im) - - index = 0 - for frame in seq: - self.assert_image_equal(im, frame) - self.assertEqual(im.tell(), index) - index += 1 - - self.assertEqual(index, 1) - - self.assertRaises(AttributeError, ImageSequence.Iterator, 0) - - def test_iterator(self): - im = Image.open("Tests/images/multipage.tiff") - i = ImageSequence.Iterator(im) - for index in range(0, im.n_frames): - self.assertEqual(i[index], next(i)) - self.assertRaises(IndexError, lambda: i[index + 1]) - self.assertRaises(StopIteration, next, i) - - def test_iterator_min_frame(self): - im = Image.open("Tests/images/hopper.psd") - i = ImageSequence.Iterator(im) - for index in range(1, im.n_frames): - self.assertEqual(i[index], next(i)) - - def _test_multipage_tiff(self): - im = Image.open("Tests/images/multipage.tiff") - for index, frame in enumerate(ImageSequence.Iterator(im)): - frame.load() - self.assertEqual(index, im.tell()) - frame.convert("RGB") - - def test_tiff(self): - self._test_multipage_tiff() - - def test_libtiff(self): - codecs = dir(Image.core) - - if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs: - self.skipTest("tiff support not available") - - TiffImagePlugin.READ_LIBTIFF = True - self._test_multipage_tiff() - TiffImagePlugin.READ_LIBTIFF = False - - def test_consecutive(self): - im = Image.open("Tests/images/multipage.tiff") - firstFrame = None - for frame in ImageSequence.Iterator(im): - if firstFrame is None: - firstFrame = frame.copy() - for frame in ImageSequence.Iterator(im): - self.assert_image_equal(frame, firstFrame) - break - - def test_palette_mmap(self): - # Using mmap in ImageFile can require to reload the palette. - im = Image.open("Tests/images/multipage-mmap.tiff") - color1 = im.getpalette()[0:3] - im.seek(0) - color2 = im.getpalette()[0:3] - self.assertEqual(color1, color2) - - def test_all_frames(self): - # Test a single image - im = Image.open("Tests/images/iss634.gif") - ims = ImageSequence.all_frames(im) - - self.assertEqual(len(ims), 42) - for i, im_frame in enumerate(ims): - self.assertFalse(im_frame is im) - - im.seek(i) - self.assert_image_equal(im, im_frame) - - # Test a series of images - ims = ImageSequence.all_frames([im, hopper(), im]) - self.assertEqual(len(ims), 85) - - # Test an operation - ims = ImageSequence.all_frames(im, lambda im_frame: im_frame.rotate(90)) - for i, im_frame in enumerate(ims): - im.seek(i) - self.assert_image_equal(im.rotate(90), im_frame) diff --git a/Tests/test_imageshow.py b/Tests/test_imageshow.py deleted file mode 100644 index 378afe2db8a..00000000000 --- a/Tests/test_imageshow.py +++ /dev/null @@ -1,46 +0,0 @@ -from PIL import Image, ImageShow - -from .helper import PillowTestCase, hopper - - -class TestImageShow(PillowTestCase): - def test_sanity(self): - dir(Image) - dir(ImageShow) - - def test_register(self): - # Test registering a viewer that is not a class - ImageShow.register("not a class") - - # Restore original state - ImageShow._viewers.pop() - - def test_show(self): - class TestViewer(ImageShow.Viewer): - methodCalled = False - - def show_image(self, image, **options): - self.methodCalled = True - return True - - viewer = TestViewer() - ImageShow.register(viewer, -1) - - for mode in ("1", "I;16", "LA", "RGB", "RGBA"): - im = hopper(mode) - self.assertTrue(ImageShow.show(im)) - self.assertTrue(viewer.methodCalled) - - # Restore original state - ImageShow._viewers.pop(0) - - def test_viewer(self): - viewer = ImageShow.Viewer() - - self.assertIsNone(viewer.get_format(None)) - - self.assertRaises(NotImplementedError, viewer.get_command, None) - - def test_viewers(self): - for viewer in ImageShow._viewers: - viewer.get_command("test.jpg") diff --git a/Tests/test_imagestat.py b/Tests/test_imagestat.py deleted file mode 100644 index d6c6a7a5594..00000000000 --- a/Tests/test_imagestat.py +++ /dev/null @@ -1,55 +0,0 @@ -from PIL import Image, ImageStat - -from .helper import PillowTestCase, hopper - - -class TestImageStat(PillowTestCase): - def test_sanity(self): - - im = hopper() - - st = ImageStat.Stat(im) - st = ImageStat.Stat(im.histogram()) - st = ImageStat.Stat(im, Image.new("1", im.size, 1)) - - # Check these run. Exceptions will cause failures. - st.extrema - st.sum - st.mean - st.median - st.rms - st.sum2 - st.var - st.stddev - - self.assertRaises(AttributeError, lambda: st.spam) - - self.assertRaises(TypeError, ImageStat.Stat, 1) - - def test_hopper(self): - - im = hopper() - - st = ImageStat.Stat(im) - - # verify a few values - self.assertEqual(st.extrema[0], (0, 255)) - self.assertEqual(st.median[0], 72) - self.assertEqual(st.sum[0], 1470218) - self.assertEqual(st.sum[1], 1311896) - self.assertEqual(st.sum[2], 1563008) - - def test_constant(self): - - im = Image.new("L", (128, 128), 128) - - st = ImageStat.Stat(im) - - self.assertEqual(st.extrema[0], (128, 128)) - self.assertEqual(st.sum[0], 128 ** 3) - self.assertEqual(st.sum2[0], 128 ** 4) - self.assertEqual(st.mean[0], 128) - self.assertEqual(st.median[0], 128) - self.assertEqual(st.rms[0], 128) - self.assertEqual(st.var[0], 0) - self.assertEqual(st.stddev[0], 0) diff --git a/Tests/test_imagetk.py b/Tests/test_imagetk.py deleted file mode 100644 index c397c84beb9..00000000000 --- a/Tests/test_imagetk.py +++ /dev/null @@ -1,88 +0,0 @@ -from PIL import Image -from PIL._util import py3 - -from .helper import PillowTestCase, hopper, unittest - -try: - from PIL import ImageTk - - if py3: - import tkinter as tk - else: - import Tkinter as tk - dir(ImageTk) - HAS_TK = True -except (OSError, ImportError): - # Skipped via setUp() - HAS_TK = False - -TK_MODES = ("1", "L", "P", "RGB", "RGBA") - - -@unittest.skipIf(not HAS_TK, "Tk not installed") -class TestImageTk(PillowTestCase): - def setUp(self): - try: - # setup tk - tk.Frame() - # root = tk.Tk() - except tk.TclError as v: - self.skipTest("TCL Error: %s" % v) - - def test_kw(self): - TEST_JPG = "Tests/images/hopper.jpg" - TEST_PNG = "Tests/images/hopper.png" - im1 = Image.open(TEST_JPG) - im2 = Image.open(TEST_PNG) - with open(TEST_PNG, "rb") as fp: - data = fp.read() - kw = {"file": TEST_JPG, "data": data} - - # Test "file" - im = ImageTk._get_image_from_kw(kw) - self.assert_image_equal(im, im1) - - # Test "data" - im = ImageTk._get_image_from_kw(kw) - self.assert_image_equal(im, im2) - - # Test no relevant entry - im = ImageTk._get_image_from_kw(kw) - self.assertIsNone(im) - - def test_photoimage(self): - for mode in TK_MODES: - # test as image: - im = hopper(mode) - - # this should not crash - im_tk = ImageTk.PhotoImage(im) - - self.assertEqual(im_tk.width(), im.width) - self.assertEqual(im_tk.height(), im.height) - - reloaded = ImageTk.getimage(im_tk) - self.assert_image_equal(reloaded, im.convert("RGBA")) - - def test_photoimage_blank(self): - # test a image using mode/size: - for mode in TK_MODES: - im_tk = ImageTk.PhotoImage(mode, (100, 100)) - - self.assertEqual(im_tk.width(), 100) - self.assertEqual(im_tk.height(), 100) - - # reloaded = ImageTk.getimage(im_tk) - # self.assert_image_equal(reloaded, im) - - def test_bitmapimage(self): - im = hopper("1") - - # this should not crash - im_tk = ImageTk.BitmapImage(im) - - self.assertEqual(im_tk.width(), im.width) - self.assertEqual(im_tk.height(), im.height) - - # reloaded = ImageTk.getimage(im_tk) - # self.assert_image_equal(reloaded, im) diff --git a/Tests/test_imagewin.py b/Tests/test_imagewin.py deleted file mode 100644 index 92fcdc28d60..00000000000 --- a/Tests/test_imagewin.py +++ /dev/null @@ -1,107 +0,0 @@ -import sys - -from PIL import ImageWin - -from .helper import PillowTestCase, hopper, unittest - - -class TestImageWin(PillowTestCase): - def test_sanity(self): - dir(ImageWin) - - def test_hdc(self): - # Arrange - dc = 50 - - # Act - hdc = ImageWin.HDC(dc) - dc2 = int(hdc) - - # Assert - self.assertEqual(dc2, 50) - - def test_hwnd(self): - # Arrange - wnd = 50 - - # Act - hwnd = ImageWin.HWND(wnd) - wnd2 = int(hwnd) - - # Assert - self.assertEqual(wnd2, 50) - - -@unittest.skipUnless(sys.platform.startswith("win32"), "Windows only") -class TestImageWinDib(PillowTestCase): - def test_dib_image(self): - # Arrange - im = hopper() - - # Act - dib = ImageWin.Dib(im) - - # Assert - self.assertEqual(dib.size, im.size) - - def test_dib_mode_string(self): - # Arrange - mode = "RGBA" - size = (128, 128) - - # Act - dib = ImageWin.Dib(mode, size) - - # Assert - self.assertEqual(dib.size, (128, 128)) - - def test_dib_paste(self): - # Arrange - im = hopper() - - mode = "RGBA" - size = (128, 128) - dib = ImageWin.Dib(mode, size) - - # Act - dib.paste(im) - - # Assert - self.assertEqual(dib.size, (128, 128)) - - def test_dib_paste_bbox(self): - # Arrange - im = hopper() - bbox = (0, 0, 10, 10) - - mode = "RGBA" - size = (128, 128) - dib = ImageWin.Dib(mode, size) - - # Act - dib.paste(im, bbox) - - # Assert - self.assertEqual(dib.size, (128, 128)) - - def test_dib_frombytes_tobytes_roundtrip(self): - # Arrange - # Make two different DIB images - im = hopper() - dib1 = ImageWin.Dib(im) - - mode = "RGB" - size = (128, 128) - dib2 = ImageWin.Dib(mode, size) - - # Confirm they're different - self.assertNotEqual(dib1.tobytes(), dib2.tobytes()) - - # Act - # Make one the same as the using tobytes()/frombytes() - test_buffer = dib1.tobytes() - dib2.frombytes(test_buffer) - - # Assert - # Confirm they're the same - self.assertEqual(dib1.tobytes(), dib2.tobytes()) diff --git a/Tests/test_imagewin_pointers.py b/Tests/test_imagewin_pointers.py deleted file mode 100644 index efa3753b951..00000000000 --- a/Tests/test_imagewin_pointers.py +++ /dev/null @@ -1,115 +0,0 @@ -import ctypes -import sys -from io import BytesIO - -from PIL import Image, ImageWin - -from .helper import PillowTestCase, hopper - -# see https://github.com/python-pillow/Pillow/pull/1431#issuecomment-144692652 - -if sys.platform.startswith("win32"): - import ctypes.wintypes - - class BITMAPFILEHEADER(ctypes.Structure): - _pack_ = 2 - _fields_ = [ - ("bfType", ctypes.wintypes.WORD), - ("bfSize", ctypes.wintypes.DWORD), - ("bfReserved1", ctypes.wintypes.WORD), - ("bfReserved2", ctypes.wintypes.WORD), - ("bfOffBits", ctypes.wintypes.DWORD), - ] - - class BITMAPINFOHEADER(ctypes.Structure): - _pack_ = 2 - _fields_ = [ - ("biSize", ctypes.wintypes.DWORD), - ("biWidth", ctypes.wintypes.LONG), - ("biHeight", ctypes.wintypes.LONG), - ("biPlanes", ctypes.wintypes.WORD), - ("biBitCount", ctypes.wintypes.WORD), - ("biCompression", ctypes.wintypes.DWORD), - ("biSizeImage", ctypes.wintypes.DWORD), - ("biXPelsPerMeter", ctypes.wintypes.LONG), - ("biYPelsPerMeter", ctypes.wintypes.LONG), - ("biClrUsed", ctypes.wintypes.DWORD), - ("biClrImportant", ctypes.wintypes.DWORD), - ] - - BI_RGB = 0 - DIB_RGB_COLORS = 0 - - memcpy = ctypes.cdll.msvcrt.memcpy - memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t] - - CreateCompatibleDC = ctypes.windll.gdi32.CreateCompatibleDC - CreateCompatibleDC.argtypes = [ctypes.wintypes.HDC] - CreateCompatibleDC.restype = ctypes.wintypes.HDC - - DeleteDC = ctypes.windll.gdi32.DeleteDC - DeleteDC.argtypes = [ctypes.wintypes.HDC] - - SelectObject = ctypes.windll.gdi32.SelectObject - SelectObject.argtypes = [ctypes.wintypes.HDC, ctypes.wintypes.HGDIOBJ] - SelectObject.restype = ctypes.wintypes.HGDIOBJ - - DeleteObject = ctypes.windll.gdi32.DeleteObject - DeleteObject.argtypes = [ctypes.wintypes.HGDIOBJ] - - CreateDIBSection = ctypes.windll.gdi32.CreateDIBSection - CreateDIBSection.argtypes = [ - ctypes.wintypes.HDC, - ctypes.c_void_p, - ctypes.c_uint, - ctypes.POINTER(ctypes.c_void_p), - ctypes.wintypes.HANDLE, - ctypes.wintypes.DWORD, - ] - CreateDIBSection.restype = ctypes.wintypes.HBITMAP - - def serialize_dib(bi, pixels): - bf = BITMAPFILEHEADER() - bf.bfType = 0x4D42 - bf.bfOffBits = ctypes.sizeof(bf) + bi.biSize - bf.bfSize = bf.bfOffBits + bi.biSizeImage - bf.bfReserved1 = bf.bfReserved2 = 0 - - buf = (ctypes.c_byte * bf.bfSize)() - bp = ctypes.addressof(buf) - memcpy(bp, ctypes.byref(bf), ctypes.sizeof(bf)) - memcpy(bp + ctypes.sizeof(bf), ctypes.byref(bi), bi.biSize) - memcpy(bp + bf.bfOffBits, pixels, bi.biSizeImage) - return bytearray(buf) - - class TestImageWinPointers(PillowTestCase): - def test_pointer(self): - im = hopper() - (width, height) = im.size - opath = self.tempfile("temp.png") - imdib = ImageWin.Dib(im) - - hdr = BITMAPINFOHEADER() - hdr.biSize = ctypes.sizeof(hdr) - hdr.biWidth = width - hdr.biHeight = height - hdr.biPlanes = 1 - hdr.biBitCount = 32 - hdr.biCompression = BI_RGB - hdr.biSizeImage = width * height * 4 - hdr.biClrUsed = 0 - hdr.biClrImportant = 0 - - hdc = CreateCompatibleDC(None) - pixels = ctypes.c_void_p() - dib = CreateDIBSection( - hdc, ctypes.byref(hdr), DIB_RGB_COLORS, ctypes.byref(pixels), None, 0 - ) - SelectObject(hdc, dib) - - imdib.expose(hdc) - bitmap = serialize_dib(hdr, pixels) - DeleteObject(dib) - DeleteDC(hdc) - - Image.open(BytesIO(bitmap)).save(opath) diff --git a/Tests/test_lib_image.py b/Tests/test_lib_image.py deleted file mode 100644 index 68e72bc4e5c..00000000000 --- a/Tests/test_lib_image.py +++ /dev/null @@ -1,36 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, unittest - - -class TestLibImage(PillowTestCase): - def test_setmode(self): - - im = Image.new("L", (1, 1), 255) - im.im.setmode("1") - self.assertEqual(im.im.getpixel((0, 0)), 255) - im.im.setmode("L") - self.assertEqual(im.im.getpixel((0, 0)), 255) - - im = Image.new("1", (1, 1), 1) - im.im.setmode("L") - self.assertEqual(im.im.getpixel((0, 0)), 255) - im.im.setmode("1") - self.assertEqual(im.im.getpixel((0, 0)), 255) - - im = Image.new("RGB", (1, 1), (1, 2, 3)) - im.im.setmode("RGB") - self.assertEqual(im.im.getpixel((0, 0)), (1, 2, 3)) - im.im.setmode("RGBA") - self.assertEqual(im.im.getpixel((0, 0)), (1, 2, 3, 255)) - im.im.setmode("RGBX") - self.assertEqual(im.im.getpixel((0, 0)), (1, 2, 3, 255)) - im.im.setmode("RGB") - self.assertEqual(im.im.getpixel((0, 0)), (1, 2, 3)) - - self.assertRaises(ValueError, im.im.setmode, "L") - self.assertRaises(ValueError, im.im.setmode, "RGBABCDE") - - -if __name__ == "__main__": - unittest.main() diff --git a/Tests/test_lib_pack.py b/Tests/test_lib_pack.py deleted file mode 100644 index 6178184bc1d..00000000000 --- a/Tests/test_lib_pack.py +++ /dev/null @@ -1,718 +0,0 @@ -import sys - -from PIL import Image - -from .helper import PillowTestCase - -X = 255 - - -class TestLibPack(PillowTestCase): - def assert_pack(self, mode, rawmode, data, *pixels): - """ - data - either raw bytes with data or just number of bytes in rawmode. - """ - im = Image.new(mode, (len(pixels), 1)) - for x, pixel in enumerate(pixels): - im.putpixel((x, 0), pixel) - - if isinstance(data, int): - data_len = data * len(pixels) - data = bytes(bytearray(range(1, data_len + 1))) - - self.assertEqual(data, im.tobytes("raw", rawmode)) - - def test_1(self): - self.assert_pack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X) - self.assert_pack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0) - self.assert_pack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0) - self.assert_pack("1", "1;IR", b"\x01", 0, X, X, X, X, X, X, X) - - self.assert_pack("1", "1", b"\xaa", X, 0, X, 0, X, 0, X, 0) - self.assert_pack("1", "1;I", b"\xaa", 0, X, 0, X, 0, X, 0, X) - self.assert_pack("1", "1;R", b"\xaa", 0, X, 0, X, 0, X, 0, X) - self.assert_pack("1", "1;IR", b"\xaa", X, 0, X, 0, X, 0, X, 0) - - self.assert_pack("1", "L", b"\xff\x00\x00\xff\x00\x00", X, 0, 0, X, 0, 0) - - def test_L(self): - self.assert_pack("L", "L", 1, 1, 2, 3, 4) - self.assert_pack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175) - self.assert_pack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175) - - def test_LA(self): - self.assert_pack("LA", "LA", 2, (1, 2), (3, 4), (5, 6)) - self.assert_pack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6)) - - def test_P(self): - self.assert_pack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 255, 0, 0) - self.assert_pack("P", "P;2", b"\xe4", 3, 2, 1, 0) - self.assert_pack("P", "P;4", b"\x02\xef", 0, 2, 14, 15) - self.assert_pack("P", "P", 1, 1, 2, 3, 4) - - def test_PA(self): - self.assert_pack("PA", "PA", 2, (1, 2), (3, 4), (5, 6)) - self.assert_pack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6)) - - def test_RGB(self): - self.assert_pack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9)) - self.assert_pack( - "RGB", "RGBX", b"\x01\x02\x03\xff\x05\x06\x07\xff", (1, 2, 3), (5, 6, 7) - ) - self.assert_pack( - "RGB", "XRGB", b"\x00\x02\x03\x04\x00\x06\x07\x08", (2, 3, 4), (6, 7, 8) - ) - self.assert_pack("RGB", "BGR", 3, (3, 2, 1), (6, 5, 4), (9, 8, 7)) - self.assert_pack( - "RGB", "BGRX", b"\x01\x02\x03\x00\x05\x06\x07\x00", (3, 2, 1), (7, 6, 5) - ) - self.assert_pack( - "RGB", "XBGR", b"\x00\x02\x03\x04\x00\x06\x07\x08", (4, 3, 2), (8, 7, 6) - ) - self.assert_pack("RGB", "RGB;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9)) - self.assert_pack("RGB", "R", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9)) - self.assert_pack("RGB", "G", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9)) - self.assert_pack("RGB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3)) - - def test_RGBA(self): - self.assert_pack("RGBA", "RGBA", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)) - self.assert_pack( - "RGBA", "RGBA;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12) - ) - self.assert_pack("RGBA", "RGB", 3, (1, 2, 3, 14), (4, 5, 6, 15), (7, 8, 9, 16)) - self.assert_pack("RGBA", "BGR", 3, (3, 2, 1, 14), (6, 5, 4, 15), (9, 8, 7, 16)) - self.assert_pack("RGBA", "BGRA", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12)) - self.assert_pack("RGBA", "ABGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)) - self.assert_pack( - "RGBA", - "BGRa", - 4, - (191, 127, 63, 4), - (223, 191, 159, 8), - (233, 212, 191, 12), - ) - self.assert_pack("RGBA", "R", 1, (1, 0, 8, 9), (2, 0, 8, 9), (3, 0, 8, 0)) - self.assert_pack("RGBA", "G", 1, (6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9)) - self.assert_pack("RGBA", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9)) - self.assert_pack("RGBA", "A", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3)) - - def test_RGBa(self): - self.assert_pack("RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)) - self.assert_pack("RGBa", "BGRa", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12)) - self.assert_pack("RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)) - - def test_RGBX(self): - self.assert_pack("RGBX", "RGBX", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)) - self.assert_pack( - "RGBX", "RGBX;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12) - ) - self.assert_pack("RGBX", "RGB", 3, (1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X)) - self.assert_pack("RGBX", "BGR", 3, (3, 2, 1, X), (6, 5, 4, X), (9, 8, 7, X)) - self.assert_pack( - "RGBX", - "BGRX", - b"\x01\x02\x03\x00\x05\x06\x07\x00\t\n\x0b\x00", - (3, 2, 1, X), - (7, 6, 5, X), - (11, 10, 9, X), - ) - self.assert_pack( - "RGBX", - "XBGR", - b"\x00\x02\x03\x04\x00\x06\x07\x08\x00\n\x0b\x0c", - (4, 3, 2, X), - (8, 7, 6, X), - (12, 11, 10, X), - ) - self.assert_pack("RGBX", "R", 1, (1, 0, 8, 9), (2, 0, 8, 9), (3, 0, 8, 0)) - self.assert_pack("RGBX", "G", 1, (6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9)) - self.assert_pack("RGBX", "B", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9)) - self.assert_pack("RGBX", "X", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3)) - - def test_CMYK(self): - self.assert_pack("CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)) - self.assert_pack( - "CMYK", - "CMYK;I", - 4, - (254, 253, 252, 251), - (250, 249, 248, 247), - (246, 245, 244, 243), - ) - self.assert_pack( - "CMYK", "CMYK;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12) - ) - self.assert_pack("CMYK", "K", 1, (6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3)) - - def test_YCbCr(self): - self.assert_pack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9)) - self.assert_pack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9)) - self.assert_pack( - "YCbCr", - "YCbCrX", - b"\x01\x02\x03\xff\x05\x06\x07\xff\t\n\x0b\xff", - (1, 2, 3), - (5, 6, 7), - (9, 10, 11), - ) - self.assert_pack( - "YCbCr", - "YCbCrK", - b"\x01\x02\x03\xff\x05\x06\x07\xff\t\n\x0b\xff", - (1, 2, 3), - (5, 6, 7), - (9, 10, 11), - ) - self.assert_pack("YCbCr", "Y", 1, (1, 0, 8, 9), (2, 0, 8, 9), (3, 0, 8, 0)) - self.assert_pack("YCbCr", "Cb", 1, (6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9)) - self.assert_pack("YCbCr", "Cr", 1, (6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9)) - - def test_LAB(self): - self.assert_pack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137)) - self.assert_pack("LAB", "L", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9)) - self.assert_pack("LAB", "A", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9)) - self.assert_pack("LAB", "B", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3)) - - def test_HSV(self): - self.assert_pack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9)) - self.assert_pack("HSV", "H", 1, (1, 9, 9), (2, 9, 9), (3, 9, 9)) - self.assert_pack("HSV", "S", 1, (9, 1, 9), (9, 2, 9), (9, 3, 9)) - self.assert_pack("HSV", "V", 1, (9, 9, 1), (9, 9, 2), (9, 9, 3)) - - def test_I(self): - self.assert_pack("I", "I;16B", 2, 0x0102, 0x0304) - self.assert_pack( - "I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", 0x01000083, -2097151999 - ) - - if sys.byteorder == "little": - self.assert_pack("I", "I", 4, 0x04030201, 0x08070605) - self.assert_pack( - "I", - "I;32NS", - b"\x83\x00\x00\x01\x01\x00\x00\x83", - 0x01000083, - -2097151999, - ) - else: - self.assert_pack("I", "I", 4, 0x01020304, 0x05060708) - self.assert_pack( - "I", - "I;32NS", - b"\x83\x00\x00\x01\x01\x00\x00\x83", - -2097151999, - 0x01000083, - ) - - def test_F_float(self): - self.assert_pack("F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34) - - if sys.byteorder == "little": - self.assert_pack("F", "F", 4, 1.539989614439558e-36, 4.063216068939723e-34) - self.assert_pack( - "F", "F;32NF", 4, 1.539989614439558e-36, 4.063216068939723e-34 - ) - else: - self.assert_pack("F", "F", 4, 2.387939260590663e-38, 6.301941157072183e-36) - self.assert_pack( - "F", "F;32NF", 4, 2.387939260590663e-38, 6.301941157072183e-36 - ) - - -class TestLibUnpack(PillowTestCase): - def assert_unpack(self, mode, rawmode, data, *pixels): - """ - data - either raw bytes with data or just number of bytes in rawmode. - """ - if isinstance(data, int): - data_len = data * len(pixels) - data = bytes(bytearray(range(1, data_len + 1))) - - im = Image.frombytes(mode, (len(pixels), 1), data, "raw", rawmode, 0, 1) - - for x, pixel in enumerate(pixels): - self.assertEqual(pixel, im.getpixel((x, 0))) - - def test_1(self): - self.assert_unpack("1", "1", b"\x01", 0, 0, 0, 0, 0, 0, 0, X) - self.assert_unpack("1", "1;I", b"\x01", X, X, X, X, X, X, X, 0) - self.assert_unpack("1", "1;R", b"\x01", X, 0, 0, 0, 0, 0, 0, 0) - self.assert_unpack("1", "1;IR", b"\x01", 0, X, X, X, X, X, X, X) - - self.assert_unpack("1", "1", b"\xaa", X, 0, X, 0, X, 0, X, 0) - self.assert_unpack("1", "1;I", b"\xaa", 0, X, 0, X, 0, X, 0, X) - self.assert_unpack("1", "1;R", b"\xaa", 0, X, 0, X, 0, X, 0, X) - self.assert_unpack("1", "1;IR", b"\xaa", X, 0, X, 0, X, 0, X, 0) - - self.assert_unpack("1", "1;8", b"\x00\x01\x02\xff", 0, X, X, X) - - def test_L(self): - self.assert_unpack("L", "L;2", b"\xe4", 255, 170, 85, 0) - self.assert_unpack("L", "L;2I", b"\xe4", 0, 85, 170, 255) - self.assert_unpack("L", "L;2R", b"\xe4", 0, 170, 85, 255) - self.assert_unpack("L", "L;2IR", b"\xe4", 255, 85, 170, 0) - - self.assert_unpack("L", "L;4", b"\x02\xef", 0, 34, 238, 255) - self.assert_unpack("L", "L;4I", b"\x02\xef", 255, 221, 17, 0) - self.assert_unpack("L", "L;4R", b"\x02\xef", 68, 0, 255, 119) - self.assert_unpack("L", "L;4IR", b"\x02\xef", 187, 255, 0, 136) - - self.assert_unpack("L", "L", 1, 1, 2, 3, 4) - self.assert_unpack("L", "L;I", 1, 254, 253, 252, 251) - self.assert_unpack("L", "L;R", 1, 128, 64, 192, 32) - self.assert_unpack("L", "L;16", 2, 2, 4, 6, 8) - self.assert_unpack("L", "L;16B", 2, 1, 3, 5, 7) - self.assert_unpack("L", "L;16", b"\x00\xc6\x00\xaf", 198, 175) - self.assert_unpack("L", "L;16B", b"\xc6\x00\xaf\x00", 198, 175) - - def test_LA(self): - self.assert_unpack("LA", "LA", 2, (1, 2), (3, 4), (5, 6)) - self.assert_unpack("LA", "LA;L", 2, (1, 4), (2, 5), (3, 6)) - - def test_P(self): - self.assert_unpack("P", "P;1", b"\xe4", 1, 1, 1, 0, 0, 1, 0, 0) - self.assert_unpack("P", "P;2", b"\xe4", 3, 2, 1, 0) - # erroneous? - # self.assert_unpack("P", "P;2L", b'\xe4', 1, 1, 1, 0) - self.assert_unpack("P", "P;4", b"\x02\xef", 0, 2, 14, 15) - # erroneous? - # self.assert_unpack("P", "P;4L", b'\x02\xef', 2, 10, 10, 0) - self.assert_unpack("P", "P", 1, 1, 2, 3, 4) - self.assert_unpack("P", "P;R", 1, 128, 64, 192, 32) - - def test_PA(self): - self.assert_unpack("PA", "PA", 2, (1, 2), (3, 4), (5, 6)) - self.assert_unpack("PA", "PA;L", 2, (1, 4), (2, 5), (3, 6)) - - def test_RGB(self): - self.assert_unpack("RGB", "RGB", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9)) - self.assert_unpack("RGB", "RGB;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9)) - self.assert_unpack("RGB", "RGB;R", 3, (128, 64, 192), (32, 160, 96)) - self.assert_unpack("RGB", "RGB;16L", 6, (2, 4, 6), (8, 10, 12)) - self.assert_unpack("RGB", "RGB;16B", 6, (1, 3, 5), (7, 9, 11)) - self.assert_unpack("RGB", "BGR", 3, (3, 2, 1), (6, 5, 4), (9, 8, 7)) - self.assert_unpack("RGB", "RGB;15", 2, (8, 131, 0), (24, 0, 8)) - self.assert_unpack("RGB", "BGR;15", 2, (0, 131, 8), (8, 0, 24)) - self.assert_unpack("RGB", "RGB;16", 2, (8, 64, 0), (24, 129, 0)) - self.assert_unpack("RGB", "BGR;16", 2, (0, 64, 8), (0, 129, 24)) - self.assert_unpack("RGB", "RGB;4B", 2, (17, 0, 34), (51, 0, 68)) - self.assert_unpack("RGB", "RGBX", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11)) - self.assert_unpack("RGB", "RGBX;L", 4, (1, 4, 7), (2, 5, 8), (3, 6, 9)) - self.assert_unpack("RGB", "BGRX", 4, (3, 2, 1), (7, 6, 5), (11, 10, 9)) - self.assert_unpack("RGB", "XRGB", 4, (2, 3, 4), (6, 7, 8), (10, 11, 12)) - self.assert_unpack("RGB", "XBGR", 4, (4, 3, 2), (8, 7, 6), (12, 11, 10)) - self.assert_unpack( - "RGB", - "YCC;P", - b"D]\x9c\x82\x1a\x91\xfaOC\xe7J\x12", # random data - (127, 102, 0), - (192, 227, 0), - (213, 255, 170), - (98, 255, 133), - ) - self.assert_unpack("RGB", "R", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0)) - self.assert_unpack("RGB", "G", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0)) - self.assert_unpack("RGB", "B", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3)) - - def test_RGBA(self): - self.assert_unpack("RGBA", "LA", 2, (1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6)) - self.assert_unpack( - "RGBA", "LA;16B", 4, (1, 1, 1, 3), (5, 5, 5, 7), (9, 9, 9, 11) - ) - self.assert_unpack( - "RGBA", "RGBA", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12) - ) - self.assert_unpack( - "RGBA", "RGBAX", 5, (1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14) - ) - self.assert_unpack( - "RGBA", "RGBAXX", 6, (1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16) - ) - self.assert_unpack( - "RGBA", - "RGBa", - 4, - (63, 127, 191, 4), - (159, 191, 223, 8), - (191, 212, 233, 12), - ) - self.assert_unpack( - "RGBA", - "RGBa", - b"\x01\x02\x03\x00\x10\x20\x30\x7f\x10\x20\x30\xff", - (0, 0, 0, 0), - (32, 64, 96, 127), - (16, 32, 48, 255), - ) - self.assert_unpack( - "RGBA", - "RGBaX", - b"\x01\x02\x03\x00-\x10\x20\x30\x7f-\x10\x20\x30\xff-", - (0, 0, 0, 0), - (32, 64, 96, 127), - (16, 32, 48, 255), - ) - self.assert_unpack( - "RGBA", - "RGBaXX", - b"\x01\x02\x03\x00==\x10\x20\x30\x7f!!\x10\x20\x30\xff??", - (0, 0, 0, 0), - (32, 64, 96, 127), - (16, 32, 48, 255), - ) - self.assert_unpack( - "RGBA", - "RGBa;16L", - 8, - (63, 127, 191, 8), - (159, 191, 223, 16), - (191, 212, 233, 24), - ) - self.assert_unpack( - "RGBA", - "RGBa;16L", - b"\x88\x01\x88\x02\x88\x03\x88\x00" b"\x88\x10\x88\x20\x88\x30\x88\xff", - (0, 0, 0, 0), - (16, 32, 48, 255), - ) - self.assert_unpack( - "RGBA", - "RGBa;16B", - 8, - (36, 109, 182, 7), - (153, 187, 221, 15), - (188, 210, 232, 23), - ) - self.assert_unpack( - "RGBA", - "RGBa;16B", - b"\x01\x88\x02\x88\x03\x88\x00\x88" b"\x10\x88\x20\x88\x30\x88\xff\x88", - (0, 0, 0, 0), - (16, 32, 48, 255), - ) - self.assert_unpack( - "RGBA", - "BGRa", - 4, - (191, 127, 63, 4), - (223, 191, 159, 8), - (233, 212, 191, 12), - ) - self.assert_unpack( - "RGBA", - "BGRa", - b"\x01\x02\x03\x00\x10\x20\x30\xff", - (0, 0, 0, 0), - (48, 32, 16, 255), - ) - self.assert_unpack( - "RGBA", - "RGBA;I", - 4, - (254, 253, 252, 4), - (250, 249, 248, 8), - (246, 245, 244, 12), - ) - self.assert_unpack( - "RGBA", "RGBA;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12) - ) - self.assert_unpack("RGBA", "RGBA;15", 2, (8, 131, 0, 0), (24, 0, 8, 0)) - self.assert_unpack("RGBA", "BGRA;15", 2, (0, 131, 8, 0), (8, 0, 24, 0)) - self.assert_unpack("RGBA", "RGBA;4B", 2, (17, 0, 34, 0), (51, 0, 68, 0)) - self.assert_unpack("RGBA", "RGBA;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16)) - self.assert_unpack("RGBA", "RGBA;16B", 8, (1, 3, 5, 7), (9, 11, 13, 15)) - self.assert_unpack( - "RGBA", "BGRA", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12) - ) - self.assert_unpack( - "RGBA", "ARGB", 4, (2, 3, 4, 1), (6, 7, 8, 5), (10, 11, 12, 9) - ) - self.assert_unpack( - "RGBA", "ABGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9) - ) - self.assert_unpack( - "RGBA", - "YCCA;P", - b"]bE\x04\xdd\xbej\xed57T\xce\xac\xce:\x11", # random data - (0, 161, 0, 4), - (255, 255, 255, 237), - (27, 158, 0, 206), - (0, 118, 0, 17), - ) - self.assert_unpack("RGBA", "R", 1, (1, 0, 0, 0), (2, 0, 0, 0), (3, 0, 0, 0)) - self.assert_unpack("RGBA", "G", 1, (0, 1, 0, 0), (0, 2, 0, 0), (0, 3, 0, 0)) - self.assert_unpack("RGBA", "B", 1, (0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0)) - self.assert_unpack("RGBA", "A", 1, (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)) - - def test_RGBa(self): - self.assert_unpack( - "RGBa", "RGBa", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12) - ) - self.assert_unpack( - "RGBa", "BGRa", 4, (3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12) - ) - self.assert_unpack( - "RGBa", "aRGB", 4, (2, 3, 4, 1), (6, 7, 8, 5), (10, 11, 12, 9) - ) - self.assert_unpack( - "RGBa", "aBGR", 4, (4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9) - ) - - def test_RGBX(self): - self.assert_unpack("RGBX", "RGB", 3, (1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X)) - self.assert_unpack("RGBX", "RGB;L", 3, (1, 4, 7, X), (2, 5, 8, X), (3, 6, 9, X)) - self.assert_unpack("RGBX", "RGB;16B", 6, (1, 3, 5, X), (7, 9, 11, X)) - self.assert_unpack("RGBX", "BGR", 3, (3, 2, 1, X), (6, 5, 4, X), (9, 8, 7, X)) - self.assert_unpack("RGBX", "RGB;15", 2, (8, 131, 0, X), (24, 0, 8, X)) - self.assert_unpack("RGBX", "BGR;15", 2, (0, 131, 8, X), (8, 0, 24, X)) - self.assert_unpack("RGBX", "RGB;4B", 2, (17, 0, 34, X), (51, 0, 68, X)) - self.assert_unpack( - "RGBX", "RGBX", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12) - ) - self.assert_unpack( - "RGBX", "RGBXX", 5, (1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14) - ) - self.assert_unpack( - "RGBX", "RGBXXX", 6, (1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16) - ) - self.assert_unpack( - "RGBX", "RGBX;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12) - ) - self.assert_unpack("RGBX", "RGBX;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16)) - self.assert_unpack("RGBX", "RGBX;16B", 8, (1, 3, 5, 7), (9, 11, 13, 15)) - self.assert_unpack( - "RGBX", "BGRX", 4, (3, 2, 1, X), (7, 6, 5, X), (11, 10, 9, X) - ) - self.assert_unpack( - "RGBX", "XRGB", 4, (2, 3, 4, X), (6, 7, 8, X), (10, 11, 12, X) - ) - self.assert_unpack( - "RGBX", "XBGR", 4, (4, 3, 2, X), (8, 7, 6, X), (12, 11, 10, X) - ) - self.assert_unpack( - "RGBX", - "YCC;P", - b"D]\x9c\x82\x1a\x91\xfaOC\xe7J\x12", # random data - (127, 102, 0, X), - (192, 227, 0, X), - (213, 255, 170, X), - (98, 255, 133, X), - ) - self.assert_unpack("RGBX", "R", 1, (1, 0, 0, 0), (2, 0, 0, 0), (3, 0, 0, 0)) - self.assert_unpack("RGBX", "G", 1, (0, 1, 0, 0), (0, 2, 0, 0), (0, 3, 0, 0)) - self.assert_unpack("RGBX", "B", 1, (0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0)) - self.assert_unpack("RGBX", "X", 1, (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)) - - def test_CMYK(self): - self.assert_unpack( - "CMYK", "CMYK", 4, (1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12) - ) - self.assert_unpack( - "CMYK", "CMYKX", 5, (1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14) - ) - self.assert_unpack( - "CMYK", "CMYKXX", 6, (1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16) - ) - self.assert_unpack( - "CMYK", - "CMYK;I", - 4, - (254, 253, 252, 251), - (250, 249, 248, 247), - (246, 245, 244, 243), - ) - self.assert_unpack( - "CMYK", "CMYK;L", 4, (1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12) - ) - self.assert_unpack("CMYK", "C", 1, (1, 0, 0, 0), (2, 0, 0, 0), (3, 0, 0, 0)) - self.assert_unpack("CMYK", "M", 1, (0, 1, 0, 0), (0, 2, 0, 0), (0, 3, 0, 0)) - self.assert_unpack("CMYK", "Y", 1, (0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0)) - self.assert_unpack("CMYK", "K", 1, (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)) - self.assert_unpack( - "CMYK", "C;I", 1, (254, 0, 0, 0), (253, 0, 0, 0), (252, 0, 0, 0) - ) - self.assert_unpack( - "CMYK", "M;I", 1, (0, 254, 0, 0), (0, 253, 0, 0), (0, 252, 0, 0) - ) - self.assert_unpack( - "CMYK", "Y;I", 1, (0, 0, 254, 0), (0, 0, 253, 0), (0, 0, 252, 0) - ) - self.assert_unpack( - "CMYK", "K;I", 1, (0, 0, 0, 254), (0, 0, 0, 253), (0, 0, 0, 252) - ) - - def test_YCbCr(self): - self.assert_unpack("YCbCr", "YCbCr", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9)) - self.assert_unpack("YCbCr", "YCbCr;L", 3, (1, 4, 7), (2, 5, 8), (3, 6, 9)) - self.assert_unpack("YCbCr", "YCbCrK", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11)) - self.assert_unpack("YCbCr", "YCbCrX", 4, (1, 2, 3), (5, 6, 7), (9, 10, 11)) - - def test_LAB(self): - self.assert_unpack("LAB", "LAB", 3, (1, 130, 131), (4, 133, 134), (7, 136, 137)) - self.assert_unpack("LAB", "L", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0)) - self.assert_unpack("LAB", "A", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0)) - self.assert_unpack("LAB", "B", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3)) - - def test_HSV(self): - self.assert_unpack("HSV", "HSV", 3, (1, 2, 3), (4, 5, 6), (7, 8, 9)) - self.assert_unpack("HSV", "H", 1, (1, 0, 0), (2, 0, 0), (3, 0, 0)) - self.assert_unpack("HSV", "S", 1, (0, 1, 0), (0, 2, 0), (0, 3, 0)) - self.assert_unpack("HSV", "V", 1, (0, 0, 1), (0, 0, 2), (0, 0, 3)) - - def test_I(self): - self.assert_unpack("I", "I;8", 1, 0x01, 0x02, 0x03, 0x04) - self.assert_unpack("I", "I;8S", b"\x01\x83", 1, -125) - self.assert_unpack("I", "I;16", 2, 0x0201, 0x0403) - self.assert_unpack("I", "I;16S", b"\x83\x01\x01\x83", 0x0183, -31999) - self.assert_unpack("I", "I;16B", 2, 0x0102, 0x0304) - self.assert_unpack("I", "I;16BS", b"\x83\x01\x01\x83", -31999, 0x0183) - self.assert_unpack("I", "I;32", 4, 0x04030201, 0x08070605) - self.assert_unpack( - "I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", 0x01000083, -2097151999 - ) - self.assert_unpack("I", "I;32B", 4, 0x01020304, 0x05060708) - self.assert_unpack( - "I", "I;32BS", b"\x83\x00\x00\x01\x01\x00\x00\x83", -2097151999, 0x01000083 - ) - - if sys.byteorder == "little": - self.assert_unpack("I", "I", 4, 0x04030201, 0x08070605) - self.assert_unpack("I", "I;16N", 2, 0x0201, 0x0403) - self.assert_unpack("I", "I;16NS", b"\x83\x01\x01\x83", 0x0183, -31999) - self.assert_unpack("I", "I;32N", 4, 0x04030201, 0x08070605) - self.assert_unpack( - "I", - "I;32NS", - b"\x83\x00\x00\x01\x01\x00\x00\x83", - 0x01000083, - -2097151999, - ) - else: - self.assert_unpack("I", "I", 4, 0x01020304, 0x05060708) - self.assert_unpack("I", "I;16N", 2, 0x0102, 0x0304) - self.assert_unpack("I", "I;16NS", b"\x83\x01\x01\x83", -31999, 0x0183) - self.assert_unpack("I", "I;32N", 4, 0x01020304, 0x05060708) - self.assert_unpack( - "I", - "I;32NS", - b"\x83\x00\x00\x01\x01\x00\x00\x83", - -2097151999, - 0x01000083, - ) - - def test_F_int(self): - self.assert_unpack("F", "F;8", 1, 0x01, 0x02, 0x03, 0x04) - self.assert_unpack("F", "F;8S", b"\x01\x83", 1, -125) - self.assert_unpack("F", "F;16", 2, 0x0201, 0x0403) - self.assert_unpack("F", "F;16S", b"\x83\x01\x01\x83", 0x0183, -31999) - self.assert_unpack("F", "F;16B", 2, 0x0102, 0x0304) - self.assert_unpack("F", "F;16BS", b"\x83\x01\x01\x83", -31999, 0x0183) - self.assert_unpack("F", "F;32", 4, 67305984, 134678016) - self.assert_unpack( - "F", "F;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", 16777348, -2097152000 - ) - self.assert_unpack("F", "F;32B", 4, 0x01020304, 0x05060708) - self.assert_unpack( - "F", "F;32BS", b"\x83\x00\x00\x01\x01\x00\x00\x83", -2097152000, 16777348 - ) - - if sys.byteorder == "little": - self.assert_unpack("F", "F;16N", 2, 0x0201, 0x0403) - self.assert_unpack("F", "F;16NS", b"\x83\x01\x01\x83", 0x0183, -31999) - self.assert_unpack("F", "F;32N", 4, 67305984, 134678016) - self.assert_unpack( - "F", - "F;32NS", - b"\x83\x00\x00\x01\x01\x00\x00\x83", - 16777348, - -2097152000, - ) - else: - self.assert_unpack("F", "F;16N", 2, 0x0102, 0x0304) - self.assert_unpack("F", "F;16NS", b"\x83\x01\x01\x83", -31999, 0x0183) - self.assert_unpack("F", "F;32N", 4, 0x01020304, 0x05060708) - self.assert_unpack( - "F", - "F;32NS", - b"\x83\x00\x00\x01\x01\x00\x00\x83", - -2097152000, - 16777348, - ) - - def test_F_float(self): - self.assert_unpack( - "F", "F;32F", 4, 1.539989614439558e-36, 4.063216068939723e-34 - ) - self.assert_unpack( - "F", "F;32BF", 4, 2.387939260590663e-38, 6.301941157072183e-36 - ) - self.assert_unpack( - "F", - "F;64F", - b"333333\xc3?\x00\x00\x00\x00\x00J\x93\xc0", # by struct.pack - 0.15000000596046448, - -1234.5, - ) - self.assert_unpack( - "F", - "F;64BF", - b"?\xc3333333\xc0\x93J\x00\x00\x00\x00\x00", # by struct.pack - 0.15000000596046448, - -1234.5, - ) - - if sys.byteorder == "little": - self.assert_unpack( - "F", "F", 4, 1.539989614439558e-36, 4.063216068939723e-34 - ) - self.assert_unpack( - "F", "F;32NF", 4, 1.539989614439558e-36, 4.063216068939723e-34 - ) - self.assert_unpack( - "F", - "F;64NF", - b"333333\xc3?\x00\x00\x00\x00\x00J\x93\xc0", - 0.15000000596046448, - -1234.5, - ) - else: - self.assert_unpack( - "F", "F", 4, 2.387939260590663e-38, 6.301941157072183e-36 - ) - self.assert_unpack( - "F", "F;32NF", 4, 2.387939260590663e-38, 6.301941157072183e-36 - ) - self.assert_unpack( - "F", - "F;64NF", - b"?\xc3333333\xc0\x93J\x00\x00\x00\x00\x00", - 0.15000000596046448, - -1234.5, - ) - - def test_I16(self): - self.assert_unpack("I;16", "I;16", 2, 0x0201, 0x0403, 0x0605) - self.assert_unpack("I;16B", "I;16B", 2, 0x0102, 0x0304, 0x0506) - self.assert_unpack("I;16L", "I;16L", 2, 0x0201, 0x0403, 0x0605) - self.assert_unpack("I;16", "I;12", 2, 0x0010, 0x0203, 0x0040) - if sys.byteorder == "little": - self.assert_unpack("I;16", "I;16N", 2, 0x0201, 0x0403, 0x0605) - self.assert_unpack("I;16B", "I;16N", 2, 0x0201, 0x0403, 0x0605) - self.assert_unpack("I;16L", "I;16N", 2, 0x0201, 0x0403, 0x0605) - else: - self.assert_unpack("I;16", "I;16N", 2, 0x0102, 0x0304, 0x0506) - self.assert_unpack("I;16B", "I;16N", 2, 0x0102, 0x0304, 0x0506) - self.assert_unpack("I;16L", "I;16N", 2, 0x0102, 0x0304, 0x0506) - - def test_CMYK16(self): - self.assert_unpack("CMYK", "CMYK;16L", 8, (2, 4, 6, 8), (10, 12, 14, 16)) - self.assert_unpack("CMYK", "CMYK;16B", 8, (1, 3, 5, 7), (9, 11, 13, 15)) - if sys.byteorder == "little": - self.assert_unpack("CMYK", "CMYK;16N", 8, (2, 4, 6, 8), (10, 12, 14, 16)) - else: - self.assert_unpack("CMYK", "CMYK;16N", 8, (1, 3, 5, 7), (9, 11, 13, 15)) - - def test_value_error(self): - self.assertRaises(ValueError, self.assert_unpack, "L", "L", 0, 0) - self.assertRaises(ValueError, self.assert_unpack, "RGB", "RGB", 2, 0) - self.assertRaises(ValueError, self.assert_unpack, "CMYK", "CMYK", 2, 0) diff --git a/Tests/test_locale.py b/Tests/test_locale.py deleted file mode 100644 index 86229dbcb0b..00000000000 --- a/Tests/test_locale.py +++ /dev/null @@ -1,34 +0,0 @@ -from __future__ import print_function - -import locale - -from PIL import Image - -from .helper import PillowTestCase, unittest - -# ref https://github.com/python-pillow/Pillow/issues/272 -# on windows, in polish locale: - -# import locale -# print(locale.setlocale(locale.LC_ALL, 'polish')) -# import string -# print(len(string.whitespace)) -# print(ord(string.whitespace[6])) - -# Polish_Poland.1250 -# 7 -# 160 - -# one of string.whitespace is not freely convertable into ascii. - -path = "Tests/images/hopper.jpg" - - -class TestLocale(PillowTestCase): - def test_sanity(self): - Image.open(path) - try: - locale.setlocale(locale.LC_ALL, "polish") - except locale.Error: - unittest.skip("Polish locale not available") - Image.open(path) diff --git a/Tests/test_main.py b/Tests/test_main.py deleted file mode 100644 index 847def83423..00000000000 --- a/Tests/test_main.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import unicode_literals - -import os -import subprocess -import sys -from unittest import TestCase - - -class TestMain(TestCase): - def test_main(self): - out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8") - lines = out.splitlines() - self.assertEqual(lines[0], "-" * 68) - self.assertTrue(lines[1].startswith("Pillow ")) - self.assertEqual(lines[2], "-" * 68) - self.assertTrue(lines[3].startswith("Python modules loaded from ")) - self.assertTrue(lines[4].startswith("Binary modules loaded from ")) - self.assertEqual(lines[5], "-" * 68) - self.assertTrue(lines[6].startswith("Python ")) - jpeg = ( - os.linesep - + "-" * 68 - + os.linesep - + "JPEG image/jpeg" - + os.linesep - + "Extensions: .jfif, .jpe, .jpeg, .jpg" - + os.linesep - + "Features: open, save" - + os.linesep - + "-" * 68 - + os.linesep - ) - self.assertIn(jpeg, out) diff --git a/Tests/test_map.py b/Tests/test_map.py deleted file mode 100644 index 3fc42651b30..00000000000 --- a/Tests/test_map.py +++ /dev/null @@ -1,37 +0,0 @@ -import sys - -from PIL import Image - -from .helper import PillowTestCase, unittest - -try: - import numpy -except ImportError: - numpy = None - - -@unittest.skipIf(sys.platform.startswith("win32"), "Win32 does not call map_buffer") -class TestMap(PillowTestCase): - def test_overflow(self): - # There is the potential to overflow comparisons in map.c - # if there are > SIZE_MAX bytes in the image or if - # the file encodes an offset that makes - # (offset + size(bytes)) > SIZE_MAX - - # Note that this image triggers the decompression bomb warning: - max_pixels = Image.MAX_IMAGE_PIXELS - Image.MAX_IMAGE_PIXELS = None - - # This image hits the offset test. - im = Image.open("Tests/images/l2rgb_read.bmp") - with self.assertRaises((ValueError, MemoryError, IOError)): - im.load() - - Image.MAX_IMAGE_PIXELS = max_pixels - - @unittest.skipIf(sys.maxsize <= 2 ** 32, "requires 64-bit system") - @unittest.skipIf(numpy is None, "Numpy is not installed") - def test_ysize(self): - # Should not raise 'Integer overflow in ysize' - arr = numpy.zeros((46341, 46341), dtype=numpy.uint8) - Image.fromarray(arr) diff --git a/Tests/test_mode_i16.py b/Tests/test_mode_i16.py deleted file mode 100644 index b1cf2a23395..00000000000 --- a/Tests/test_mode_i16.py +++ /dev/null @@ -1,107 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase, hopper - - -class TestModeI16(PillowTestCase): - - original = hopper().resize((32, 32)).convert("I") - - def verify(self, im1): - im2 = self.original.copy() - self.assertEqual(im1.size, im2.size) - pix1 = im1.load() - pix2 = im2.load() - for y in range(im1.size[1]): - for x in range(im1.size[0]): - xy = x, y - p1 = pix1[xy] - p2 = pix2[xy] - self.assertEqual( - p1, - p2, - ("got %r from mode %s at %s, expected %r" % (p1, im1.mode, xy, p2)), - ) - - def test_basic(self): - # PIL 1.1 has limited support for 16-bit image data. Check that - # create/copy/transform and save works as expected. - - def basic(mode): - - imIn = self.original.convert(mode) - self.verify(imIn) - - w, h = imIn.size - - imOut = imIn.copy() - self.verify(imOut) # copy - - imOut = imIn.transform((w, h), Image.EXTENT, (0, 0, w, h)) - self.verify(imOut) # transform - - filename = self.tempfile("temp.im") - imIn.save(filename) - - imOut = Image.open(filename) - - self.verify(imIn) - self.verify(imOut) - - imOut = imIn.crop((0, 0, w, h)) - self.verify(imOut) - - imOut = Image.new(mode, (w, h), None) - imOut.paste(imIn.crop((0, 0, w // 2, h)), (0, 0)) - imOut.paste(imIn.crop((w // 2, 0, w, h)), (w // 2, 0)) - - self.verify(imIn) - self.verify(imOut) - - imIn = Image.new(mode, (1, 1), 1) - self.assertEqual(imIn.getpixel((0, 0)), 1) - - imIn.putpixel((0, 0), 2) - self.assertEqual(imIn.getpixel((0, 0)), 2) - - if mode == "L": - maximum = 255 - else: - maximum = 32767 - - imIn = Image.new(mode, (1, 1), 256) - self.assertEqual(imIn.getpixel((0, 0)), min(256, maximum)) - - imIn.putpixel((0, 0), 512) - self.assertEqual(imIn.getpixel((0, 0)), min(512, maximum)) - - basic("L") - - basic("I;16") - basic("I;16B") - basic("I;16L") - - basic("I") - - def test_tobytes(self): - def tobytes(mode): - return Image.new(mode, (1, 1), 1).tobytes() - - order = 1 if Image._ENDIAN == "<" else -1 - - self.assertEqual(tobytes("L"), b"\x01") - self.assertEqual(tobytes("I;16"), b"\x01\x00") - self.assertEqual(tobytes("I;16B"), b"\x00\x01") - self.assertEqual(tobytes("I"), b"\x01\x00\x00\x00"[::order]) - - def test_convert(self): - - im = self.original.copy() - - self.verify(im.convert("I;16")) - self.verify(im.convert("I;16").convert("L")) - self.verify(im.convert("I;16").convert("I")) - - self.verify(im.convert("I;16B")) - self.verify(im.convert("I;16B").convert("L")) - self.verify(im.convert("I;16B").convert("I")) diff --git a/Tests/test_numpy.py b/Tests/test_numpy.py deleted file mode 100644 index 872ecdbb600..00000000000 --- a/Tests/test_numpy.py +++ /dev/null @@ -1,223 +0,0 @@ -from __future__ import print_function - -from PIL import Image - -from .helper import PillowTestCase, hopper, unittest - -try: - import numpy -except ImportError: - numpy = None - - -TEST_IMAGE_SIZE = (10, 10) - - -@unittest.skipIf(numpy is None, "Numpy is not installed") -class TestNumpy(PillowTestCase): - def test_numpy_to_image(self): - def to_image(dtype, bands=1, boolean=0): - if bands == 1: - if boolean: - data = [0, 255] * 50 - else: - data = list(range(100)) - a = numpy.array(data, dtype=dtype) - a.shape = TEST_IMAGE_SIZE - i = Image.fromarray(a) - if list(i.getdata()) != data: - print("data mismatch for", dtype) - else: - data = list(range(100)) - a = numpy.array([[x] * bands for x in data], dtype=dtype) - a.shape = TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], bands - i = Image.fromarray(a) - if list(i.getchannel(0).getdata()) != list(range(100)): - print("data mismatch for", dtype) - return i - - # Check supported 1-bit integer formats - self.assert_image(to_image(numpy.bool, 1, 1), "1", TEST_IMAGE_SIZE) - self.assert_image(to_image(numpy.bool8, 1, 1), "1", TEST_IMAGE_SIZE) - - # Check supported 8-bit integer formats - self.assert_image(to_image(numpy.uint8), "L", TEST_IMAGE_SIZE) - self.assert_image(to_image(numpy.uint8, 3), "RGB", TEST_IMAGE_SIZE) - self.assert_image(to_image(numpy.uint8, 4), "RGBA", TEST_IMAGE_SIZE) - self.assert_image(to_image(numpy.int8), "I", TEST_IMAGE_SIZE) - - # Check non-fixed-size integer types - # These may fail, depending on the platform, since we have no native - # 64 bit int image types. - # self.assert_image(to_image(numpy.uint), "I", TEST_IMAGE_SIZE) - # self.assert_image(to_image(numpy.int), "I", TEST_IMAGE_SIZE) - - # Check 16-bit integer formats - if Image._ENDIAN == "<": - self.assert_image(to_image(numpy.uint16), "I;16", TEST_IMAGE_SIZE) - else: - self.assert_image(to_image(numpy.uint16), "I;16B", TEST_IMAGE_SIZE) - - self.assert_image(to_image(numpy.int16), "I", TEST_IMAGE_SIZE) - - # Check 32-bit integer formats - self.assert_image(to_image(numpy.uint32), "I", TEST_IMAGE_SIZE) - self.assert_image(to_image(numpy.int32), "I", TEST_IMAGE_SIZE) - - # Check 64-bit integer formats - self.assertRaises(TypeError, to_image, numpy.uint64) - self.assertRaises(TypeError, to_image, numpy.int64) - - # Check floating-point formats - self.assert_image(to_image(numpy.float), "F", TEST_IMAGE_SIZE) - self.assertRaises(TypeError, to_image, numpy.float16) - self.assert_image(to_image(numpy.float32), "F", TEST_IMAGE_SIZE) - self.assert_image(to_image(numpy.float64), "F", TEST_IMAGE_SIZE) - - self.assert_image(to_image(numpy.uint8, 2), "LA", (10, 10)) - self.assert_image(to_image(numpy.uint8, 3), "RGB", (10, 10)) - self.assert_image(to_image(numpy.uint8, 4), "RGBA", (10, 10)) - - # based on an erring example at - # https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function - def test_3d_array(self): - size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1]) - a = numpy.ones(size, dtype=numpy.uint8) - self.assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE) - size = (TEST_IMAGE_SIZE[0], 5, TEST_IMAGE_SIZE[1]) - a = numpy.ones(size, dtype=numpy.uint8) - self.assert_image(Image.fromarray(a[:, 1, :]), "L", TEST_IMAGE_SIZE) - size = (TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1], 5) - a = numpy.ones(size, dtype=numpy.uint8) - self.assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE) - - def _test_img_equals_nparray(self, img, np): - self.assertGreaterEqual(len(np.shape), 2) - np_size = np.shape[1], np.shape[0] - self.assertEqual(img.size, np_size) - px = img.load() - for x in range(0, img.size[0], int(img.size[0] / 10)): - for y in range(0, img.size[1], int(img.size[1] / 10)): - self.assert_deep_equal(px[x, y], np[y, x]) - - def test_16bit(self): - img = Image.open("Tests/images/16bit.cropped.tif") - np_img = numpy.array(img) - self._test_img_equals_nparray(img, np_img) - self.assertEqual(np_img.dtype, numpy.dtype("u2"), - ("I;16L", "", 0), (b"\x90\x1F\xA3", 8)) - self.assertEqual( - PdfParser.get_value(b"asd < 9 0 1 f A > qwe", 3), (b"\x90\x1F\xA0", 17) - ) - self.assertEqual(PdfParser.get_value(b"(asd)", 0), (b"asd", 5)) - self.assertEqual( - PdfParser.get_value(b"(asd(qwe)zxc)zzz(aaa)", 0), (b"asd(qwe)zxc", 13) - ) - self.assertEqual( - PdfParser.get_value(b"(Two \\\nwords.)", 0), (b"Two words.", 14) - ) - self.assertEqual(PdfParser.get_value(b"(Two\nlines.)", 0), (b"Two\nlines.", 12)) - self.assertEqual( - PdfParser.get_value(b"(Two\r\nlines.)", 0), (b"Two\nlines.", 13) - ) - self.assertEqual( - PdfParser.get_value(b"(Two\\nlines.)", 0), (b"Two\nlines.", 13) - ) - self.assertEqual(PdfParser.get_value(b"(One\\(paren).", 0), (b"One(paren", 12)) - self.assertEqual(PdfParser.get_value(b"(One\\)paren).", 0), (b"One)paren", 12)) - self.assertEqual(PdfParser.get_value(b"(\\0053)", 0), (b"\x053", 7)) - self.assertEqual(PdfParser.get_value(b"(\\053)", 0), (b"\x2B", 6)) - self.assertEqual(PdfParser.get_value(b"(\\53)", 0), (b"\x2B", 5)) - self.assertEqual(PdfParser.get_value(b"(\\53a)", 0), (b"\x2Ba", 6)) - self.assertEqual(PdfParser.get_value(b"(\\1111)", 0), (b"\x491", 7)) - self.assertEqual(PdfParser.get_value(b" 123 (", 0), (123, 4)) - self.assertAlmostEqual(PdfParser.get_value(b" 123.4 %", 0)[0], 123.4) - self.assertEqual(PdfParser.get_value(b" 123.4 %", 0)[1], 6) - self.assertRaises(PdfFormatError, PdfParser.get_value, b"]", 0) - d = PdfParser.get_value(b"<>", 0)[0] - self.assertIsInstance(d, PdfDict) - self.assertEqual(len(d), 2) - self.assertEqual(d.Name, "value") - self.assertEqual(d[b"Name"], b"value") - self.assertEqual(d.N, PdfName("V")) - a = PdfParser.get_value(b"[/Name (value) /N /V]", 0)[0] - self.assertIsInstance(a, list) - self.assertEqual(len(a), 4) - self.assertEqual(a[0], PdfName("Name")) - s = PdfParser.get_value( - b"<>\nstream\nabcde\nendstream<<...", 0 - )[0] - self.assertIsInstance(s, PdfStream) - self.assertEqual(s.dictionary.Name, "value") - self.assertEqual(s.decode(), b"abcde") - for name in ["CreationDate", "ModDate"]: - for date, value in { - b"20180729214124": "20180729214124", - b"D:20180729214124": "20180729214124", - b"D:2018072921": "20180729210000", - b"D:20180729214124Z": "20180729214124", - b"D:20180729214124+08'00'": "20180729134124", - b"D:20180729214124-05'00'": "20180730024124", - }.items(): - d = PdfParser.get_value( - b"<>", 0 - )[0] - self.assertEqual(time.strftime("%Y%m%d%H%M%S", getattr(d, name)), value) - - def test_pdf_repr(self): - self.assertEqual(bytes(IndirectReference(1, 2)), b"1 2 R") - self.assertEqual(bytes(IndirectObjectDef(*IndirectReference(1, 2))), b"1 2 obj") - self.assertEqual(bytes(PdfName(b"Name#Hash")), b"/Name#23Hash") - self.assertEqual(bytes(PdfName("Name#Hash")), b"/Name#23Hash") - self.assertEqual( - bytes(PdfDict({b"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" - ) - self.assertEqual( - bytes(PdfDict({"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" - ) - self.assertEqual(pdf_repr(IndirectReference(1, 2)), b"1 2 R") - self.assertEqual( - pdf_repr(IndirectObjectDef(*IndirectReference(1, 2))), b"1 2 obj" - ) - self.assertEqual(pdf_repr(PdfName(b"Name#Hash")), b"/Name#23Hash") - self.assertEqual(pdf_repr(PdfName("Name#Hash")), b"/Name#23Hash") - self.assertEqual( - pdf_repr(PdfDict({b"Name": IndirectReference(1, 2)})), - b"<<\n/Name 1 2 R\n>>", - ) - self.assertEqual( - pdf_repr(PdfDict({"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" - ) - self.assertEqual(pdf_repr(123), b"123") - self.assertEqual(pdf_repr(True), b"true") - self.assertEqual(pdf_repr(False), b"false") - self.assertEqual(pdf_repr(None), b"null") - self.assertEqual(pdf_repr(b"a)/b\\(c"), br"(a\)/b\\\(c)") - self.assertEqual( - pdf_repr([123, True, {"a": PdfName(b"b")}]), b"[ 123 true <<\n/a /b\n>> ]" - ) - self.assertEqual(pdf_repr(PdfBinary(b"\x90\x1F\xA0")), b"<901FA0>") diff --git a/Tests/test_pickle.py b/Tests/test_pickle.py deleted file mode 100644 index 42f47f169ab..00000000000 --- a/Tests/test_pickle.py +++ /dev/null @@ -1,125 +0,0 @@ -from PIL import Image - -from .helper import PillowTestCase - - -class TestPickle(PillowTestCase): - def helper_pickle_file(self, pickle, protocol=0, mode=None): - # Arrange - im = Image.open("Tests/images/hopper.jpg") - filename = self.tempfile("temp.pkl") - if mode: - im = im.convert(mode) - - # Act - with open(filename, "wb") as f: - pickle.dump(im, f, protocol) - with open(filename, "rb") as f: - loaded_im = pickle.load(f) - - # Assert - self.assertEqual(im, loaded_im) - - def helper_pickle_string( - self, pickle, protocol=0, test_file="Tests/images/hopper.jpg", mode=None - ): - im = Image.open(test_file) - if mode: - im = im.convert(mode) - - # Act - dumped_string = pickle.dumps(im, protocol) - loaded_im = pickle.loads(dumped_string) - - # Assert - self.assertEqual(im, loaded_im) - - def test_pickle_image(self): - # Arrange - import pickle - - # Act / Assert - for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1): - self.helper_pickle_string(pickle, protocol) - self.helper_pickle_file(pickle, protocol) - - def test_cpickle_image(self): - # Arrange - try: - import cPickle - except ImportError: - return - - # Act / Assert - for protocol in range(0, cPickle.HIGHEST_PROTOCOL + 1): - self.helper_pickle_string(cPickle, protocol) - self.helper_pickle_file(cPickle, protocol) - - def test_pickle_p_mode(self): - # Arrange - import pickle - - # Act / Assert - for test_file in [ - "Tests/images/test-card.png", - "Tests/images/zero_bb.png", - "Tests/images/zero_bb_scale2.png", - "Tests/images/non_zero_bb.png", - "Tests/images/non_zero_bb_scale2.png", - "Tests/images/p_trns_single.png", - "Tests/images/pil123p.png", - "Tests/images/itxt_chunks.png", - ]: - for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1): - self.helper_pickle_string( - pickle, protocol=protocol, test_file=test_file - ) - - def test_pickle_pa_mode(self): - # Arrange - import pickle - - # Act / Assert - for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1): - self.helper_pickle_string(pickle, protocol, mode="PA") - self.helper_pickle_file(pickle, protocol, mode="PA") - - def test_pickle_l_mode(self): - # Arrange - import pickle - - # Act / Assert - for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1): - self.helper_pickle_string(pickle, protocol, mode="L") - self.helper_pickle_file(pickle, protocol, mode="L") - - def test_pickle_la_mode_with_palette(self): - # Arrange - import pickle - - im = Image.open("Tests/images/hopper.jpg") - filename = self.tempfile("temp.pkl") - im = im.convert("PA") - - # Act / Assert - for protocol in range(0, pickle.HIGHEST_PROTOCOL + 1): - im.mode = "LA" - with open(filename, "wb") as f: - pickle.dump(im, f, protocol) - with open(filename, "rb") as f: - loaded_im = pickle.load(f) - - im.mode = "PA" - self.assertEqual(im, loaded_im) - - def test_cpickle_l_mode(self): - # Arrange - try: - import cPickle - except ImportError: - return - - # Act / Assert - for protocol in range(0, cPickle.HIGHEST_PROTOCOL + 1): - self.helper_pickle_string(cPickle, protocol, mode="L") - self.helper_pickle_file(cPickle, protocol, mode="L") diff --git a/Tests/test_psdraw.py b/Tests/test_psdraw.py deleted file mode 100644 index 561df4ee602..00000000000 --- a/Tests/test_psdraw.py +++ /dev/null @@ -1,63 +0,0 @@ -import os -import sys - -from PIL import Image, PSDraw - -from .helper import PillowTestCase - - -class TestPsDraw(PillowTestCase): - def _create_document(self, ps): - im = Image.open("Tests/images/hopper.ppm") - title = "hopper" - box = (1 * 72, 2 * 72, 7 * 72, 10 * 72) # in points - - ps.begin_document(title) - - # draw diagonal lines in a cross - ps.line((1 * 72, 2 * 72), (7 * 72, 10 * 72)) - ps.line((7 * 72, 2 * 72), (1 * 72, 10 * 72)) - - # draw the image (75 dpi) - ps.image(box, im, 75) - ps.rectangle(box) - - # draw title - ps.setfont("Courier", 36) - ps.text((3 * 72, 4 * 72), title) - - ps.end_document() - - def test_draw_postscript(self): - - # Based on Pillow tutorial, but there is no textsize: - # https://pillow.readthedocs.io/en/latest/handbook/tutorial.html#drawing-postscript - - # Arrange - tempfile = self.tempfile("temp.ps") - with open(tempfile, "wb") as fp: - # Act - ps = PSDraw.PSDraw(fp) - self._create_document(ps) - - # Assert - # Check non-zero file was created - self.assertTrue(os.path.isfile(tempfile)) - self.assertGreater(os.path.getsize(tempfile), 0) - - def test_stdout(self): - # Temporarily redirect stdout - try: - from cStringIO import StringIO - except ImportError: - from io import StringIO - old_stdout = sys.stdout - sys.stdout = mystdout = StringIO() - - ps = PSDraw.PSDraw() - self._create_document(ps) - - # Reset stdout - sys.stdout = old_stdout - - self.assertNotEqual(mystdout.getvalue(), "") diff --git a/Tests/test_pyroma.py b/Tests/test_pyroma.py deleted file mode 100644 index 3455a502bc7..00000000000 --- a/Tests/test_pyroma.py +++ /dev/null @@ -1,30 +0,0 @@ -from PIL import __version__ - -from .helper import PillowTestCase, unittest - -try: - import pyroma -except ImportError: - pyroma = None - - -@unittest.skipIf(pyroma is None, "Pyroma is not installed") -class TestPyroma(PillowTestCase): - def test_pyroma(self): - # Arrange - data = pyroma.projectdata.get_data(".") - - # Act - rating = pyroma.ratings.rate(data) - - # Assert - if "rc" in __version__: - # Pyroma needs to chill about RC versions and not kill all our tests. - self.assertEqual( - rating, - (9, ["The package's version number does not comply with PEP-386."]), - ) - - else: - # Should have a perfect score - self.assertEqual(rating, (10, [])) diff --git a/Tests/test_qt_image_fromqpixmap.py b/Tests/test_qt_image_fromqpixmap.py deleted file mode 100644 index 1cff26d88db..00000000000 --- a/Tests/test_qt_image_fromqpixmap.py +++ /dev/null @@ -1,15 +0,0 @@ -from PIL import ImageQt - -from .helper import PillowTestCase, hopper -from .test_imageqt import PillowQPixmapTestCase - - -class TestFromQPixmap(PillowQPixmapTestCase, PillowTestCase): - def roundtrip(self, expected): - result = ImageQt.fromqpixmap(ImageQt.toqpixmap(expected)) - # Qt saves all pixmaps as rgb - self.assert_image_equal(result, expected.convert("RGB")) - - def test_sanity(self): - for mode in ("1", "RGB", "RGBA", "L", "P"): - self.roundtrip(hopper(mode)) diff --git a/Tests/test_qt_image_toqimage.py b/Tests/test_qt_image_toqimage.py deleted file mode 100644 index d0c223b1ad3..00000000000 --- a/Tests/test_qt_image_toqimage.py +++ /dev/null @@ -1,92 +0,0 @@ -from PIL import Image, ImageQt - -from .helper import PillowTestCase, hopper -from .test_imageqt import PillowQtTestCase - -if ImageQt.qt_is_installed: - from PIL.ImageQt import QImage - - try: - from PyQt5 import QtGui - from PyQt5.QtWidgets import QWidget, QHBoxLayout, QLabel, QApplication - - QT_VERSION = 5 - except (ImportError, RuntimeError): - try: - from PySide2 import QtGui - from PySide2.QtWidgets import QWidget, QHBoxLayout, QLabel, QApplication - - QT_VERSION = 5 - except (ImportError, RuntimeError): - try: - from PyQt4 import QtGui - from PyQt4.QtGui import QWidget, QHBoxLayout, QLabel, QApplication - - QT_VERSION = 4 - except (ImportError, RuntimeError): - from PySide import QtGui - from PySide.QtGui import QWidget, QHBoxLayout, QLabel, QApplication - - QT_VERSION = 4 - - -class TestToQImage(PillowQtTestCase, PillowTestCase): - def test_sanity(self): - for mode in ("RGB", "RGBA", "L", "P", "1"): - src = hopper(mode) - data = ImageQt.toqimage(src) - - self.assertIsInstance(data, QImage) - self.assertFalse(data.isNull()) - - # reload directly from the qimage - rt = ImageQt.fromqimage(data) - if mode in ("L", "P", "1"): - self.assert_image_equal(rt, src.convert("RGB")) - else: - self.assert_image_equal(rt, src) - - if mode == "1": - # BW appears to not save correctly on QT4 and QT5 - # kicks out errors on console: - # libpng warning: Invalid color type/bit depth combination - # in IHDR - # libpng error: Invalid IHDR data - continue - - # Test saving the file - tempfile = self.tempfile("temp_{}.png".format(mode)) - data.save(tempfile) - - # Check that it actually worked. - reloaded = Image.open(tempfile) - # Gray images appear to come back in palette mode. - # They're roughly equivalent - if QT_VERSION == 4 and mode == "L": - src = src.convert("P") - self.assert_image_equal(reloaded, src) - - def test_segfault(self): - app = QApplication([]) - ex = Example() - assert app # Silence warning - assert ex # Silence warning - - -if ImageQt.qt_is_installed: - - class Example(QWidget): - def __init__(self): - super(Example, self).__init__() - - img = hopper().resize((1000, 1000)) - - qimage = ImageQt.ImageQt(img) - - pixmap1 = QtGui.QPixmap.fromImage(qimage) - - QHBoxLayout(self) # hbox - - lbl = QLabel(self) - # Segfault in the problem - lbl.setPixmap(pixmap1.copy()) diff --git a/Tests/test_qt_image_toqpixmap.py b/Tests/test_qt_image_toqpixmap.py deleted file mode 100644 index 2c07f1bf53c..00000000000 --- a/Tests/test_qt_image_toqpixmap.py +++ /dev/null @@ -1,20 +0,0 @@ -from PIL import ImageQt - -from .helper import PillowTestCase, hopper -from .test_imageqt import PillowQPixmapTestCase - -if ImageQt.qt_is_installed: - from PIL.ImageQt import QPixmap - - -class TestToQPixmap(PillowQPixmapTestCase, PillowTestCase): - def test_sanity(self): - for mode in ("1", "RGB", "RGBA", "L", "P"): - data = ImageQt.toqpixmap(hopper(mode)) - - self.assertIsInstance(data, QPixmap) - self.assertFalse(data.isNull()) - - # Test saving the file - tempfile = self.tempfile("temp_{}.png".format(mode)) - data.save(tempfile) diff --git a/Tests/test_shell_injection.py b/Tests/test_shell_injection.py deleted file mode 100644 index 35a3dcfcd86..00000000000 --- a/Tests/test_shell_injection.py +++ /dev/null @@ -1,51 +0,0 @@ -import shutil -import sys - -from PIL import GifImagePlugin, Image, JpegImagePlugin - -from .helper import ( - PillowTestCase, - cjpeg_available, - djpeg_available, - netpbm_available, - unittest, -) - -TEST_JPG = "Tests/images/hopper.jpg" -TEST_GIF = "Tests/images/hopper.gif" - -test_filenames = ("temp_';", 'temp_";', "temp_'\"|", "temp_'\"||", "temp_'\"&&") - - -@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS") -class TestShellInjection(PillowTestCase): - def assert_save_filename_check(self, src_img, save_func): - for filename in test_filenames: - dest_file = self.tempfile(filename) - save_func(src_img, 0, dest_file) - # If file can't be opened, shell injection probably occurred - Image.open(dest_file).load() - - @unittest.skipUnless(djpeg_available(), "djpeg not available") - def test_load_djpeg_filename(self): - for filename in test_filenames: - src_file = self.tempfile(filename) - shutil.copy(TEST_JPG, src_file) - - im = Image.open(src_file) - im.load_djpeg() - - @unittest.skipUnless(cjpeg_available(), "cjpeg not available") - def test_save_cjpeg_filename(self): - im = Image.open(TEST_JPG) - self.assert_save_filename_check(im, JpegImagePlugin._save_cjpeg) - - @unittest.skipUnless(netpbm_available(), "netpbm not available") - def test_save_netpbm_filename_bmp_mode(self): - im = Image.open(TEST_GIF).convert("RGB") - self.assert_save_filename_check(im, GifImagePlugin._save_netpbm) - - @unittest.skipUnless(netpbm_available(), "netpbm not available") - def test_save_netpbm_filename_l_mode(self): - im = Image.open(TEST_GIF).convert("L") - self.assert_save_filename_check(im, GifImagePlugin._save_netpbm) diff --git a/Tests/test_tiff_ifdrational.py b/Tests/test_tiff_ifdrational.py deleted file mode 100644 index f210c87377c..00000000000 --- a/Tests/test_tiff_ifdrational.py +++ /dev/null @@ -1,58 +0,0 @@ -from fractions import Fraction - -from PIL import Image, TiffImagePlugin -from PIL.TiffImagePlugin import IFDRational - -from .helper import PillowTestCase, hopper - - -class Test_IFDRational(PillowTestCase): - def _test_equal(self, num, denom, target): - - t = IFDRational(num, denom) - - self.assertEqual(target, t) - self.assertEqual(t, target) - - def test_sanity(self): - - self._test_equal(1, 1, 1) - self._test_equal(1, 1, Fraction(1, 1)) - - self._test_equal(2, 2, 1) - self._test_equal(1.0, 1, Fraction(1, 1)) - - self._test_equal(Fraction(1, 1), 1, Fraction(1, 1)) - self._test_equal(IFDRational(1, 1), 1, 1) - - self._test_equal(1, 2, Fraction(1, 2)) - self._test_equal(1, 2, IFDRational(1, 2)) - - def test_nonetype(self): - # Fails if the _delegate function doesn't return a valid function - - xres = IFDRational(72) - yres = IFDRational(72) - self.assertIsNotNone(xres._val) - self.assertIsNotNone(xres.numerator) - self.assertIsNotNone(xres.denominator) - self.assertIsNotNone(yres._val) - - self.assertTrue(xres and 1) - self.assertTrue(xres and yres) - - def test_ifd_rational_save(self): - methods = (True, False) - if "libtiff_encoder" not in dir(Image.core): - methods = (False,) - - for libtiff in methods: - TiffImagePlugin.WRITE_LIBTIFF = libtiff - - im = hopper() - out = self.tempfile("temp.tiff") - res = IFDRational(301, 1) - im.save(out, dpi=(res, res), compression="raw") - - reloaded = Image.open(out) - self.assertEqual(float(IFDRational(301, 1)), float(reloaded.tag_v2[282])) diff --git a/Tests/test_uploader.py b/Tests/test_uploader.py deleted file mode 100644 index 46dbd824aa9..00000000000 --- a/Tests/test_uploader.py +++ /dev/null @@ -1,13 +0,0 @@ -from .helper import PillowTestCase, hopper - - -class TestUploader(PillowTestCase): - def check_upload_equal(self): - result = hopper("P").convert("RGB") - target = hopper("RGB") - self.assert_image_equal(result, target) - - def check_upload_similar(self): - result = hopper("P").convert("RGB") - target = hopper("RGB") - self.assert_image_similar(result, target, 0) diff --git a/Tests/test_util.py b/Tests/test_util.py deleted file mode 100644 index 5ec21a77cbc..00000000000 --- a/Tests/test_util.py +++ /dev/null @@ -1,88 +0,0 @@ -from PIL import _util - -from .helper import PillowTestCase, unittest - - -class TestUtil(PillowTestCase): - def test_is_string_type(self): - # Arrange - color = "red" - - # Act - it_is = _util.isStringType(color) - - # Assert - self.assertTrue(it_is) - - def test_is_not_string_type(self): - # Arrange - color = (255, 0, 0) - - # Act - it_is_not = _util.isStringType(color) - - # Assert - self.assertFalse(it_is_not) - - def test_is_path(self): - # Arrange - fp = "filename.ext" - - # Act - it_is = _util.isPath(fp) - - # Assert - self.assertTrue(it_is) - - @unittest.skipIf(not _util.py36, "os.path support for Paths added in 3.6") - def test_path_obj_is_path(self): - # Arrange - from pathlib import Path - - test_path = Path("filename.ext") - - # Act - it_is = _util.isPath(test_path) - - # Assert - self.assertTrue(it_is) - - def test_is_not_path(self): - # Arrange - filename = self.tempfile("temp.ext") - fp = open(filename, "w").close() - - # Act - it_is_not = _util.isPath(fp) - - # Assert - self.assertFalse(it_is_not) - - def test_is_directory(self): - # Arrange - directory = "Tests" - - # Act - it_is = _util.isDirectory(directory) - - # Assert - self.assertTrue(it_is) - - def test_is_not_directory(self): - # Arrange - text = "abc" - - # Act - it_is_not = _util.isDirectory(text) - - # Assert - self.assertFalse(it_is_not) - - def test_deferred_error(self): - # Arrange - - # Act - thing = _util.deferred_error(ValueError("Some error text")) - - # Assert - self.assertRaises(ValueError, lambda: thing.some_attr) diff --git a/Tests/test_webp_leaks.py b/Tests/test_webp_leaks.py deleted file mode 100644 index 93a6c2db0cc..00000000000 --- a/Tests/test_webp_leaks.py +++ /dev/null @@ -1,24 +0,0 @@ -from io import BytesIO - -from PIL import Image, features - -from .helper import PillowLeakTestCase, unittest - -test_file = "Tests/images/hopper.webp" - - -@unittest.skipUnless(features.check("webp"), "WebP is not installed") -class TestWebPLeaks(PillowLeakTestCase): - - mem_limit = 3 * 1024 # kb - iterations = 100 - - def test_leak_load(self): - with open(test_file, "rb") as f: - im_data = f.read() - - def core(): - with Image.open(BytesIO(im_data)) as im: - im.load() - - self._test_leak(core)