Replace unittest with pytest

This commit is contained in:
Hugo 2020-02-12 18:29:19 +02:00
parent 098406c304
commit affade7595
39 changed files with 4415 additions and 4180 deletions

View File

@ -1,7 +1,6 @@
import pytest
from PIL import Image, ImageFilter from PIL import Image, ImageFilter
from .helper import PillowTestCase
sample = Image.new("L", (7, 5)) sample = Image.new("L", (7, 5))
# fmt: off # fmt: off
sample.putdata(sum([ sample.putdata(sum([
@ -21,43 +20,50 @@ def test_imageops_box_blur():
assert isinstance(i, Image.Image) assert isinstance(i, Image.Image)
class TestBoxBlur(PillowTestCase): def box_blur(image, radius=1, n=1):
def box_blur(self, image, radius=1, n=1):
return image._new(image.im.box_blur(radius, n)) return image._new(image.im.box_blur(radius, n))
def assertImage(self, im, data, delta=0):
def assertImage(im, data, delta=0):
it = iter(im.getdata()) it = iter(im.getdata())
for data_row in data: for data_row in data:
im_row = [next(it) for _ in range(im.size[0])] im_row = [next(it) for _ in range(im.size[0])]
if any( if any(abs(data_v - im_v) > delta for data_v, im_v in zip(data_row, im_row)):
abs(data_v - im_v) > delta for data_v, im_v in zip(data_row, im_row) assert im_row == data_row
): with pytest.raises(StopIteration):
self.assertEqual(im_row, data_row) next(it)
self.assertRaises(StopIteration, next, it)
def assertBlur(self, im, radius, data, passes=1, delta=0):
def assertBlur(im, radius, data, passes=1, delta=0):
# check grayscale image # check grayscale image
self.assertImage(self.box_blur(im, radius, passes), data, delta) assertImage(box_blur(im, radius, passes), data, delta)
rgba = Image.merge("RGBA", (im, im, im, im)) rgba = Image.merge("RGBA", (im, im, im, im))
for band in self.box_blur(rgba, radius, passes).split(): for band in box_blur(rgba, radius, passes).split():
self.assertImage(band, data, delta) 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): def test_color_modes():
self.assertBlur( with pytest.raises(ValueError):
box_blur(sample.convert("1"))
with pytest.raises(ValueError):
box_blur(sample.convert("P"))
box_blur(sample.convert("L"))
box_blur(sample.convert("LA"))
box_blur(sample.convert("LA").convert("La"))
with pytest.raises(ValueError):
box_blur(sample.convert("I"))
with pytest.raises(ValueError):
box_blur(sample.convert("F"))
box_blur(sample.convert("RGB"))
box_blur(sample.convert("RGBA"))
box_blur(sample.convert("RGBA").convert("RGBa"))
box_blur(sample.convert("CMYK"))
with pytest.raises(ValueError):
box_blur(sample.convert("YCbCr"))
def test_radius_0():
assertBlur(
sample, sample,
0, 0,
[ [
@ -71,8 +77,9 @@ class TestBoxBlur(PillowTestCase):
], ],
) )
def test_radius_0_02(self):
self.assertBlur( def test_radius_0_02():
assertBlur(
sample, sample,
0.02, 0.02,
[ [
@ -87,8 +94,9 @@ class TestBoxBlur(PillowTestCase):
delta=2, delta=2,
) )
def test_radius_0_05(self):
self.assertBlur( def test_radius_0_05():
assertBlur(
sample, sample,
0.05, 0.05,
[ [
@ -103,8 +111,9 @@ class TestBoxBlur(PillowTestCase):
delta=2, delta=2,
) )
def test_radius_0_1(self):
self.assertBlur( def test_radius_0_1():
assertBlur(
sample, sample,
0.1, 0.1,
[ [
@ -119,8 +128,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_radius_0_5(self):
self.assertBlur( def test_radius_0_5():
assertBlur(
sample, sample,
0.5, 0.5,
[ [
@ -135,8 +145,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_radius_1(self):
self.assertBlur( def test_radius_1():
assertBlur(
sample, sample,
1, 1,
[ [
@ -151,8 +162,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_radius_1_5(self):
self.assertBlur( def test_radius_1_5():
assertBlur(
sample, sample,
1.5, 1.5,
[ [
@ -167,8 +179,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_radius_bigger_then_half(self):
self.assertBlur( def test_radius_bigger_then_half():
assertBlur(
sample, sample,
3, 3,
[ [
@ -183,8 +196,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_radius_bigger_then_width(self):
self.assertBlur( def test_radius_bigger_then_width():
assertBlur(
sample, sample,
10, 10,
[ [
@ -197,8 +211,9 @@ class TestBoxBlur(PillowTestCase):
delta=0, delta=0,
) )
def test_extreme_large_radius(self):
self.assertBlur( def test_extreme_large_radius():
assertBlur(
sample, sample,
600, 600,
[ [
@ -211,8 +226,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_two_passes(self):
self.assertBlur( def test_two_passes():
assertBlur(
sample, sample,
1, 1,
[ [
@ -228,8 +244,9 @@ class TestBoxBlur(PillowTestCase):
delta=1, delta=1,
) )
def test_three_passes(self):
self.assertBlur( def test_three_passes():
assertBlur(
sample, sample,
1, 1,
[ [

View File

@ -22,7 +22,7 @@ class TestDecompressionBomb(PillowTestCase):
# Arrange # Arrange
# Turn limit off # Turn limit off
Image.MAX_IMAGE_PIXELS = None Image.MAX_IMAGE_PIXELS = None
self.assertIsNone(Image.MAX_IMAGE_PIXELS) assert Image.MAX_IMAGE_PIXELS is None
# Act / Assert # Act / Assert
# Implicit assert: no warning. # Implicit assert: no warning.
@ -33,7 +33,7 @@ class TestDecompressionBomb(PillowTestCase):
def test_warning(self): def test_warning(self):
# Set limit to trigger warning on the test file # Set limit to trigger warning on the test file
Image.MAX_IMAGE_PIXELS = 128 * 128 - 1 Image.MAX_IMAGE_PIXELS = 128 * 128 - 1
self.assertEqual(Image.MAX_IMAGE_PIXELS, 128 * 128 - 1) assert Image.MAX_IMAGE_PIXELS == 128 * 128 - 1
def open(): def open():
with Image.open(TEST_FILE): with Image.open(TEST_FILE):
@ -44,18 +44,18 @@ class TestDecompressionBomb(PillowTestCase):
def test_exception(self): def test_exception(self):
# Set limit to trigger exception on the test file # Set limit to trigger exception on the test file
Image.MAX_IMAGE_PIXELS = 64 * 128 - 1 Image.MAX_IMAGE_PIXELS = 64 * 128 - 1
self.assertEqual(Image.MAX_IMAGE_PIXELS, 64 * 128 - 1) assert Image.MAX_IMAGE_PIXELS == 64 * 128 - 1
with self.assertRaises(Image.DecompressionBombError): with pytest.raises(Image.DecompressionBombError):
with Image.open(TEST_FILE): with Image.open(TEST_FILE):
pass pass
def test_exception_ico(self): def test_exception_ico(self):
with self.assertRaises(Image.DecompressionBombError): with pytest.raises(Image.DecompressionBombError):
Image.open("Tests/images/decompression_bomb.ico") Image.open("Tests/images/decompression_bomb.ico")
def test_exception_gif(self): def test_exception_gif(self):
with self.assertRaises(Image.DecompressionBombError): with pytest.raises(Image.DecompressionBombError):
Image.open("Tests/images/decompression_bomb.gif") Image.open("Tests/images/decompression_bomb.gif")
@ -85,11 +85,11 @@ class TestDecompressionCrop(PillowTestCase):
error_values = ((-99909, -99990, 99999, 99999), (99909, 99990, -99999, -99999)) error_values = ((-99909, -99990, 99999, 99999), (99909, 99990, -99999, -99999))
for value in good_values: for value in good_values:
self.assertEqual(im.crop(value).size, (9, 9)) assert im.crop(value).size == (9, 9)
for value in warning_values: for value in warning_values:
pytest.warns(Image.DecompressionBombWarning, im.crop, value) pytest.warns(Image.DecompressionBombWarning, im.crop, value)
for value in error_values: for value in error_values:
with self.assertRaises(Image.DecompressionBombError): with pytest.raises(Image.DecompressionBombError):
im.crop(value) im.crop(value)

View File

@ -1,36 +1,35 @@
import unittest
import pytest import pytest
from PIL import DcxImagePlugin, Image from PIL import DcxImagePlugin, Image
from .helper import PillowTestCase, assert_image_equal, hopper, is_pypy from .helper import assert_image_equal, hopper, is_pypy
# Created with ImageMagick: convert hopper.ppm hopper.dcx # Created with ImageMagick: convert hopper.ppm hopper.dcx
TEST_FILE = "Tests/images/hopper.dcx" TEST_FILE = "Tests/images/hopper.dcx"
class TestFileDcx(PillowTestCase): def test_sanity():
def test_sanity(self):
# Arrange # Arrange
# Act # Act
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
# Assert # Assert
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertIsInstance(im, DcxImagePlugin.DcxImageFile) assert isinstance(im, DcxImagePlugin.DcxImageFile)
orig = hopper() orig = hopper()
assert_image_equal(im, orig) assert_image_equal(im, orig)
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self): @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open(): def open():
im = Image.open(TEST_FILE) im = Image.open(TEST_FILE)
im.load() im.load()
pytest.warns(ResourceWarning, open) pytest.warns(ResourceWarning, open)
def test_closed_file(self):
def test_closed_file():
def open(): def open():
im = Image.open(TEST_FILE) im = Image.open(TEST_FILE)
im.load() im.load()
@ -38,18 +37,22 @@ class TestFileDcx(PillowTestCase):
pytest.warns(None, open) pytest.warns(None, open)
def test_context_manager(self):
def test_context_manager():
def open(): def open():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
im.load() im.load()
pytest.warns(None, open) pytest.warns(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): def test_invalid_file():
with open("Tests/images/flower.jpg", "rb") as fp:
with pytest.raises(SyntaxError):
DcxImagePlugin.DcxImageFile(fp)
def test_tell():
# Arrange # Arrange
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
@ -57,28 +60,33 @@ class TestFileDcx(PillowTestCase):
frame = im.tell() frame = im.tell()
# Assert # Assert
self.assertEqual(frame, 0) assert frame == 0
def test_n_frames(self):
def test_n_frames():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
self.assertEqual(im.n_frames, 1) assert im.n_frames == 1
self.assertFalse(im.is_animated) assert not im.is_animated
def test_eoferror(self):
def test_eoferror():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
n_frames = im.n_frames n_frames = im.n_frames
# Test seeking past the last frame # Test seeking past the last frame
self.assertRaises(EOFError, im.seek, n_frames) with pytest.raises(EOFError):
self.assertLess(im.tell(), n_frames) im.seek(n_frames)
assert im.tell() < n_frames
# Test that seeking to the last frame does not raise an error # Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1) im.seek(n_frames - 1)
def test_seek_too_far(self):
def test_seek_too_far():
# Arrange # Arrange
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
frame = 999 # too big on purpose frame = 999 # too big on purpose
# Act / Assert # Act / Assert
self.assertRaises(EOFError, im.seek, frame) with pytest.raises(EOFError):
im.seek(frame)

View File

@ -1,8 +1,10 @@
"""Test DdsImagePlugin"""
from io import BytesIO from io import BytesIO
import pytest
from PIL import DdsImagePlugin, Image from PIL import DdsImagePlugin, Image
from .helper import PillowTestCase, assert_image_equal from .helper import assert_image_equal
TEST_FILE_DXT1 = "Tests/images/dxt1-rgb-4bbp-noalpha_MipMaps-1.dds" 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_DXT3 = "Tests/images/dxt3-argb-8bbp-explicitalpha_MipMaps-1.dds"
@ -12,100 +14,99 @@ TEST_FILE_DX10_BC7_UNORM_SRGB = "Tests/images/DXGI_FORMAT_BC7_UNORM_SRGB.dds"
TEST_FILE_UNCOMPRESSED_RGB = "Tests/images/uncompressed_rgb.dds" TEST_FILE_UNCOMPRESSED_RGB = "Tests/images/uncompressed_rgb.dds"
class TestFileDds(PillowTestCase): def test_sanity_dxt1():
"""Test DdsImagePlugin"""
def test_sanity_dxt1(self):
"""Check DXT1 images can be opened""" """Check DXT1 images can be opened"""
with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target: with Image.open(TEST_FILE_DXT1.replace(".dds", ".png")) as target:
target = target.convert("RGBA") target = target.convert("RGBA")
with Image.open(TEST_FILE_DXT1) as im: with Image.open(TEST_FILE_DXT1) as im:
im.load() im.load()
self.assertEqual(im.format, "DDS") assert im.format == "DDS"
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (256, 256)) assert im.size == (256, 256)
assert_image_equal(im, target) assert_image_equal(im, target)
def test_sanity_dxt5(self):
def test_sanity_dxt5():
"""Check DXT5 images can be opened""" """Check DXT5 images can be opened"""
with Image.open(TEST_FILE_DXT5) as im: with Image.open(TEST_FILE_DXT5) as im:
im.load() im.load()
self.assertEqual(im.format, "DDS") assert im.format == "DDS"
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (256, 256)) assert im.size == (256, 256)
with Image.open(TEST_FILE_DXT5.replace(".dds", ".png")) as target: with Image.open(TEST_FILE_DXT5.replace(".dds", ".png")) as target:
assert_image_equal(target, im) assert_image_equal(target, im)
def test_sanity_dxt3(self):
def test_sanity_dxt3():
"""Check DXT3 images can be opened""" """Check DXT3 images can be opened"""
with Image.open(TEST_FILE_DXT3.replace(".dds", ".png")) as target: with Image.open(TEST_FILE_DXT3.replace(".dds", ".png")) as target:
with Image.open(TEST_FILE_DXT3) as im: with Image.open(TEST_FILE_DXT3) as im:
im.load() im.load()
self.assertEqual(im.format, "DDS") assert im.format == "DDS"
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (256, 256)) assert im.size == (256, 256)
assert_image_equal(target, im) assert_image_equal(target, im)
def test_dx10_bc7(self):
def test_dx10_bc7():
"""Check DX10 images can be opened""" """Check DX10 images can be opened"""
with Image.open(TEST_FILE_DX10_BC7) as im: with Image.open(TEST_FILE_DX10_BC7) as im:
im.load() im.load()
self.assertEqual(im.format, "DDS") assert im.format == "DDS"
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (256, 256)) assert im.size == (256, 256)
with Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png")) as target: with Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png")) as target:
assert_image_equal(target, im) assert_image_equal(target, im)
def test_dx10_bc7_unorm_srgb(self):
def test_dx10_bc7_unorm_srgb():
"""Check DX10 unsigned normalized integer images can be opened""" """Check DX10 unsigned normalized integer images can be opened"""
with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im: with Image.open(TEST_FILE_DX10_BC7_UNORM_SRGB) as im:
im.load() im.load()
self.assertEqual(im.format, "DDS") assert im.format == "DDS"
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (16, 16)) assert im.size == (16, 16)
self.assertEqual(im.info["gamma"], 1 / 2.2) assert im.info["gamma"] == 1 / 2.2
with Image.open( with Image.open(
TEST_FILE_DX10_BC7_UNORM_SRGB.replace(".dds", ".png") TEST_FILE_DX10_BC7_UNORM_SRGB.replace(".dds", ".png")
) as target: ) as target:
assert_image_equal(target, im) 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): def test_unimplemented_dxgi_format():
with pytest.raises(NotImplementedError):
Image.open("Tests/images/unimplemented_dxgi_format.dds",)
def test_uncompressed_rgb():
"""Check uncompressed RGB images can be opened""" """Check uncompressed RGB images can be opened"""
with Image.open(TEST_FILE_UNCOMPRESSED_RGB) as im: with Image.open(TEST_FILE_UNCOMPRESSED_RGB) as im:
im.load() im.load()
self.assertEqual(im.format, "DDS") assert im.format == "DDS"
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (800, 600)) assert im.size == (800, 600)
with Image.open( with Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png")) as target:
TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png")
) as target:
assert_image_equal(target, im) assert_image_equal(target, im)
def test__validate_true(self):
def test__validate_true():
"""Check valid prefix""" """Check valid prefix"""
# Arrange # Arrange
prefix = b"DDS etc" prefix = b"DDS etc"
@ -114,9 +115,10 @@ class TestFileDds(PillowTestCase):
output = DdsImagePlugin._validate(prefix) output = DdsImagePlugin._validate(prefix)
# Assert # Assert
self.assertTrue(output) assert output
def test__validate_false(self):
def test__validate_false():
"""Check invalid prefix""" """Check invalid prefix"""
# Arrange # Arrange
prefix = b"something invalid" prefix = b"something invalid"
@ -125,9 +127,10 @@ class TestFileDds(PillowTestCase):
output = DdsImagePlugin._validate(prefix) output = DdsImagePlugin._validate(prefix)
# Assert # Assert
self.assertFalse(output) assert not output
def test_short_header(self):
def test_short_header():
""" Check a short header""" """ Check a short header"""
with open(TEST_FILE_DXT5, "rb") as f: with open(TEST_FILE_DXT5, "rb") as f:
img_file = f.read() img_file = f.read()
@ -135,9 +138,11 @@ class TestFileDds(PillowTestCase):
def short_header(): def short_header():
Image.open(BytesIO(img_file[:119])) Image.open(BytesIO(img_file[:119]))
self.assertRaises(IOError, short_header) with pytest.raises(IOError):
short_header()
def test_short_file(self):
def test_short_file():
""" Check that the appropriate error is thrown for a short file""" """ Check that the appropriate error is thrown for a short file"""
with open(TEST_FILE_DXT5, "rb") as f: with open(TEST_FILE_DXT5, "rb") as f:
@ -147,11 +152,10 @@ class TestFileDds(PillowTestCase):
with Image.open(BytesIO(img_file[:-100])) as im: with Image.open(BytesIO(img_file[:-100])) as im:
im.load() im.load()
self.assertRaises(IOError, short_file) with pytest.raises(IOError):
short_file()
def test_unimplemented_pixel_format(self):
self.assertRaises( def test_unimplemented_pixel_format():
NotImplementedError, with pytest.raises(NotImplementedError):
Image.open, Image.open("Tests/images/unimplemented_pixel_format.dds",)
"Tests/images/unimplemented_pixel_format.dds",
)

View File

@ -1,9 +1,7 @@
import unittest
import pytest import pytest
from PIL import FliImagePlugin, Image from PIL import FliImagePlugin, Image
from .helper import PillowTestCase, assert_image_equal, is_pypy from .helper import assert_image_equal, is_pypy
# created as an export of a palette image from Gimp2.6 # created as an export of a palette image from Gimp2.6
# save as...-> hopper.fli, default options. # save as...-> hopper.fli, default options.
@ -13,31 +11,32 @@ static_test_file = "Tests/images/hopper.fli"
animated_test_file = "Tests/images/a.fli" animated_test_file = "Tests/images/a.fli"
class TestFileFli(PillowTestCase): def test_sanity():
def test_sanity(self):
with Image.open(static_test_file) as im: with Image.open(static_test_file) as im:
im.load() im.load()
self.assertEqual(im.mode, "P") assert im.mode == "P"
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertEqual(im.format, "FLI") assert im.format == "FLI"
self.assertFalse(im.is_animated) assert not im.is_animated
with Image.open(animated_test_file) as im: with Image.open(animated_test_file) as im:
self.assertEqual(im.mode, "P") assert im.mode == "P"
self.assertEqual(im.size, (320, 200)) assert im.size == (320, 200)
self.assertEqual(im.format, "FLI") assert im.format == "FLI"
self.assertEqual(im.info["duration"], 71) assert im.info["duration"] == 71
self.assertTrue(im.is_animated) assert im.is_animated
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self): @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open(): def open():
im = Image.open(static_test_file) im = Image.open(static_test_file)
im.load() im.load()
pytest.warns(ResourceWarning, open) pytest.warns(ResourceWarning, open)
def test_closed_file(self):
def test_closed_file():
def open(): def open():
im = Image.open(static_test_file) im = Image.open(static_test_file)
im.load() im.load()
@ -45,14 +44,16 @@ class TestFileFli(PillowTestCase):
pytest.warns(None, open) pytest.warns(None, open)
def test_context_manager(self):
def test_context_manager():
def open(): def open():
with Image.open(static_test_file) as im: with Image.open(static_test_file) as im:
im.load() im.load()
pytest.warns(None, open) pytest.warns(None, open)
def test_tell(self):
def test_tell():
# Arrange # Arrange
with Image.open(static_test_file) as im: with Image.open(static_test_file) as im:
@ -60,56 +61,63 @@ class TestFileFli(PillowTestCase):
frame = im.tell() frame = im.tell()
# Assert # Assert
self.assertEqual(frame, 0) assert frame == 0
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, FliImagePlugin.FliImageFile, invalid_file) with pytest.raises(SyntaxError):
FliImagePlugin.FliImageFile(invalid_file)
def test_n_frames(self):
def test_n_frames():
with Image.open(static_test_file) as im: with Image.open(static_test_file) as im:
self.assertEqual(im.n_frames, 1) assert im.n_frames == 1
self.assertFalse(im.is_animated) assert not im.is_animated
with Image.open(animated_test_file) as im: with Image.open(animated_test_file) as im:
self.assertEqual(im.n_frames, 384) assert im.n_frames == 384
self.assertTrue(im.is_animated) assert im.is_animated
def test_eoferror(self):
def test_eoferror():
with Image.open(animated_test_file) as im: with Image.open(animated_test_file) as im:
n_frames = im.n_frames n_frames = im.n_frames
# Test seeking past the last frame # Test seeking past the last frame
self.assertRaises(EOFError, im.seek, n_frames) with pytest.raises(EOFError):
self.assertLess(im.tell(), n_frames) im.seek(n_frames)
assert im.tell() < n_frames
# Test that seeking to the last frame does not raise an error # Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1) im.seek(n_frames - 1)
def test_seek_tell(self):
def test_seek_tell():
with Image.open(animated_test_file) as im: with Image.open(animated_test_file) as im:
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 0) assert layer_number == 0
im.seek(0) im.seek(0)
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 0) assert layer_number == 0
im.seek(1) im.seek(1)
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 1) assert layer_number == 1
im.seek(2) im.seek(2)
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 2) assert layer_number == 2
im.seek(1) im.seek(1)
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 1) assert layer_number == 1
def test_seek(self):
def test_seek():
with Image.open(animated_test_file) as im: with Image.open(animated_test_file) as im:
im.seek(50) im.seek(50)

View File

@ -1,9 +1,6 @@
import unittest import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase
try: try:
from PIL import FpxImagePlugin from PIL import FpxImagePlugin
except ImportError: except ImportError:
@ -11,18 +8,23 @@ except ImportError:
else: else:
olefile_installed = True olefile_installed = True
pytestmark = pytest.mark.skipif(
not olefile_installed, reason="olefile package not installed"
)
@unittest.skipUnless(olefile_installed, "olefile package not installed")
class TestFileFpx(PillowTestCase): def test_invalid_file():
def test_invalid_file(self):
# Test an invalid OLE file # Test an invalid OLE file
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, invalid_file) with pytest.raises(SyntaxError):
FpxImagePlugin.FpxImageFile(invalid_file)
# Test a valid OLE file, but not an FPX file # Test a valid OLE file, but not an FPX file
ole_file = "Tests/images/test-ole-file.doc" ole_file = "Tests/images/test-ole-file.doc"
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file) with pytest.raises(SyntaxError):
FpxImagePlugin.FpxImageFile(ole_file)
def test_fpx_invalid_number_of_bands(self):
with self.assertRaisesRegex(IOError, "Invalid number of bands"): def test_fpx_invalid_number_of_bands():
with pytest.raises(IOError, match="Invalid number of bands"):
Image.open("Tests/images/input_bw_five_bands.fpx") Image.open("Tests/images/input_bw_five_bands.fpx")

View File

@ -1,15 +1,17 @@
import pytest
from PIL import GbrImagePlugin, Image from PIL import GbrImagePlugin, Image
from .helper import PillowTestCase, assert_image_equal from .helper import assert_image_equal
class TestFileGbr(PillowTestCase): def test_invalid_file():
def test_invalid_file(self):
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, GbrImagePlugin.GbrImageFile, invalid_file) with pytest.raises(SyntaxError):
GbrImagePlugin.GbrImageFile(invalid_file)
def test_gbr_file(self):
def test_gbr_file():
with Image.open("Tests/images/gbr.gbr") as im: with Image.open("Tests/images/gbr.gbr") as im:
with Image.open("Tests/images/gbr.png") as target: with Image.open("Tests/images/gbr.png") as target:
assert_image_equal(target, im) assert_image_equal(target, im)

View File

@ -1,10 +1,7 @@
from PIL import GimpGradientFile from PIL import GimpGradientFile
from .helper import PillowTestCase
def test_linear_pos_le_middle():
class TestImage(PillowTestCase):
def test_linear_pos_le_middle(self):
# Arrange # Arrange
middle = 0.5 middle = 0.5
pos = 0.25 pos = 0.25
@ -13,9 +10,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.linear(middle, pos) ret = GimpGradientFile.linear(middle, pos)
# Assert # Assert
self.assertEqual(ret, 0.25) assert ret == 0.25
def test_linear_pos_le_small_middle(self):
def test_linear_pos_le_small_middle():
# Arrange # Arrange
middle = 1e-11 middle = 1e-11
pos = 1e-12 pos = 1e-12
@ -24,9 +22,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.linear(middle, pos) ret = GimpGradientFile.linear(middle, pos)
# Assert # Assert
self.assertEqual(ret, 0.0) assert ret == 0.0
def test_linear_pos_gt_middle(self):
def test_linear_pos_gt_middle():
# Arrange # Arrange
middle = 0.5 middle = 0.5
pos = 0.75 pos = 0.75
@ -35,9 +34,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.linear(middle, pos) ret = GimpGradientFile.linear(middle, pos)
# Assert # Assert
self.assertEqual(ret, 0.75) assert ret == 0.75
def test_linear_pos_gt_small_middle(self):
def test_linear_pos_gt_small_middle():
# Arrange # Arrange
middle = 1 - 1e-11 middle = 1 - 1e-11
pos = 1 - 1e-12 pos = 1 - 1e-12
@ -46,9 +46,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.linear(middle, pos) ret = GimpGradientFile.linear(middle, pos)
# Assert # Assert
self.assertEqual(ret, 1.0) assert ret == 1.0
def test_curved(self):
def test_curved():
# Arrange # Arrange
middle = 0.5 middle = 0.5
pos = 0.75 pos = 0.75
@ -57,9 +58,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.curved(middle, pos) ret = GimpGradientFile.curved(middle, pos)
# Assert # Assert
self.assertEqual(ret, 0.75) assert ret == 0.75
def test_sine(self):
def test_sine():
# Arrange # Arrange
middle = 0.5 middle = 0.5
pos = 0.75 pos = 0.75
@ -68,9 +70,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.sine(middle, pos) ret = GimpGradientFile.sine(middle, pos)
# Assert # Assert
self.assertEqual(ret, 0.8535533905932737) assert ret == 0.8535533905932737
def test_sphere_increasing(self):
def test_sphere_increasing():
# Arrange # Arrange
middle = 0.5 middle = 0.5
pos = 0.75 pos = 0.75
@ -79,9 +82,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.sphere_increasing(middle, pos) ret = GimpGradientFile.sphere_increasing(middle, pos)
# Assert # Assert
self.assertAlmostEqual(ret, 0.9682458365518543) assert round(abs(ret - 0.9682458365518543), 7) == 0
def test_sphere_decreasing(self):
def test_sphere_decreasing():
# Arrange # Arrange
middle = 0.5 middle = 0.5
pos = 0.75 pos = 0.75
@ -90,9 +94,10 @@ class TestImage(PillowTestCase):
ret = GimpGradientFile.sphere_decreasing(middle, pos) ret = GimpGradientFile.sphere_decreasing(middle, pos)
# Assert # Assert
self.assertEqual(ret, 0.3385621722338523) assert ret == 0.3385621722338523
def test_load_via_imagepalette(self):
def test_load_via_imagepalette():
# Arrange # Arrange
from PIL import ImagePalette from PIL import ImagePalette
@ -103,10 +108,11 @@ class TestImage(PillowTestCase):
# Assert # Assert
# load returns raw palette information # load returns raw palette information
self.assertEqual(len(palette[0]), 1024) assert len(palette[0]) == 1024
self.assertEqual(palette[1], "RGBA") assert palette[1] == "RGBA"
def test_load_1_3_via_imagepalette(self):
def test_load_1_3_via_imagepalette():
# Arrange # Arrange
from PIL import ImagePalette from PIL import ImagePalette
@ -118,5 +124,5 @@ class TestImage(PillowTestCase):
# Assert # Assert
# load returns raw palette information # load returns raw palette information
self.assertEqual(len(palette[0]), 1024) assert len(palette[0]) == 1024
self.assertEqual(palette[1], "RGBA") assert palette[1] == "RGBA"

View File

@ -1,15 +1,17 @@
import pytest
from PIL import Image, McIdasImagePlugin from PIL import Image, McIdasImagePlugin
from .helper import PillowTestCase, assert_image_equal from .helper import assert_image_equal
class TestFileMcIdas(PillowTestCase): def test_invalid_file():
def test_invalid_file(self):
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, McIdasImagePlugin.McIdasImageFile, invalid_file) with pytest.raises(SyntaxError):
McIdasImagePlugin.McIdasImageFile(invalid_file)
def test_valid_file(self):
def test_valid_file():
# Arrange # Arrange
# https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8 # https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8
# https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/ # https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/
@ -21,8 +23,8 @@ class TestFileMcIdas(PillowTestCase):
im.load() im.load()
# Assert # Assert
self.assertEqual(im.format, "MCIDAS") assert im.format == "MCIDAS"
self.assertEqual(im.mode, "I") assert im.mode == "I"
self.assertEqual(im.size, (1800, 400)) assert im.size == (1800, 400)
with Image.open(saved_file) as im2: with Image.open(saved_file) as im2:
assert_image_equal(im, im2) assert_image_equal(im, im2)

View File

@ -1,8 +1,7 @@
import unittest import pytest
from PIL import Image, ImagePalette, features from PIL import Image, ImagePalette, features
from .helper import PillowTestCase, assert_image_similar, hopper from .helper import assert_image_similar, hopper
try: try:
from PIL import MicImagePlugin from PIL import MicImagePlugin
@ -14,15 +13,18 @@ else:
TEST_FILE = "Tests/images/hopper.mic" TEST_FILE = "Tests/images/hopper.mic"
@unittest.skipUnless(olefile_installed, "olefile package not installed") pytestmark = [
@unittest.skipUnless(features.check("libtiff"), "libtiff not installed") pytest.mark.skipif(not olefile_installed, reason="olefile package not installed"),
class TestFileMic(PillowTestCase): pytest.mark.skipif(not features.check("libtiff"), reason="libtiff not installed"),
def test_sanity(self): ]
def test_sanity():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
im.load() im.load()
self.assertEqual(im.mode, "RGBA") assert im.mode == "RGBA"
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertEqual(im.format, "MIC") assert im.format == "MIC"
# Adjust for the gamma of 2.2 encoded into the file # Adjust for the gamma of 2.2 encoded into the file
lut = ImagePalette.make_gamma_lut(1 / 2.2) lut = ImagePalette.make_gamma_lut(1 / 2.2)
@ -31,35 +33,39 @@ class TestFileMic(PillowTestCase):
im2 = hopper("RGBA") im2 = hopper("RGBA")
assert_image_similar(im, im2, 10) assert_image_similar(im, im2, 10)
def test_n_frames(self):
def test_n_frames():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
assert im.n_frames == 1
self.assertEqual(im.n_frames, 1)
def test_is_animated(self): def test_is_animated():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
assert not im.is_animated
self.assertFalse(im.is_animated)
def test_tell(self): def test_tell():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
assert im.tell() == 0
self.assertEqual(im.tell(), 0)
def test_seek(self): def test_seek():
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
im.seek(0) im.seek(0)
self.assertEqual(im.tell(), 0) assert im.tell() == 0
self.assertRaises(EOFError, im.seek, 99) with pytest.raises(EOFError):
self.assertEqual(im.tell(), 0) im.seek(99)
assert im.tell() == 0
def test_invalid_file(self):
def test_invalid_file():
# Test an invalid OLE file # Test an invalid OLE file
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, MicImagePlugin.MicImageFile, invalid_file) with pytest.raises(SyntaxError):
MicImagePlugin.MicImageFile(invalid_file)
# Test a valid OLE file, but not a MIC file # Test a valid OLE file, but not a MIC file
ole_file = "Tests/images/test-ole-file.doc" ole_file = "Tests/images/test-ole-file.doc"
self.assertRaises(SyntaxError, MicImagePlugin.MicImageFile, ole_file) with pytest.raises(SyntaxError):
MicImagePlugin.MicImageFile(ole_file)

View File

@ -1,21 +1,20 @@
import unittest
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image_similar, is_pypy from .helper import assert_image_similar, is_pypy
test_files = ["Tests/images/sugarshack.mpo", "Tests/images/frozenpond.mpo"] test_files = ["Tests/images/sugarshack.mpo", "Tests/images/frozenpond.mpo"]
class TestFileMpo(PillowTestCase): def setup_module():
def setUp(self):
codecs = dir(Image.core) codecs = dir(Image.core)
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
self.skipTest("jpeg support not available") pytest.skip("jpeg support not available")
def frame_roundtrip(self, im, **options):
def frame_roundtrip(im, **options):
# Note that for now, there is no MPO saving functionality # Note that for now, there is no MPO saving functionality
out = BytesIO() out = BytesIO()
im.save(out, "MPO", **options) im.save(out, "MPO", **options)
@ -25,23 +24,26 @@ class TestFileMpo(PillowTestCase):
im.bytes = test_bytes # for testing only im.bytes = test_bytes # for testing only
return im return im
def test_sanity(self):
def test_sanity():
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
im.load() im.load()
self.assertEqual(im.mode, "RGB") assert im.mode == "RGB"
self.assertEqual(im.size, (640, 480)) assert im.size == (640, 480)
self.assertEqual(im.format, "MPO") assert im.format == "MPO"
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self): @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open(): def open():
im = Image.open(test_files[0]) im = Image.open(test_files[0])
im.load() im.load()
pytest.warns(ResourceWarning, open) pytest.warns(ResourceWarning, open)
def test_closed_file(self):
def test_closed_file():
def open(): def open():
im = Image.open(test_files[0]) im = Image.open(test_files[0])
im.load() im.load()
@ -49,79 +51,86 @@ class TestFileMpo(PillowTestCase):
pytest.warns(None, open) pytest.warns(None, open)
def test_context_manager(self):
def test_context_manager():
def open(): def open():
with Image.open(test_files[0]) as im: with Image.open(test_files[0]) as im:
im.load() im.load()
pytest.warns(None, open) pytest.warns(None, open)
def test_app(self):
def test_app():
for test_file in test_files: for test_file in test_files:
# Test APP/COM reader (@PIL135) # Test APP/COM reader (@PIL135)
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertEqual(im.applist[0][0], "APP1") assert im.applist[0][0] == "APP1"
self.assertEqual(im.applist[1][0], "APP2") assert im.applist[1][0] == "APP2"
self.assertEqual( assert (
im.applist[1][1][:16], im.applist[1][1][:16]
b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00", == b"MPF\x00MM\x00*\x00\x00\x00\x08\x00\x03\xb0\x00"
) )
self.assertEqual(len(im.applist), 2) assert len(im.applist) == 2
def test_exif(self):
def test_exif():
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
info = im._getexif() info = im._getexif()
self.assertEqual(info[272], "Nintendo 3DS") assert info[272] == "Nintendo 3DS"
self.assertEqual(info[296], 2) assert info[296] == 2
self.assertEqual(info[34665], 188) assert info[34665] == 188
def test_frame_size(self):
def test_frame_size():
# This image has been hexedited to contain a different size # This image has been hexedited to contain a different size
# in the EXIF data of the second frame # in the EXIF data of the second frame
with Image.open("Tests/images/sugarshack_frame_size.mpo") as im: with Image.open("Tests/images/sugarshack_frame_size.mpo") as im:
self.assertEqual(im.size, (640, 480)) assert im.size == (640, 480)
im.seek(1) im.seek(1)
self.assertEqual(im.size, (680, 480)) assert im.size == (680, 480)
def test_parallax(self):
def test_parallax():
# Nintendo # Nintendo
with Image.open("Tests/images/sugarshack.mpo") as im: with Image.open("Tests/images/sugarshack.mpo") as im:
exif = im.getexif() exif = im.getexif()
self.assertEqual( assert exif.get_ifd(0x927C)[0x1101]["Parallax"] == -44.798187255859375
exif.get_ifd(0x927C)[0x1101]["Parallax"], -44.798187255859375
)
# Fujifilm # Fujifilm
with Image.open("Tests/images/fujifilm.mpo") as im: with Image.open("Tests/images/fujifilm.mpo") as im:
im.seek(1) im.seek(1)
exif = im.getexif() exif = im.getexif()
self.assertEqual(exif.get_ifd(0x927C)[0xB211], -3.125) assert exif.get_ifd(0x927C)[0xB211] == -3.125
def test_mp(self):
def test_mp():
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
mpinfo = im._getmp() mpinfo = im._getmp()
self.assertEqual(mpinfo[45056], b"0100") assert mpinfo[45056] == b"0100"
self.assertEqual(mpinfo[45057], 2) assert mpinfo[45057] == 2
def test_mp_offset(self):
def test_mp_offset():
# This image has been manually hexedited to have an IFD offset of 10 # This image has been manually hexedited to have an IFD offset of 10
# in APP2 data, in contrast to normal 8 # in APP2 data, in contrast to normal 8
with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im: with Image.open("Tests/images/sugarshack_ifd_offset.mpo") as im:
mpinfo = im._getmp() mpinfo = im._getmp()
self.assertEqual(mpinfo[45056], b"0100") assert mpinfo[45056] == b"0100"
self.assertEqual(mpinfo[45057], 2) assert mpinfo[45057] == 2
def test_mp_no_data(self):
def test_mp_no_data():
# This image has been manually hexedited to have the second frame # This image has been manually hexedited to have the second frame
# beyond the end of the file # beyond the end of the file
with Image.open("Tests/images/sugarshack_no_data.mpo") as im: with Image.open("Tests/images/sugarshack_no_data.mpo") as im:
with self.assertRaises(ValueError): with pytest.raises(ValueError):
im.seek(1) im.seek(1)
def test_mp_attribute(self):
def test_mp_attribute():
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
mpinfo = im._getmp() mpinfo = im._getmp()
@ -129,74 +138,84 @@ class TestFileMpo(PillowTestCase):
for mpentry in mpinfo[45058]: for mpentry in mpinfo[45058]:
mpattr = mpentry["Attribute"] mpattr = mpentry["Attribute"]
if frameNumber: if frameNumber:
self.assertFalse(mpattr["RepresentativeImageFlag"]) assert not mpattr["RepresentativeImageFlag"]
else: else:
self.assertTrue(mpattr["RepresentativeImageFlag"]) assert mpattr["RepresentativeImageFlag"]
self.assertFalse(mpattr["DependentParentImageFlag"]) assert not mpattr["DependentParentImageFlag"]
self.assertFalse(mpattr["DependentChildImageFlag"]) assert not mpattr["DependentChildImageFlag"]
self.assertEqual(mpattr["ImageDataFormat"], "JPEG") assert mpattr["ImageDataFormat"] == "JPEG"
self.assertEqual(mpattr["MPType"], "Multi-Frame Image: (Disparity)") assert mpattr["MPType"] == "Multi-Frame Image: (Disparity)"
self.assertEqual(mpattr["Reserved"], 0) assert mpattr["Reserved"] == 0
frameNumber += 1 frameNumber += 1
def test_seek(self):
def test_seek():
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertEqual(im.tell(), 0) assert im.tell() == 0
# prior to first image raises an error, both blatant and borderline # prior to first image raises an error, both blatant and borderline
self.assertRaises(EOFError, im.seek, -1) with pytest.raises(EOFError):
self.assertRaises(EOFError, im.seek, -523) im.seek(-1)
with pytest.raises(EOFError):
im.seek(-523)
# after the final image raises an error, # after the final image raises an error,
# both blatant and borderline # both blatant and borderline
self.assertRaises(EOFError, im.seek, 2) with pytest.raises(EOFError):
self.assertRaises(EOFError, im.seek, 523) im.seek(2)
with pytest.raises(EOFError):
im.seek(523)
# bad calls shouldn't change the frame # bad calls shouldn't change the frame
self.assertEqual(im.tell(), 0) assert im.tell() == 0
# this one will work # this one will work
im.seek(1) im.seek(1)
self.assertEqual(im.tell(), 1) assert im.tell() == 1
# and this one, too # and this one, too
im.seek(0) im.seek(0)
self.assertEqual(im.tell(), 0) assert im.tell() == 0
def test_n_frames(self):
def test_n_frames():
with Image.open("Tests/images/sugarshack.mpo") as im: with Image.open("Tests/images/sugarshack.mpo") as im:
self.assertEqual(im.n_frames, 2) assert im.n_frames == 2
self.assertTrue(im.is_animated) assert im.is_animated
def test_eoferror(self):
def test_eoferror():
with Image.open("Tests/images/sugarshack.mpo") as im: with Image.open("Tests/images/sugarshack.mpo") as im:
n_frames = im.n_frames n_frames = im.n_frames
# Test seeking past the last frame # Test seeking past the last frame
self.assertRaises(EOFError, im.seek, n_frames) with pytest.raises(EOFError):
self.assertLess(im.tell(), n_frames) im.seek(n_frames)
assert im.tell() < n_frames
# Test that seeking to the last frame does not raise an error # Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1) im.seek(n_frames - 1)
def test_image_grab(self):
def test_image_grab():
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertEqual(im.tell(), 0) assert im.tell() == 0
im0 = im.tobytes() im0 = im.tobytes()
im.seek(1) im.seek(1)
self.assertEqual(im.tell(), 1) assert im.tell() == 1
im1 = im.tobytes() im1 = im.tobytes()
im.seek(0) im.seek(0)
self.assertEqual(im.tell(), 0) assert im.tell() == 0
im02 = im.tobytes() im02 = im.tobytes()
self.assertEqual(im0, im02) assert im0 == im02
self.assertNotEqual(im0, im1) assert im0 != im1
def test_save(self):
def test_save():
# Note that only individual frames can be saved at present # Note that only individual frames can be saved at present
for test_file in test_files: for test_file in test_files:
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertEqual(im.tell(), 0) assert im.tell() == 0
jpg0 = self.frame_roundtrip(im) jpg0 = frame_roundtrip(im)
assert_image_similar(im, jpg0, 30) assert_image_similar(im, jpg0, 30)
im.seek(1) im.seek(1)
self.assertEqual(im.tell(), 1) assert im.tell() == 1
jpg1 = self.frame_roundtrip(im) jpg1 = frame_roundtrip(im)
assert_image_similar(im, jpg1, 30) assert_image_similar(im, jpg1, 30)

View File

@ -1,23 +1,25 @@
import pytest
from PIL import Image, PixarImagePlugin from PIL import Image, PixarImagePlugin
from .helper import PillowTestCase, assert_image_similar, hopper from .helper import assert_image_similar, hopper
TEST_FILE = "Tests/images/hopper.pxr" TEST_FILE = "Tests/images/hopper.pxr"
class TestFilePixar(PillowTestCase): def test_sanity():
def test_sanity(self):
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
im.load() im.load()
self.assertEqual(im.mode, "RGB") assert im.mode == "RGB"
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertEqual(im.format, "PIXAR") assert im.format == "PIXAR"
self.assertIsNone(im.get_format_mimetype()) assert im.get_format_mimetype() is None
im2 = hopper() im2 = hopper()
assert_image_similar(im, im2, 4.8) assert_image_similar(im, im2, 4.8)
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, PixarImagePlugin.PixarImageFile, invalid_file) with pytest.raises(SyntaxError):
PixarImagePlugin.PixarImageFile(invalid_file)

View File

@ -1,33 +1,32 @@
import unittest
import pytest import pytest
from PIL import Image, PsdImagePlugin from PIL import Image, PsdImagePlugin
from .helper import PillowTestCase, assert_image_similar, hopper, is_pypy from .helper import assert_image_similar, hopper, is_pypy
test_file = "Tests/images/hopper.psd" test_file = "Tests/images/hopper.psd"
class TestImagePsd(PillowTestCase): def test_sanity():
def test_sanity(self):
with Image.open(test_file) as im: with Image.open(test_file) as im:
im.load() im.load()
self.assertEqual(im.mode, "RGB") assert im.mode == "RGB"
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertEqual(im.format, "PSD") assert im.format == "PSD"
im2 = hopper() im2 = hopper()
assert_image_similar(im, im2, 4.8) assert_image_similar(im, im2, 4.8)
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self): @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open(): def open():
im = Image.open(test_file) im = Image.open(test_file)
im.load() im.load()
pytest.warns(ResourceWarning, open) pytest.warns(ResourceWarning, open)
def test_closed_file(self):
def test_closed_file():
def open(): def open():
im = Image.open(test_file) im = Image.open(test_file)
im.load() im.load()
@ -35,82 +34,96 @@ class TestImagePsd(PillowTestCase):
pytest.warns(None, open) pytest.warns(None, open)
def test_context_manager(self):
def test_context_manager():
def open(): def open():
with Image.open(test_file) as im: with Image.open(test_file) as im:
im.load() im.load()
pytest.warns(None, open) pytest.warns(None, open)
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, PsdImagePlugin.PsdImageFile, invalid_file) with pytest.raises(SyntaxError):
PsdImagePlugin.PsdImageFile(invalid_file)
def test_n_frames(self):
def test_n_frames():
with Image.open("Tests/images/hopper_merged.psd") as im: with Image.open("Tests/images/hopper_merged.psd") as im:
self.assertEqual(im.n_frames, 1) assert im.n_frames == 1
self.assertFalse(im.is_animated) assert not im.is_animated
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertEqual(im.n_frames, 2) assert im.n_frames == 2
self.assertTrue(im.is_animated) assert im.is_animated
def test_eoferror(self):
def test_eoferror():
with Image.open(test_file) as im: with Image.open(test_file) as im:
# PSD seek index starts at 1 rather than 0 # PSD seek index starts at 1 rather than 0
n_frames = im.n_frames + 1 n_frames = im.n_frames + 1
# Test seeking past the last frame # Test seeking past the last frame
self.assertRaises(EOFError, im.seek, n_frames) with pytest.raises(EOFError):
self.assertLess(im.tell(), n_frames) im.seek(n_frames)
assert im.tell() < n_frames
# Test that seeking to the last frame does not raise an error # Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1) im.seek(n_frames - 1)
def test_seek_tell(self):
def test_seek_tell():
with Image.open(test_file) as im: with Image.open(test_file) as im:
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 1) assert layer_number == 1
self.assertRaises(EOFError, im.seek, 0) with pytest.raises(EOFError):
im.seek(0)
im.seek(1) im.seek(1)
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 1) assert layer_number == 1
im.seek(2) im.seek(2)
layer_number = im.tell() layer_number = im.tell()
self.assertEqual(layer_number, 2) assert layer_number == 2
def test_seek_eoferror(self):
def test_seek_eoferror():
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertRaises(EOFError, im.seek, -1) with pytest.raises(EOFError):
im.seek(-1)
def test_open_after_exclusive_load(self):
def test_open_after_exclusive_load():
with Image.open(test_file) as im: with Image.open(test_file) as im:
im.load() im.load()
im.seek(im.tell() + 1) im.seek(im.tell() + 1)
im.load() im.load()
def test_icc_profile(self):
def test_icc_profile():
with Image.open(test_file) as im: with Image.open(test_file) as im:
self.assertIn("icc_profile", im.info) assert "icc_profile" in im.info
icc_profile = im.info["icc_profile"] icc_profile = im.info["icc_profile"]
self.assertEqual(len(icc_profile), 3144) assert len(icc_profile) == 3144
def test_no_icc_profile(self):
def test_no_icc_profile():
with Image.open("Tests/images/hopper_merged.psd") as im: with Image.open("Tests/images/hopper_merged.psd") as im:
self.assertNotIn("icc_profile", im.info) assert "icc_profile" not in im.info
def test_combined_larger_than_size(self):
def test_combined_larger_than_size():
# The 'combined' sizes of the individual parts is larger than the # The 'combined' sizes of the individual parts is larger than the
# declared 'size' of the extra data field, resulting in a backwards seek. # declared 'size' of the extra data field, resulting in a backwards seek.
# If we instead take the 'size' of the extra data field as the source of truth, # If we instead take the 'size' of the extra data field as the source of truth,
# then the seek can't be negative # then the seek can't be negative
with self.assertRaises(IOError): with pytest.raises(IOError):
Image.open("Tests/images/combined_larger_than_size.psd") Image.open("Tests/images/combined_larger_than_size.psd")

View File

@ -1,15 +1,14 @@
import os import os
import unittest
import pytest
from PIL import Image, SunImagePlugin from PIL import Image, SunImagePlugin
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper from .helper import assert_image_equal, assert_image_similar, hopper
EXTRA_DIR = "Tests/images/sunraster" EXTRA_DIR = "Tests/images/sunraster"
class TestFileSun(PillowTestCase): def test_sanity():
def test_sanity(self):
# Arrange # Arrange
# Created with ImageMagick: convert hopper.jpg hopper.ras # Created with ImageMagick: convert hopper.jpg hopper.ras
test_file = "Tests/images/hopper.ras" test_file = "Tests/images/hopper.ras"
@ -18,20 +17,25 @@ class TestFileSun(PillowTestCase):
with Image.open(test_file) as im: with Image.open(test_file) as im:
# Assert # Assert
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
assert_image_similar(im, hopper(), 5) # visually verified assert_image_similar(im, hopper(), 5) # visually verified
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, SunImagePlugin.SunImageFile, invalid_file) with pytest.raises(SyntaxError):
SunImagePlugin.SunImageFile(invalid_file)
def test_im1(self):
def test_im1():
with Image.open("Tests/images/sunraster.im1") as im: with Image.open("Tests/images/sunraster.im1") as im:
with Image.open("Tests/images/sunraster.im1.png") as target: with Image.open("Tests/images/sunraster.im1.png") as target:
assert_image_equal(im, target) assert_image_equal(im, target)
@unittest.skipUnless(os.path.exists(EXTRA_DIR), "Extra image files not installed")
def test_others(self): @pytest.mark.skipif(
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
def test_others():
files = ( files = (
os.path.join(EXTRA_DIR, f) os.path.join(EXTRA_DIR, f)
for f in os.listdir(EXTRA_DIR) for f in os.listdir(EXTRA_DIR)
@ -40,7 +44,7 @@ class TestFileSun(PillowTestCase):
for path in files: for path in files:
with Image.open(path) as im: with Image.open(path) as im:
im.load() im.load()
self.assertIsInstance(im, SunImagePlugin.SunImageFile) assert isinstance(im, SunImagePlugin.SunImageFile)
target_path = "%s.png" % os.path.splitext(path)[0] target_path = "%s.png" % os.path.splitext(path)[0]
# im.save(target_file) # im.save(target_file)
with Image.open(target_path) as target: with Image.open(target_path) as target:

View File

@ -1,9 +1,7 @@
import unittest
import pytest import pytest
from PIL import Image, TarIO from PIL import Image, TarIO
from .helper import PillowTestCase, is_pypy from .helper import is_pypy
codecs = dir(Image.core) codecs = dir(Image.core)
@ -11,12 +9,12 @@ codecs = dir(Image.core)
TEST_TAR_FILE = "Tests/images/hopper.tar" TEST_TAR_FILE = "Tests/images/hopper.tar"
class TestFileTar(PillowTestCase): def setup_module():
def setUp(self):
if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs: if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs:
self.skipTest("neither jpeg nor zip support available") pytest.skip("neither jpeg nor zip support available")
def test_sanity(self):
def test_sanity():
for codec, test_path, format in [ for codec, test_path, format in [
["zip_decoder", "hopper.png", "PNG"], ["zip_decoder", "hopper.png", "PNG"],
["jpeg_decoder", "hopper.jpg", "JPEG"], ["jpeg_decoder", "hopper.jpg", "JPEG"],
@ -25,25 +23,28 @@ class TestFileTar(PillowTestCase):
with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar: with TarIO.TarIO(TEST_TAR_FILE, test_path) as tar:
with Image.open(tar) as im: with Image.open(tar) as im:
im.load() im.load()
self.assertEqual(im.mode, "RGB") assert im.mode == "RGB"
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertEqual(im.format, format) assert im.format == format
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self): @pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open(): def open():
TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
pytest.warns(ResourceWarning, open) pytest.warns(ResourceWarning, open)
def test_close(self):
def test_close():
def open(): def open():
tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg") tar = TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg")
tar.close() tar.close()
pytest.warns(None, open) pytest.warns(None, open)
def test_contextmanager(self):
def test_contextmanager():
def open(): def open():
with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"): with TarIO.TarIO(TEST_TAR_FILE, "hopper.jpg"):
pass pass

View File

@ -1,27 +1,30 @@
import pytest
from PIL import Image, XpmImagePlugin from PIL import Image, XpmImagePlugin
from .helper import PillowTestCase, assert_image_similar, hopper from .helper import assert_image_similar, hopper
TEST_FILE = "Tests/images/hopper.xpm" TEST_FILE = "Tests/images/hopper.xpm"
class TestFileXpm(PillowTestCase): def test_sanity():
def test_sanity(self):
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
im.load() im.load()
self.assertEqual(im.mode, "P") assert im.mode == "P"
self.assertEqual(im.size, (128, 128)) assert im.size == (128, 128)
self.assertEqual(im.format, "XPM") assert im.format == "XPM"
# large error due to quantization->44 colors. # large error due to quantization->44 colors.
assert_image_similar(im.convert("RGB"), hopper("RGB"), 60) assert_image_similar(im.convert("RGB"), hopper("RGB"), 60)
def test_invalid_file(self):
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, XpmImagePlugin.XpmImageFile, invalid_file) with pytest.raises(SyntaxError):
XpmImagePlugin.XpmImageFile(invalid_file)
def test_load_read(self):
def test_load_read():
# Arrange # Arrange
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
dummy_bytes = 1 dummy_bytes = 1
@ -30,4 +33,4 @@ class TestFileXpm(PillowTestCase):
data = im.load_read(dummy_bytes) data = im.load_read(dummy_bytes)
# Assert # Assert
self.assertEqual(len(data), 16384) assert len(data) == 16384

View File

@ -1,35 +1,37 @@
import pytest
from PIL import Image, XVThumbImagePlugin from PIL import Image, XVThumbImagePlugin
from .helper import PillowTestCase, assert_image_similar, hopper from .helper import assert_image_similar, hopper
TEST_FILE = "Tests/images/hopper.p7" TEST_FILE = "Tests/images/hopper.p7"
class TestFileXVThumb(PillowTestCase): def test_open():
def test_open(self):
# Act # Act
with Image.open(TEST_FILE) as im: with Image.open(TEST_FILE) as im:
# Assert # Assert
self.assertEqual(im.format, "XVThumb") assert im.format == "XVThumb"
# Create a Hopper image with a similar XV palette # Create a Hopper image with a similar XV palette
im_hopper = hopper().quantize(palette=im) im_hopper = hopper().quantize(palette=im)
assert_image_similar(im, im_hopper, 9) assert_image_similar(im, im_hopper, 9)
def test_unexpected_eof(self):
def test_unexpected_eof():
# Test unexpected EOF reading XV thumbnail file # Test unexpected EOF reading XV thumbnail file
# Arrange # Arrange
bad_file = "Tests/images/hopper_bad.p7" bad_file = "Tests/images/hopper_bad.p7"
# Act / Assert # Act / Assert
self.assertRaises(SyntaxError, XVThumbImagePlugin.XVThumbImageFile, bad_file) with pytest.raises(SyntaxError):
XVThumbImagePlugin.XVThumbImageFile(bad_file)
def test_invalid_file(self):
def test_invalid_file():
# Arrange # Arrange
invalid_file = "Tests/images/flower.jpg" invalid_file = "Tests/images/flower.jpg"
# Act / Assert # Act / Assert
self.assertRaises( with pytest.raises(SyntaxError):
SyntaxError, XVThumbImagePlugin.XVThumbImageFile, invalid_file XVThumbImagePlugin.XVThumbImageFile(invalid_file)
)

View File

@ -1,22 +1,23 @@
import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
class TestImageCrop(PillowTestCase): def test_crop():
def test_crop(self):
def crop(mode): def crop(mode):
im = hopper(mode) im = hopper(mode)
assert_image_equal(im.crop(), im) assert_image_equal(im.crop(), im)
cropped = im.crop((50, 50, 100, 100)) cropped = im.crop((50, 50, 100, 100))
self.assertEqual(cropped.mode, mode) assert cropped.mode == mode
self.assertEqual(cropped.size, (50, 50)) assert cropped.size == (50, 50)
for mode in "1", "P", "L", "RGB", "I", "F": for mode in "1", "P", "L", "RGB", "I", "F":
crop(mode) crop(mode)
def test_wide_crop(self):
def test_wide_crop():
def crop(*bbox): def crop(*bbox):
i = im.crop(bbox) i = im.crop(bbox)
h = i.histogram() h = i.histogram()
@ -26,51 +27,55 @@ class TestImageCrop(PillowTestCase):
im = Image.new("L", (100, 100), 1) im = Image.new("L", (100, 100), 1)
self.assertEqual(crop(0, 0, 100, 100), (0, 10000)) assert crop(0, 0, 100, 100) == (0, 10000)
self.assertEqual(crop(25, 25, 75, 75), (0, 2500)) assert crop(25, 25, 75, 75) == (0, 2500)
# sides # sides
self.assertEqual(crop(-25, 0, 25, 50), (1250, 1250)) assert crop(-25, 0, 25, 50) == (1250, 1250)
self.assertEqual(crop(0, -25, 50, 25), (1250, 1250)) assert crop(0, -25, 50, 25) == (1250, 1250)
self.assertEqual(crop(75, 0, 125, 50), (1250, 1250)) assert crop(75, 0, 125, 50) == (1250, 1250)
self.assertEqual(crop(0, 75, 50, 125), (1250, 1250)) assert crop(0, 75, 50, 125) == (1250, 1250)
self.assertEqual(crop(-25, 25, 125, 75), (2500, 5000)) assert crop(-25, 25, 125, 75) == (2500, 5000)
self.assertEqual(crop(25, -25, 75, 125), (2500, 5000)) assert crop(25, -25, 75, 125) == (2500, 5000)
# corners # corners
self.assertEqual(crop(-25, -25, 25, 25), (1875, 625)) assert crop(-25, -25, 25, 25) == (1875, 625)
self.assertEqual(crop(75, -25, 125, 25), (1875, 625)) assert crop(75, -25, 125, 25) == (1875, 625)
self.assertEqual(crop(75, 75, 125, 125), (1875, 625)) assert crop(75, 75, 125, 125) == (1875, 625)
self.assertEqual(crop(-25, 75, 25, 125), (1875, 625)) assert crop(-25, 75, 25, 125) == (1875, 625)
def test_negative_crop(self):
def test_negative_crop():
# Check negative crop size (@PIL171) # Check negative crop size (@PIL171)
im = Image.new("L", (512, 512)) im = Image.new("L", (512, 512))
im = im.crop((400, 400, 200, 200)) im = im.crop((400, 400, 200, 200))
self.assertEqual(im.size, (0, 0)) assert im.size == (0, 0)
self.assertEqual(len(im.getdata()), 0) assert len(im.getdata()) == 0
self.assertRaises(IndexError, lambda: im.getdata()[0]) with pytest.raises(IndexError):
im.getdata()[0]
def test_crop_float(self):
def test_crop_float():
# Check cropping floats are rounded to nearest integer # Check cropping floats are rounded to nearest integer
# https://github.com/python-pillow/Pillow/issues/1744 # https://github.com/python-pillow/Pillow/issues/1744
# Arrange # Arrange
im = Image.new("RGB", (10, 10)) im = Image.new("RGB", (10, 10))
self.assertEqual(im.size, (10, 10)) assert im.size == (10, 10)
# Act # Act
cropped = im.crop((0.9, 1.1, 4.2, 5.8)) cropped = im.crop((0.9, 1.1, 4.2, 5.8))
# Assert # Assert
self.assertEqual(cropped.size, (3, 5)) assert cropped.size == (3, 5)
def test_crop_crash(self):
def test_crop_crash():
# Image.crop crashes prepatch with an access violation # Image.crop crashes prepatch with an access violation
# apparently a use after free on windows, see # apparently a use after free on Windows, see
# https://github.com/python-pillow/Pillow/issues/1077 # https://github.com/python-pillow/Pillow/issues/1077
test_img = "Tests/images/bmp/g/pal8-0.bmp" test_img = "Tests/images/bmp/g/pal8-0.bmp"
@ -85,19 +90,20 @@ class TestImageCrop(PillowTestCase):
img = img.crop(extents) img = img.crop(extents)
img.load() img.load()
def test_crop_zero(self):
def test_crop_zero():
im = Image.new("RGB", (0, 0), "white") im = Image.new("RGB", (0, 0), "white")
cropped = im.crop((0, 0, 0, 0)) cropped = im.crop((0, 0, 0, 0))
self.assertEqual(cropped.size, (0, 0)) assert cropped.size == (0, 0)
cropped = im.crop((10, 10, 20, 20)) cropped = im.crop((10, 10, 20, 20))
self.assertEqual(cropped.size, (10, 10)) assert cropped.size == (10, 10)
self.assertEqual(cropped.getdata()[0], (0, 0, 0)) assert cropped.getdata()[0] == (0, 0, 0)
im = Image.new("RGB", (0, 0)) im = Image.new("RGB", (0, 0))
cropped = im.crop((10, 10, 20, 20)) cropped = im.crop((10, 10, 20, 20))
self.assertEqual(cropped.size, (10, 10)) assert cropped.size == (10, 10)
self.assertEqual(cropped.getdata()[2], (0, 0, 0)) assert cropped.getdata()[2] == (0, 0, 0)

View File

@ -1,26 +1,28 @@
import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, fromstring, tostring from .helper import fromstring, tostring
class TestImageDraft(PillowTestCase): def setup_module():
def setUp(self):
codecs = dir(Image.core) codecs = dir(Image.core)
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
self.skipTest("jpeg support not available") pytest.skip("jpeg support not available")
def draft_roundtrip(self, in_mode, in_size, req_mode, req_size):
def draft_roundtrip(in_mode, in_size, req_mode, req_size):
im = Image.new(in_mode, in_size) im = Image.new(in_mode, in_size)
data = tostring(im, "JPEG") data = tostring(im, "JPEG")
im = fromstring(data) im = fromstring(data)
mode, box = im.draft(req_mode, req_size) mode, box = im.draft(req_mode, req_size)
scale, _ = im.decoderconfig scale, _ = im.decoderconfig
self.assertEqual(box[:2], (0, 0)) assert box[:2] == (0, 0)
self.assertTrue((im.width - scale) < box[2] <= im.width) assert (im.width - scale) < box[2] <= im.width
self.assertTrue((im.height - scale) < box[3] <= im.height) assert (im.height - scale) < box[3] <= im.height
return im return im
def test_size(self):
def test_size():
for in_size, req_size, out_size in [ for in_size, req_size, out_size in [
((435, 361), (2048, 2048), (435, 361)), # bigger ((435, 361), (2048, 2048), (435, 361)), # bigger
((435, 361), (435, 361), (435, 361)), # same ((435, 361), (435, 361), (435, 361)), # same
@ -44,11 +46,12 @@ class TestImageDraft(PillowTestCase):
((435, 361), (32, 45), (55, 46)), # more than 8x ((435, 361), (32, 45), (55, 46)), # more than 8x
((435, 361), (16, 22), (55, 46)), # more than 16x ((435, 361), (16, 22), (55, 46)), # more than 16x
]: ]:
im = self.draft_roundtrip("L", in_size, None, req_size) im = draft_roundtrip("L", in_size, None, req_size)
im.load() im.load()
self.assertEqual(im.size, out_size) assert im.size == out_size
def test_mode(self):
def test_mode():
for in_mode, req_mode, out_mode in [ for in_mode, req_mode, out_mode in [
("RGB", "1", "RGB"), ("RGB", "1", "RGB"),
("RGB", "L", "L"), ("RGB", "L", "L"),
@ -63,11 +66,12 @@ class TestImageDraft(PillowTestCase):
("CMYK", "RGB", "CMYK"), ("CMYK", "RGB", "CMYK"),
("CMYK", "YCbCr", "CMYK"), ("CMYK", "YCbCr", "CMYK"),
]: ]:
im = self.draft_roundtrip(in_mode, (64, 64), req_mode, None) im = draft_roundtrip(in_mode, (64, 64), req_mode, None)
im.load() im.load()
self.assertEqual(im.mode, out_mode) assert im.mode == out_mode
def test_several_drafts(self):
im = self.draft_roundtrip("L", (128, 128), None, (64, 64)) def test_several_drafts():
im = draft_roundtrip("L", (128, 128), None, (64, 64))
im.draft(None, (64, 64)) im.draft(None, (64, 64))
im.load() im.load()

View File

@ -1,17 +1,16 @@
from .helper import PillowTestCase, hopper from .helper import hopper
class TestImageEntropy(PillowTestCase): def test_entropy():
def test_entropy(self):
def entropy(mode): def entropy(mode):
return hopper(mode).entropy() return hopper(mode).entropy()
self.assertAlmostEqual(entropy("1"), 0.9138803254693582) assert round(abs(entropy("1") - 0.9138803254693582), 7) == 0
self.assertAlmostEqual(entropy("L"), 7.063008716585465) assert round(abs(entropy("L") - 7.063008716585465), 7) == 0
self.assertAlmostEqual(entropy("I"), 7.063008716585465) assert round(abs(entropy("I") - 7.063008716585465), 7) == 0
self.assertAlmostEqual(entropy("F"), 7.063008716585465) assert round(abs(entropy("F") - 7.063008716585465), 7) == 0
self.assertAlmostEqual(entropy("P"), 5.0530452472519745) assert round(abs(entropy("P") - 5.0530452472519745), 7) == 0
self.assertAlmostEqual(entropy("RGB"), 8.821286587714319) assert round(abs(entropy("RGB") - 8.821286587714319), 7) == 0
self.assertAlmostEqual(entropy("RGBA"), 7.42724306524488) assert round(abs(entropy("RGBA") - 7.42724306524488), 7) == 0
self.assertAlmostEqual(entropy("CMYK"), 7.4272430652448795) assert round(abs(entropy("CMYK") - 7.4272430652448795), 7) == 0
self.assertAlmostEqual(entropy("YCbCr"), 7.698360534903628) assert round(abs(entropy("YCbCr") - 7.698360534903628), 7) == 0

View File

@ -1,40 +1,42 @@
import pytest
from PIL import Image, ImageFilter from PIL import Image, ImageFilter
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
class TestImageFilter(PillowTestCase): def test_sanity():
def test_sanity(self): def apply_filter(filter_to_apply):
def filter(filter):
for mode in ["L", "RGB", "CMYK"]: for mode in ["L", "RGB", "CMYK"]:
im = hopper(mode) im = hopper(mode)
out = im.filter(filter) out = im.filter(filter_to_apply)
self.assertEqual(out.mode, im.mode) assert out.mode == im.mode
self.assertEqual(out.size, im.size) assert out.size == im.size
filter(ImageFilter.BLUR) apply_filter(ImageFilter.BLUR)
filter(ImageFilter.CONTOUR) apply_filter(ImageFilter.CONTOUR)
filter(ImageFilter.DETAIL) apply_filter(ImageFilter.DETAIL)
filter(ImageFilter.EDGE_ENHANCE) apply_filter(ImageFilter.EDGE_ENHANCE)
filter(ImageFilter.EDGE_ENHANCE_MORE) apply_filter(ImageFilter.EDGE_ENHANCE_MORE)
filter(ImageFilter.EMBOSS) apply_filter(ImageFilter.EMBOSS)
filter(ImageFilter.FIND_EDGES) apply_filter(ImageFilter.FIND_EDGES)
filter(ImageFilter.SMOOTH) apply_filter(ImageFilter.SMOOTH)
filter(ImageFilter.SMOOTH_MORE) apply_filter(ImageFilter.SMOOTH_MORE)
filter(ImageFilter.SHARPEN) apply_filter(ImageFilter.SHARPEN)
filter(ImageFilter.MaxFilter) apply_filter(ImageFilter.MaxFilter)
filter(ImageFilter.MedianFilter) apply_filter(ImageFilter.MedianFilter)
filter(ImageFilter.MinFilter) apply_filter(ImageFilter.MinFilter)
filter(ImageFilter.ModeFilter) apply_filter(ImageFilter.ModeFilter)
filter(ImageFilter.GaussianBlur) apply_filter(ImageFilter.GaussianBlur)
filter(ImageFilter.GaussianBlur(5)) apply_filter(ImageFilter.GaussianBlur(5))
filter(ImageFilter.BoxBlur(5)) apply_filter(ImageFilter.BoxBlur(5))
filter(ImageFilter.UnsharpMask) apply_filter(ImageFilter.UnsharpMask)
filter(ImageFilter.UnsharpMask(10)) apply_filter(ImageFilter.UnsharpMask(10))
self.assertRaises(TypeError, filter, "hello") with pytest.raises(TypeError):
apply_filter("hello")
def test_crash(self):
def test_crash():
# crashes on small images # crashes on small images
im = Image.new("RGB", (1, 1)) im = Image.new("RGB", (1, 1))
@ -46,7 +48,8 @@ class TestImageFilter(PillowTestCase):
im = Image.new("RGB", (3, 3)) im = Image.new("RGB", (3, 3))
im.filter(ImageFilter.SMOOTH) im.filter(ImageFilter.SMOOTH)
def test_modefilter(self):
def test_modefilter():
def modefilter(mode): def modefilter(mode):
im = Image.new(mode, (3, 3), None) im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9))) im.putdata(list(range(9)))
@ -59,12 +62,13 @@ class TestImageFilter(PillowTestCase):
mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1)) mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
return mod, mod2 return mod, mod2
self.assertEqual(modefilter("1"), (4, 0)) assert modefilter("1") == (4, 0)
self.assertEqual(modefilter("L"), (4, 0)) assert modefilter("L") == (4, 0)
self.assertEqual(modefilter("P"), (4, 0)) assert modefilter("P") == (4, 0)
self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0))) assert modefilter("RGB") == ((4, 0, 0), (0, 0, 0))
def test_rankfilter(self):
def test_rankfilter():
def rankfilter(mode): def rankfilter(mode):
im = Image.new(mode, (3, 3), None) im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9))) im.putdata(list(range(9)))
@ -77,28 +81,35 @@ class TestImageFilter(PillowTestCase):
maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1)) maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1))
return minimum, med, maximum return minimum, med, maximum
self.assertEqual(rankfilter("1"), (0, 4, 8)) assert rankfilter("1") == (0, 4, 8)
self.assertEqual(rankfilter("L"), (0, 4, 8)) assert rankfilter("L") == (0, 4, 8)
self.assertRaises(ValueError, rankfilter, "P") with pytest.raises(ValueError):
self.assertEqual(rankfilter("RGB"), ((0, 0, 0), (4, 0, 0), (8, 0, 0))) rankfilter("P")
self.assertEqual(rankfilter("I"), (0, 4, 8)) assert rankfilter("RGB") == ((0, 0, 0), (4, 0, 0), (8, 0, 0))
self.assertEqual(rankfilter("F"), (0.0, 4.0, 8.0)) assert rankfilter("I") == (0, 4, 8)
assert rankfilter("F") == (0.0, 4.0, 8.0)
def test_rankfilter_properties(self):
def test_rankfilter_properties():
rankfilter = ImageFilter.RankFilter(1, 2) rankfilter = ImageFilter.RankFilter(1, 2)
self.assertEqual(rankfilter.size, 1) assert rankfilter.size == 1
self.assertEqual(rankfilter.rank, 2) assert rankfilter.rank == 2
def test_builtinfilter_p(self):
def test_builtinfilter_p():
builtinFilter = ImageFilter.BuiltinFilter() builtinFilter = ImageFilter.BuiltinFilter()
self.assertRaises(ValueError, builtinFilter.filter, hopper("P")) with pytest.raises(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): def test_kernel_not_enough_coefficients():
with pytest.raises(ValueError):
ImageFilter.Kernel((3, 3), (0, 0))
def test_consistency_3x3():
with Image.open("Tests/images/hopper.bmp") as source: with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss.bmp") as reference: with Image.open("Tests/images/hopper_emboss.bmp") as reference:
kernel = ImageFilter.Kernel( # noqa: E127 kernel = ImageFilter.Kernel( # noqa: E127
@ -119,7 +130,8 @@ class TestImageFilter(PillowTestCase):
Image.merge(mode, reference[: len(mode)]), Image.merge(mode, reference[: len(mode)]),
) )
def test_consistency_5x5(self):
def test_consistency_5x5():
with Image.open("Tests/images/hopper.bmp") as source: with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss_more.bmp") as reference: with Image.open("Tests/images/hopper_emboss_more.bmp") as reference:
kernel = ImageFilter.Kernel( # noqa: E127 kernel = ImageFilter.Kernel( # noqa: E127

View File

@ -1,14 +1,16 @@
import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
class TestImageFromBytes(PillowTestCase): def test_sanity():
def test_sanity(self):
im1 = hopper() im1 = hopper()
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes()) im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
assert_image_equal(im1, im2) assert_image_equal(im1, im2)
def test_not_implemented(self):
self.assertRaises(NotImplementedError, Image.fromstring) def test_not_implemented():
with pytest.raises(NotImplementedError):
Image.fromstring()

View File

@ -1,30 +1,37 @@
from .helper import PillowTestCase, assert_image_equal, hopper import pytest
from .helper import assert_image_equal, hopper
class TestImagePoint(PillowTestCase): def test_sanity():
def test_sanity(self):
im = hopper() im = hopper()
self.assertRaises(ValueError, im.point, list(range(256))) with pytest.raises(ValueError):
im.point(list(range(256)))
im.point(list(range(256)) * 3) im.point(list(range(256)) * 3)
im.point(lambda x: x) im.point(lambda x: x)
im = im.convert("I") im = im.convert("I")
self.assertRaises(ValueError, im.point, list(range(256))) with pytest.raises(ValueError):
im.point(list(range(256)))
im.point(lambda x: x * 1) im.point(lambda x: x * 1)
im.point(lambda x: x + 1) im.point(lambda x: x + 1)
im.point(lambda x: x * 1 + 1) im.point(lambda x: x * 1 + 1)
self.assertRaises(TypeError, im.point, lambda x: x - 1) with pytest.raises(TypeError):
self.assertRaises(TypeError, im.point, lambda x: x / 1) im.point(lambda x: x - 1)
with pytest.raises(TypeError):
im.point(lambda x: x / 1)
def test_16bit_lut(self):
def test_16bit_lut():
""" Tests for 16 bit -> 8 bit lut for converting I->L images """ Tests for 16 bit -> 8 bit lut for converting I->L images
see https://github.com/python-pillow/Pillow/issues/440 see https://github.com/python-pillow/Pillow/issues/440
""" """
im = hopper("I") im = hopper("I")
im.point(list(range(256)) * 256, "L") im.point(list(range(256)) * 256, "L")
def test_f_lut(self):
def test_f_lut():
""" Tests for floating point lut of 8bit gray image """ """ Tests for floating point lut of 8bit gray image """
im = hopper("L") im = hopper("L")
lut = [0.5 * float(x) for x in range(256)] lut = [0.5 * float(x) for x in range(256)]
@ -34,6 +41,8 @@ class TestImagePoint(PillowTestCase):
int_lut = [x // 2 for x in range(256)] int_lut = [x // 2 for x in range(256)]
assert_image_equal(out.convert("L"), im.point(int_lut, "L")) assert_image_equal(out.convert("L"), im.point(int_lut, "L"))
def test_f_mode(self):
def test_f_mode():
im = hopper("F") im = hopper("F")
self.assertRaises(ValueError, im.point, None) with pytest.raises(ValueError):
im.point(None)

View File

@ -3,12 +3,10 @@ from array import array
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
class TestImagePutData(PillowTestCase): def test_sanity():
def test_sanity(self):
im1 = hopper() im1 = hopper()
data = list(im1.getdata()) data = list(im1.getdata())
@ -23,48 +21,53 @@ class TestImagePutData(PillowTestCase):
im2.readonly = 1 im2.readonly = 1
im2.putdata(data) im2.putdata(data)
self.assertFalse(im2.readonly) assert not im2.readonly
assert_image_equal(im1, im2) assert_image_equal(im1, im2)
def test_long_integers(self):
def test_long_integers():
# see bug-200802-systemerror # see bug-200802-systemerror
def put(value): def put(value):
im = Image.new("RGBA", (1, 1)) im = Image.new("RGBA", (1, 1))
im.putdata([value]) im.putdata([value])
return im.getpixel((0, 0)) return im.getpixel((0, 0))
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255)) assert put(0xFFFFFFFF) == (255, 255, 255, 255)
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255)) assert put(0xFFFFFFFF) == (255, 255, 255, 255)
self.assertEqual(put(-1), (255, 255, 255, 255)) assert put(-1) == (255, 255, 255, 255)
self.assertEqual(put(-1), (255, 255, 255, 255)) assert put(-1) == (255, 255, 255, 255)
if sys.maxsize > 2 ** 32: if sys.maxsize > 2 ** 32:
self.assertEqual(put(sys.maxsize), (255, 255, 255, 255)) assert put(sys.maxsize) == (255, 255, 255, 255)
else: else:
self.assertEqual(put(sys.maxsize), (255, 255, 255, 127)) assert put(sys.maxsize) == (255, 255, 255, 127)
def test_pypy_performance(self):
def test_pypy_performance():
im = Image.new("L", (256, 256)) im = Image.new("L", (256, 256))
im.putdata(list(range(256)) * 256) im.putdata(list(range(256)) * 256)
def test_mode_i(self):
def test_mode_i():
src = hopper("L") src = hopper("L")
data = list(src.getdata()) data = list(src.getdata())
im = Image.new("I", src.size, 0) im = Image.new("I", src.size, 0)
im.putdata(data, 2, 256) im.putdata(data, 2, 256)
target = [2 * elt + 256 for elt in data] target = [2 * elt + 256 for elt in data]
self.assertEqual(list(im.getdata()), target) assert list(im.getdata()) == target
def test_mode_F(self):
def test_mode_F():
src = hopper("L") src = hopper("L")
data = list(src.getdata()) data = list(src.getdata())
im = Image.new("F", src.size, 0) im = Image.new("F", src.size, 0)
im.putdata(data, 2.0, 256.0) im.putdata(data, 2.0, 256.0)
target = [2.0 * float(elt) + 256.0 for elt in data] target = [2.0 * float(elt) + 256.0 for elt in data]
self.assertEqual(list(im.getdata()), target) assert list(im.getdata()) == target
def test_array_B(self):
def test_array_B():
# shouldn't segfault # shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008 # see https://github.com/python-pillow/Pillow/issues/1008
@ -72,9 +75,10 @@ class TestImagePutData(PillowTestCase):
im = Image.new("L", (150, 100)) im = Image.new("L", (150, 100))
im.putdata(arr) im.putdata(arr)
self.assertEqual(len(im.getdata()), len(arr)) assert len(im.getdata()) == len(arr)
def test_array_F(self):
def test_array_F():
# shouldn't segfault # shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008 # see https://github.com/python-pillow/Pillow/issues/1008
@ -82,4 +86,4 @@ class TestImagePutData(PillowTestCase):
arr = array("f", [0.0]) * 15000 arr = array("f", [0.0]) * 15000
im.putdata(arr) im.putdata(arr)
self.assertEqual(len(im.getdata()), len(arr)) assert len(im.getdata()) == len(arr)

View File

@ -1,10 +1,10 @@
import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image, assert_image_similar, hopper from .helper import assert_image, assert_image_similar, hopper
class TestImageQuantize(PillowTestCase): def test_sanity():
def test_sanity(self):
image = hopper() image = hopper()
converted = image.quantize() converted = image.quantize()
assert_image(converted, "P", converted.size) assert_image(converted, "P", converted.size)
@ -15,40 +15,46 @@ class TestImageQuantize(PillowTestCase):
assert_image(converted, "P", converted.size) assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 60) assert_image_similar(converted.convert("RGB"), image, 60)
def test_libimagequant_quantize(self):
def test_libimagequant_quantize():
image = hopper() image = hopper()
try: try:
converted = image.quantize(100, Image.LIBIMAGEQUANT) converted = image.quantize(100, Image.LIBIMAGEQUANT)
except ValueError as ex: except ValueError as ex:
if "dependency" in str(ex).lower(): if "dependency" in str(ex).lower():
self.skipTest("libimagequant support not available") pytest.skip("libimagequant support not available")
else: else:
raise raise
assert_image(converted, "P", converted.size) assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 15) assert_image_similar(converted.convert("RGB"), image, 15)
self.assertEqual(len(converted.getcolors()), 100) assert len(converted.getcolors()) == 100
def test_octree_quantize(self):
def test_octree_quantize():
image = hopper() image = hopper()
converted = image.quantize(100, Image.FASTOCTREE) converted = image.quantize(100, Image.FASTOCTREE)
assert_image(converted, "P", converted.size) assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 20) assert_image_similar(converted.convert("RGB"), image, 20)
self.assertEqual(len(converted.getcolors()), 100) assert len(converted.getcolors()) == 100
def test_rgba_quantize(self):
def test_rgba_quantize():
image = hopper("RGBA") image = hopper("RGBA")
self.assertRaises(ValueError, image.quantize, method=0) with pytest.raises(ValueError):
image.quantize(method=0)
self.assertEqual(image.quantize().convert().mode, "RGBA") assert image.quantize().convert().mode == "RGBA"
def test_quantize(self):
def test_quantize():
with Image.open("Tests/images/caption_6_33_22.png") as image: with Image.open("Tests/images/caption_6_33_22.png") as image:
image = image.convert("RGB") image = image.convert("RGB")
converted = image.quantize() converted = image.quantize()
assert_image(converted, "P", converted.size) assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 1) assert_image_similar(converted.convert("RGB"), image, 1)
def test_quantize_no_dither(self):
def test_quantize_no_dither():
image = hopper() image = hopper()
with Image.open("Tests/images/caption_6_33_22.png") as palette: with Image.open("Tests/images/caption_6_33_22.png") as palette:
palette = palette.convert("P") palette = palette.convert("P")
@ -56,7 +62,8 @@ class TestImageQuantize(PillowTestCase):
converted = image.quantize(dither=0, palette=palette) converted = image.quantize(dither=0, palette=palette)
assert_image(converted, "P", converted.size) assert_image(converted, "P", converted.size)
def test_quantize_dither_diff(self):
def test_quantize_dither_diff():
image = hopper() image = hopper()
with Image.open("Tests/images/caption_6_33_22.png") as palette: with Image.open("Tests/images/caption_6_33_22.png") as palette:
palette = palette.convert("P") palette = palette.convert("P")
@ -64,4 +71,4 @@ class TestImageQuantize(PillowTestCase):
dither = image.quantize(dither=1, palette=palette) dither = image.quantize(dither=1, palette=palette)
nodither = image.quantize(dither=0, palette=palette) nodither = image.quantize(dither=0, palette=palette)
self.assertNotEqual(dither.tobytes(), nodither.tobytes()) assert dither.tobytes() != nodither.tobytes()

View File

@ -1,38 +1,41 @@
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper from .helper import assert_image_equal, assert_image_similar, hopper
class TestImageRotate(PillowTestCase): def rotate(im, mode, angle, center=None, translate=None):
def rotate(self, im, mode, angle, center=None, translate=None):
out = im.rotate(angle, center=center, translate=translate) out = im.rotate(angle, center=center, translate=translate)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size) # default rotate clips output assert out.size == im.size # default rotate clips output
out = im.rotate(angle, center=center, translate=translate, expand=1) out = im.rotate(angle, center=center, translate=translate, expand=1)
self.assertEqual(out.mode, mode) assert out.mode == mode
if angle % 180 == 0: if angle % 180 == 0:
self.assertEqual(out.size, im.size) assert out.size == im.size
elif im.size == (0, 0): elif im.size == (0, 0):
self.assertEqual(out.size, im.size) assert out.size == im.size
else: else:
self.assertNotEqual(out.size, im.size) assert out.size != im.size
def test_mode(self):
def test_mode():
for mode in ("1", "P", "L", "RGB", "I", "F"): for mode in ("1", "P", "L", "RGB", "I", "F"):
im = hopper(mode) im = hopper(mode)
self.rotate(im, mode, 45) rotate(im, mode, 45)
def test_angle(self):
def test_angle():
for angle in (0, 90, 180, 270): for angle in (0, 90, 180, 270):
with Image.open("Tests/images/test-card.png") as im: with Image.open("Tests/images/test-card.png") as im:
self.rotate(im, im.mode, angle) rotate(im, im.mode, angle)
def test_zero(self):
def test_zero():
for angle in (0, 45, 90, 180, 270): for angle in (0, 45, 90, 180, 270):
im = Image.new("RGB", (0, 0)) im = Image.new("RGB", (0, 0))
self.rotate(im, im.mode, angle) rotate(im, im.mode, angle)
def test_resample(self):
def test_resample():
# Target image creation, inspected by eye. # Target image creation, inspected by eye.
# >>> im = Image.open('Tests/images/hopper.ppm') # >>> im = Image.open('Tests/images/hopper.ppm')
# >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True) # >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True)
@ -48,7 +51,8 @@ class TestImageRotate(PillowTestCase):
im = im.rotate(45, resample=resample, expand=True) im = im.rotate(45, resample=resample, expand=True)
assert_image_similar(im, target, epsilon) assert_image_similar(im, target, epsilon)
def test_center_0(self):
def test_center_0():
im = hopper() im = hopper()
im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC) im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC)
@ -58,7 +62,8 @@ class TestImageRotate(PillowTestCase):
assert_image_similar(im, target, 15) assert_image_similar(im, target, 15)
def test_center_14(self):
def test_center_14():
im = hopper() im = hopper()
im = im.rotate(45, center=(14, 14), resample=Image.BICUBIC) im = im.rotate(45, center=(14, 14), resample=Image.BICUBIC)
@ -68,7 +73,8 @@ class TestImageRotate(PillowTestCase):
assert_image_similar(im, target, 10) assert_image_similar(im, target, 10)
def test_translate(self):
def test_translate():
im = hopper() im = hopper()
with Image.open("Tests/images/hopper_45.png") as target: with Image.open("Tests/images/hopper_45.png") as target:
target_origin = (target.size[1] / 2 - 64) - 5 target_origin = (target.size[1] / 2 - 64) - 5
@ -80,48 +86,55 @@ class TestImageRotate(PillowTestCase):
assert_image_similar(im, target, 1) assert_image_similar(im, target, 1)
def test_fastpath_center(self):
def test_fastpath_center():
# if the center is -1,-1 and we rotate by 90<=x<=270 the # if the center is -1,-1 and we rotate by 90<=x<=270 the
# resulting image should be black # resulting image should be black
for angle in (90, 180, 270): for angle in (90, 180, 270):
im = hopper().rotate(angle, center=(-1, -1)) im = hopper().rotate(angle, center=(-1, -1))
assert_image_equal(im, Image.new("RGB", im.size, "black")) assert_image_equal(im, Image.new("RGB", im.size, "black"))
def test_fastpath_translate(self):
def test_fastpath_translate():
# if we post-translate by -128 # if we post-translate by -128
# resulting image should be black # resulting image should be black
for angle in (0, 90, 180, 270): for angle in (0, 90, 180, 270):
im = hopper().rotate(angle, translate=(-128, -128)) im = hopper().rotate(angle, translate=(-128, -128))
assert_image_equal(im, Image.new("RGB", im.size, "black")) 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): def test_center():
im = hopper()
rotate(im, im.mode, 45, center=(0, 0))
rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0))
rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0))
def test_rotate_no_fill():
im = Image.new("RGB", (100, 100), "green") im = Image.new("RGB", (100, 100), "green")
im = im.rotate(45) im = im.rotate(45)
with Image.open("Tests/images/rotate_45_no_fill.png") as target: with Image.open("Tests/images/rotate_45_no_fill.png") as target:
assert_image_equal(im, target) assert_image_equal(im, target)
def test_rotate_with_fill(self):
def test_rotate_with_fill():
im = Image.new("RGB", (100, 100), "green") im = Image.new("RGB", (100, 100), "green")
im = im.rotate(45, fillcolor="white") im = im.rotate(45, fillcolor="white")
with Image.open("Tests/images/rotate_45_with_fill.png") as target: with Image.open("Tests/images/rotate_45_with_fill.png") as target:
assert_image_equal(im, target) assert_image_equal(im, target)
def test_alpha_rotate_no_fill(self):
def test_alpha_rotate_no_fill():
# Alpha images are handled differently internally # Alpha images are handled differently internally
im = Image.new("RGBA", (10, 10), "green") im = Image.new("RGBA", (10, 10), "green")
im = im.rotate(45, expand=1) im = im.rotate(45, expand=1)
corner = im.getpixel((0, 0)) corner = im.getpixel((0, 0))
self.assertEqual(corner, (0, 0, 0, 0)) assert corner == (0, 0, 0, 0)
def test_alpha_rotate_with_fill(self):
def test_alpha_rotate_with_fill():
# Alpha images are handled differently internally # Alpha images are handled differently internally
im = Image.new("RGBA", (10, 10), "green") im = Image.new("RGBA", (10, 10), "green")
im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255)) im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255))
corner = im.getpixel((0, 0)) corner = im.getpixel((0, 0))
self.assertEqual(corner, (255, 0, 0, 255)) assert corner == (255, 0, 0, 255)

View File

@ -1,7 +1,7 @@
import pytest
from PIL import Image from PIL import Image
from .helper import ( from .helper import (
PillowTestCase,
assert_image_equal, assert_image_equal,
assert_image_similar, assert_image_similar,
fromstring, fromstring,
@ -10,63 +10,66 @@ from .helper import (
) )
class TestImageThumbnail(PillowTestCase): def test_sanity():
def test_sanity(self):
im = hopper() im = hopper()
self.assertIsNone(im.thumbnail((100, 100))) assert im.thumbnail((100, 100)) is None
self.assertEqual(im.size, (100, 100)) assert im.size == (100, 100)
def test_aspect(self):
def test_aspect():
im = Image.new("L", (128, 128)) im = Image.new("L", (128, 128))
im.thumbnail((100, 100)) im.thumbnail((100, 100))
self.assertEqual(im.size, (100, 100)) assert im.size == (100, 100)
im = Image.new("L", (128, 256)) im = Image.new("L", (128, 256))
im.thumbnail((100, 100)) im.thumbnail((100, 100))
self.assertEqual(im.size, (50, 100)) assert im.size == (50, 100)
im = Image.new("L", (128, 256)) im = Image.new("L", (128, 256))
im.thumbnail((50, 100)) im.thumbnail((50, 100))
self.assertEqual(im.size, (50, 100)) assert im.size == (50, 100)
im = Image.new("L", (256, 128)) im = Image.new("L", (256, 128))
im.thumbnail((100, 100)) im.thumbnail((100, 100))
self.assertEqual(im.size, (100, 50)) assert im.size == (100, 50)
im = Image.new("L", (256, 128)) im = Image.new("L", (256, 128))
im.thumbnail((100, 50)) im.thumbnail((100, 50))
self.assertEqual(im.size, (100, 50)) assert im.size == (100, 50)
im = Image.new("L", (128, 128)) im = Image.new("L", (128, 128))
im.thumbnail((100, 100)) im.thumbnail((100, 100))
self.assertEqual(im.size, (100, 100)) assert im.size == (100, 100)
im = Image.new("L", (256, 162)) # ratio is 1.5802469136 im = Image.new("L", (256, 162)) # ratio is 1.5802469136
im.thumbnail((33, 33)) im.thumbnail((33, 33))
self.assertEqual(im.size, (33, 21)) # ratio is 1.5714285714 assert im.size == (33, 21) # ratio is 1.5714285714
im = Image.new("L", (162, 256)) # ratio is 0.6328125 im = Image.new("L", (162, 256)) # ratio is 0.6328125
im.thumbnail((33, 33)) im.thumbnail((33, 33))
self.assertEqual(im.size, (21, 33)) # ratio is 0.6363636364 assert im.size == (21, 33) # ratio is 0.6363636364
def test_float(self):
def test_float():
im = Image.new("L", (128, 128)) im = Image.new("L", (128, 128))
im.thumbnail((99.9, 99.9)) im.thumbnail((99.9, 99.9))
self.assertEqual(im.size, (100, 100)) assert im.size == (100, 100)
def test_no_resize(self):
def test_no_resize():
# Check that draft() can resize the image to the destination size # Check that draft() can resize the image to the destination size
with Image.open("Tests/images/hopper.jpg") as im: with Image.open("Tests/images/hopper.jpg") as im:
im.draft(None, (64, 64)) im.draft(None, (64, 64))
self.assertEqual(im.size, (64, 64)) assert im.size == (64, 64)
# Test thumbnail(), where only draft() is necessary to resize the image # Test thumbnail(), where only draft() is necessary to resize the image
with Image.open("Tests/images/hopper.jpg") as im: with Image.open("Tests/images/hopper.jpg") as im:
im.thumbnail((64, 64)) im.thumbnail((64, 64))
self.assertEqual(im.size, (64, 64)) assert im.size == (64, 64)
def test_DCT_scaling_edges(self):
def test_DCT_scaling_edges():
# Make an image with red borders and size (N * 8) + 1 to cross DCT grid # Make an image with red borders and size (N * 8) + 1 to cross DCT grid
im = Image.new("RGB", (257, 257), "red") im = Image.new("RGB", (257, 257), "red")
im.paste(Image.new("RGB", (235, 235)), (11, 11)) im.paste(Image.new("RGB", (235, 235)), (11, 11))
@ -79,7 +82,8 @@ class TestImageThumbnail(PillowTestCase):
# This is still JPEG, some error is present. Without the fix it is 11.5 # This is still JPEG, some error is present. Without the fix it is 11.5
assert_image_similar(thumb, ref, 1.5) assert_image_similar(thumb, ref, 1.5)
def test_reducing_gap_values(self):
def test_reducing_gap_values():
im = hopper() im = hopper()
im.thumbnail((18, 18), Image.BICUBIC) im.thumbnail((18, 18), Image.BICUBIC)
@ -90,12 +94,13 @@ class TestImageThumbnail(PillowTestCase):
ref = hopper() ref = hopper()
ref.thumbnail((18, 18), Image.BICUBIC, reducing_gap=None) ref.thumbnail((18, 18), Image.BICUBIC, reducing_gap=None)
with self.assertRaises(AssertionError): with pytest.raises(AssertionError):
assert_image_equal(ref, im) assert_image_equal(ref, im)
assert_image_similar(ref, im, 3.5) assert_image_similar(ref, im, 3.5)
def test_reducing_gap_for_DCT_scaling(self):
def test_reducing_gap_for_DCT_scaling():
with Image.open("Tests/images/hopper.jpg") as ref: with Image.open("Tests/images/hopper.jpg") as ref:
# thumbnail should call draft with reducing_gap scale # thumbnail should call draft with reducing_gap scale
ref.draft(None, (18 * 3, 18 * 3)) ref.draft(None, (18 * 3, 18 * 3))

View File

@ -1,14 +1,16 @@
from .helper import PillowTestCase, assert_image_equal, fromstring, hopper import pytest
from .helper import assert_image_equal, fromstring, hopper
class TestImageToBitmap(PillowTestCase): def test_sanity():
def test_sanity(self):
self.assertRaises(ValueError, lambda: hopper().tobitmap()) with pytest.raises(ValueError):
hopper().tobitmap()
im1 = hopper().convert("1") im1 = hopper().convert("1")
bitmap = im1.tobitmap() bitmap = im1.tobitmap()
self.assertIsInstance(bitmap, bytes) assert isinstance(bitmap, bytes)
assert_image_equal(im1, fromstring(bitmap)) assert_image_equal(im1, fromstring(bitmap))

View File

@ -9,131 +9,136 @@ from PIL.Image import (
) )
from . import helper from . import helper
from .helper import PillowTestCase, assert_image_equal from .helper import assert_image_equal
HOPPER = {
class TestImageTranspose(PillowTestCase):
hopper = {
mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy() mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy()
for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"] for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"]
} }
def test_flip_left_right(self):
def test_flip_left_right():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(FLIP_LEFT_RIGHT) out = im.transpose(FLIP_LEFT_RIGHT)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size) assert out.size == im.size
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, 1))) assert im.getpixel((1, 1)) == out.getpixel((x - 2, 1))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1))) assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, y - 2))) assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, y - 2))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, y - 2))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, y - 2))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_flip_top_bottom(self):
def test_flip_top_bottom():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(FLIP_TOP_BOTTOM) out = im.transpose(FLIP_TOP_BOTTOM)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size) assert out.size == im.size
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y - 2))) assert im.getpixel((1, 1)) == out.getpixel((1, y - 2))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((x - 2, y - 2))) assert im.getpixel((x - 2, 1)) == out.getpixel((x - 2, y - 2))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1))) assert im.getpixel((1, y - 2)) == out.getpixel((1, 1))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((x - 2, 1))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((x - 2, 1))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_rotate_90(self):
def test_rotate_90():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(ROTATE_90) out = im.transpose(ROTATE_90)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size[::-1]) assert out.size == im.size[::-1]
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, x - 2))) assert im.getpixel((1, 1)) == out.getpixel((1, x - 2))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1))) assert im.getpixel((x - 2, 1)) == out.getpixel((1, 1))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, x - 2))) assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, x - 2))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, 1))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, 1))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_rotate_180(self):
def test_rotate_180():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(ROTATE_180) out = im.transpose(ROTATE_180)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size) assert out.size == im.size
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, y - 2))) assert im.getpixel((1, 1)) == out.getpixel((x - 2, y - 2))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, y - 2))) assert im.getpixel((x - 2, 1)) == out.getpixel((1, y - 2))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, 1))) assert im.getpixel((1, y - 2)) == out.getpixel((x - 2, 1))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_rotate_270(self):
def test_rotate_270():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(ROTATE_270) out = im.transpose(ROTATE_270)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size[::-1]) assert out.size == im.size[::-1]
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, 1))) assert im.getpixel((1, 1)) == out.getpixel((y - 2, 1))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, x - 2))) assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, x - 2))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1))) assert im.getpixel((1, y - 2)) == out.getpixel((1, 1))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, x - 2))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, x - 2))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_transpose(self):
def test_transpose():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(TRANSPOSE) out = im.transpose(TRANSPOSE)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size[::-1]) assert out.size == im.size[::-1]
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, 1))) assert im.getpixel((1, 1)) == out.getpixel((1, 1))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, x - 2))) assert im.getpixel((x - 2, 1)) == out.getpixel((1, x - 2))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, 1))) assert im.getpixel((1, y - 2)) == out.getpixel((y - 2, 1))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, x - 2))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((y - 2, x - 2))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_tranverse(self):
def test_tranverse():
def transpose(mode): def transpose(mode):
im = self.hopper[mode] im = HOPPER[mode]
out = im.transpose(TRANSVERSE) out = im.transpose(TRANSVERSE)
self.assertEqual(out.mode, mode) assert out.mode == mode
self.assertEqual(out.size, im.size[::-1]) assert out.size == im.size[::-1]
x, y = im.size x, y = im.size
self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, x - 2))) assert im.getpixel((1, 1)) == out.getpixel((y - 2, x - 2))
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, 1))) assert im.getpixel((x - 2, 1)) == out.getpixel((y - 2, 1))
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, x - 2))) assert im.getpixel((1, y - 2)) == out.getpixel((1, x - 2))
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1))) assert im.getpixel((x - 2, y - 2)) == out.getpixel((1, 1))
for mode in self.hopper: for mode in HOPPER:
transpose(mode) transpose(mode)
def test_roundtrip(self):
for mode in self.hopper: def test_roundtrip():
im = self.hopper[mode] for mode in HOPPER:
im = HOPPER[mode]
def transpose(first, second): def transpose(first, second):
return im.transpose(first).transpose(second) return im.transpose(first).transpose(second)
@ -154,6 +159,4 @@ class TestImageTranspose(PillowTestCase):
assert_image_equal( assert_image_equal(
im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM) im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM)
) )
assert_image_equal( assert_image_equal(im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE))
im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE)
)

View File

@ -1,6 +1,6 @@
from PIL import Image, ImageChops from PIL import Image, ImageChops
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
BLACK = (0, 0, 0) BLACK = (0, 0, 0)
BROWN = (127, 64, 0) BROWN = (127, 64, 0)
@ -13,9 +13,7 @@ WHITE = (255, 255, 255)
GREY = 128 GREY = 128
class TestImageChops(PillowTestCase): def test_sanity():
def test_sanity(self):
im = hopper("L") im = hopper("L")
ImageChops.constant(im, 128) ImageChops.constant(im, 128)
@ -43,7 +41,8 @@ class TestImageChops(PillowTestCase):
ImageChops.offset(im, 10) ImageChops.offset(im, 10)
ImageChops.offset(im, 10, 20) ImageChops.offset(im, 10, 20)
def test_add(self):
def test_add():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -52,10 +51,11 @@ class TestImageChops(PillowTestCase):
new = ImageChops.add(im1, im2) new = ImageChops.add(im1, im2)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76)) assert new.getbbox() == (25, 25, 76, 76)
self.assertEqual(new.getpixel((50, 50)), ORANGE) assert new.getpixel((50, 50)) == ORANGE
def test_add_scale_offset(self):
def test_add_scale_offset():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -64,10 +64,11 @@ class TestImageChops(PillowTestCase):
new = ImageChops.add(im1, im2, scale=2.5, offset=100) new = ImageChops.add(im1, im2, scale=2.5, offset=100)
# Assert # Assert
self.assertEqual(new.getbbox(), (0, 0, 100, 100)) assert new.getbbox() == (0, 0, 100, 100)
self.assertEqual(new.getpixel((50, 50)), (202, 151, 100)) assert new.getpixel((50, 50)) == (202, 151, 100)
def test_add_clip(self):
def test_add_clip():
# Arrange # Arrange
im = hopper() im = hopper()
@ -75,9 +76,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.add(im, im) new = ImageChops.add(im, im)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (255, 255, 254)) assert new.getpixel((50, 50)) == (255, 255, 254)
def test_add_modulo(self):
def test_add_modulo():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -86,10 +88,11 @@ class TestImageChops(PillowTestCase):
new = ImageChops.add_modulo(im1, im2) new = ImageChops.add_modulo(im1, im2)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76)) assert new.getbbox() == (25, 25, 76, 76)
self.assertEqual(new.getpixel((50, 50)), ORANGE) assert new.getpixel((50, 50)) == ORANGE
def test_add_modulo_no_clip(self):
def test_add_modulo_no_clip():
# Arrange # Arrange
im = hopper() im = hopper()
@ -97,9 +100,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.add_modulo(im, im) new = ImageChops.add_modulo(im, im)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (224, 76, 254)) assert new.getpixel((50, 50)) == (224, 76, 254)
def test_blend(self):
def test_blend():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -108,10 +112,11 @@ class TestImageChops(PillowTestCase):
new = ImageChops.blend(im1, im2, 0.5) new = ImageChops.blend(im1, im2, 0.5)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76)) assert new.getbbox() == (25, 25, 76, 76)
self.assertEqual(new.getpixel((50, 50)), BROWN) assert new.getpixel((50, 50)) == BROWN
def test_constant(self):
def test_constant():
# Arrange # Arrange
im = Image.new("RGB", (20, 10)) im = Image.new("RGB", (20, 10))
@ -119,11 +124,12 @@ class TestImageChops(PillowTestCase):
new = ImageChops.constant(im, GREY) new = ImageChops.constant(im, GREY)
# Assert # Assert
self.assertEqual(new.size, im.size) assert new.size == im.size
self.assertEqual(new.getpixel((0, 0)), GREY) assert new.getpixel((0, 0)) == GREY
self.assertEqual(new.getpixel((19, 9)), GREY) assert new.getpixel((19, 9)) == GREY
def test_darker_image(self):
def test_darker_image():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -134,7 +140,8 @@ class TestImageChops(PillowTestCase):
# Assert # Assert
assert_image_equal(new, im2) assert_image_equal(new, im2)
def test_darker_pixel(self):
def test_darker_pixel():
# Arrange # Arrange
im1 = hopper() im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -143,9 +150,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.darker(im1, im2) new = ImageChops.darker(im1, im2)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (240, 166, 0)) assert new.getpixel((50, 50)) == (240, 166, 0)
def test_difference(self):
def test_difference():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1: with Image.open("Tests/images/imagedraw_arc_end_le_start.png") as im1:
with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2: with Image.open("Tests/images/imagedraw_arc_no_loops.png") as im2:
@ -154,9 +162,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.difference(im1, im2) new = ImageChops.difference(im1, im2)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76)) assert new.getbbox() == (25, 25, 76, 76)
def test_difference_pixel(self):
def test_difference_pixel():
# Arrange # Arrange
im1 = hopper() im1 = hopper()
with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2: with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
@ -165,9 +174,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.difference(im1, im2) new = ImageChops.difference(im1, im2)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (240, 166, 128)) assert new.getpixel((50, 50)) == (240, 166, 128)
def test_duplicate(self):
def test_duplicate():
# Arrange # Arrange
im = hopper() im = hopper()
@ -177,7 +187,8 @@ class TestImageChops(PillowTestCase):
# Assert # Assert
assert_image_equal(new, im) assert_image_equal(new, im)
def test_invert(self):
def test_invert():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
@ -185,11 +196,12 @@ class TestImageChops(PillowTestCase):
new = ImageChops.invert(im) new = ImageChops.invert(im)
# Assert # Assert
self.assertEqual(new.getbbox(), (0, 0, 100, 100)) assert new.getbbox() == (0, 0, 100, 100)
self.assertEqual(new.getpixel((0, 0)), WHITE) assert new.getpixel((0, 0)) == WHITE
self.assertEqual(new.getpixel((50, 50)), CYAN) assert new.getpixel((50, 50)) == CYAN
def test_lighter_image(self):
def test_lighter_image():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -200,7 +212,8 @@ class TestImageChops(PillowTestCase):
# Assert # Assert
assert_image_equal(new, im1) assert_image_equal(new, im1)
def test_lighter_pixel(self):
def test_lighter_pixel():
# Arrange # Arrange
im1 = hopper() im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -209,9 +222,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.lighter(im1, im2) new = ImageChops.lighter(im1, im2)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (255, 255, 127)) assert new.getpixel((50, 50)) == (255, 255, 127)
def test_multiply_black(self):
def test_multiply_black():
"""If you multiply an image with a solid black image, """If you multiply an image with a solid black image,
the result is black.""" the result is black."""
# Arrange # Arrange
@ -224,7 +238,8 @@ class TestImageChops(PillowTestCase):
# Assert # Assert
assert_image_equal(new, black) assert_image_equal(new, black)
def test_multiply_green(self):
def test_multiply_green():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
green = Image.new("RGB", im.size, "green") green = Image.new("RGB", im.size, "green")
@ -233,13 +248,13 @@ class TestImageChops(PillowTestCase):
new = ImageChops.multiply(im, green) new = ImageChops.multiply(im, green)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76)) assert new.getbbox() == (25, 25, 76, 76)
self.assertEqual(new.getpixel((25, 25)), DARK_GREEN) assert new.getpixel((25, 25)) == DARK_GREEN
self.assertEqual(new.getpixel((50, 50)), BLACK) assert new.getpixel((50, 50)) == BLACK
def test_multiply_white(self):
"""If you multiply with a solid white image, def test_multiply_white():
the image is unaffected.""" """If you multiply with a solid white image, the image is unaffected."""
# Arrange # Arrange
im1 = hopper() im1 = hopper()
white = Image.new("RGB", im1.size, "white") white = Image.new("RGB", im1.size, "white")
@ -250,7 +265,8 @@ class TestImageChops(PillowTestCase):
# Assert # Assert
assert_image_equal(new, im1) assert_image_equal(new, im1)
def test_offset(self):
def test_offset():
# Arrange # Arrange
xoffset = 45 xoffset = 45
yoffset = 20 yoffset = 20
@ -260,16 +276,15 @@ class TestImageChops(PillowTestCase):
new = ImageChops.offset(im, xoffset, yoffset) new = ImageChops.offset(im, xoffset, yoffset)
# Assert # Assert
self.assertEqual(new.getbbox(), (0, 45, 100, 96)) assert new.getbbox() == (0, 45, 100, 96)
self.assertEqual(new.getpixel((50, 50)), BLACK) assert new.getpixel((50, 50)) == BLACK
self.assertEqual(new.getpixel((50 + xoffset, 50 + yoffset)), DARK_GREEN) assert new.getpixel((50 + xoffset, 50 + yoffset)) == DARK_GREEN
# Test no yoffset # Test no yoffset
self.assertEqual( assert ImageChops.offset(im, xoffset) == ImageChops.offset(im, xoffset, xoffset)
ImageChops.offset(im, xoffset), ImageChops.offset(im, xoffset, xoffset)
)
def test_screen(self):
def test_screen():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1: with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2: with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
@ -278,10 +293,11 @@ class TestImageChops(PillowTestCase):
new = ImageChops.screen(im1, im2) new = ImageChops.screen(im1, im2)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76)) assert new.getbbox() == (25, 25, 76, 76)
self.assertEqual(new.getpixel((50, 50)), ORANGE) assert new.getpixel((50, 50)) == ORANGE
def test_subtract(self):
def test_subtract():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -290,11 +306,12 @@ class TestImageChops(PillowTestCase):
new = ImageChops.subtract(im1, im2) new = ImageChops.subtract(im1, im2)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 50, 76, 76)) assert new.getbbox() == (25, 50, 76, 76)
self.assertEqual(new.getpixel((50, 50)), GREEN) assert new.getpixel((50, 50)) == GREEN
self.assertEqual(new.getpixel((50, 51)), BLACK) assert new.getpixel((50, 51)) == BLACK
def test_subtract_scale_offset(self):
def test_subtract_scale_offset():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -303,10 +320,11 @@ class TestImageChops(PillowTestCase):
new = ImageChops.subtract(im1, im2, scale=2.5, offset=100) new = ImageChops.subtract(im1, im2, scale=2.5, offset=100)
# Assert # Assert
self.assertEqual(new.getbbox(), (0, 0, 100, 100)) assert new.getbbox() == (0, 0, 100, 100)
self.assertEqual(new.getpixel((50, 50)), (100, 202, 100)) assert new.getpixel((50, 50)) == (100, 202, 100)
def test_subtract_clip(self):
def test_subtract_clip():
# Arrange # Arrange
im1 = hopper() im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -315,9 +333,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.subtract(im1, im2) new = ImageChops.subtract(im1, im2)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (0, 0, 127)) assert new.getpixel((50, 50)) == (0, 0, 127)
def test_subtract_modulo(self):
def test_subtract_modulo():
# Arrange # Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
@ -326,11 +345,12 @@ class TestImageChops(PillowTestCase):
new = ImageChops.subtract_modulo(im1, im2) new = ImageChops.subtract_modulo(im1, im2)
# Assert # Assert
self.assertEqual(new.getbbox(), (25, 50, 76, 76)) assert new.getbbox() == (25, 50, 76, 76)
self.assertEqual(new.getpixel((50, 50)), GREEN) assert new.getpixel((50, 50)) == GREEN
self.assertEqual(new.getpixel((50, 51)), BLACK) assert new.getpixel((50, 51)) == BLACK
def test_subtract_modulo_no_clip(self):
def test_subtract_modulo_no_clip():
# Arrange # Arrange
im1 = hopper() im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2: with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
@ -339,9 +359,10 @@ class TestImageChops(PillowTestCase):
new = ImageChops.subtract_modulo(im1, im2) new = ImageChops.subtract_modulo(im1, im2)
# Assert # Assert
self.assertEqual(new.getpixel((50, 50)), (241, 167, 127)) assert new.getpixel((50, 50)) == (241, 167, 127)
def test_logical(self):
def test_logical():
def table(op, a, b): def table(op, a, b):
out = [] out = []
for x in (a, b): for x in (a, b):
@ -351,14 +372,14 @@ class TestImageChops(PillowTestCase):
out.append(op(imx, imy).getpixel((0, 0))) out.append(op(imx, imy).getpixel((0, 0)))
return tuple(out) return tuple(out)
self.assertEqual(table(ImageChops.logical_and, 0, 1), (0, 0, 0, 255)) assert table(ImageChops.logical_and, 0, 1) == (0, 0, 0, 255)
self.assertEqual(table(ImageChops.logical_or, 0, 1), (0, 255, 255, 255)) assert table(ImageChops.logical_or, 0, 1) == (0, 255, 255, 255)
self.assertEqual(table(ImageChops.logical_xor, 0, 1), (0, 255, 255, 0)) assert table(ImageChops.logical_xor, 0, 1) == (0, 255, 255, 0)
self.assertEqual(table(ImageChops.logical_and, 0, 128), (0, 0, 0, 255)) assert table(ImageChops.logical_and, 0, 128) == (0, 0, 0, 255)
self.assertEqual(table(ImageChops.logical_or, 0, 128), (0, 255, 255, 255)) assert table(ImageChops.logical_or, 0, 128) == (0, 255, 255, 255)
self.assertEqual(table(ImageChops.logical_xor, 0, 128), (0, 255, 255, 0)) assert table(ImageChops.logical_xor, 0, 128) == (0, 255, 255, 0)
self.assertEqual(table(ImageChops.logical_and, 0, 255), (0, 0, 0, 255)) assert table(ImageChops.logical_and, 0, 255) == (0, 0, 0, 255)
self.assertEqual(table(ImageChops.logical_or, 0, 255), (0, 255, 255, 255)) assert table(ImageChops.logical_or, 0, 255) == (0, 255, 255, 255)
self.assertEqual(table(ImageChops.logical_xor, 0, 255), (0, 255, 255, 0)) assert table(ImageChops.logical_xor, 0, 255) == (0, 255, 255, 0)

View File

@ -1,17 +1,12 @@
import datetime import datetime
import os import os
import re
from io import BytesIO from io import BytesIO
import pytest import pytest
from PIL import Image, ImageMode from PIL import Image, ImageMode
from .helper import ( from .helper import assert_image, assert_image_equal, assert_image_similar, hopper
PillowTestCase,
assert_image,
assert_image_equal,
assert_image_similar,
hopper,
)
try: try:
from PIL import ImageCms from PIL import ImageCms
@ -19,7 +14,7 @@ try:
ImageCms.core.profile_open ImageCms.core.profile_open
except ImportError: except ImportError:
# Skipped via setUp() # Skipped via setup_module()
pass pass
@ -27,33 +22,33 @@ SRGB = "Tests/icc/sRGB_IEC61966-2-1_black_scaled.icc"
HAVE_PROFILE = os.path.exists(SRGB) HAVE_PROFILE = os.path.exists(SRGB)
class TestImageCms(PillowTestCase): def setup_module():
def setUp(self):
try: try:
from PIL import ImageCms from PIL import ImageCms
# need to hit getattr to trigger the delayed import error # need to hit getattr to trigger the delayed import error
ImageCms.core.profile_open ImageCms.core.profile_open
except ImportError as v: except ImportError as v:
self.skipTest(v) pytest.skip(str(v))
def skip_missing(self):
def skip_missing():
if not HAVE_PROFILE: if not HAVE_PROFILE:
self.skipTest("SRGB profile not available") pytest.skip("SRGB profile not available")
def test_sanity(self):
def test_sanity():
# basic smoke test. # basic smoke test.
# this mostly follows the cms_test outline. # this mostly follows the cms_test outline.
v = ImageCms.versions() # should return four strings v = ImageCms.versions() # should return four strings
self.assertEqual(v[0], "1.0.0 pil") assert v[0] == "1.0.0 pil"
self.assertEqual(list(map(type, v)), [str, str, str, str]) assert list(map(type, v)) == [str, str, str, str]
# internal version number # internal version number
self.assertRegex(ImageCms.core.littlecms_version, r"\d+\.\d+$") assert re.search(r"\d+\.\d+$", ImageCms.core.littlecms_version)
self.skip_missing() skip_missing()
i = ImageCms.profileToProfile(hopper(), SRGB, SRGB) i = ImageCms.profileToProfile(hopper(), SRGB, SRGB)
assert_image(i, "RGB", (128, 128)) assert_image(i, "RGB", (128, 128))
@ -77,130 +72,137 @@ class TestImageCms(PillowTestCase):
assert_image(i, "RGB", (128, 128)) assert_image(i, "RGB", (128, 128))
t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB") t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB")
self.assertEqual(t.inputMode, "RGB") assert t.inputMode == "RGB"
self.assertEqual(t.outputMode, "RGB") assert t.outputMode == "RGB"
i = ImageCms.applyTransform(hopper(), t) i = ImageCms.applyTransform(hopper(), t)
assert_image(i, "RGB", (128, 128)) assert_image(i, "RGB", (128, 128))
# test PointTransform convenience API # test PointTransform convenience API
hopper().point(t) hopper().point(t)
def test_name(self):
self.skip_missing() def test_name():
skip_missing()
# get profile information for file # get profile information for file
self.assertEqual( assert (
ImageCms.getProfileName(SRGB).strip(), ImageCms.getProfileName(SRGB).strip()
"IEC 61966-2-1 Default RGB Colour Space - sRGB", == "IEC 61966-2-1 Default RGB Colour Space - sRGB"
) )
def test_info(self):
self.skip_missing() def test_info():
self.assertEqual( skip_missing()
ImageCms.getProfileInfo(SRGB).splitlines(), assert ImageCms.getProfileInfo(SRGB).splitlines() == [
[
"sRGB IEC61966-2-1 black scaled", "sRGB IEC61966-2-1 black scaled",
"", "",
"Copyright International Color Consortium, 2009", "Copyright International Color Consortium, 2009",
"", "",
], ]
def test_copyright():
skip_missing()
assert (
ImageCms.getProfileCopyright(SRGB).strip()
== "Copyright International Color Consortium, 2009"
) )
def test_copyright(self):
self.skip_missing() def test_manufacturer():
self.assertEqual( skip_missing()
ImageCms.getProfileCopyright(SRGB).strip(), assert ImageCms.getProfileManufacturer(SRGB).strip() == ""
"Copyright International Color Consortium, 2009",
def test_model():
skip_missing()
assert (
ImageCms.getProfileModel(SRGB).strip()
== "IEC 61966-2-1 Default RGB Colour Space - sRGB"
) )
def test_manufacturer(self):
self.skip_missing()
self.assertEqual(ImageCms.getProfileManufacturer(SRGB).strip(), "")
def test_model(self): def test_description():
self.skip_missing() skip_missing()
self.assertEqual( assert (
ImageCms.getProfileModel(SRGB).strip(), ImageCms.getProfileDescription(SRGB).strip() == "sRGB IEC61966-2-1 black scaled"
"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): def test_intent():
self.skip_missing() skip_missing()
self.assertEqual(ImageCms.getDefaultIntent(SRGB), 0) assert ImageCms.getDefaultIntent(SRGB) == 0
self.assertEqual( support = ImageCms.isIntentSupported(
ImageCms.isIntentSupported(
SRGB, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, ImageCms.DIRECTION_INPUT SRGB, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, ImageCms.DIRECTION_INPUT
),
1,
) )
assert support == 1
def test_profile_object(self):
def test_profile_object():
# same, using profile object # same, using profile object
p = ImageCms.createProfile("sRGB") p = ImageCms.createProfile("sRGB")
# self.assertEqual(ImageCms.getProfileName(p).strip(), # assert ImageCms.getProfileName(p).strip() == "sRGB built-in - (lcms internal)"
# 'sRGB built-in - (lcms internal)') # assert ImageCms.getProfileInfo(p).splitlines() ==
# self.assertEqual(ImageCms.getProfileInfo(p).splitlines(), # ["sRGB built-in", "", "WhitePoint : D65 (daylight)", "", ""]
# ['sRGB built-in', '', 'WhitePoint : D65 (daylight)', '', '']) assert ImageCms.getDefaultIntent(p) == 0
self.assertEqual(ImageCms.getDefaultIntent(p), 0) support = ImageCms.isIntentSupported(
self.assertEqual(
ImageCms.isIntentSupported(
p, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, ImageCms.DIRECTION_INPUT p, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, ImageCms.DIRECTION_INPUT
),
1,
) )
assert support == 1
def test_extensions(self):
def test_extensions():
# extensions # extensions
with Image.open("Tests/images/rgb.jpg") as i: with Image.open("Tests/images/rgb.jpg") as i:
p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"])) p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"]))
self.assertEqual( assert (
ImageCms.getProfileName(p).strip(), ImageCms.getProfileName(p).strip()
"IEC 61966-2.1 Default RGB colour space - sRGB", == "IEC 61966-2.1 Default RGB colour space - sRGB"
) )
def test_exceptions(self):
def test_exceptions():
# Test mode mismatch # Test mode mismatch
psRGB = ImageCms.createProfile("sRGB") psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB") pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB")
self.assertRaises(ValueError, t.apply_in_place, hopper("RGBA")) with pytest.raises(ValueError):
t.apply_in_place(hopper("RGBA"))
# the procedural pyCMS API uses PyCMSError for all sorts of errors # the procedural pyCMS API uses PyCMSError for all sorts of errors
with hopper() as im: with hopper() as im:
self.assertRaises( with pytest.raises(ImageCms.PyCMSError):
ImageCms.PyCMSError, ImageCms.profileToProfile, im, "foo", "bar" ImageCms.profileToProfile(im, "foo", "bar")
) with pytest.raises(ImageCms.PyCMSError):
self.assertRaises( ImageCms.buildTransform("foo", "bar", "RGB", "RGB")
ImageCms.PyCMSError, ImageCms.buildTransform, "foo", "bar", "RGB", "RGB" with pytest.raises(ImageCms.PyCMSError):
) ImageCms.getProfileName(None)
self.assertRaises(ImageCms.PyCMSError, ImageCms.getProfileName, None) skip_missing()
self.skip_missing() with pytest.raises(ImageCms.PyCMSError):
self.assertRaises( ImageCms.isIntentSupported(SRGB, None, None)
ImageCms.PyCMSError, ImageCms.isIntentSupported, SRGB, None, None
)
def test_display_profile(self):
def test_display_profile():
# try fetching the profile for the current display device # try fetching the profile for the current display device
ImageCms.get_display_profile() ImageCms.get_display_profile()
def test_lab_color_profile(self):
def test_lab_color_profile():
ImageCms.createProfile("LAB", 5000) ImageCms.createProfile("LAB", 5000)
ImageCms.createProfile("LAB", 6500) ImageCms.createProfile("LAB", 6500)
def test_unsupported_color_space(self):
self.assertRaises(ImageCms.PyCMSError, ImageCms.createProfile, "unsupported")
def test_invalid_color_temperature(self): def test_unsupported_color_space():
self.assertRaises(ImageCms.PyCMSError, ImageCms.createProfile, "LAB", "invalid") with pytest.raises(ImageCms.PyCMSError):
ImageCms.createProfile("unsupported")
def test_simple_lab(self):
def test_invalid_color_temperature():
with pytest.raises(ImageCms.PyCMSError):
ImageCms.createProfile("LAB", "invalid")
def test_simple_lab():
i = Image.new("RGB", (10, 10), (128, 128, 128)) i = Image.new("RGB", (10, 10), (128, 128, 128))
psRGB = ImageCms.createProfile("sRGB") psRGB = ImageCms.createProfile("sRGB")
@ -209,28 +211,28 @@ class TestImageCms(PillowTestCase):
i_lab = ImageCms.applyTransform(i, t) i_lab = ImageCms.applyTransform(i, t)
self.assertEqual(i_lab.mode, "LAB") assert i_lab.mode == "LAB"
k = i_lab.getpixel((0, 0)) k = i_lab.getpixel((0, 0))
# not a linear luminance map. so L != 128: # not a linear luminance map. so L != 128:
self.assertEqual(k, (137, 128, 128)) assert k == (137, 128, 128)
l_data = i_lab.getdata(0) l_data = i_lab.getdata(0)
a_data = i_lab.getdata(1) a_data = i_lab.getdata(1)
b_data = i_lab.getdata(2) b_data = i_lab.getdata(2)
self.assertEqual(list(l_data), [137] * 100) assert list(l_data) == [137] * 100
self.assertEqual(list(a_data), [128] * 100) assert list(a_data) == [128] * 100
self.assertEqual(list(b_data), [128] * 100) assert list(b_data) == [128] * 100
def test_lab_color(self):
def test_lab_color():
psRGB = ImageCms.createProfile("sRGB") psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB") pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB") t = ImageCms.buildTransform(psRGB, pLab, "RGB", "LAB")
# Need to add a type mapping for some PIL type to TYPE_Lab_8 in # Need to add a type mapping for some PIL type to TYPE_Lab_8 in findLCMSType, and
# findLCMSType, and have that mapping work back to a PIL mode # have that mapping work back to a PIL mode (likely RGB).
# (likely RGB).
i = ImageCms.applyTransform(hopper(), t) i = ImageCms.applyTransform(hopper(), t)
assert_image(i, "LAB", (128, 128)) assert_image(i, "LAB", (128, 128))
@ -239,7 +241,8 @@ class TestImageCms(PillowTestCase):
with Image.open("Tests/images/hopper.Lab.tif") as target: with Image.open("Tests/images/hopper.Lab.tif") as target:
assert_image_similar(i, target, 3.5) assert_image_similar(i, target, 3.5)
def test_lab_srgb(self):
def test_lab_srgb():
psRGB = ImageCms.createProfile("sRGB") psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB") pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB") t = ImageCms.buildTransform(pLab, psRGB, "LAB", "RGB")
@ -250,12 +253,13 @@ class TestImageCms(PillowTestCase):
# img_srgb.save('temp.srgb.tif') # visually verified vs ps. # img_srgb.save('temp.srgb.tif') # visually verified vs ps.
assert_image_similar(hopper(), img_srgb, 30) assert_image_similar(hopper(), img_srgb, 30)
self.assertTrue(img_srgb.info["icc_profile"]) assert img_srgb.info["icc_profile"]
profile = ImageCmsProfile(BytesIO(img_srgb.info["icc_profile"])) profile = ImageCmsProfile(BytesIO(img_srgb.info["icc_profile"]))
self.assertIn("sRGB", ImageCms.getProfileDescription(profile)) assert "sRGB" in ImageCms.getProfileDescription(profile)
def test_lab_roundtrip(self):
def test_lab_roundtrip():
# check to see if we're at least internally consistent. # check to see if we're at least internally consistent.
psRGB = ImageCms.createProfile("sRGB") psRGB = ImageCms.createProfile("sRGB")
pLab = ImageCms.createProfile("LAB") pLab = ImageCms.createProfile("LAB")
@ -265,28 +269,27 @@ class TestImageCms(PillowTestCase):
i = ImageCms.applyTransform(hopper(), t) i = ImageCms.applyTransform(hopper(), t)
self.assertEqual(i.info["icc_profile"], ImageCmsProfile(pLab).tobytes()) assert i.info["icc_profile"] == ImageCmsProfile(pLab).tobytes()
out = ImageCms.applyTransform(i, t2) out = ImageCms.applyTransform(i, t2)
assert_image_similar(hopper(), out, 2) assert_image_similar(hopper(), out, 2)
def test_profile_tobytes(self):
def test_profile_tobytes():
with Image.open("Tests/images/rgb.jpg") as i: with Image.open("Tests/images/rgb.jpg") as i:
p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"])) p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"]))
p2 = ImageCms.getOpenProfile(BytesIO(p.tobytes())) p2 = ImageCms.getOpenProfile(BytesIO(p.tobytes()))
# not the same bytes as the original icc_profile, # not the same bytes as the original icc_profile, but it does roundtrip
# but it does roundtrip assert p.tobytes() == p2.tobytes()
self.assertEqual(p.tobytes(), p2.tobytes()) assert ImageCms.getProfileName(p) == ImageCms.getProfileName(p2)
self.assertEqual(ImageCms.getProfileName(p), ImageCms.getProfileName(p2)) assert ImageCms.getProfileDescription(p) == ImageCms.getProfileDescription(p2)
self.assertEqual(
ImageCms.getProfileDescription(p), ImageCms.getProfileDescription(p2)
)
def test_extended_information(self):
self.skip_missing() def test_extended_information():
skip_missing()
o = ImageCms.getOpenProfile(SRGB) o = ImageCms.getOpenProfile(SRGB)
p = o.profile p = o.profile
@ -303,9 +306,9 @@ class TestImageCms(PillowTestCase):
for val in tuple_or_float for val in tuple_or_float
) )
self.assertEqual(truncate_tuple(tup1), truncate_tuple(tup2)) assert truncate_tuple(tup1) == truncate_tuple(tup2)
self.assertEqual(p.attributes, 4294967296) assert p.attributes == 4294967296
assert_truncated_tuple_equal( assert_truncated_tuple_equal(
p.blue_colorant, p.blue_colorant,
( (
@ -335,24 +338,21 @@ class TestImageCms(PillowTestCase):
), ),
), ),
) )
self.assertIsNone(p.chromaticity) assert p.chromaticity is None
self.assertEqual( assert p.clut == {
p.clut,
{
0: (False, False, True), 0: (False, False, True),
1: (False, False, True), 1: (False, False, True),
2: (False, False, True), 2: (False, False, True),
3: (False, False, True), 3: (False, False, True),
}, }
)
self.assertIsNone(p.colorant_table) assert p.colorant_table is None
self.assertIsNone(p.colorant_table_out) assert p.colorant_table_out is None
self.assertIsNone(p.colorimetric_intent) assert p.colorimetric_intent is None
self.assertEqual(p.connection_space, "XYZ ") assert p.connection_space == "XYZ "
self.assertEqual(p.copyright, "Copyright International Color Consortium, 2009") assert p.copyright == "Copyright International Color Consortium, 2009"
self.assertEqual(p.creation_date, datetime.datetime(2009, 2, 27, 21, 36, 31)) assert p.creation_date == datetime.datetime(2009, 2, 27, 21, 36, 31)
self.assertEqual(p.device_class, "mntr") assert p.device_class == "mntr"
assert_truncated_tuple_equal( assert_truncated_tuple_equal(
p.green_colorant, p.green_colorant,
( (
@ -367,33 +367,27 @@ class TestImageCms(PillowTestCase):
(0.32119768793686687, 0.5978443567149709, 0.7168731974161346), (0.32119768793686687, 0.5978443567149709, 0.7168731974161346),
), ),
) )
self.assertEqual(p.header_flags, 0) assert p.header_flags == 0
self.assertEqual(p.header_manufacturer, "\x00\x00\x00\x00") assert p.header_manufacturer == "\x00\x00\x00\x00"
self.assertEqual(p.header_model, "\x00\x00\x00\x00") assert p.header_model == "\x00\x00\x00\x00"
self.assertEqual( assert p.icc_measurement_condition == {
p.icc_measurement_condition,
{
"backing": (0.0, 0.0, 0.0), "backing": (0.0, 0.0, 0.0),
"flare": 0.0, "flare": 0.0,
"geo": "unknown", "geo": "unknown",
"observer": 1, "observer": 1,
"illuminant_type": "D65", "illuminant_type": "D65",
}, }
) assert p.icc_version == 33554432
self.assertEqual(p.icc_version, 33554432) assert p.icc_viewing_condition is None
self.assertIsNone(p.icc_viewing_condition) assert p.intent_supported == {
self.assertEqual(
p.intent_supported,
{
0: (True, True, True), 0: (True, True, True),
1: (True, True, True), 1: (True, True, True),
2: (True, True, True), 2: (True, True, True),
3: (True, True, True), 3: (True, True, True),
}, }
) assert p.is_matrix_shaper
self.assertTrue(p.is_matrix_shaper) assert p.luminance == ((0.0, 80.0, 0.0), (0.0, 1.0, 80.0))
self.assertEqual(p.luminance, ((0.0, 80.0, 0.0), (0.0, 1.0, 80.0))) assert p.manufacturer is None
self.assertIsNone(p.manufacturer)
assert_truncated_tuple_equal( assert_truncated_tuple_equal(
p.media_black_point, p.media_black_point,
( (
@ -411,12 +405,12 @@ class TestImageCms(PillowTestCase):
assert_truncated_tuple_equal( assert_truncated_tuple_equal(
(p.media_white_point_temperature,), (5000.722328847392,) (p.media_white_point_temperature,), (5000.722328847392,)
) )
self.assertEqual(p.model, "IEC 61966-2-1 Default RGB Colour Space - sRGB") assert p.model == "IEC 61966-2-1 Default RGB Colour Space - sRGB"
self.assertIsNone(p.perceptual_rendering_intent_gamut) assert p.perceptual_rendering_intent_gamut is None
self.assertEqual(p.profile_description, "sRGB IEC61966-2-1 black scaled") assert 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 p.profile_id == b")\xf8=\xde\xaf\xf2U\xaexB\xfa\xe4\xca\x839\r"
assert_truncated_tuple_equal( assert_truncated_tuple_equal(
p.red_colorant, p.red_colorant,
( (
@ -431,25 +425,24 @@ class TestImageCms(PillowTestCase):
(0.6484536250319214, 0.3308524944738204, 0.22248840582960838), (0.6484536250319214, 0.3308524944738204, 0.22248840582960838),
), ),
) )
self.assertEqual(p.rendering_intent, 0) assert p.rendering_intent == 0
self.assertIsNone(p.saturation_rendering_intent_gamut) assert p.saturation_rendering_intent_gamut is None
self.assertIsNone(p.screening_description) assert p.screening_description is None
self.assertIsNone(p.target) assert p.target is None
self.assertEqual(p.technology, "CRT ") assert p.technology == "CRT "
self.assertEqual(p.version, 2.0) assert p.version == 2.0
self.assertEqual( assert p.viewing_condition == "Reference Viewing Condition in IEC 61966-2-1"
p.viewing_condition, "Reference Viewing Condition in IEC 61966-2-1" assert p.xcolor_space == "RGB "
)
self.assertEqual(p.xcolor_space, "RGB ")
def test_deprecations(self):
self.skip_missing() def test_deprecations():
skip_missing()
o = ImageCms.getOpenProfile(SRGB) o = ImageCms.getOpenProfile(SRGB)
p = o.profile p = o.profile
def helper_deprecated(attr, expected): def helper_deprecated(attr, expected):
result = pytest.warns(DeprecationWarning, getattr, p, attr) result = pytest.warns(DeprecationWarning, getattr, p, attr)
self.assertEqual(result, expected) assert result == expected
# p.color_space # p.color_space
helper_deprecated("color_space", "RGB") helper_deprecated("color_space", "RGB")
@ -472,22 +465,22 @@ class TestImageCms(PillowTestCase):
helper_deprecated("product_manufacturer", "") helper_deprecated("product_manufacturer", "")
# p.product_model # p.product_model
helper_deprecated( helper_deprecated("product_model", "IEC 61966-2-1 Default RGB Colour Space - sRGB")
"product_model", "IEC 61966-2-1 Default RGB Colour Space - sRGB"
)
def test_profile_typesafety(self):
def test_profile_typesafety():
""" Profile init type safety """ Profile init type safety
prepatch, these would segfault, postpatch they should emit a typeerror prepatch, these would segfault, postpatch they should emit a typeerror
""" """
with self.assertRaises(TypeError): with pytest.raises(TypeError):
ImageCms.ImageCmsProfile(0).tobytes() ImageCms.ImageCmsProfile(0).tobytes()
with self.assertRaises(TypeError): with pytest.raises(TypeError):
ImageCms.ImageCmsProfile(1).tobytes() ImageCms.ImageCmsProfile(1).tobytes()
def assert_aux_channel_preserved(self, mode, transform_in_place, preserved_channel):
def assert_aux_channel_preserved(mode, transform_in_place, preserved_channel):
def create_test_image(): def create_test_image():
# set up test image with something interesting in the tested aux channel. # set up test image with something interesting in the tested aux channel.
# fmt: off # fmt: off
@ -541,27 +534,32 @@ class TestImageCms(PillowTestCase):
assert_image_equal(source_image_aux, result_image_aux) assert_image_equal(source_image_aux, result_image_aux)
def test_preserve_auxiliary_channels_rgba(self):
self.assert_aux_channel_preserved( def test_preserve_auxiliary_channels_rgba():
assert_aux_channel_preserved(
mode="RGBA", transform_in_place=False, preserved_channel="A" mode="RGBA", transform_in_place=False, preserved_channel="A"
) )
def test_preserve_auxiliary_channels_rgba_in_place(self):
self.assert_aux_channel_preserved( def test_preserve_auxiliary_channels_rgba_in_place():
assert_aux_channel_preserved(
mode="RGBA", transform_in_place=True, preserved_channel="A" mode="RGBA", transform_in_place=True, preserved_channel="A"
) )
def test_preserve_auxiliary_channels_rgbx(self):
self.assert_aux_channel_preserved( def test_preserve_auxiliary_channels_rgbx():
assert_aux_channel_preserved(
mode="RGBX", transform_in_place=False, preserved_channel="X" mode="RGBX", transform_in_place=False, preserved_channel="X"
) )
def test_preserve_auxiliary_channels_rgbx_in_place(self):
self.assert_aux_channel_preserved( def test_preserve_auxiliary_channels_rgbx_in_place():
assert_aux_channel_preserved(
mode="RGBX", transform_in_place=True, preserved_channel="X" mode="RGBX", transform_in_place=True, preserved_channel="X"
) )
def test_auxiliary_channels_isolated(self):
def test_auxiliary_channels_isolated():
# test data in aux channels does not affect non-aux channels # test data in aux channels does not affect non-aux channels
aux_channel_formats = [ aux_channel_formats = [
# format, profile, color-only format, source test image # format, profile, color-only format, source test image
@ -590,9 +588,7 @@ class TestImageCms(PillowTestCase):
# test conversion from aux-ful source # test conversion from aux-ful source
if transform_in_place: if transform_in_place:
test_image = source_image.copy() test_image = source_image.copy()
ImageCms.applyTransform( ImageCms.applyTransform(test_image, test_transform, inPlace=True)
test_image, test_transform, inPlace=True
)
else: else:
test_image = ImageCms.applyTransform( test_image = ImageCms.applyTransform(
source_image, test_transform, inPlace=False source_image, test_transform, inPlace=False
@ -609,6 +605,4 @@ class TestImageCms(PillowTestCase):
source_image.convert(src_format[2]), reference_transform source_image.convert(src_format[2]), reference_transform
) )
assert_image_equal( assert_image_equal(test_image.convert(dst_format[2]), reference_image)
test_image.convert(dst_format[2]), reference_image
)

View File

@ -1,9 +1,9 @@
import os.path import os.path
import unittest
import pytest
from PIL import Image, ImageColor, ImageDraw, ImageFont, features from PIL import Image, ImageColor, ImageDraw, ImageFont, features
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper from .helper import assert_image_equal, assert_image_similar, hopper
BLACK = (0, 0, 0) BLACK = (0, 0, 0)
WHITE = (255, 255, 255) WHITE = (255, 255, 255)
@ -33,8 +33,7 @@ KITE_POINTS = [(10, 50), (70, 10), (90, 50), (70, 90), (10, 50)]
HAS_FREETYPE = features.check("freetype2") HAS_FREETYPE = features.check("freetype2")
class TestImageDraw(PillowTestCase): def test_sanity():
def test_sanity(self):
im = hopper("RGB").copy() im = hopper("RGB").copy()
draw = ImageDraw.ImageDraw(im) draw = ImageDraw.ImageDraw(im)
@ -45,18 +44,22 @@ class TestImageDraw(PillowTestCase):
draw.polygon(list(range(100))) draw.polygon(list(range(100)))
draw.rectangle(list(range(4))) draw.rectangle(list(range(4)))
def test_valueerror(self):
def test_valueerror():
with Image.open("Tests/images/chi.gif") as im: with Image.open("Tests/images/chi.gif") as im:
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
draw.line((0, 0), fill=(0, 0, 0)) draw.line((0, 0), fill=(0, 0, 0))
def test_mode_mismatch(self):
def test_mode_mismatch():
im = hopper("RGB").copy() im = hopper("RGB").copy()
self.assertRaises(ValueError, ImageDraw.ImageDraw, im, mode="L") with pytest.raises(ValueError):
ImageDraw.ImageDraw(im, mode="L")
def helper_arc(self, bbox, start, end):
def helper_arc(bbox, start, end):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -67,15 +70,18 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open("Tests/images/imagedraw_arc.png"), 1) 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): def test_arc1():
self.helper_arc(BBOX2, 0, 180) helper_arc(BBOX1, 0, 180)
self.helper_arc(BBOX2, 0.5, 180.4) helper_arc(BBOX1, 0.5, 180.4)
def test_arc_end_le_start(self):
def test_arc2():
helper_arc(BBOX2, 0, 180)
helper_arc(BBOX2, 0.5, 180.4)
def test_arc_end_le_start():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -86,11 +92,10 @@ class TestImageDraw(PillowTestCase):
draw.arc(BBOX1, start=start, end=end) draw.arc(BBOX1, start=start, end=end)
# Assert # Assert
assert_image_equal( assert_image_equal(im, Image.open("Tests/images/imagedraw_arc_end_le_start.png"))
im, Image.open("Tests/images/imagedraw_arc_end_le_start.png")
)
def test_arc_no_loops(self):
def test_arc_no_loops():
# No need to go in loops # No need to go in loops
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
@ -102,11 +107,10 @@ class TestImageDraw(PillowTestCase):
draw.arc(BBOX1, start=start, end=end) draw.arc(BBOX1, start=start, end=end)
# Assert # Assert
assert_image_similar( assert_image_similar(im, Image.open("Tests/images/imagedraw_arc_no_loops.png"), 1)
im, Image.open("Tests/images/imagedraw_arc_no_loops.png"), 1
)
def test_arc_width(self):
def test_arc_width():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -118,7 +122,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_arc_width_pieslice_large(self):
def test_arc_width_pieslice_large():
# Tests an arc with a large enough width that it is a pieslice # Tests an arc with a large enough width that it is a pieslice
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
@ -131,7 +136,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_arc_width_fill(self):
def test_arc_width_fill():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -143,7 +149,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_arc_width_non_whole_angle(self):
def test_arc_width_non_whole_angle():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -155,7 +162,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_bitmap(self):
def test_bitmap():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -168,7 +176,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_bitmap.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_bitmap.png"))
def helper_chord(self, mode, bbox, start, end):
def helper_chord(mode, bbox, start, end):
# Arrange # Arrange
im = Image.new(mode, (W, H)) im = Image.new(mode, (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -180,17 +189,20 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) 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): def test_chord1():
for mode in ["RGB", "L"]: for mode in ["RGB", "L"]:
self.helper_chord(mode, BBOX2, 0, 180) helper_chord(mode, BBOX1, 0, 180)
self.helper_chord(mode, BBOX2, 0.5, 180.4) helper_chord(mode, BBOX1, 0.5, 180.4)
def test_chord_width(self):
def test_chord2():
for mode in ["RGB", "L"]:
helper_chord(mode, BBOX2, 0, 180)
helper_chord(mode, BBOX2, 0.5, 180.4)
def test_chord_width():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -202,7 +214,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_chord_width_fill(self):
def test_chord_width_fill():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -214,7 +227,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def helper_ellipse(self, mode, bbox):
def helper_ellipse(mode, bbox):
# Arrange # Arrange
im = Image.new(mode, (W, H)) im = Image.new(mode, (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -226,15 +240,18 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) 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): def test_ellipse1():
for mode in ["RGB", "L"]: for mode in ["RGB", "L"]:
self.helper_ellipse(mode, BBOX2) helper_ellipse(mode, BBOX1)
def test_ellipse_edge(self):
def test_ellipse2():
for mode in ["RGB", "L"]:
helper_ellipse(mode, BBOX2)
def test_ellipse_edge():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -243,18 +260,18 @@ class TestImageDraw(PillowTestCase):
draw.ellipse(((0, 0), (W - 1, H)), fill="white") draw.ellipse(((0, 0), (W - 1, H)), fill="white")
# Assert # Assert
assert_image_similar( assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1)
im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1
)
def test_ellipse_symmetric(self):
def test_ellipse_symmetric():
for bbox in [(25, 25, 76, 76), (25, 25, 75, 75)]: for bbox in [(25, 25, 76, 76), (25, 25, 75, 75)]:
im = Image.new("RGB", (101, 101)) im = Image.new("RGB", (101, 101))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
draw.ellipse(bbox, fill="green", outline="blue") draw.ellipse(bbox, fill="green", outline="blue")
assert_image_equal(im, im.transpose(Image.FLIP_LEFT_RIGHT)) assert_image_equal(im, im.transpose(Image.FLIP_LEFT_RIGHT))
def test_ellipse_width(self):
def test_ellipse_width():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -266,7 +283,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_ellipse_width_large(self):
def test_ellipse_width_large():
# Arrange # Arrange
im = Image.new("RGB", (500, 500)) im = Image.new("RGB", (500, 500))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -278,7 +296,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_ellipse_width_fill(self):
def test_ellipse_width_fill():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -290,7 +309,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def helper_line(self, points):
def helper_line(points):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -301,13 +321,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
def test_line1(self):
self.helper_line(POINTS1)
def test_line2(self): def test_line1():
self.helper_line(POINTS2) helper_line(POINTS1)
def test_shape1(self):
def test_line2():
helper_line(POINTS2)
def test_shape1():
# Arrange # Arrange
im = Image.new("RGB", (100, 100), "white") im = Image.new("RGB", (100, 100), "white")
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -327,7 +350,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_shape1.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_shape1.png"))
def test_shape2(self):
def test_shape2():
# Arrange # Arrange
im = Image.new("RGB", (100, 100), "white") im = Image.new("RGB", (100, 100), "white")
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -347,7 +371,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_shape2.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_shape2.png"))
def helper_pieslice(self, bbox, start, end):
def helper_pieslice(bbox, start, end):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -358,15 +383,18 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open("Tests/images/imagedraw_pieslice.png"), 1) 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): def test_pieslice1():
self.helper_pieslice(BBOX2, -90, 45) helper_pieslice(BBOX1, -90, 45)
self.helper_pieslice(BBOX2, -90.5, 45.4) helper_pieslice(BBOX1, -90.5, 45.4)
def test_pieslice_width(self):
def test_pieslice2():
helper_pieslice(BBOX2, -90, 45)
helper_pieslice(BBOX2, -90.5, 45.4)
def test_pieslice_width():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -378,7 +406,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_pieslice_width_fill(self):
def test_pieslice_width_fill():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -390,7 +419,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def helper_point(self, points):
def helper_point(points):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -401,13 +431,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_point.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_point.png"))
def test_point1(self):
self.helper_point(POINTS1)
def test_point2(self): def test_point1():
self.helper_point(POINTS2) helper_point(POINTS1)
def helper_polygon(self, points):
def test_point2():
helper_point(POINTS2)
def helper_polygon(points):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -418,13 +451,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png"))
def test_polygon1(self):
self.helper_polygon(POINTS1)
def test_polygon2(self): def test_polygon1():
self.helper_polygon(POINTS2) helper_polygon(POINTS1)
def test_polygon_kite(self):
def test_polygon2():
helper_polygon(POINTS2)
def test_polygon_kite():
# Test drawing lines of different gradients (dx>dy, dy>dx) and # Test drawing lines of different gradients (dx>dy, dy>dx) and
# vertical (dx==0) and horizontal (dy==0) lines # vertical (dx==0) and horizontal (dy==0) lines
for mode in ["RGB", "L"]: for mode in ["RGB", "L"]:
@ -439,7 +475,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open(expected)) assert_image_equal(im, Image.open(expected))
def helper_rectangle(self, bbox):
def helper_rectangle(bbox):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -450,13 +487,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png"))
def test_rectangle1(self):
self.helper_rectangle(BBOX1)
def test_rectangle2(self): def test_rectangle1():
self.helper_rectangle(BBOX2) helper_rectangle(BBOX1)
def test_big_rectangle(self):
def test_rectangle2():
helper_rectangle(BBOX2)
def test_big_rectangle():
# Test drawing a rectangle bigger than the image # Test drawing a rectangle bigger than the image
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
@ -470,7 +510,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_rectangle_width(self):
def test_rectangle_width():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -482,7 +523,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open(expected)) assert_image_equal(im, Image.open(expected))
def test_rectangle_width_fill(self):
def test_rectangle_width_fill():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -494,7 +536,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open(expected)) assert_image_equal(im, Image.open(expected))
def test_rectangle_I16(self):
def test_rectangle_I16():
# Arrange # Arrange
im = Image.new("I;16", (W, H)) im = Image.new("I;16", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -507,7 +550,8 @@ class TestImageDraw(PillowTestCase):
im.convert("I"), Image.open("Tests/images/imagedraw_rectangle_I.png") im.convert("I"), Image.open("Tests/images/imagedraw_rectangle_I.png")
) )
def test_floodfill(self):
def test_floodfill():
red = ImageColor.getrgb("red") red = ImageColor.getrgb("red")
for mode, value in [("L", 1), ("RGBA", (255, 0, 0, 0)), ("RGB", red)]: for mode, value in [("L", 1), ("RGBA", (255, 0, 0, 0)), ("RGB", red)]:
@ -538,7 +582,8 @@ class TestImageDraw(PillowTestCase):
ImageDraw.floodfill(im, (0, 0), red) ImageDraw.floodfill(im, (0, 0), red)
assert_image_equal(im, Image.new("RGB", (1, 1), red)) assert_image_equal(im, Image.new("RGB", (1, 1), red))
def test_floodfill_border(self):
def test_floodfill_border():
# floodfill() is experimental # floodfill() is experimental
# Arrange # Arrange
@ -549,16 +594,14 @@ class TestImageDraw(PillowTestCase):
# Act # Act
ImageDraw.floodfill( ImageDraw.floodfill(
im, im, centre_point, ImageColor.getrgb("red"), border=ImageColor.getrgb("black"),
centre_point,
ImageColor.getrgb("red"),
border=ImageColor.getrgb("black"),
) )
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png"))
def test_floodfill_thresh(self):
def test_floodfill_thresh():
# floodfill() is experimental # floodfill() is experimental
# Arrange # Arrange
@ -573,7 +616,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_floodfill2.png"))
def test_floodfill_not_negative(self):
def test_floodfill_not_negative():
# floodfill() is experimental # floodfill() is experimental
# Test that floodfill does not extend into negative coordinates # Test that floodfill does not extend into negative coordinates
@ -591,8 +635,9 @@ class TestImageDraw(PillowTestCase):
im, Image.open("Tests/images/imagedraw_floodfill_not_negative.png") im, Image.open("Tests/images/imagedraw_floodfill_not_negative.png")
) )
def create_base_image_draw( def create_base_image_draw(
self, size, mode=DEFAULT_MODE, background1=WHITE, background2=GRAY size, mode=DEFAULT_MODE, background1=WHITE, background2=GRAY
): ):
img = Image.new(mode, size, background1) img = Image.new(mode, size, background1)
for x in range(0, size[0]): for x in range(0, size[0]):
@ -601,35 +646,38 @@ class TestImageDraw(PillowTestCase):
img.putpixel((x, y), background2) img.putpixel((x, y), background2)
return img, ImageDraw.Draw(img) return img, ImageDraw.Draw(img)
def test_square(self):
def test_square():
with Image.open(os.path.join(IMAGES_PATH, "square.png")) as expected: with Image.open(os.path.join(IMAGES_PATH, "square.png")) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((10, 10)) img, draw = create_base_image_draw((10, 10))
draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK) draw.polygon([(2, 2), (2, 7), (7, 7), (7, 2)], BLACK)
assert_image_equal(img, expected, "square as normal polygon failed") assert_image_equal(img, expected, "square as normal polygon failed")
img, draw = self.create_base_image_draw((10, 10)) img, draw = create_base_image_draw((10, 10))
draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK) draw.polygon([(7, 7), (7, 2), (2, 2), (2, 7)], BLACK)
assert_image_equal(img, expected, "square as inverted polygon failed") assert_image_equal(img, expected, "square as inverted polygon failed")
img, draw = self.create_base_image_draw((10, 10)) img, draw = create_base_image_draw((10, 10))
draw.rectangle((2, 2, 7, 7), BLACK) draw.rectangle((2, 2, 7, 7), BLACK)
assert_image_equal(img, expected, "square as normal rectangle failed") assert_image_equal(img, expected, "square as normal rectangle failed")
img, draw = self.create_base_image_draw((10, 10)) img, draw = create_base_image_draw((10, 10))
draw.rectangle((7, 7, 2, 2), BLACK) draw.rectangle((7, 7, 2, 2), BLACK)
assert_image_equal(img, expected, "square as inverted rectangle failed") assert_image_equal(img, expected, "square as inverted rectangle failed")
def test_triangle_right(self):
def test_triangle_right():
with Image.open(os.path.join(IMAGES_PATH, "triangle_right.png")) as expected: with Image.open(os.path.join(IMAGES_PATH, "triangle_right.png")) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK) draw.polygon([(3, 5), (17, 5), (10, 12)], BLACK)
assert_image_equal(img, expected, "triangle right failed") assert_image_equal(img, expected, "triangle right failed")
def test_line_horizontal(self):
def test_line_horizontal():
with Image.open( with Image.open(
os.path.join(IMAGES_PATH, "line_horizontal_w2px_normal.png") os.path.join(IMAGES_PATH, "line_horizontal_w2px_normal.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 5), BLACK, 2) draw.line((5, 5, 14, 5), BLACK, 2)
assert_image_equal( assert_image_equal(
img, expected, "line straight horizontal normal 2px wide failed" img, expected, "line straight horizontal normal 2px wide failed"
@ -638,21 +686,19 @@ class TestImageDraw(PillowTestCase):
os.path.join(IMAGES_PATH, "line_horizontal_w2px_inverted.png") os.path.join(IMAGES_PATH, "line_horizontal_w2px_inverted.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((14, 5, 5, 5), BLACK, 2) draw.line((14, 5, 5, 5), BLACK, 2)
assert_image_equal( assert_image_equal(
img, expected, "line straight horizontal inverted 2px wide failed" img, expected, "line straight horizontal inverted 2px wide failed"
) )
with Image.open( with Image.open(os.path.join(IMAGES_PATH, "line_horizontal_w3px.png")) as expected:
os.path.join(IMAGES_PATH, "line_horizontal_w3px.png")
) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 5), BLACK, 3) draw.line((5, 5, 14, 5), BLACK, 3)
assert_image_equal( assert_image_equal(
img, expected, "line straight horizontal normal 3px wide failed" img, expected, "line straight horizontal normal 3px wide failed"
) )
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((14, 5, 5, 5), BLACK, 3) draw.line((14, 5, 5, 5), BLACK, 3)
assert_image_equal( assert_image_equal(
img, expected, "line straight horizontal inverted 3px wide failed" img, expected, "line straight horizontal inverted 3px wide failed"
@ -661,30 +707,28 @@ class TestImageDraw(PillowTestCase):
os.path.join(IMAGES_PATH, "line_horizontal_w101px.png") os.path.join(IMAGES_PATH, "line_horizontal_w101px.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((200, 110)) img, draw = create_base_image_draw((200, 110))
draw.line((5, 55, 195, 55), BLACK, 101) draw.line((5, 55, 195, 55), BLACK, 101)
assert_image_equal( assert_image_equal(img, expected, "line straight horizontal 101px wide failed")
img, expected, "line straight horizontal 101px wide failed"
)
def test_line_h_s1_w2(self):
self.skipTest("failing") def test_line_h_s1_w2():
pytest.skip("failing")
with Image.open( with Image.open(
os.path.join(IMAGES_PATH, "line_horizontal_slope1px_w2px.png") os.path.join(IMAGES_PATH, "line_horizontal_slope1px_w2px.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 6), BLACK, 2) draw.line((5, 5, 14, 6), BLACK, 2)
assert_image_equal( assert_image_equal(img, expected, "line horizontal 1px slope 2px wide failed")
img, expected, "line horizontal 1px slope 2px wide failed"
)
def test_line_vertical(self):
def test_line_vertical():
with Image.open( with Image.open(
os.path.join(IMAGES_PATH, "line_vertical_w2px_normal.png") os.path.join(IMAGES_PATH, "line_vertical_w2px_normal.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 5, 14), BLACK, 2) draw.line((5, 5, 5, 14), BLACK, 2)
assert_image_equal( assert_image_equal(
img, expected, "line straight vertical normal 2px wide failed" img, expected, "line straight vertical normal 2px wide failed"
@ -693,75 +737,62 @@ class TestImageDraw(PillowTestCase):
os.path.join(IMAGES_PATH, "line_vertical_w2px_inverted.png") os.path.join(IMAGES_PATH, "line_vertical_w2px_inverted.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 14, 5, 5), BLACK, 2) draw.line((5, 14, 5, 5), BLACK, 2)
assert_image_equal( assert_image_equal(
img, expected, "line straight vertical inverted 2px wide failed" img, expected, "line straight vertical inverted 2px wide failed"
) )
with Image.open( with Image.open(os.path.join(IMAGES_PATH, "line_vertical_w3px.png")) as expected:
os.path.join(IMAGES_PATH, "line_vertical_w3px.png")
) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 5, 14), BLACK, 3) draw.line((5, 5, 5, 14), BLACK, 3)
assert_image_equal( assert_image_equal(
img, expected, "line straight vertical normal 3px wide failed" img, expected, "line straight vertical normal 3px wide failed"
) )
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 14, 5, 5), BLACK, 3) draw.line((5, 14, 5, 5), BLACK, 3)
assert_image_equal( assert_image_equal(
img, expected, "line straight vertical inverted 3px wide failed" img, expected, "line straight vertical inverted 3px wide failed"
) )
with Image.open( with Image.open(os.path.join(IMAGES_PATH, "line_vertical_w101px.png")) as expected:
os.path.join(IMAGES_PATH, "line_vertical_w101px.png")
) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((110, 200)) img, draw = create_base_image_draw((110, 200))
draw.line((55, 5, 55, 195), BLACK, 101) draw.line((55, 5, 55, 195), BLACK, 101)
assert_image_equal( assert_image_equal(img, expected, "line straight vertical 101px wide failed")
img, expected, "line straight vertical 101px wide failed"
)
with Image.open( with Image.open(
os.path.join(IMAGES_PATH, "line_vertical_slope1px_w2px.png") os.path.join(IMAGES_PATH, "line_vertical_slope1px_w2px.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 6, 14), BLACK, 2) draw.line((5, 5, 6, 14), BLACK, 2)
assert_image_equal(img, expected, "line vertical 1px slope 2px wide failed") assert_image_equal(img, expected, "line vertical 1px slope 2px wide failed")
def test_line_oblique_45(self):
def test_line_oblique_45():
with Image.open( with Image.open(
os.path.join(IMAGES_PATH, "line_oblique_45_w3px_a.png") os.path.join(IMAGES_PATH, "line_oblique_45_w3px_a.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((5, 5, 14, 14), BLACK, 3) draw.line((5, 5, 14, 14), BLACK, 3)
assert_image_equal( assert_image_equal(img, expected, "line oblique 45 normal 3px wide A failed")
img, expected, "line oblique 45 normal 3px wide A failed" img, draw = create_base_image_draw((20, 20))
)
img, draw = self.create_base_image_draw((20, 20))
draw.line((14, 14, 5, 5), BLACK, 3) draw.line((14, 14, 5, 5), BLACK, 3)
assert_image_equal( assert_image_equal(img, expected, "line oblique 45 inverted 3px wide A failed")
img, expected, "line oblique 45 inverted 3px wide A failed"
)
with Image.open( with Image.open(
os.path.join(IMAGES_PATH, "line_oblique_45_w3px_b.png") os.path.join(IMAGES_PATH, "line_oblique_45_w3px_b.png")
) as expected: ) as expected:
expected.load() expected.load()
img, draw = self.create_base_image_draw((20, 20)) img, draw = create_base_image_draw((20, 20))
draw.line((14, 5, 5, 14), BLACK, 3) draw.line((14, 5, 5, 14), BLACK, 3)
assert_image_equal( assert_image_equal(img, expected, "line oblique 45 normal 3px wide B failed")
img, expected, "line oblique 45 normal 3px wide B failed" img, draw = create_base_image_draw((20, 20))
)
img, draw = self.create_base_image_draw((20, 20))
draw.line((5, 14, 14, 5), BLACK, 3) draw.line((5, 14, 14, 5), BLACK, 3)
assert_image_equal( assert_image_equal(img, expected, "line oblique 45 inverted 3px wide B failed")
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 def test_wide_line_dot():
# a single point # Test drawing a wide "line" from one point to another just draws a single point
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -773,7 +804,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_line_joint(self):
def test_line_joint():
im = Image.new("RGB", (500, 325)) im = Image.new("RGB", (500, 325))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
expected = "Tests/images/imagedraw_line_joint_curve.png" expected = "Tests/images/imagedraw_line_joint_curve.png"
@ -800,7 +832,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 3) assert_image_similar(im, Image.open(expected), 3)
def test_textsize_empty_string(self):
def test_textsize_empty_string():
# https://github.com/python-pillow/Pillow/issues/2783 # https://github.com/python-pillow/Pillow/issues/2783
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
@ -813,21 +846,21 @@ class TestImageDraw(PillowTestCase):
draw.textsize("\n") draw.textsize("\n")
draw.textsize("test\n") draw.textsize("test\n")
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_textsize_stroke(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_textsize_stroke():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 20) font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 20)
# Act / Assert # Act / Assert
self.assertEqual(draw.textsize("A", font, stroke_width=2), (16, 20)) assert draw.textsize("A", font, stroke_width=2) == (16, 20)
self.assertEqual( assert draw.multiline_textsize("ABC\nAaaa", font, stroke_width=2) == (52, 44)
draw.multiline_textsize("ABC\nAaaa", font, stroke_width=2), (52, 44)
)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_stroke(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_stroke():
for suffix, stroke_fill in {"same": None, "different": "#0f0"}.items(): for suffix, stroke_fill in {"same": None, "different": "#0f0"}.items():
# Arrange # Arrange
im = Image.new("RGB", (120, 130)) im = Image.new("RGB", (120, 130))
@ -835,17 +868,16 @@ class TestImageDraw(PillowTestCase):
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120) font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 120)
# Act # Act
draw.text( draw.text((10, 10), "A", "#f00", font, stroke_width=2, stroke_fill=stroke_fill)
(10, 10), "A", "#f00", font, stroke_width=2, stroke_fill=stroke_fill
)
# Assert # Assert
assert_image_similar( assert_image_similar(
im, Image.open("Tests/images/imagedraw_stroke_" + suffix + ".png"), 3.1 im, Image.open("Tests/images/imagedraw_stroke_" + suffix + ".png"), 3.1
) )
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_stroke_multiline(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_stroke_multiline():
# Arrange # Arrange
im = Image.new("RGB", (100, 250)) im = Image.new("RGB", (100, 250))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
@ -861,7 +893,8 @@ class TestImageDraw(PillowTestCase):
im, Image.open("Tests/images/imagedraw_stroke_multiline.png"), 3.3 im, Image.open("Tests/images/imagedraw_stroke_multiline.png"), 3.3
) )
def test_same_color_outline(self):
def test_same_color_outline():
# Prepare shape # Prepare shape
x0, y0 = 5, 5 x0, y0 = 5, 5
x1, y1 = 5, 50 x1, y1 = 5, 50

View File

@ -1,9 +1,9 @@
import os.path import os.path
import unittest
import pytest
from PIL import Image, ImageDraw2, features from PIL import Image, ImageDraw2, features
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper from .helper import assert_image_equal, assert_image_similar, hopper
BLACK = (0, 0, 0) BLACK = (0, 0, 0)
WHITE = (255, 255, 255) WHITE = (255, 255, 255)
@ -34,8 +34,7 @@ HAS_FREETYPE = features.check("freetype2")
FONT_PATH = "Tests/fonts/FreeMono.ttf" FONT_PATH = "Tests/fonts/FreeMono.ttf"
class TestImageDraw(PillowTestCase): def test_sanity():
def test_sanity(self):
im = hopper("RGB").copy() im = hopper("RGB").copy()
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -48,7 +47,8 @@ class TestImageDraw(PillowTestCase):
pen = ImageDraw2.Pen("blue", width=7) pen = ImageDraw2.Pen("blue", width=7)
draw.line(list(range(10)), pen) draw.line(list(range(10)), pen)
def helper_ellipse(self, mode, bbox):
def helper_ellipse(mode, bbox):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -62,13 +62,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
def test_ellipse1(self):
self.helper_ellipse("RGB", BBOX1)
def test_ellipse2(self): def test_ellipse1():
self.helper_ellipse("RGB", BBOX2) helper_ellipse("RGB", BBOX1)
def test_ellipse_edge(self):
def test_ellipse2():
helper_ellipse("RGB", BBOX2)
def test_ellipse_edge():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -78,11 +81,10 @@ class TestImageDraw(PillowTestCase):
draw.ellipse(((0, 0), (W - 1, H)), brush) draw.ellipse(((0, 0), (W - 1, H)), brush)
# Assert # Assert
assert_image_similar( assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1)
im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1
)
def helper_line(self, points):
def helper_line(points):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -94,13 +96,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) 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): def test_line1_pen():
self.helper_line(POINTS2) helper_line(POINTS1)
def test_line_pen_as_brush(self):
def test_line2_pen():
helper_line(POINTS2)
def test_line_pen_as_brush():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -114,7 +119,8 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
def helper_polygon(self, points):
def helper_polygon(points):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -127,13 +133,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png"))
def test_polygon1(self):
self.helper_polygon(POINTS1)
def test_polygon2(self): def test_polygon1():
self.helper_polygon(POINTS2) helper_polygon(POINTS1)
def helper_rectangle(self, bbox):
def test_polygon2():
helper_polygon(POINTS2)
def helper_rectangle(bbox):
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -146,13 +155,16 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png")) assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png"))
def test_rectangle1(self):
self.helper_rectangle(BBOX1)
def test_rectangle2(self): def test_rectangle1():
self.helper_rectangle(BBOX2) helper_rectangle(BBOX1)
def test_big_rectangle(self):
def test_rectangle2():
helper_rectangle(BBOX2)
def test_big_rectangle():
# Test drawing a rectangle bigger than the image # Test drawing a rectangle bigger than the image
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
@ -167,8 +179,9 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 1) assert_image_similar(im, Image.open(expected), 1)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_text(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_text():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -181,8 +194,9 @@ class TestImageDraw(PillowTestCase):
# Assert # Assert
assert_image_similar(im, Image.open(expected), 13) assert_image_similar(im, Image.open(expected), 13)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_textsize(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_textsize():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -192,10 +206,11 @@ class TestImageDraw(PillowTestCase):
size = draw.textsize("ImageDraw2", font) size = draw.textsize("ImageDraw2", font)
# Assert # Assert
self.assertEqual(size[1], 12) assert size[1] == 12
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_textsize_empty_string(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_textsize_empty_string():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)
@ -208,8 +223,9 @@ class TestImageDraw(PillowTestCase):
draw.textsize("\n", font) draw.textsize("\n", font)
draw.textsize("test\n", font) draw.textsize("test\n", font)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_flush(self): @pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_flush():
# Arrange # Arrange
im = Image.new("RGB", (W, H)) im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im) draw = ImageDraw2.Draw(im)

View File

@ -1,11 +1,9 @@
from PIL import Image, ImageEnhance from PIL import Image, ImageEnhance
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
class TestImageEnhance(PillowTestCase): def test_sanity():
def test_sanity(self):
# FIXME: assert_image # FIXME: assert_image
# Implicit asserts no exception: # Implicit asserts no exception:
ImageEnhance.Color(hopper()).enhance(0.5) ImageEnhance.Color(hopper()).enhance(0.5)
@ -13,13 +11,14 @@ class TestImageEnhance(PillowTestCase):
ImageEnhance.Brightness(hopper()).enhance(0.5) ImageEnhance.Brightness(hopper()).enhance(0.5)
ImageEnhance.Sharpness(hopper()).enhance(0.5) ImageEnhance.Sharpness(hopper()).enhance(0.5)
def test_crash(self):
def test_crash():
# crashes on small images # crashes on small images
im = Image.new("RGB", (1, 1)) im = Image.new("RGB", (1, 1))
ImageEnhance.Sharpness(im).enhance(0.5) ImageEnhance.Sharpness(im).enhance(0.5)
def _half_transparent_image(self):
def _half_transparent_image():
# returns an image, half transparent, half solid # returns an image, half transparent, half solid
im = hopper("RGB") im = hopper("RGB")
@ -30,23 +29,25 @@ class TestImageEnhance(PillowTestCase):
return im return im
def _check_alpha(self, im, original, op, amount):
self.assertEqual(im.getbands(), original.getbands()) def _check_alpha(im, original, op, amount):
assert im.getbands() == original.getbands()
assert_image_equal( assert_image_equal(
im.getchannel("A"), im.getchannel("A"),
original.getchannel("A"), original.getchannel("A"),
"Diff on {}: {}".format(op, amount), "Diff on {}: {}".format(op, amount),
) )
def test_alpha(self):
def test_alpha():
# Issue https://github.com/python-pillow/Pillow/issues/899 # Issue https://github.com/python-pillow/Pillow/issues/899
# Is alpha preserved through image enhancement? # Is alpha preserved through image enhancement?
original = self._half_transparent_image() original = _half_transparent_image()
for op in ["Color", "Brightness", "Contrast", "Sharpness"]: for op in ["Color", "Brightness", "Contrast", "Sharpness"]:
for amount in [0, 0.5, 1.0]: for amount in [0, 0.5, 1.0]:
self._check_alpha( _check_alpha(
getattr(ImageEnhance, op)(original).enhance(amount), getattr(ImageEnhance, op)(original).enhance(amount),
original, original,
op, op,

View File

@ -1,7 +1,7 @@
import pytest
from PIL import Image, ImageOps from PIL import Image, ImageOps
from .helper import ( from .helper import (
PillowTestCase,
assert_image_equal, assert_image_equal,
assert_image_similar, assert_image_similar,
assert_tuple_approx_equal, assert_tuple_approx_equal,
@ -16,15 +16,16 @@ except ImportError:
HAVE_WEBP = False HAVE_WEBP = False
class TestImageOps(PillowTestCase):
class Deformer: class Deformer:
def getmesh(self, im): def getmesh(self, im):
x, y = im.size x, y = im.size
return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))] return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))]
deformer = Deformer() deformer = Deformer()
def test_sanity(self):
def test_sanity():
ImageOps.autocontrast(hopper("L")) ImageOps.autocontrast(hopper("L"))
ImageOps.autocontrast(hopper("RGB")) ImageOps.autocontrast(hopper("RGB"))
@ -41,8 +42,8 @@ class TestImageOps(PillowTestCase):
ImageOps.crop(hopper("L"), 1) ImageOps.crop(hopper("L"), 1)
ImageOps.crop(hopper("RGB"), 1) ImageOps.crop(hopper("RGB"), 1)
ImageOps.deform(hopper("L"), self.deformer) ImageOps.deform(hopper("L"), deformer)
ImageOps.deform(hopper("RGB"), self.deformer) ImageOps.deform(hopper("RGB"), deformer)
ImageOps.equalize(hopper("L")) ImageOps.equalize(hopper("L"))
ImageOps.equalize(hopper("RGB")) ImageOps.equalize(hopper("RGB"))
@ -76,18 +77,20 @@ class TestImageOps(PillowTestCase):
ImageOps.exif_transpose(hopper("L")) ImageOps.exif_transpose(hopper("L"))
ImageOps.exif_transpose(hopper("RGB")) ImageOps.exif_transpose(hopper("RGB"))
def test_1pxfit(self):
def test_1pxfit():
# Division by zero in equalize if image is 1 pixel high # Division by zero in equalize if image is 1 pixel high
newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35)) newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
self.assertEqual(newimg.size, (35, 35)) assert newimg.size == (35, 35)
newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35)) newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35))
self.assertEqual(newimg.size, (35, 35)) assert newimg.size == (35, 35)
newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35)) newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35))
self.assertEqual(newimg.size, (35, 35)) assert newimg.size == (35, 35)
def test_fit_same_ratio(self):
def test_fit_same_ratio():
# The ratio for this image is 1000.0 / 755 = 1.3245033112582782 # The ratio for this image is 1000.0 / 755 = 1.3245033112582782
# If the ratios are not acknowledged to be the same, # If the ratios are not acknowledged to be the same,
# and Pillow attempts to adjust the width to # and Pillow attempts to adjust the width to
@ -95,14 +98,15 @@ class TestImageOps(PillowTestCase):
# then centering this greater width causes a negative x offset when cropping # then centering this greater width causes a negative x offset when cropping
with Image.new("RGB", (1000, 755)) as im: with Image.new("RGB", (1000, 755)) as im:
new_im = ImageOps.fit(im, (1000, 755)) new_im = ImageOps.fit(im, (1000, 755))
self.assertEqual(new_im.size, (1000, 755)) assert new_im.size == (1000, 755)
def test_pad(self):
def test_pad():
# Same ratio # Same ratio
im = hopper() im = hopper()
new_size = (im.width * 2, im.height * 2) new_size = (im.width * 2, im.height * 2)
new_im = ImageOps.pad(im, new_size) new_im = ImageOps.pad(im, new_size)
self.assertEqual(new_im.size, new_size) assert new_im.size == new_size
for label, color, new_size in [ for label, color, new_size in [
("h", None, (im.width * 4, im.height * 2)), ("h", None, (im.width * 4, im.height * 2)),
@ -110,14 +114,15 @@ class TestImageOps(PillowTestCase):
]: ]:
for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]): for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]):
new_im = ImageOps.pad(im, new_size, color=color, centering=centering) new_im = ImageOps.pad(im, new_size, color=color, centering=centering)
self.assertEqual(new_im.size, new_size) assert new_im.size == new_size
with Image.open( with Image.open(
"Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg" "Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg"
) as target: ) as target:
assert_image_similar(new_im, target, 6) assert_image_similar(new_im, target, 6)
def test_pil163(self):
def test_pil163():
# Division by zero in equalize if < 255 pixels in image (@PIL163) # Division by zero in equalize if < 255 pixels in image (@PIL163)
i = hopper("RGB").resize((15, 16)) i = hopper("RGB").resize((15, 16))
@ -126,23 +131,25 @@ class TestImageOps(PillowTestCase):
ImageOps.equalize(i.convert("P")) ImageOps.equalize(i.convert("P"))
ImageOps.equalize(i.convert("RGB")) ImageOps.equalize(i.convert("RGB"))
def test_scale(self):
def test_scale():
# Test the scaling function # Test the scaling function
i = hopper("L").resize((50, 50)) i = hopper("L").resize((50, 50))
with self.assertRaises(ValueError): with pytest.raises(ValueError):
ImageOps.scale(i, -1) ImageOps.scale(i, -1)
newimg = ImageOps.scale(i, 1) newimg = ImageOps.scale(i, 1)
self.assertEqual(newimg.size, (50, 50)) assert newimg.size == (50, 50)
newimg = ImageOps.scale(i, 2) newimg = ImageOps.scale(i, 2)
self.assertEqual(newimg.size, (100, 100)) assert newimg.size == (100, 100)
newimg = ImageOps.scale(i, 0.5) newimg = ImageOps.scale(i, 0.5)
self.assertEqual(newimg.size, (25, 25)) assert newimg.size == (25, 25)
def test_colorize_2color(self):
def test_colorize_2color():
# Test the colorizing function with 2-color functionality # Test the colorizing function with 2-color functionality
# Open test image (256px by 10px, black to white) # Open test image (256px by 10px, black to white)
@ -175,7 +182,8 @@ class TestImageOps(PillowTestCase):
msg="white test pixel incorrect", msg="white test pixel incorrect",
) )
def test_colorize_2color_offset(self):
def test_colorize_2color_offset():
# Test the colorizing function with 2-color functionality and offset # Test the colorizing function with 2-color functionality and offset
# Open test image (256px by 10px, black to white) # Open test image (256px by 10px, black to white)
@ -210,7 +218,8 @@ class TestImageOps(PillowTestCase):
msg="white test pixel incorrect", msg="white test pixel incorrect",
) )
def test_colorize_3color_offset(self):
def test_colorize_3color_offset():
# Test the colorizing function with 3-color functionality and offset # Test the colorizing function with 3-color functionality and offset
# Open test image (256px by 10px, black to white) # Open test image (256px by 10px, black to white)
@ -262,7 +271,8 @@ class TestImageOps(PillowTestCase):
msg="white test pixel incorrect", msg="white test pixel incorrect",
) )
def test_exif_transpose(self):
def test_exif_transpose():
exts = [".jpg"] exts = [".jpg"]
if HAVE_WEBP and _webp.HAVE_WEBPANIM: if HAVE_WEBP and _webp.HAVE_WEBPANIM:
exts.append(".webp") exts.append(".webp")
@ -275,22 +285,19 @@ class TestImageOps(PillowTestCase):
orientation_im.copy(), orientation_im.copy(),
]: # ImageFile # Image ]: # ImageFile # Image
if orientation_im is base_im: if orientation_im is base_im:
self.assertNotIn("exif", im.info) assert "exif" not in im.info
else: else:
original_exif = im.info["exif"] original_exif = im.info["exif"]
transposed_im = ImageOps.exif_transpose(im) transposed_im = ImageOps.exif_transpose(im)
assert_image_similar(base_im, transposed_im, 17) assert_image_similar(base_im, transposed_im, 17)
if orientation_im is base_im: if orientation_im is base_im:
self.assertNotIn("exif", im.info) assert "exif" not in im.info
else: else:
self.assertNotEqual( assert transposed_im.info["exif"] != original_exif
transposed_im.info["exif"], original_exif
)
self.assertNotIn(0x0112, transposed_im.getexif()) assert 0x0112 not in transposed_im.getexif()
# Repeat the operation # Repeat the operation to test that it does not keep transposing
# to test that it does not keep transposing
transposed_im2 = ImageOps.exif_transpose(transposed_im) transposed_im2 = ImageOps.exif_transpose(transposed_im)
assert_image_equal(transposed_im2, transposed_im) assert_image_equal(transposed_im2, transposed_im)

View File

@ -1,8 +1,7 @@
import unittest import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
try: try:
from PIL import ImageTk from PIL import ImageTk
@ -12,23 +11,25 @@ try:
dir(ImageTk) dir(ImageTk)
HAS_TK = True HAS_TK = True
except (OSError, ImportError): except (OSError, ImportError):
# Skipped via setUp() # Skipped via pytestmark
HAS_TK = False HAS_TK = False
TK_MODES = ("1", "L", "P", "RGB", "RGBA") TK_MODES = ("1", "L", "P", "RGB", "RGBA")
@unittest.skipUnless(HAS_TK, "Tk not installed") pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed")
class TestImageTk(PillowTestCase):
def setUp(self):
def setup_module():
try: try:
# setup tk # setup tk
tk.Frame() tk.Frame()
# root = tk.Tk() # root = tk.Tk()
except tk.TclError as v: except tk.TclError as v:
self.skipTest("TCL Error: %s" % v) pytest.skip("TCL Error: %s" % v)
def test_kw(self):
def test_kw():
TEST_JPG = "Tests/images/hopper.jpg" TEST_JPG = "Tests/images/hopper.jpg"
TEST_PNG = "Tests/images/hopper.png" TEST_PNG = "Tests/images/hopper.png"
with Image.open(TEST_JPG) as im1: with Image.open(TEST_JPG) as im1:
@ -47,9 +48,10 @@ class TestImageTk(PillowTestCase):
# Test no relevant entry # Test no relevant entry
im = ImageTk._get_image_from_kw(kw) im = ImageTk._get_image_from_kw(kw)
self.assertIsNone(im) assert im is None
def test_photoimage(self):
def test_photoimage():
for mode in TK_MODES: for mode in TK_MODES:
# test as image: # test as image:
im = hopper(mode) im = hopper(mode)
@ -57,31 +59,33 @@ class TestImageTk(PillowTestCase):
# this should not crash # this should not crash
im_tk = ImageTk.PhotoImage(im) im_tk = ImageTk.PhotoImage(im)
self.assertEqual(im_tk.width(), im.width) assert im_tk.width() == im.width
self.assertEqual(im_tk.height(), im.height) assert im_tk.height() == im.height
reloaded = ImageTk.getimage(im_tk) reloaded = ImageTk.getimage(im_tk)
assert_image_equal(reloaded, im.convert("RGBA")) assert_image_equal(reloaded, im.convert("RGBA"))
def test_photoimage_blank(self):
def test_photoimage_blank():
# test a image using mode/size: # test a image using mode/size:
for mode in TK_MODES: for mode in TK_MODES:
im_tk = ImageTk.PhotoImage(mode, (100, 100)) im_tk = ImageTk.PhotoImage(mode, (100, 100))
self.assertEqual(im_tk.width(), 100) assert im_tk.width() == 100
self.assertEqual(im_tk.height(), 100) assert im_tk.height() == 100
# reloaded = ImageTk.getimage(im_tk) # reloaded = ImageTk.getimage(im_tk)
# assert_image_equal(reloaded, im) # assert_image_equal(reloaded, im)
def test_bitmapimage(self):
def test_bitmapimage():
im = hopper("1") im = hopper("1")
# this should not crash # this should not crash
im_tk = ImageTk.BitmapImage(im) im_tk = ImageTk.BitmapImage(im)
self.assertEqual(im_tk.width(), im.width) assert im_tk.width() == im.width
self.assertEqual(im_tk.height(), im.height) assert im_tk.height() == im.height
# reloaded = ImageTk.getimage(im_tk) # reloaded = ImageTk.getimage(im_tk)
# assert_image_equal(reloaded, im) # assert_image_equal(reloaded, im)

View File

@ -1,19 +1,19 @@
import sys import sys
import unittest
import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, is_win32 from .helper import is_win32
try: try:
import numpy import numpy
except ImportError: except ImportError:
numpy = None numpy = None
pytestmark = pytest.mark.skipif(is_win32(), reason="Win32 does not call map_buffer")
@unittest.skipIf(is_win32(), "Win32 does not call map_buffer")
class TestMap(PillowTestCase): def test_overflow():
def test_overflow(self):
# There is the potential to overflow comparisons in map.c # There is the potential to overflow comparisons in map.c
# if there are > SIZE_MAX bytes in the image or if # if there are > SIZE_MAX bytes in the image or if
# the file encodes an offset that makes # the file encodes an offset that makes
@ -25,14 +25,15 @@ class TestMap(PillowTestCase):
# This image hits the offset test. # This image hits the offset test.
with Image.open("Tests/images/l2rgb_read.bmp") as im: with Image.open("Tests/images/l2rgb_read.bmp") as im:
with self.assertRaises((ValueError, MemoryError, IOError)): with pytest.raises((ValueError, MemoryError, IOError)):
im.load() im.load()
Image.MAX_IMAGE_PIXELS = max_pixels 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") @pytest.mark.skipif(sys.maxsize <= 2 ** 32, reason="Requires 64-bit system")
def test_ysize(self): @pytest.mark.skipif(numpy is None, reason="NumPy is not installed")
def test_ysize():
# Should not raise 'Integer overflow in ysize' # Should not raise 'Integer overflow in ysize'
arr = numpy.zeros((46341, 46341), dtype=numpy.uint8) arr = numpy.zeros((46341, 46341), dtype=numpy.uint8)
Image.fromarray(arr) Image.fromarray(arr)

View File

@ -1,9 +1,7 @@
import unittest
import pytest import pytest
from PIL import Image from PIL import Image
from .helper import PillowTestCase, assert_deep_equal, assert_image, hopper from .helper import assert_deep_equal, assert_image, hopper
try: try:
import numpy import numpy
@ -14,9 +12,10 @@ except ImportError:
TEST_IMAGE_SIZE = (10, 10) TEST_IMAGE_SIZE = (10, 10)
@unittest.skipIf(numpy is None, "Numpy is not installed") pytestmark = pytest.mark.skipif(numpy is None, reason="NumPy is not installed")
class TestNumpy(PillowTestCase):
def test_numpy_to_image(self):
def test_numpy_to_image():
def to_image(dtype, bands=1, boolean=0): def to_image(dtype, bands=1, boolean=0):
if bands == 1: if bands == 1:
if boolean: if boolean:
@ -49,7 +48,7 @@ class TestNumpy(PillowTestCase):
# Check non-fixed-size integer types # Check non-fixed-size integer types
# These may fail, depending on the platform, since we have no native # These may fail, depending on the platform, since we have no native
# 64 bit int image types. # 64-bit int image types.
# assert_image(to_image(numpy.uint), "I", TEST_IMAGE_SIZE) # assert_image(to_image(numpy.uint), "I", TEST_IMAGE_SIZE)
# assert_image(to_image(numpy.int), "I", TEST_IMAGE_SIZE) # assert_image(to_image(numpy.int), "I", TEST_IMAGE_SIZE)
@ -66,12 +65,15 @@ class TestNumpy(PillowTestCase):
assert_image(to_image(numpy.int32), "I", TEST_IMAGE_SIZE) assert_image(to_image(numpy.int32), "I", TEST_IMAGE_SIZE)
# Check 64-bit integer formats # Check 64-bit integer formats
self.assertRaises(TypeError, to_image, numpy.uint64) with pytest.raises(TypeError):
self.assertRaises(TypeError, to_image, numpy.int64) to_image(numpy.uint64)
with pytest.raises(TypeError):
to_image(numpy.int64)
# Check floating-point formats # Check floating-point formats
assert_image(to_image(numpy.float), "F", TEST_IMAGE_SIZE) assert_image(to_image(numpy.float), "F", TEST_IMAGE_SIZE)
self.assertRaises(TypeError, to_image, numpy.float16) with pytest.raises(TypeError):
to_image(numpy.float16)
assert_image(to_image(numpy.float32), "F", TEST_IMAGE_SIZE) assert_image(to_image(numpy.float32), "F", TEST_IMAGE_SIZE)
assert_image(to_image(numpy.float64), "F", TEST_IMAGE_SIZE) assert_image(to_image(numpy.float64), "F", TEST_IMAGE_SIZE)
@ -79,9 +81,10 @@ class TestNumpy(PillowTestCase):
assert_image(to_image(numpy.uint8, 3), "RGB", (10, 10)) assert_image(to_image(numpy.uint8, 3), "RGB", (10, 10))
assert_image(to_image(numpy.uint8, 4), "RGBA", (10, 10)) assert_image(to_image(numpy.uint8, 4), "RGBA", (10, 10))
# based on an erring example at
# Based on an erring example at
# https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function # https://stackoverflow.com/questions/10854903/what-is-causing-dimension-dependent-attributeerror-in-pil-fromarray-function
def test_3d_array(self): def test_3d_array():
size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1]) size = (5, TEST_IMAGE_SIZE[0], TEST_IMAGE_SIZE[1])
a = numpy.ones(size, dtype=numpy.uint8) a = numpy.ones(size, dtype=numpy.uint8)
assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE) assert_image(Image.fromarray(a[1, :, :]), "L", TEST_IMAGE_SIZE)
@ -92,31 +95,35 @@ class TestNumpy(PillowTestCase):
a = numpy.ones(size, dtype=numpy.uint8) a = numpy.ones(size, dtype=numpy.uint8)
assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE) assert_image(Image.fromarray(a[:, :, 1]), "L", TEST_IMAGE_SIZE)
def _test_img_equals_nparray(self, img, np):
self.assertGreaterEqual(len(np.shape), 2) def _test_img_equals_nparray(img, np):
assert len(np.shape) >= 2
np_size = np.shape[1], np.shape[0] np_size = np.shape[1], np.shape[0]
self.assertEqual(img.size, np_size) assert img.size == np_size
px = img.load() px = img.load()
for x in range(0, img.size[0], int(img.size[0] / 10)): 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)): for y in range(0, img.size[1], int(img.size[1] / 10)):
assert_deep_equal(px[x, y], np[y, x]) assert_deep_equal(px[x, y], np[y, x])
def test_16bit(self):
def test_16bit():
with Image.open("Tests/images/16bit.cropped.tif") as img: with Image.open("Tests/images/16bit.cropped.tif") as img:
np_img = numpy.array(img) np_img = numpy.array(img)
self._test_img_equals_nparray(img, np_img) _test_img_equals_nparray(img, np_img)
self.assertEqual(np_img.dtype, numpy.dtype("<u2")) assert np_img.dtype == numpy.dtype("<u2")
def test_1bit(self):
def test_1bit():
# Test that 1-bit arrays convert to numpy and back # Test that 1-bit arrays convert to numpy and back
# See: https://github.com/python-pillow/Pillow/issues/350 # See: https://github.com/python-pillow/Pillow/issues/350
arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1") arr = numpy.array([[1, 0, 0, 1, 0], [0, 1, 0, 0, 0]], "u1")
img = Image.fromarray(arr * 255).convert("1") img = Image.fromarray(arr * 255).convert("1")
self.assertEqual(img.mode, "1") assert img.mode == "1"
arr_back = numpy.array(img) arr_back = numpy.array(img)
numpy.testing.assert_array_equal(arr, arr_back) numpy.testing.assert_array_equal(arr, arr_back)
def test_save_tiff_uint16(self):
def test_save_tiff_uint16():
# Tests that we're getting the pixel value in the right byte order. # Tests that we're getting the pixel value in the right byte order.
pixel_value = 0x1234 pixel_value = 0x1234
a = numpy.array( a = numpy.array(
@ -126,19 +133,20 @@ class TestNumpy(PillowTestCase):
img = Image.fromarray(a) img = Image.fromarray(a)
img_px = img.load() img_px = img.load()
self.assertEqual(img_px[0, 0], pixel_value) assert img_px[0, 0] == pixel_value
def test_to_array(self):
def test_to_array():
def _to_array(mode, dtype): def _to_array(mode, dtype):
img = hopper(mode) img = hopper(mode)
# Resize to non-square # Resize to non-square
img = img.crop((3, 0, 124, 127)) img = img.crop((3, 0, 124, 127))
self.assertEqual(img.size, (121, 127)) assert img.size == (121, 127)
np_img = numpy.array(img) np_img = numpy.array(img)
self._test_img_equals_nparray(img, np_img) _test_img_equals_nparray(img, np_img)
self.assertEqual(np_img.dtype, dtype) assert np_img.dtype == dtype
modes = [ modes = [
("L", numpy.uint8), ("L", numpy.uint8),
@ -159,8 +167,9 @@ class TestNumpy(PillowTestCase):
for mode in modes: for mode in modes:
_to_array(*mode) _to_array(*mode)
def test_point_lut(self):
# see https://github.com/python-pillow/Pillow/issues/439 def test_point_lut():
# See https://github.com/python-pillow/Pillow/issues/439
data = list(range(256)) * 3 data = list(range(256)) * 3
lut = numpy.array(data, dtype=numpy.uint8) lut = numpy.array(data, dtype=numpy.uint8)
@ -169,17 +178,19 @@ class TestNumpy(PillowTestCase):
im.point(lut) im.point(lut)
def test_putdata(self):
# shouldn't segfault def test_putdata():
# see https://github.com/python-pillow/Pillow/issues/1008 # Shouldn't segfault
# See https://github.com/python-pillow/Pillow/issues/1008
im = Image.new("F", (150, 100)) im = Image.new("F", (150, 100))
arr = numpy.zeros((15000,), numpy.float32) arr = numpy.zeros((15000,), numpy.float32)
im.putdata(arr) im.putdata(arr)
self.assertEqual(len(im.getdata()), len(arr)) assert len(im.getdata()) == len(arr)
def test_roundtrip_eye(self):
def test_roundtrip_eye():
for dtype in ( for dtype in (
numpy.bool, numpy.bool,
numpy.bool8, numpy.bool8,
@ -196,23 +207,26 @@ class TestNumpy(PillowTestCase):
arr = numpy.eye(10, dtype=dtype) arr = numpy.eye(10, dtype=dtype)
numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr))) numpy.testing.assert_array_equal(arr, numpy.array(Image.fromarray(arr)))
def test_zero_size(self):
def test_zero_size():
# Shouldn't cause floating point exception # Shouldn't cause floating point exception
# See https://github.com/python-pillow/Pillow/issues/2259 # See https://github.com/python-pillow/Pillow/issues/2259
im = Image.fromarray(numpy.empty((0, 0), dtype=numpy.uint8)) im = Image.fromarray(numpy.empty((0, 0), dtype=numpy.uint8))
self.assertEqual(im.size, (0, 0)) assert im.size == (0, 0)
def test_bool(self):
def test_bool():
# https://github.com/python-pillow/Pillow/issues/2044 # https://github.com/python-pillow/Pillow/issues/2044
a = numpy.zeros((10, 2), dtype=numpy.bool) a = numpy.zeros((10, 2), dtype=numpy.bool)
a[0][0] = True a[0][0] = True
im2 = Image.fromarray(a) im2 = Image.fromarray(a)
self.assertEqual(im2.getdata()[0], 255) assert im2.getdata()[0] == 255
def test_no_resource_warning_for_numpy_array(self):
def test_no_resource_warning_for_numpy_array():
# https://github.com/python-pillow/Pillow/issues/835 # https://github.com/python-pillow/Pillow/issues/835
# Arrange # Arrange
from numpy import array from numpy import array

View File

@ -1,5 +1,6 @@
import time import time
import pytest
from PIL.PdfParser import ( from PIL.PdfParser import (
IndirectObjectDef, IndirectObjectDef,
IndirectReference, IndirectReference,
@ -14,83 +15,69 @@ from PIL.PdfParser import (
pdf_repr, pdf_repr,
) )
from .helper import PillowTestCase
def test_text_encode_decode():
assert encode_text("abc") == b"\xFE\xFF\x00a\x00b\x00c"
assert decode_text(b"\xFE\xFF\x00a\x00b\x00c") == "abc"
assert decode_text(b"abc") == "abc"
assert decode_text(b"\x1B a \x1C") == "\u02D9 a \u02DD"
class TestPdfParser(PillowTestCase): def test_indirect_refs():
def test_text_encode_decode(self): assert IndirectReference(1, 2) == IndirectReference(1, 2)
self.assertEqual(encode_text("abc"), b"\xFE\xFF\x00a\x00b\x00c") assert IndirectReference(1, 2) != IndirectReference(1, 3)
self.assertEqual(decode_text(b"\xFE\xFF\x00a\x00b\x00c"), "abc") assert IndirectReference(1, 2) != IndirectObjectDef(1, 2)
self.assertEqual(decode_text(b"abc"), "abc") assert IndirectReference(1, 2) != (1, 2)
self.assertEqual(decode_text(b"\x1B a \x1C"), "\u02D9 a \u02DD") assert IndirectObjectDef(1, 2) == IndirectObjectDef(1, 2)
assert IndirectObjectDef(1, 2) != IndirectObjectDef(1, 3)
assert IndirectObjectDef(1, 2) != IndirectReference(1, 2)
assert IndirectObjectDef(1, 2) != (1, 2)
def test_indirect_refs(self):
self.assertEqual(IndirectReference(1, 2), IndirectReference(1, 2))
self.assertNotEqual(IndirectReference(1, 2), IndirectReference(1, 3))
self.assertNotEqual(IndirectReference(1, 2), IndirectObjectDef(1, 2))
self.assertNotEqual(IndirectReference(1, 2), (1, 2))
self.assertEqual(IndirectObjectDef(1, 2), IndirectObjectDef(1, 2))
self.assertNotEqual(IndirectObjectDef(1, 2), IndirectObjectDef(1, 3))
self.assertNotEqual(IndirectObjectDef(1, 2), IndirectReference(1, 2))
self.assertNotEqual(IndirectObjectDef(1, 2), (1, 2))
def test_parsing(self): def test_parsing():
self.assertEqual(PdfParser.interpret_name(b"Name#23Hash"), b"Name#Hash") assert PdfParser.interpret_name(b"Name#23Hash") == b"Name#Hash"
self.assertEqual( assert PdfParser.interpret_name(b"Name#23Hash", as_text=True) == "Name#Hash"
PdfParser.interpret_name(b"Name#23Hash", as_text=True), "Name#Hash" assert PdfParser.get_value(b"1 2 R ", 0) == (IndirectReference(1, 2), 5)
) assert PdfParser.get_value(b"true[", 0) == (True, 4)
self.assertEqual( assert PdfParser.get_value(b"false%", 0) == (False, 5)
PdfParser.get_value(b"1 2 R ", 0), (IndirectReference(1, 2), 5) assert PdfParser.get_value(b"null<", 0) == (None, 4)
) assert PdfParser.get_value(b"%cmt\n %cmt\n 123\n", 0) == (123, 15)
self.assertEqual(PdfParser.get_value(b"true[", 0), (True, 4)) assert PdfParser.get_value(b"<901FA3>", 0) == (b"\x90\x1F\xA3", 8)
self.assertEqual(PdfParser.get_value(b"false%", 0), (False, 5)) assert PdfParser.get_value(b"asd < 9 0 1 f A > qwe", 3) == (b"\x90\x1F\xA0", 17)
self.assertEqual(PdfParser.get_value(b"null<", 0), (None, 4)) assert PdfParser.get_value(b"(asd)", 0) == (b"asd", 5)
self.assertEqual(PdfParser.get_value(b"%cmt\n %cmt\n 123\n", 0), (123, 15)) assert PdfParser.get_value(b"(asd(qwe)zxc)zzz(aaa)", 0) == (b"asd(qwe)zxc", 13)
self.assertEqual(PdfParser.get_value(b"<901FA3>", 0), (b"\x90\x1F\xA3", 8)) assert PdfParser.get_value(b"(Two \\\nwords.)", 0) == (b"Two words.", 14)
self.assertEqual( assert PdfParser.get_value(b"(Two\nlines.)", 0) == (b"Two\nlines.", 12)
PdfParser.get_value(b"asd < 9 0 1 f A > qwe", 3), (b"\x90\x1F\xA0", 17) assert PdfParser.get_value(b"(Two\r\nlines.)", 0) == (b"Two\nlines.", 13)
) assert PdfParser.get_value(b"(Two\\nlines.)", 0) == (b"Two\nlines.", 13)
self.assertEqual(PdfParser.get_value(b"(asd)", 0), (b"asd", 5)) assert PdfParser.get_value(b"(One\\(paren).", 0) == (b"One(paren", 12)
self.assertEqual( assert PdfParser.get_value(b"(One\\)paren).", 0) == (b"One)paren", 12)
PdfParser.get_value(b"(asd(qwe)zxc)zzz(aaa)", 0), (b"asd(qwe)zxc", 13) assert PdfParser.get_value(b"(\\0053)", 0) == (b"\x053", 7)
) assert PdfParser.get_value(b"(\\053)", 0) == (b"\x2B", 6)
self.assertEqual( assert PdfParser.get_value(b"(\\53)", 0) == (b"\x2B", 5)
PdfParser.get_value(b"(Two \\\nwords.)", 0), (b"Two words.", 14) assert PdfParser.get_value(b"(\\53a)", 0) == (b"\x2Ba", 6)
) assert PdfParser.get_value(b"(\\1111)", 0) == (b"\x491", 7)
self.assertEqual(PdfParser.get_value(b"(Two\nlines.)", 0), (b"Two\nlines.", 12)) assert PdfParser.get_value(b" 123 (", 0) == (123, 4)
self.assertEqual( assert round(abs(PdfParser.get_value(b" 123.4 %", 0)[0] - 123.4), 7) == 0
PdfParser.get_value(b"(Two\r\nlines.)", 0), (b"Two\nlines.", 13) assert PdfParser.get_value(b" 123.4 %", 0)[1] == 6
) with pytest.raises(PdfFormatError):
self.assertEqual( PdfParser.get_value(b"]", 0)
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"<</Name (value) /N /V>>", 0)[0] d = PdfParser.get_value(b"<</Name (value) /N /V>>", 0)[0]
self.assertIsInstance(d, PdfDict) assert isinstance(d, PdfDict)
self.assertEqual(len(d), 2) assert len(d) == 2
self.assertEqual(d.Name, "value") assert d.Name == "value"
self.assertEqual(d[b"Name"], b"value") assert d[b"Name"] == b"value"
self.assertEqual(d.N, PdfName("V")) assert d.N == PdfName("V")
a = PdfParser.get_value(b"[/Name (value) /N /V]", 0)[0] a = PdfParser.get_value(b"[/Name (value) /N /V]", 0)[0]
self.assertIsInstance(a, list) assert isinstance(a, list)
self.assertEqual(len(a), 4) assert len(a) == 4
self.assertEqual(a[0], PdfName("Name")) assert a[0] == PdfName("Name")
s = PdfParser.get_value( s = PdfParser.get_value(
b"<</Name (value) /Length 5>>\nstream\nabcde\nendstream<<...", 0 b"<</Name (value) /Length 5>>\nstream\nabcde\nendstream<<...", 0
)[0] )[0]
self.assertIsInstance(s, PdfStream) assert isinstance(s, PdfStream)
self.assertEqual(s.dictionary.Name, "value") assert s.dictionary.Name == "value"
self.assertEqual(s.decode(), b"abcde") assert s.decode() == b"abcde"
for name in ["CreationDate", "ModDate"]: for name in ["CreationDate", "ModDate"]:
for date, value in { for date, value in {
b"20180729214124": "20180729214124", b"20180729214124": "20180729214124",
@ -100,41 +87,33 @@ class TestPdfParser(PillowTestCase):
b"D:20180729214124+08'00'": "20180729134124", b"D:20180729214124+08'00'": "20180729134124",
b"D:20180729214124-05'00'": "20180730024124", b"D:20180729214124-05'00'": "20180730024124",
}.items(): }.items():
d = PdfParser.get_value( d = PdfParser.get_value(b"<</" + name.encode() + b" (" + date + b")>>", 0)[
b"<</" + name.encode() + b" (" + date + b")>>", 0 0
)[0] ]
self.assertEqual(time.strftime("%Y%m%d%H%M%S", getattr(d, name)), value) assert 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") def test_pdf_repr():
self.assertEqual(bytes(IndirectObjectDef(*IndirectReference(1, 2))), b"1 2 obj") assert bytes(IndirectReference(1, 2)) == b"1 2 R"
self.assertEqual(bytes(PdfName(b"Name#Hash")), b"/Name#23Hash") assert bytes(IndirectObjectDef(*IndirectReference(1, 2))) == b"1 2 obj"
self.assertEqual(bytes(PdfName("Name#Hash")), b"/Name#23Hash") assert bytes(PdfName(b"Name#Hash")) == b"/Name#23Hash"
self.assertEqual( assert bytes(PdfName("Name#Hash")) == b"/Name#23Hash"
bytes(PdfDict({b"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" assert bytes(PdfDict({b"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>"
assert bytes(PdfDict({"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>"
assert pdf_repr(IndirectReference(1, 2)) == b"1 2 R"
assert pdf_repr(IndirectObjectDef(*IndirectReference(1, 2))) == b"1 2 obj"
assert pdf_repr(PdfName(b"Name#Hash")) == b"/Name#23Hash"
assert pdf_repr(PdfName("Name#Hash")) == b"/Name#23Hash"
assert (
pdf_repr(PdfDict({b"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>"
) )
self.assertEqual( assert (
bytes(PdfDict({"Name": IndirectReference(1, 2)})), b"<<\n/Name 1 2 R\n>>" pdf_repr(PdfDict({"Name": IndirectReference(1, 2)})) == b"<<\n/Name 1 2 R\n>>"
) )
self.assertEqual(pdf_repr(IndirectReference(1, 2)), b"1 2 R") assert pdf_repr(123) == b"123"
self.assertEqual( assert pdf_repr(True) == b"true"
pdf_repr(IndirectObjectDef(*IndirectReference(1, 2))), b"1 2 obj" assert pdf_repr(False) == b"false"
) assert pdf_repr(None) == b"null"
self.assertEqual(pdf_repr(PdfName(b"Name#Hash")), b"/Name#23Hash") assert pdf_repr(b"a)/b\\(c") == br"(a\)/b\\\(c)"
self.assertEqual(pdf_repr(PdfName("Name#Hash")), b"/Name#23Hash") assert pdf_repr([123, True, {"a": PdfName(b"b")}]) == b"[ 123 true <<\n/a /b\n>> ]"
self.assertEqual( assert pdf_repr(PdfBinary(b"\x90\x1F\xA0")) == b"<901FA0>"
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>")