mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-27 10:26:19 +03:00
Merge pull request #4446 from hugovk/convert-asserts
Convert some tests to pytest style
This commit is contained in:
commit
de179eb5c6
|
@ -49,7 +49,7 @@ class BenchCffiAccess(PillowTestCase):
|
|||
caccess = im.im.pixel_access(False)
|
||||
access = PyAccess.new(im, False)
|
||||
|
||||
self.assertEqual(caccess[(0, 0)], access[(0, 0)])
|
||||
assert caccess[(0, 0)] == access[(0, 0)]
|
||||
|
||||
print("Size: %sx%s" % im.size)
|
||||
timer(iterate_get, "PyAccess - get", im.size, access)
|
||||
|
|
|
@ -26,7 +26,7 @@ class TestImagingLeaks(PillowTestCase):
|
|||
mem_limit = mem + 1
|
||||
continue
|
||||
msg = "memory usage limit exceeded after %d iterations" % (i + 1)
|
||||
self.assertLessEqual(mem, mem_limit, msg)
|
||||
assert mem <= mem_limit, msg
|
||||
|
||||
def test_leak_putdata(self):
|
||||
im = Image.new("RGB", (25, 25))
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import unittest
|
||||
from array import array
|
||||
|
||||
import pytest
|
||||
from PIL import Image, ImageFilter
|
||||
|
||||
from .helper import PillowTestCase, assert_image_equal
|
||||
from .helper import assert_image_equal
|
||||
|
||||
try:
|
||||
import numpy
|
||||
|
@ -12,7 +11,7 @@ except ImportError:
|
|||
numpy = None
|
||||
|
||||
|
||||
class TestColorLut3DCoreAPI(PillowTestCase):
|
||||
class TestColorLut3DCoreAPI:
|
||||
def generate_identity_table(self, channels, size):
|
||||
if isinstance(size, tuple):
|
||||
size1D, size2D, size3D = size
|
||||
|
@ -42,37 +41,37 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
def test_wrong_args(self):
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "filter"):
|
||||
with pytest.raises(ValueError, match="filter"):
|
||||
im.im.color_lut_3d("RGB", Image.CUBIC, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "image mode"):
|
||||
with pytest.raises(ValueError, match="image mode"):
|
||||
im.im.color_lut_3d(
|
||||
"wrong", Image.LINEAR, *self.generate_identity_table(3, 3)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table_channels"):
|
||||
with pytest.raises(ValueError, match="table_channels"):
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(5, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table_channels"):
|
||||
with pytest.raises(ValueError, match="table_channels"):
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(1, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table_channels"):
|
||||
with pytest.raises(ValueError, match="table_channels"):
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(2, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "Table size"):
|
||||
with pytest.raises(ValueError, match="Table size"):
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (1, 3, 3))
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "Table size"):
|
||||
with pytest.raises(ValueError, match="Table size"):
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (66, 3, 3))
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"):
|
||||
with pytest.raises(ValueError, match=r"size1D \* size2D \* size3D"):
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 7)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"):
|
||||
with pytest.raises(ValueError, match=r"size1D \* size2D \* size3D"):
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 9)
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
|
@ -105,25 +104,25 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
)
|
||||
|
||||
def test_wrong_mode(self):
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
with pytest.raises(ValueError, match="wrong mode"):
|
||||
im = Image.new("L", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
with pytest.raises(ValueError, match="wrong mode"):
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
with pytest.raises(ValueError, match="wrong mode"):
|
||||
im = Image.new("L", (10, 10), 0)
|
||||
im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
with pytest.raises(ValueError, match="wrong mode"):
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d(
|
||||
"RGBA", Image.LINEAR, *self.generate_identity_table(3, 3)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
with pytest.raises(ValueError, match="wrong mode"):
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(4, 3))
|
||||
|
||||
|
@ -271,33 +270,33 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
assert transformed[205, 205] == (255, 255, 0)
|
||||
|
||||
|
||||
class TestColorLut3DFilter(PillowTestCase):
|
||||
class TestColorLut3DFilter:
|
||||
def test_wrong_args(self):
|
||||
with self.assertRaisesRegex(ValueError, "should be either an integer"):
|
||||
with pytest.raises(ValueError, match="should be either an integer"):
|
||||
ImageFilter.Color3DLUT("small", [1])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should be either an integer"):
|
||||
with pytest.raises(ValueError, match="should be either an integer"):
|
||||
ImageFilter.Color3DLUT((11, 11), [1])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, r"in \[2, 65\] range"):
|
||||
with pytest.raises(ValueError, match=r"in \[2, 65\] range"):
|
||||
ImageFilter.Color3DLUT((11, 11, 1), [1])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, r"in \[2, 65\] range"):
|
||||
with pytest.raises(ValueError, match=r"in \[2, 65\] range"):
|
||||
ImageFilter.Color3DLUT((11, 11, 66), [1])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table should have .+ items"):
|
||||
with pytest.raises(ValueError, match="table should have .+ items"):
|
||||
ImageFilter.Color3DLUT((3, 3, 3), [1, 1, 1])
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table should have .+ items"):
|
||||
with pytest.raises(ValueError, match="table should have .+ items"):
|
||||
ImageFilter.Color3DLUT((3, 3, 3), [[1, 1, 1]] * 2)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have a length of 4"):
|
||||
with pytest.raises(ValueError, match="should have a length of 4"):
|
||||
ImageFilter.Color3DLUT((3, 3, 3), [[1, 1, 1]] * 27, channels=4)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have a length of 3"):
|
||||
with pytest.raises(ValueError, match="should have a length of 3"):
|
||||
ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "Only 3 or 4 output"):
|
||||
with pytest.raises(ValueError, match="Only 3 or 4 output"):
|
||||
ImageFilter.Color3DLUT((2, 2, 2), [[1, 1]] * 8, channels=2)
|
||||
|
||||
def test_convert_table(self):
|
||||
|
@ -317,10 +316,10 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
assert tuple(lut.size) == (2, 2, 2)
|
||||
assert lut.table == list(range(4)) * 8
|
||||
|
||||
@unittest.skipIf(numpy is None, "Numpy is not installed")
|
||||
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
|
||||
def test_numpy_sources(self):
|
||||
table = numpy.ones((5, 6, 7, 3), dtype=numpy.float16)
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
with pytest.raises(ValueError, match="should have either channels"):
|
||||
lut = ImageFilter.Color3DLUT((5, 6, 7), table)
|
||||
|
||||
table = numpy.ones((7, 6, 5, 3), dtype=numpy.float16)
|
||||
|
@ -350,7 +349,7 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
table[0] = 33
|
||||
assert lut.table[0] == 33
|
||||
|
||||
@unittest.skipIf(numpy is None, "Numpy is not installed")
|
||||
@pytest.mark.skipif(numpy is None, reason="NumPy not installed")
|
||||
def test_numpy_formats(self):
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
|
@ -359,12 +358,12 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float32)[:-1]
|
||||
with self.assertRaisesRegex(ValueError, "should have table_channels"):
|
||||
with pytest.raises(ValueError, match="should have table_channels"):
|
||||
im.filter(lut)
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float32).reshape((7 * 9 * 11), 3)
|
||||
with self.assertRaisesRegex(ValueError, "should have table_channels"):
|
||||
with pytest.raises(ValueError, match="should have table_channels"):
|
||||
im.filter(lut)
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
|
@ -402,17 +401,17 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
)
|
||||
|
||||
|
||||
class TestGenerateColorLut3D(PillowTestCase):
|
||||
class TestGenerateColorLut3D:
|
||||
def test_wrong_channels_count(self):
|
||||
with self.assertRaisesRegex(ValueError, "3 or 4 output channels"):
|
||||
with pytest.raises(ValueError, match="3 or 4 output channels"):
|
||||
ImageFilter.Color3DLUT.generate(
|
||||
5, channels=2, callback=lambda r, g, b: (r, g, b)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
with pytest.raises(ValueError, match="should have either channels"):
|
||||
ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b, r))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
with pytest.raises(ValueError, match="should have either channels"):
|
||||
ImageFilter.Color3DLUT.generate(
|
||||
5, channels=4, callback=lambda r, g, b: (r, g, b)
|
||||
)
|
||||
|
@ -450,17 +449,17 @@ class TestGenerateColorLut3D(PillowTestCase):
|
|||
assert im == im.filter(lut)
|
||||
|
||||
|
||||
class TestTransformColorLut3D(PillowTestCase):
|
||||
class TestTransformColorLut3D:
|
||||
def test_wrong_args(self):
|
||||
source = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "Only 3 or 4 output"):
|
||||
with pytest.raises(ValueError, match="Only 3 or 4 output"):
|
||||
source.transform(lambda r, g, b: (r, g, b), channels=8)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
with pytest.raises(ValueError, match="should have either channels"):
|
||||
source.transform(lambda r, g, b: (r, g, b), channels=4)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
with pytest.raises(ValueError, match="should have either channels"):
|
||||
source.transform(lambda r, g, b: (r, g, b, 1))
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
|
|
|
@ -1,65 +1,65 @@
|
|||
import io
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
from PIL import EpsImagePlugin, Image, features
|
||||
|
||||
from .helper import PillowTestCase, assert_image_similar, hopper, skip_unless_feature
|
||||
from .helper import assert_image_similar, hopper, skip_unless_feature
|
||||
|
||||
HAS_GHOSTSCRIPT = EpsImagePlugin.has_ghostscript()
|
||||
|
||||
# Our two EPS test files (they are identical except for their bounding boxes)
|
||||
file1 = "Tests/images/zero_bb.eps"
|
||||
file2 = "Tests/images/non_zero_bb.eps"
|
||||
FILE1 = "Tests/images/zero_bb.eps"
|
||||
FILE2 = "Tests/images/non_zero_bb.eps"
|
||||
|
||||
# Due to palletization, we'll need to convert these to RGB after load
|
||||
file1_compare = "Tests/images/zero_bb.png"
|
||||
file1_compare_scale2 = "Tests/images/zero_bb_scale2.png"
|
||||
FILE1_COMPARE = "Tests/images/zero_bb.png"
|
||||
FILE1_COMPARE_SCALE2 = "Tests/images/zero_bb_scale2.png"
|
||||
|
||||
file2_compare = "Tests/images/non_zero_bb.png"
|
||||
file2_compare_scale2 = "Tests/images/non_zero_bb_scale2.png"
|
||||
FILE2_COMPARE = "Tests/images/non_zero_bb.png"
|
||||
FILE2_COMPARE_SCALE2 = "Tests/images/non_zero_bb_scale2.png"
|
||||
|
||||
# EPS test files with binary preview
|
||||
file3 = "Tests/images/binary_preview_map.eps"
|
||||
FILE3 = "Tests/images/binary_preview_map.eps"
|
||||
|
||||
|
||||
class TestFileEps(PillowTestCase):
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_sanity(self):
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_sanity():
|
||||
# Regular scale
|
||||
with Image.open(file1) as image1:
|
||||
with Image.open(FILE1) as image1:
|
||||
image1.load()
|
||||
assert image1.mode == "RGB"
|
||||
assert image1.size == (460, 352)
|
||||
assert image1.format == "EPS"
|
||||
|
||||
with Image.open(file2) as image2:
|
||||
with Image.open(FILE2) as image2:
|
||||
image2.load()
|
||||
assert image2.mode == "RGB"
|
||||
assert image2.size == (360, 252)
|
||||
assert image2.format == "EPS"
|
||||
|
||||
# Double scale
|
||||
with Image.open(file1) as image1_scale2:
|
||||
with Image.open(FILE1) as image1_scale2:
|
||||
image1_scale2.load(scale=2)
|
||||
assert image1_scale2.mode == "RGB"
|
||||
assert image1_scale2.size == (920, 704)
|
||||
assert image1_scale2.format == "EPS"
|
||||
|
||||
with Image.open(file2) as image2_scale2:
|
||||
with Image.open(FILE2) as image2_scale2:
|
||||
image2_scale2.load(scale=2)
|
||||
assert image2_scale2.mode == "RGB"
|
||||
assert image2_scale2.size == (720, 504)
|
||||
assert image2_scale2.format == "EPS"
|
||||
|
||||
def test_invalid_file(self):
|
||||
|
||||
def test_invalid_file():
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
with pytest.raises(SyntaxError):
|
||||
EpsImagePlugin.EpsImageFile(invalid_file)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_cmyk(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_cmyk():
|
||||
with Image.open("Tests/images/pil_sample_cmyk.eps") as cmyk_image:
|
||||
|
||||
assert cmyk_image.mode == "CMYK"
|
||||
|
@ -73,8 +73,9 @@ class TestFileEps(PillowTestCase):
|
|||
with Image.open("Tests/images/pil_sample_rgb.jpg") as target:
|
||||
assert_image_similar(cmyk_image, target, 10)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_showpage(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_showpage():
|
||||
# See https://github.com/python-pillow/Pillow/issues/2615
|
||||
with Image.open("Tests/images/reqd_showpage.eps") as plot_image:
|
||||
with Image.open("Tests/images/reqd_showpage.png") as target:
|
||||
|
@ -83,108 +84,124 @@ class TestFileEps(PillowTestCase):
|
|||
# fonts could be slightly different
|
||||
assert_image_similar(plot_image, target, 6)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_file_object(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_file_object(tmp_path):
|
||||
# issue 479
|
||||
with Image.open(file1) as image1:
|
||||
with open(self.tempfile("temp_file.eps"), "wb") as fh:
|
||||
with Image.open(FILE1) as image1:
|
||||
with open(str(tmp_path / "temp.eps"), "wb") as fh:
|
||||
image1.save(fh, "EPS")
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_iobase_object(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_iobase_object(tmp_path):
|
||||
# issue 479
|
||||
with Image.open(file1) as image1:
|
||||
with open(self.tempfile("temp_iobase.eps"), "wb") as fh:
|
||||
with Image.open(FILE1) as image1:
|
||||
with open(str(tmp_path / "temp_iobase.eps"), "wb") as fh:
|
||||
image1.save(fh, "EPS")
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_bytesio_object(self):
|
||||
with open(file1, "rb") as f:
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_bytesio_object():
|
||||
with open(FILE1, "rb") as f:
|
||||
img_bytes = io.BytesIO(f.read())
|
||||
|
||||
with Image.open(img_bytes) as img:
|
||||
img.load()
|
||||
|
||||
with Image.open(file1_compare) as image1_scale1_compare:
|
||||
with Image.open(FILE1_COMPARE) as image1_scale1_compare:
|
||||
image1_scale1_compare = image1_scale1_compare.convert("RGB")
|
||||
image1_scale1_compare.load()
|
||||
assert_image_similar(img, image1_scale1_compare, 5)
|
||||
|
||||
def test_image_mode_not_supported(self):
|
||||
|
||||
def test_image_mode_not_supported(tmp_path):
|
||||
im = hopper("RGBA")
|
||||
tmpfile = self.tempfile("temp.eps")
|
||||
tmpfile = str(tmp_path / "temp.eps")
|
||||
with pytest.raises(ValueError):
|
||||
im.save(tmpfile)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
@skip_unless_feature("zlib")
|
||||
def test_render_scale1(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
@skip_unless_feature("zlib")
|
||||
def test_render_scale1():
|
||||
# We need png support for these render test
|
||||
|
||||
# Zero bounding box
|
||||
with Image.open(file1) as image1_scale1:
|
||||
with Image.open(FILE1) as image1_scale1:
|
||||
image1_scale1.load()
|
||||
with Image.open(file1_compare) as image1_scale1_compare:
|
||||
with Image.open(FILE1_COMPARE) as image1_scale1_compare:
|
||||
image1_scale1_compare = image1_scale1_compare.convert("RGB")
|
||||
image1_scale1_compare.load()
|
||||
assert_image_similar(image1_scale1, image1_scale1_compare, 5)
|
||||
|
||||
# Non-Zero bounding box
|
||||
with Image.open(file2) as image2_scale1:
|
||||
with Image.open(FILE2) as image2_scale1:
|
||||
image2_scale1.load()
|
||||
with Image.open(file2_compare) as image2_scale1_compare:
|
||||
with Image.open(FILE2_COMPARE) as image2_scale1_compare:
|
||||
image2_scale1_compare = image2_scale1_compare.convert("RGB")
|
||||
image2_scale1_compare.load()
|
||||
assert_image_similar(image2_scale1, image2_scale1_compare, 10)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
@skip_unless_feature("zlib")
|
||||
def test_render_scale2(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
@skip_unless_feature("zlib")
|
||||
def test_render_scale2():
|
||||
# We need png support for these render test
|
||||
|
||||
# Zero bounding box
|
||||
with Image.open(file1) as image1_scale2:
|
||||
with Image.open(FILE1) as image1_scale2:
|
||||
image1_scale2.load(scale=2)
|
||||
with Image.open(file1_compare_scale2) as image1_scale2_compare:
|
||||
with Image.open(FILE1_COMPARE_SCALE2) as image1_scale2_compare:
|
||||
image1_scale2_compare = image1_scale2_compare.convert("RGB")
|
||||
image1_scale2_compare.load()
|
||||
assert_image_similar(image1_scale2, image1_scale2_compare, 5)
|
||||
|
||||
# Non-Zero bounding box
|
||||
with Image.open(file2) as image2_scale2:
|
||||
with Image.open(FILE2) as image2_scale2:
|
||||
image2_scale2.load(scale=2)
|
||||
with Image.open(file2_compare_scale2) as image2_scale2_compare:
|
||||
with Image.open(FILE2_COMPARE_SCALE2) as image2_scale2_compare:
|
||||
image2_scale2_compare = image2_scale2_compare.convert("RGB")
|
||||
image2_scale2_compare.load()
|
||||
assert_image_similar(image2_scale2, image2_scale2_compare, 10)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_resize(self):
|
||||
files = [file1, file2, "Tests/images/illu10_preview.eps"]
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_resize():
|
||||
files = [FILE1, FILE2, "Tests/images/illu10_preview.eps"]
|
||||
for fn in files:
|
||||
with Image.open(fn) as im:
|
||||
new_size = (100, 100)
|
||||
im = im.resize(new_size)
|
||||
assert im.size == new_size
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_thumbnail(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_thumbnail():
|
||||
# Issue #619
|
||||
# Arrange
|
||||
files = [file1, file2]
|
||||
files = [FILE1, FILE2]
|
||||
for fn in files:
|
||||
with Image.open(file1) as im:
|
||||
with Image.open(FILE1) as im:
|
||||
new_size = (100, 100)
|
||||
im.thumbnail(new_size)
|
||||
assert max(im.size) == max(new_size)
|
||||
|
||||
def test_read_binary_preview(self):
|
||||
|
||||
def test_read_binary_preview():
|
||||
# Issue 302
|
||||
# open image with binary preview
|
||||
with Image.open(file3):
|
||||
with Image.open(FILE3):
|
||||
pass
|
||||
|
||||
def _test_readline(self, t, ending):
|
||||
|
||||
def test_readline(tmp_path):
|
||||
# check all the freaking line endings possible from the spec
|
||||
# test_string = u'something\r\nelse\n\rbaz\rbif\n'
|
||||
line_endings = ["\r\n", "\n", "\n\r", "\r"]
|
||||
strings = ["something", "else", "baz", "bif"]
|
||||
|
||||
def _test_readline(t, ending):
|
||||
ending = "Failure with line ending: %s" % (
|
||||
"".join("%s" % ord(s) for s in ending)
|
||||
)
|
||||
|
@ -193,32 +210,27 @@ class TestFileEps(PillowTestCase):
|
|||
assert t.readline().strip("\r\n") == "baz", ending
|
||||
assert t.readline().strip("\r\n") == "bif", ending
|
||||
|
||||
def _test_readline_io_psfile(self, test_string, ending):
|
||||
def _test_readline_io_psfile(test_string, ending):
|
||||
f = io.BytesIO(test_string.encode("latin-1"))
|
||||
t = EpsImagePlugin.PSFile(f)
|
||||
self._test_readline(t, ending)
|
||||
_test_readline(t, ending)
|
||||
|
||||
def _test_readline_file_psfile(self, test_string, ending):
|
||||
f = self.tempfile("temp.txt")
|
||||
def _test_readline_file_psfile(test_string, ending):
|
||||
f = str(tmp_path / "temp.txt")
|
||||
with open(f, "wb") as w:
|
||||
w.write(test_string.encode("latin-1"))
|
||||
|
||||
with open(f, "rb") as r:
|
||||
t = EpsImagePlugin.PSFile(r)
|
||||
self._test_readline(t, ending)
|
||||
|
||||
def test_readline(self):
|
||||
# check all the freaking line endings possible from the spec
|
||||
# test_string = u'something\r\nelse\n\rbaz\rbif\n'
|
||||
line_endings = ["\r\n", "\n", "\n\r", "\r"]
|
||||
strings = ["something", "else", "baz", "bif"]
|
||||
_test_readline(t, ending)
|
||||
|
||||
for ending in line_endings:
|
||||
s = ending.join(strings)
|
||||
self._test_readline_io_psfile(s, ending)
|
||||
self._test_readline_file_psfile(s, ending)
|
||||
_test_readline_io_psfile(s, ending)
|
||||
_test_readline_file_psfile(s, ending)
|
||||
|
||||
def test_open_eps(self):
|
||||
|
||||
def test_open_eps():
|
||||
# https://github.com/python-pillow/Pillow/issues/1104
|
||||
# Arrange
|
||||
FILES = [
|
||||
|
@ -233,8 +245,9 @@ class TestFileEps(PillowTestCase):
|
|||
with Image.open(filename) as img:
|
||||
assert img.mode == "RGB"
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_emptyline(self):
|
||||
|
||||
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||
def test_emptyline():
|
||||
# Test file includes an empty line in the header data
|
||||
emptyline_file = "Tests/images/zero_bb_emptyline.eps"
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import unittest
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
from PIL import GifImagePlugin, Image, ImageDraw, ImagePalette, features
|
||||
|
||||
from .helper import (
|
||||
PillowTestCase,
|
||||
assert_image_equal,
|
||||
assert_image_similar,
|
||||
hopper,
|
||||
|
@ -20,8 +18,7 @@ with open(TEST_GIF, "rb") as f:
|
|||
data = f.read()
|
||||
|
||||
|
||||
class TestFileGif(PillowTestCase):
|
||||
def test_sanity(self):
|
||||
def test_sanity():
|
||||
with Image.open(TEST_GIF) as im:
|
||||
im.load()
|
||||
assert im.mode == "P"
|
||||
|
@ -29,15 +26,17 @@ class TestFileGif(PillowTestCase):
|
|||
assert im.format == "GIF"
|
||||
assert im.info["version"] == b"GIF89a"
|
||||
|
||||
@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():
|
||||
im = Image.open(TEST_GIF)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
|
||||
def test_closed_file(self):
|
||||
|
||||
def test_closed_file():
|
||||
def open():
|
||||
im = Image.open(TEST_GIF)
|
||||
im.load()
|
||||
|
@ -45,20 +44,23 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
pytest.warns(None, open)
|
||||
|
||||
def test_context_manager(self):
|
||||
|
||||
def test_context_manager():
|
||||
def open():
|
||||
with Image.open(TEST_GIF) as im:
|
||||
im.load()
|
||||
|
||||
pytest.warns(None, open)
|
||||
|
||||
def test_invalid_file(self):
|
||||
|
||||
def test_invalid_file():
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
with pytest.raises(SyntaxError):
|
||||
GifImagePlugin.GifImageFile(invalid_file)
|
||||
|
||||
def test_optimize(self):
|
||||
|
||||
def test_optimize():
|
||||
def test_grayscale(optimize):
|
||||
im = Image.new("L", (1, 1), 0)
|
||||
filename = BytesIO()
|
||||
|
@ -76,7 +78,8 @@ class TestFileGif(PillowTestCase):
|
|||
assert test_bilevel(0) == 800
|
||||
assert test_bilevel(1) == 800
|
||||
|
||||
def test_optimize_correctness(self):
|
||||
|
||||
def test_optimize_correctness():
|
||||
# 256 color Palette image, posterize to > 128 and < 128 levels
|
||||
# Size bigger and smaller than 512x512
|
||||
# Check the palette for number of colors allocated.
|
||||
|
@ -92,9 +95,7 @@ class TestFileGif(PillowTestCase):
|
|||
outfile.seek(0)
|
||||
with Image.open(outfile) as reloaded:
|
||||
# check palette length
|
||||
palette_length = max(
|
||||
i + 1 for i, v in enumerate(reloaded.histogram()) if v
|
||||
)
|
||||
palette_length = max(i + 1 for i, v in enumerate(reloaded.histogram()) if v)
|
||||
assert expected_palette_length == palette_length
|
||||
|
||||
assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
|
||||
|
@ -109,28 +110,31 @@ class TestFileGif(PillowTestCase):
|
|||
check(64, 513, 256)
|
||||
check(4, 513, 256)
|
||||
|
||||
# other limits that don't optimize the palette
|
||||
# Other limits that don't optimize the palette
|
||||
check(129, 511, 256)
|
||||
check(255, 511, 256)
|
||||
check(256, 511, 256)
|
||||
|
||||
def test_optimize_full_l(self):
|
||||
|
||||
def test_optimize_full_l():
|
||||
im = Image.frombytes("L", (16, 16), bytes(range(256)))
|
||||
test_file = BytesIO()
|
||||
im.save(test_file, "GIF", optimize=True)
|
||||
assert im.mode == "L"
|
||||
|
||||
def test_roundtrip(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_roundtrip(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = hopper()
|
||||
im.save(out)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
assert_image_similar(reread.convert("RGB"), im, 50)
|
||||
|
||||
def test_roundtrip2(self):
|
||||
|
||||
def test_roundtrip2(tmp_path):
|
||||
# see https://github.com/python-pillow/Pillow/issues/403
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
with Image.open(TEST_GIF) as im:
|
||||
im2 = im.copy()
|
||||
im2.save(out)
|
||||
|
@ -138,9 +142,10 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
assert_image_similar(reread.convert("RGB"), hopper(), 50)
|
||||
|
||||
def test_roundtrip_save_all(self):
|
||||
|
||||
def test_roundtrip_save_all(tmp_path):
|
||||
# Single frame image
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = hopper()
|
||||
im.save(out, save_all=True)
|
||||
with Image.open(out) as reread:
|
||||
|
@ -149,28 +154,29 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
# Multiframe image
|
||||
with Image.open("Tests/images/dispose_bgnd.gif") as im:
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, save_all=True)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
with Image.open(out) as reread:
|
||||
assert reread.n_frames == 5
|
||||
|
||||
def test_headers_saving_for_animated_gifs(self):
|
||||
|
||||
def test_headers_saving_for_animated_gifs(tmp_path):
|
||||
important_headers = ["background", "version", "duration", "loop"]
|
||||
# Multiframe image
|
||||
with Image.open("Tests/images/dispose_bgnd.gif") as im:
|
||||
|
||||
info = im.info.copy()
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, save_all=True)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
for header in important_headers:
|
||||
assert info[header] == reread.info[header]
|
||||
|
||||
def test_palette_handling(self):
|
||||
|
||||
def test_palette_handling(tmp_path):
|
||||
# see https://github.com/python-pillow/Pillow/issues/513
|
||||
|
||||
with Image.open(TEST_GIF) as im:
|
||||
|
@ -179,18 +185,19 @@ class TestFileGif(PillowTestCase):
|
|||
im = im.resize((100, 100), Image.LANCZOS)
|
||||
im2 = im.convert("P", palette=Image.ADAPTIVE, colors=256)
|
||||
|
||||
f = self.tempfile("temp.gif")
|
||||
f = str(tmp_path / "temp.gif")
|
||||
im2.save(f, optimize=True)
|
||||
|
||||
with Image.open(f) as reloaded:
|
||||
|
||||
assert_image_similar(im, reloaded.convert("RGB"), 10)
|
||||
|
||||
def test_palette_434(self):
|
||||
|
||||
def test_palette_434(tmp_path):
|
||||
# see https://github.com/python-pillow/Pillow/issues/434
|
||||
|
||||
def roundtrip(im, *args, **kwargs):
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.copy().save(out, *args, **kwargs)
|
||||
reloaded = Image.open(out)
|
||||
|
||||
|
@ -210,37 +217,41 @@ class TestFileGif(PillowTestCase):
|
|||
reloaded = reloaded.convert("RGB")
|
||||
assert_image_equal(im, reloaded)
|
||||
|
||||
@unittest.skipUnless(netpbm_available(), "netpbm not available")
|
||||
def test_save_netpbm_bmp_mode(self):
|
||||
|
||||
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
|
||||
def test_save_netpbm_bmp_mode(tmp_path):
|
||||
with Image.open(TEST_GIF) as img:
|
||||
img = img.convert("RGB")
|
||||
|
||||
tempfile = self.tempfile("temp.gif")
|
||||
tempfile = str(tmp_path / "temp.gif")
|
||||
GifImagePlugin._save_netpbm(img, 0, tempfile)
|
||||
with Image.open(tempfile) as reloaded:
|
||||
assert_image_similar(img, reloaded.convert("RGB"), 0)
|
||||
|
||||
@unittest.skipUnless(netpbm_available(), "netpbm not available")
|
||||
def test_save_netpbm_l_mode(self):
|
||||
|
||||
@pytest.mark.skipif(not netpbm_available(), reason="Netpbm not available")
|
||||
def test_save_netpbm_l_mode(tmp_path):
|
||||
with Image.open(TEST_GIF) as img:
|
||||
img = img.convert("L")
|
||||
|
||||
tempfile = self.tempfile("temp.gif")
|
||||
tempfile = str(tmp_path / "temp.gif")
|
||||
GifImagePlugin._save_netpbm(img, 0, tempfile)
|
||||
with Image.open(tempfile) as reloaded:
|
||||
assert_image_similar(img, reloaded.convert("L"), 0)
|
||||
|
||||
def test_seek(self):
|
||||
|
||||
def test_seek():
|
||||
with Image.open("Tests/images/dispose_none.gif") as img:
|
||||
framecount = 0
|
||||
frame_count = 0
|
||||
try:
|
||||
while True:
|
||||
framecount += 1
|
||||
frame_count += 1
|
||||
img.seek(img.tell() + 1)
|
||||
except EOFError:
|
||||
assert framecount == 5
|
||||
assert frame_count == 5
|
||||
|
||||
def test_seek_info(self):
|
||||
|
||||
def test_seek_info():
|
||||
with Image.open("Tests/images/iss634.gif") as im:
|
||||
info = im.info.copy()
|
||||
|
||||
|
@ -249,7 +260,8 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
assert im.info == info
|
||||
|
||||
def test_seek_rewind(self):
|
||||
|
||||
def test_seek_rewind():
|
||||
with Image.open("Tests/images/iss634.gif") as im:
|
||||
im.seek(2)
|
||||
im.seek(1)
|
||||
|
@ -258,7 +270,8 @@ class TestFileGif(PillowTestCase):
|
|||
expected.seek(1)
|
||||
assert_image_equal(im, expected)
|
||||
|
||||
def test_n_frames(self):
|
||||
|
||||
def test_n_frames():
|
||||
for path, n_frames in [[TEST_GIF, 1], ["Tests/images/iss634.gif", 42]]:
|
||||
# Test is_animated before n_frames
|
||||
with Image.open(path) as im:
|
||||
|
@ -269,7 +282,8 @@ class TestFileGif(PillowTestCase):
|
|||
assert im.n_frames == n_frames
|
||||
assert im.is_animated == (n_frames != 1)
|
||||
|
||||
def test_eoferror(self):
|
||||
|
||||
def test_eoferror():
|
||||
with Image.open(TEST_GIF) as im:
|
||||
n_frames = im.n_frames
|
||||
|
||||
|
@ -281,7 +295,8 @@ class TestFileGif(PillowTestCase):
|
|||
# Test that seeking to the last frame does not raise an error
|
||||
im.seek(n_frames - 1)
|
||||
|
||||
def test_dispose_none(self):
|
||||
|
||||
def test_dispose_none():
|
||||
with Image.open("Tests/images/dispose_none.gif") as img:
|
||||
try:
|
||||
while True:
|
||||
|
@ -290,7 +305,8 @@ class TestFileGif(PillowTestCase):
|
|||
except EOFError:
|
||||
pass
|
||||
|
||||
def test_dispose_background(self):
|
||||
|
||||
def test_dispose_background():
|
||||
with Image.open("Tests/images/dispose_bgnd.gif") as img:
|
||||
try:
|
||||
while True:
|
||||
|
@ -299,7 +315,8 @@ class TestFileGif(PillowTestCase):
|
|||
except EOFError:
|
||||
pass
|
||||
|
||||
def test_dispose_previous(self):
|
||||
|
||||
def test_dispose_previous():
|
||||
with Image.open("Tests/images/dispose_prev.gif") as img:
|
||||
try:
|
||||
while True:
|
||||
|
@ -308,23 +325,22 @@ class TestFileGif(PillowTestCase):
|
|||
except EOFError:
|
||||
pass
|
||||
|
||||
def test_save_dispose(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_save_dispose(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im_list = [
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#111"),
|
||||
Image.new("L", (100, 100), "#222"),
|
||||
]
|
||||
for method in range(0, 4):
|
||||
im_list[0].save(
|
||||
out, save_all=True, append_images=im_list[1:], disposal=method
|
||||
)
|
||||
im_list[0].save(out, save_all=True, append_images=im_list[1:], disposal=method)
|
||||
with Image.open(out) as img:
|
||||
for _ in range(2):
|
||||
img.seek(img.tell() + 1)
|
||||
assert img.disposal_method == method
|
||||
|
||||
# check per frame disposal
|
||||
# Check per frame disposal
|
||||
im_list[0].save(
|
||||
out,
|
||||
save_all=True,
|
||||
|
@ -338,8 +354,9 @@ class TestFileGif(PillowTestCase):
|
|||
img.seek(img.tell() + 1)
|
||||
assert img.disposal_method == i + 1
|
||||
|
||||
def test_dispose2_palette(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_dispose2_palette(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
# 4 backgrounds: White, Grey, Black, Red
|
||||
circles = [(255, 255, 255), (153, 153, 153), (0, 0, 0), (255, 0, 0)]
|
||||
|
@ -367,8 +384,9 @@ class TestFileGif(PillowTestCase):
|
|||
# Center remains red every frame
|
||||
assert rgb_img.getpixel((50, 50)) == circle
|
||||
|
||||
def test_dispose2_diff(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_dispose2_diff(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
# 4 frames: red/blue, red/red, blue/blue, red/blue
|
||||
circles = [
|
||||
|
@ -408,8 +426,9 @@ class TestFileGif(PillowTestCase):
|
|||
# Check BG is correct colour
|
||||
assert rgb_img.getpixel((1, 1)) == (255, 255, 255, 0)
|
||||
|
||||
def test_dispose2_background(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_dispose2_background(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
im_list = []
|
||||
|
||||
|
@ -433,18 +452,19 @@ class TestFileGif(PillowTestCase):
|
|||
im.seek(1)
|
||||
assert im.getpixel((0, 0)) == 0
|
||||
|
||||
def test_iss634(self):
|
||||
|
||||
def test_iss634():
|
||||
with Image.open("Tests/images/iss634.gif") as img:
|
||||
# seek to the second frame
|
||||
# Seek to the second frame
|
||||
img.seek(img.tell() + 1)
|
||||
# all transparent pixels should be replaced with the color from the
|
||||
# first frame
|
||||
# All transparent pixels should be replaced with the color from the first frame
|
||||
assert img.histogram()[img.info["transparency"]] == 0
|
||||
|
||||
def test_duration(self):
|
||||
|
||||
def test_duration(tmp_path):
|
||||
duration = 1000
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
|
||||
# Check that the argument has priority over the info settings
|
||||
|
@ -454,17 +474,18 @@ class TestFileGif(PillowTestCase):
|
|||
with Image.open(out) as reread:
|
||||
assert reread.info["duration"] == duration
|
||||
|
||||
def test_multiple_duration(self):
|
||||
|
||||
def test_multiple_duration(tmp_path):
|
||||
duration_list = [1000, 2000, 3000]
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im_list = [
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#111"),
|
||||
Image.new("L", (100, 100), "#222"),
|
||||
]
|
||||
|
||||
# duration as list
|
||||
# Duration as list
|
||||
im_list[0].save(
|
||||
out, save_all=True, append_images=im_list[1:], duration=duration_list
|
||||
)
|
||||
|
@ -477,7 +498,7 @@ class TestFileGif(PillowTestCase):
|
|||
except EOFError:
|
||||
pass
|
||||
|
||||
# duration as tuple
|
||||
# Duration as tuple
|
||||
im_list[0].save(
|
||||
out, save_all=True, append_images=im_list[1:], duration=tuple(duration_list)
|
||||
)
|
||||
|
@ -490,10 +511,11 @@ class TestFileGif(PillowTestCase):
|
|||
except EOFError:
|
||||
pass
|
||||
|
||||
def test_identical_frames(self):
|
||||
|
||||
def test_identical_frames(tmp_path):
|
||||
duration_list = [1000, 1500, 2000, 4000]
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im_list = [
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
|
@ -501,7 +523,7 @@ class TestFileGif(PillowTestCase):
|
|||
Image.new("L", (100, 100), "#111"),
|
||||
]
|
||||
|
||||
# duration as list
|
||||
# Duration as list
|
||||
im_list[0].save(
|
||||
out, save_all=True, append_images=im_list[1:], duration=duration_list
|
||||
)
|
||||
|
@ -513,9 +535,10 @@ class TestFileGif(PillowTestCase):
|
|||
# Assert that the new duration is the total of the identical frames
|
||||
assert reread.info["duration"] == 4500
|
||||
|
||||
def test_identical_frames_to_single_frame(self):
|
||||
|
||||
def test_identical_frames_to_single_frame(tmp_path):
|
||||
for duration in ([1000, 1500, 2000, 4000], (1000, 1500, 2000, 4000), 8500):
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im_list = [
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
|
@ -532,18 +555,20 @@ class TestFileGif(PillowTestCase):
|
|||
# Assert that the new duration is the total of the identical frames
|
||||
assert reread.info["duration"] == 8500
|
||||
|
||||
def test_number_of_loops(self):
|
||||
|
||||
def test_number_of_loops(tmp_path):
|
||||
number_of_loops = 2
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.save(out, loop=number_of_loops)
|
||||
with Image.open(out) as reread:
|
||||
|
||||
assert reread.info["loop"] == number_of_loops
|
||||
|
||||
def test_background(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_background(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.info["background"] = 1
|
||||
im.save(out)
|
||||
|
@ -556,11 +581,12 @@ class TestFileGif(PillowTestCase):
|
|||
assert isinstance(im.info["background"], tuple)
|
||||
im.save(out)
|
||||
|
||||
def test_comment(self):
|
||||
|
||||
def test_comment(tmp_path):
|
||||
with Image.open(TEST_GIF) as im:
|
||||
assert im.info["comment"] == b"File written by Adobe Photoshop\xa8 4.0"
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.info["comment"] = b"Test comment text"
|
||||
im.save(out)
|
||||
|
@ -572,8 +598,9 @@ class TestFileGif(PillowTestCase):
|
|||
with Image.open(out) as reread:
|
||||
assert reread.info["comment"] == im.info["comment"].encode()
|
||||
|
||||
def test_comment_over_255(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_comment_over_255(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
comment = b"Test comment text"
|
||||
while len(comment) < 256:
|
||||
|
@ -584,13 +611,15 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
assert reread.info["comment"] == comment
|
||||
|
||||
def test_zero_comment_subblocks(self):
|
||||
|
||||
def test_zero_comment_subblocks():
|
||||
with Image.open("Tests/images/hopper_zero_comment_subblocks.gif") as im:
|
||||
with Image.open(TEST_GIF) as expected:
|
||||
assert_image_equal(im, expected)
|
||||
|
||||
def test_version(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_version(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
def assertVersionAfterSave(im, version):
|
||||
im.save(out)
|
||||
|
@ -618,8 +647,9 @@ class TestFileGif(PillowTestCase):
|
|||
im.info["version"] = b"GIF89a"
|
||||
assertVersionAfterSave(im, b"GIF87a")
|
||||
|
||||
def test_append_images(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_append_images(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
# Test appending single frame images
|
||||
im = Image.new("RGB", (100, 100), "#f00")
|
||||
|
@ -646,12 +676,12 @@ class TestFileGif(PillowTestCase):
|
|||
with Image.open(out) as reread:
|
||||
assert reread.n_frames == 10
|
||||
|
||||
def test_transparent_optimize(self):
|
||||
# from issue #2195, if the transparent color is incorrectly
|
||||
# optimized out, gif loses transparency
|
||||
# Need a palette that isn't using the 0 color, and one
|
||||
# that's > 128 items where the transparent color is actually
|
||||
# the top palette entry to trigger the bug.
|
||||
|
||||
def test_transparent_optimize(tmp_path):
|
||||
# From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
|
||||
# transparency.
|
||||
# Need a palette that isn't using the 0 color, and one that's > 128 items where the
|
||||
# transparent color is actually the top palette entry to trigger the bug.
|
||||
|
||||
data = bytes(range(1, 254))
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||
|
@ -660,14 +690,15 @@ class TestFileGif(PillowTestCase):
|
|||
im.frombytes(data)
|
||||
im.putpalette(palette)
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, transparency=253)
|
||||
with Image.open(out) as reloaded:
|
||||
|
||||
assert reloaded.info["transparency"] == 253
|
||||
|
||||
def test_rgb_transparency(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_rgb_transparency(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
# Single frame
|
||||
im = Image.new("RGB", (1, 1))
|
||||
|
@ -686,8 +717,9 @@ class TestFileGif(PillowTestCase):
|
|||
with Image.open(out) as reloaded:
|
||||
assert "transparency" not in reloaded.info
|
||||
|
||||
def test_bbox(self):
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def test_bbox(tmp_path):
|
||||
out = str(tmp_path / "temp.gif")
|
||||
|
||||
im = Image.new("RGB", (100, 100), "#fff")
|
||||
ims = [Image.new("RGB", (100, 100), "#000")]
|
||||
|
@ -696,63 +728,66 @@ class TestFileGif(PillowTestCase):
|
|||
with Image.open(out) as reread:
|
||||
assert reread.n_frames == 2
|
||||
|
||||
def test_palette_save_L(self):
|
||||
# generate an L mode image with a separate palette
|
||||
|
||||
def test_palette_save_L(tmp_path):
|
||||
# Generate an L mode image with a separate palette
|
||||
|
||||
im = hopper("P")
|
||||
im_l = Image.frombytes("L", im.size, im.tobytes())
|
||||
palette = bytes(im.getpalette())
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im_l.save(out, palette=palette)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
|
||||
assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
|
||||
|
||||
def test_palette_save_P(self):
|
||||
# pass in a different palette, then construct what the image
|
||||
# would look like.
|
||||
|
||||
def test_palette_save_P(tmp_path):
|
||||
# Pass in a different palette, then construct what the image would look like.
|
||||
# Forcing a non-straight grayscale palette.
|
||||
|
||||
im = hopper("P")
|
||||
palette = bytes([255 - i // 3 for i in range(768)])
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, palette=palette)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
im.putpalette(palette)
|
||||
assert_image_equal(reloaded, im)
|
||||
|
||||
def test_palette_save_ImagePalette(self):
|
||||
# pass in a different palette, as an ImagePalette.ImagePalette
|
||||
|
||||
def test_palette_save_ImagePalette(tmp_path):
|
||||
# Pass in a different palette, as an ImagePalette.ImagePalette
|
||||
# effectively the same as test_palette_save_P
|
||||
|
||||
im = hopper("P")
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256))[::-1] * 3)
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out, palette=palette)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
im.putpalette(palette)
|
||||
assert_image_equal(reloaded, im)
|
||||
|
||||
def test_save_I(self):
|
||||
|
||||
def test_save_I(tmp_path):
|
||||
# Test saving something that would trigger the auto-convert to 'L'
|
||||
|
||||
im = hopper("I")
|
||||
|
||||
out = self.tempfile("temp.gif")
|
||||
out = str(tmp_path / "temp.gif")
|
||||
im.save(out)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
assert_image_equal(reloaded.convert("L"), im.convert("L"))
|
||||
|
||||
def test_getdata(self):
|
||||
# test getheader/getdata against legacy values
|
||||
# Create a 'P' image with holes in the palette
|
||||
|
||||
def test_getdata():
|
||||
# Test getheader/getdata against legacy values.
|
||||
# Create a 'P' image with holes in the palette.
|
||||
im = Image._wedge().resize((16, 16), Image.NEAREST)
|
||||
im.putpalette(ImagePalette.ImagePalette("RGB"))
|
||||
im.info = {"background": 0}
|
||||
|
@ -777,14 +812,16 @@ class TestFileGif(PillowTestCase):
|
|||
finally:
|
||||
GifImagePlugin._FORCE_OPTIMIZE = False
|
||||
|
||||
def test_lzw_bits(self):
|
||||
|
||||
def test_lzw_bits():
|
||||
# see https://github.com/python-pillow/Pillow/issues/2811
|
||||
with Image.open("Tests/images/issue_2811.gif") as im:
|
||||
assert im.tile[0][3][0] == 11 # LZW bits
|
||||
# codec error prepatch
|
||||
im.load()
|
||||
|
||||
def test_extents(self):
|
||||
|
||||
def test_extents():
|
||||
with Image.open("Tests/images/test_extents.gif") as im:
|
||||
assert im.size == (100, 100)
|
||||
im.seek(1)
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
import io
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
from PIL import IcnsImagePlugin, Image
|
||||
|
||||
from .helper import PillowTestCase, assert_image_equal, assert_image_similar
|
||||
from .helper import assert_image_equal, assert_image_similar
|
||||
|
||||
# sample icon file
|
||||
TEST_FILE = "Tests/images/pillow.icns"
|
||||
|
||||
enable_jpeg2k = hasattr(Image.core, "jp2klib_version")
|
||||
ENABLE_JPEG2K = hasattr(Image.core, "jp2klib_version")
|
||||
|
||||
|
||||
class TestFileIcns(PillowTestCase):
|
||||
def test_sanity(self):
|
||||
def test_sanity():
|
||||
# Loading this icon by default should result in the largest size
|
||||
# (512x512@2x) being loaded
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
@ -26,9 +24,10 @@ class TestFileIcns(PillowTestCase):
|
|||
assert im.size == (1024, 1024)
|
||||
assert im.format == "ICNS"
|
||||
|
||||
@unittest.skipIf(sys.platform != "darwin", "requires macOS")
|
||||
def test_save(self):
|
||||
temp_file = self.tempfile("temp.icns")
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "darwin", reason="Requires macOS")
|
||||
def test_save(tmp_path):
|
||||
temp_file = str(tmp_path / "temp.icns")
|
||||
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.save(temp_file)
|
||||
|
@ -38,9 +37,10 @@ class TestFileIcns(PillowTestCase):
|
|||
assert reread.size == (1024, 1024)
|
||||
assert reread.format == "ICNS"
|
||||
|
||||
@unittest.skipIf(sys.platform != "darwin", "requires macOS")
|
||||
def test_save_append_images(self):
|
||||
temp_file = self.tempfile("temp.icns")
|
||||
|
||||
@pytest.mark.skipif(sys.platform != "darwin", reason="Requires macOS")
|
||||
def test_save_append_images(tmp_path):
|
||||
temp_file = str(tmp_path / "temp.icns")
|
||||
provided_im = Image.new("RGBA", (32, 32), (255, 0, 0, 128))
|
||||
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
@ -54,7 +54,8 @@ class TestFileIcns(PillowTestCase):
|
|||
reread.load()
|
||||
assert_image_equal(reread, provided_im)
|
||||
|
||||
def test_sizes(self):
|
||||
|
||||
def test_sizes():
|
||||
# Check that we can load all of the sizes, and that the final pixel
|
||||
# dimensions are as expected
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
@ -70,7 +71,8 @@ class TestFileIcns(PillowTestCase):
|
|||
with pytest.raises(ValueError):
|
||||
im.size = (1, 1)
|
||||
|
||||
def test_older_icon(self):
|
||||
|
||||
def test_older_icon():
|
||||
# This icon was made with Icon Composer rather than iconutil; it still
|
||||
# uses PNG rather than JP2, however (since it was made on 10.9).
|
||||
with Image.open("Tests/images/pillow2.icns") as im:
|
||||
|
@ -83,7 +85,8 @@ class TestFileIcns(PillowTestCase):
|
|||
assert im2.mode == "RGBA"
|
||||
assert im2.size == (wr, hr)
|
||||
|
||||
def test_jp2_icon(self):
|
||||
|
||||
def test_jp2_icon():
|
||||
# This icon was made by using Uli Kusterer's oldiconutil to replace
|
||||
# the PNG images with JPEG 2000 ones. The advantage of doing this is
|
||||
# that OS X 10.5 supports JPEG 2000 but not PNG; some commercial
|
||||
|
@ -91,7 +94,7 @@ class TestFileIcns(PillowTestCase):
|
|||
|
||||
# (oldiconutil is here: https://github.com/uliwitness/oldiconutil)
|
||||
|
||||
if not enable_jpeg2k:
|
||||
if not ENABLE_JPEG2K:
|
||||
return
|
||||
|
||||
with Image.open("Tests/images/pillow3.icns") as im:
|
||||
|
@ -104,7 +107,8 @@ class TestFileIcns(PillowTestCase):
|
|||
assert im2.mode == "RGBA"
|
||||
assert im2.size == (wr, hr)
|
||||
|
||||
def test_getimage(self):
|
||||
|
||||
def test_getimage():
|
||||
with open(TEST_FILE, "rb") as fp:
|
||||
icns_file = IcnsImagePlugin.IcnsFile(fp)
|
||||
|
||||
|
@ -116,7 +120,8 @@ class TestFileIcns(PillowTestCase):
|
|||
assert im.mode == "RGBA"
|
||||
assert im.size == (512, 512)
|
||||
|
||||
def test_not_an_icns_file(self):
|
||||
|
||||
def test_not_an_icns_file():
|
||||
with io.BytesIO(b"invalid\n") as fp:
|
||||
with pytest.raises(SyntaxError):
|
||||
IcnsImagePlugin.IcnsFile(fp)
|
||||
|
|
|
@ -3,13 +3,12 @@ import io
|
|||
import pytest
|
||||
from PIL import IcoImagePlugin, Image, ImageDraw
|
||||
|
||||
from .helper import PillowTestCase, assert_image_equal, hopper
|
||||
from .helper import assert_image_equal, hopper
|
||||
|
||||
TEST_ICO_FILE = "Tests/images/hopper.ico"
|
||||
|
||||
|
||||
class TestFileIco(PillowTestCase):
|
||||
def test_sanity(self):
|
||||
def test_sanity():
|
||||
with Image.open(TEST_ICO_FILE) as im:
|
||||
im.load()
|
||||
assert im.mode == "RGBA"
|
||||
|
@ -17,17 +16,19 @@ class TestFileIco(PillowTestCase):
|
|||
assert im.format == "ICO"
|
||||
assert im.get_format_mimetype() == "image/x-icon"
|
||||
|
||||
def test_invalid_file(self):
|
||||
|
||||
def test_invalid_file():
|
||||
with open("Tests/images/flower.jpg", "rb") as fp:
|
||||
with pytest.raises(SyntaxError):
|
||||
IcoImagePlugin.IcoImageFile(fp)
|
||||
|
||||
def test_save_to_bytes(self):
|
||||
|
||||
def test_save_to_bytes():
|
||||
output = io.BytesIO()
|
||||
im = hopper()
|
||||
im.save(output, "ico", sizes=[(32, 32), (64, 64)])
|
||||
|
||||
# the default image
|
||||
# The default image
|
||||
output.seek(0)
|
||||
with Image.open(output) as reloaded:
|
||||
assert reloaded.info["sizes"] == {(32, 32), (64, 64)}
|
||||
|
@ -37,7 +38,7 @@ class TestFileIco(PillowTestCase):
|
|||
assert reloaded.format == "ICO"
|
||||
assert_image_equal(reloaded, hopper().resize((64, 64), Image.LANCZOS))
|
||||
|
||||
# the other one
|
||||
# The other one
|
||||
output.seek(0)
|
||||
with Image.open(output) as reloaded:
|
||||
reloaded.size = (32, 32)
|
||||
|
@ -47,16 +48,18 @@ class TestFileIco(PillowTestCase):
|
|||
assert reloaded.format == "ICO"
|
||||
assert_image_equal(reloaded, hopper().resize((32, 32), Image.LANCZOS))
|
||||
|
||||
def test_incorrect_size(self):
|
||||
|
||||
def test_incorrect_size():
|
||||
with Image.open(TEST_ICO_FILE) as im:
|
||||
with pytest.raises(ValueError):
|
||||
im.size = (1, 1)
|
||||
|
||||
def test_save_256x256(self):
|
||||
|
||||
def test_save_256x256(tmp_path):
|
||||
"""Issue #2264 https://github.com/python-pillow/Pillow/issues/2264"""
|
||||
# Arrange
|
||||
with Image.open("Tests/images/hopper_256x256.ico") as im:
|
||||
outfile = self.tempfile("temp_saved_hopper_256x256.ico")
|
||||
outfile = str(tmp_path / "temp_saved_hopper_256x256.ico")
|
||||
|
||||
# Act
|
||||
im.save(outfile)
|
||||
|
@ -65,14 +68,15 @@ class TestFileIco(PillowTestCase):
|
|||
# Assert
|
||||
assert im_saved.size == (256, 256)
|
||||
|
||||
def test_only_save_relevant_sizes(self):
|
||||
|
||||
def test_only_save_relevant_sizes(tmp_path):
|
||||
"""Issue #2266 https://github.com/python-pillow/Pillow/issues/2266
|
||||
Should save in 16x16, 24x24, 32x32, 48x48 sizes
|
||||
and not in 16x16, 24x24, 32x32, 48x48, 48x48, 48x48, 48x48 sizes
|
||||
"""
|
||||
# Arrange
|
||||
with Image.open("Tests/images/python.ico") as im: # 16x16, 32x32, 48x48
|
||||
outfile = self.tempfile("temp_saved_python.ico")
|
||||
outfile = str(tmp_path / "temp_saved_python.ico")
|
||||
# Act
|
||||
im.save(outfile)
|
||||
|
||||
|
@ -80,7 +84,8 @@ class TestFileIco(PillowTestCase):
|
|||
# Assert
|
||||
assert im_saved.info["sizes"] == {(16, 16), (24, 24), (32, 32), (48, 48)}
|
||||
|
||||
def test_unexpected_size(self):
|
||||
|
||||
def test_unexpected_size():
|
||||
# This image has been manually hexedited to state that it is 16x32
|
||||
# while the image within is still 16x16
|
||||
def open():
|
||||
|
@ -89,9 +94,10 @@ class TestFileIco(PillowTestCase):
|
|||
|
||||
pytest.warns(UserWarning, open)
|
||||
|
||||
def test_draw_reloaded(self):
|
||||
|
||||
def test_draw_reloaded(tmp_path):
|
||||
with Image.open(TEST_ICO_FILE) as im:
|
||||
outfile = self.tempfile("temp_saved_hopper_draw.ico")
|
||||
outfile = str(tmp_path / "temp_saved_hopper_draw.ico")
|
||||
|
||||
draw = ImageDraw.Draw(im)
|
||||
draw.line((0, 0) + im.size, "#f00")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
import re
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
@ -42,7 +43,7 @@ class TestFileJpeg(PillowTestCase):
|
|||
def test_sanity(self):
|
||||
|
||||
# internal version number
|
||||
self.assertRegex(Image.core.jpeglib_version, r"\d+\.\d+$")
|
||||
assert re.search(r"\d+\.\d+$", Image.core.jpeglib_version)
|
||||
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
@ -34,7 +35,7 @@ class TestFileJpeg2k(PillowTestCase):
|
|||
|
||||
def test_sanity(self):
|
||||
# Internal version number
|
||||
self.assertRegex(Image.core.jp2klib_version, r"\d+\.\d+\.\d+$")
|
||||
assert re.search(r"\d+\.\d+\.\d+$", Image.core.jp2klib_version)
|
||||
|
||||
with Image.open("Tests/images/test-card-lossless.jp2") as im:
|
||||
px = im.load()
|
||||
|
|
|
@ -295,7 +295,9 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||
and libtiff
|
||||
):
|
||||
# libtiff does not support real RATIONALS
|
||||
self.assertAlmostEqual(float(reloaded_value), float(value))
|
||||
assert (
|
||||
round(abs(float(reloaded_value) - float(value)), 7) == 0
|
||||
)
|
||||
continue
|
||||
|
||||
if libtiff and isinstance(value, bytes):
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
import os
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
from PIL import Image, MspImagePlugin
|
||||
|
||||
from .helper import PillowTestCase, assert_image_equal, hopper
|
||||
from .helper import assert_image_equal, hopper
|
||||
|
||||
TEST_FILE = "Tests/images/hopper.msp"
|
||||
EXTRA_DIR = "Tests/images/picins"
|
||||
YA_EXTRA_DIR = "Tests/images/msp"
|
||||
|
||||
|
||||
class TestFileMsp(PillowTestCase):
|
||||
def test_sanity(self):
|
||||
test_file = self.tempfile("temp.msp")
|
||||
def test_sanity(tmp_path):
|
||||
test_file = str(tmp_path / "temp.msp")
|
||||
|
||||
hopper("1").save(test_file)
|
||||
|
||||
|
@ -23,13 +21,15 @@ class TestFileMsp(PillowTestCase):
|
|||
assert im.size == (128, 128)
|
||||
assert im.format == "MSP"
|
||||
|
||||
def test_invalid_file(self):
|
||||
|
||||
def test_invalid_file():
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
with pytest.raises(SyntaxError):
|
||||
MspImagePlugin.MspImageFile(invalid_file)
|
||||
|
||||
def test_bad_checksum(self):
|
||||
|
||||
def test_bad_checksum():
|
||||
# Arrange
|
||||
# This was created by forcing Pillow to save with checksum=0
|
||||
bad_checksum = "Tests/images/hopper_bad_checksum.msp"
|
||||
|
@ -38,7 +38,8 @@ class TestFileMsp(PillowTestCase):
|
|||
with pytest.raises(SyntaxError):
|
||||
MspImagePlugin.MspImageFile(bad_checksum)
|
||||
|
||||
def test_open_windows_v1(self):
|
||||
|
||||
def test_open_windows_v1():
|
||||
# Arrange
|
||||
# Act
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
@ -47,13 +48,17 @@ class TestFileMsp(PillowTestCase):
|
|||
assert_image_equal(im, hopper("1"))
|
||||
assert isinstance(im, MspImagePlugin.MspImageFile)
|
||||
|
||||
def _assert_file_image_equal(self, source_path, target_path):
|
||||
|
||||
def _assert_file_image_equal(source_path, target_path):
|
||||
with Image.open(source_path) as im:
|
||||
with Image.open(target_path) as target:
|
||||
assert_image_equal(im, target)
|
||||
|
||||
@unittest.skipUnless(os.path.exists(EXTRA_DIR), "Extra image files not installed")
|
||||
def test_open_windows_v2(self):
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
|
||||
)
|
||||
def test_open_windows_v2():
|
||||
|
||||
files = (
|
||||
os.path.join(EXTRA_DIR, f)
|
||||
|
@ -61,22 +66,24 @@ class TestFileMsp(PillowTestCase):
|
|||
if os.path.splitext(f)[1] == ".msp"
|
||||
)
|
||||
for path in files:
|
||||
self._assert_file_image_equal(path, path.replace(".msp", ".png"))
|
||||
_assert_file_image_equal(path, path.replace(".msp", ".png"))
|
||||
|
||||
@unittest.skipIf(
|
||||
not os.path.exists(YA_EXTRA_DIR), "Even More Extra image files not installed"
|
||||
)
|
||||
def test_msp_v2(self):
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not os.path.exists(YA_EXTRA_DIR), reason="Even More Extra image files not installed"
|
||||
)
|
||||
def test_msp_v2():
|
||||
for f in os.listdir(YA_EXTRA_DIR):
|
||||
if ".MSP" not in f:
|
||||
continue
|
||||
path = os.path.join(YA_EXTRA_DIR, f)
|
||||
self._assert_file_image_equal(path, path.replace(".MSP", ".png"))
|
||||
_assert_file_image_equal(path, path.replace(".MSP", ".png"))
|
||||
|
||||
def test_cannot_save_wrong_mode(self):
|
||||
|
||||
def test_cannot_save_wrong_mode(tmp_path):
|
||||
# Arrange
|
||||
im = hopper()
|
||||
filename = self.tempfile("temp.msp")
|
||||
filename = str(tmp_path / "temp.msp")
|
||||
|
||||
# Act/Assert
|
||||
with pytest.raises(IOError):
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
import unittest
|
||||
import zlib
|
||||
from io import BytesIO
|
||||
|
@ -75,7 +76,7 @@ class TestFilePng(PillowTestCase):
|
|||
def test_sanity(self):
|
||||
|
||||
# internal version number
|
||||
self.assertRegex(Image.core.zlib_version, r"\d+\.\d+\.\d+(\.\d+)?$")
|
||||
assert re.search(r"\d+\.\d+\.\d+(\.\d+)?$", Image.core.zlib_version)
|
||||
|
||||
test_file = self.tempfile("temp.png")
|
||||
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
import tempfile
|
||||
import unittest
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
from PIL import Image, ImageSequence, SpiderImagePlugin
|
||||
|
||||
from .helper import PillowTestCase, assert_image_equal, hopper, is_pypy
|
||||
from .helper import assert_image_equal, hopper, is_pypy
|
||||
|
||||
TEST_FILE = "Tests/images/hopper.spider"
|
||||
|
||||
|
||||
class TestImageSpider(PillowTestCase):
|
||||
def test_sanity(self):
|
||||
def test_sanity():
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
assert im.mode == "F"
|
||||
assert im.size == (128, 128)
|
||||
assert im.format == "SPIDER"
|
||||
|
||||
@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():
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
|
||||
pytest.warns(ResourceWarning, open)
|
||||
|
||||
def test_closed_file(self):
|
||||
|
||||
def test_closed_file():
|
||||
def open():
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
|
@ -34,16 +34,18 @@ class TestImageSpider(PillowTestCase):
|
|||
|
||||
pytest.warns(None, open)
|
||||
|
||||
def test_context_manager(self):
|
||||
|
||||
def test_context_manager():
|
||||
def open():
|
||||
with Image.open(TEST_FILE) as im:
|
||||
im.load()
|
||||
|
||||
pytest.warns(None, open)
|
||||
|
||||
def test_save(self):
|
||||
|
||||
def test_save(tmp_path):
|
||||
# Arrange
|
||||
temp = self.tempfile("temp.spider")
|
||||
temp = str(tmp_path / "temp.spider")
|
||||
im = hopper()
|
||||
|
||||
# Act
|
||||
|
@ -55,7 +57,8 @@ class TestImageSpider(PillowTestCase):
|
|||
assert im2.size == (128, 128)
|
||||
assert im2.format == "SPIDER"
|
||||
|
||||
def test_tempfile(self):
|
||||
|
||||
def test_tempfile():
|
||||
# Arrange
|
||||
im = hopper()
|
||||
|
||||
|
@ -70,10 +73,12 @@ class TestImageSpider(PillowTestCase):
|
|||
assert reloaded.size == (128, 128)
|
||||
assert reloaded.format == "SPIDER"
|
||||
|
||||
def test_isSpiderImage(self):
|
||||
|
||||
def test_is_spider_image():
|
||||
assert SpiderImagePlugin.isSpiderImage(TEST_FILE)
|
||||
|
||||
def test_tell(self):
|
||||
|
||||
def test_tell():
|
||||
# Arrange
|
||||
with Image.open(TEST_FILE) as im:
|
||||
|
||||
|
@ -83,12 +88,14 @@ class TestImageSpider(PillowTestCase):
|
|||
# Assert
|
||||
assert index == 0
|
||||
|
||||
def test_n_frames(self):
|
||||
|
||||
def test_n_frames():
|
||||
with Image.open(TEST_FILE) as im:
|
||||
assert im.n_frames == 1
|
||||
assert not im.is_animated
|
||||
|
||||
def test_loadImageSeries(self):
|
||||
|
||||
def test_load_image_series():
|
||||
# Arrange
|
||||
not_spider_file = "Tests/images/hopper.ppm"
|
||||
file_list = [TEST_FILE, not_spider_file, "path/not_found.ext"]
|
||||
|
@ -101,7 +108,8 @@ class TestImageSpider(PillowTestCase):
|
|||
assert isinstance(img_list[0], Image.Image)
|
||||
assert img_list[0].size == (128, 128)
|
||||
|
||||
def test_loadImageSeries_no_input(self):
|
||||
|
||||
def test_load_image_series_no_input():
|
||||
# Arrange
|
||||
file_list = None
|
||||
|
||||
|
@ -111,7 +119,8 @@ class TestImageSpider(PillowTestCase):
|
|||
# Assert
|
||||
assert img_list is None
|
||||
|
||||
def test_isInt_not_a_number(self):
|
||||
|
||||
def test_is_int_not_a_number():
|
||||
# Arrange
|
||||
not_a_number = "a"
|
||||
|
||||
|
@ -121,24 +130,28 @@ class TestImageSpider(PillowTestCase):
|
|||
# Assert
|
||||
assert ret == 0
|
||||
|
||||
def test_invalid_file(self):
|
||||
|
||||
def test_invalid_file():
|
||||
invalid_file = "Tests/images/invalid.spider"
|
||||
|
||||
with pytest.raises(IOError):
|
||||
Image.open(invalid_file)
|
||||
|
||||
def test_nonstack_file(self):
|
||||
|
||||
def test_nonstack_file():
|
||||
with Image.open(TEST_FILE) as im:
|
||||
with pytest.raises(EOFError):
|
||||
im.seek(0)
|
||||
|
||||
def test_nonstack_dos(self):
|
||||
|
||||
def test_nonstack_dos():
|
||||
with Image.open(TEST_FILE) as im:
|
||||
for i, frame in enumerate(ImageSequence.Iterator(im)):
|
||||
assert i <= 1, "Non-stack DOS file test failed"
|
||||
|
||||
# for issue #4093
|
||||
def test_odd_size(self):
|
||||
|
||||
# for issue #4093
|
||||
def test_odd_size():
|
||||
data = BytesIO()
|
||||
width = 100
|
||||
im = Image.new("F", (width, 64))
|
||||
|
|
|
@ -65,9 +65,9 @@ class TestFileTiffMetadata(PillowTestCase):
|
|||
assert loaded.tag_v2[ImageDescription] == reloaded_textdata
|
||||
|
||||
loaded_float = loaded.tag[tag_ids["RollAngle"]][0]
|
||||
self.assertAlmostEqual(loaded_float, floatdata, places=5)
|
||||
assert round(abs(loaded_float - floatdata), 5) == 0
|
||||
loaded_double = loaded.tag[tag_ids["YawAngle"]][0]
|
||||
self.assertAlmostEqual(loaded_double, doubledata)
|
||||
assert round(abs(loaded_double - doubledata), 7) == 0
|
||||
|
||||
# check with 2 element ImageJMetaDataByteCounts, issue #2006
|
||||
|
||||
|
|
|
@ -2,13 +2,11 @@ import io
|
|||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
from PIL import Image, ImageDraw, ImagePalette, UnidentifiedImageError
|
||||
|
||||
from .helper import (
|
||||
PillowTestCase,
|
||||
assert_image_equal,
|
||||
assert_image_similar,
|
||||
assert_not_all_same,
|
||||
|
@ -17,7 +15,7 @@ from .helper import (
|
|||
)
|
||||
|
||||
|
||||
class TestImage(PillowTestCase):
|
||||
class TestImage:
|
||||
def test_image_modes_success(self):
|
||||
for mode in [
|
||||
"1",
|
||||
|
@ -109,7 +107,7 @@ class TestImage(PillowTestCase):
|
|||
with pytest.raises(ValueError):
|
||||
Image.open(io.StringIO())
|
||||
|
||||
def test_pathlib(self):
|
||||
def test_pathlib(self, tmp_path):
|
||||
from PIL.Image import Path
|
||||
|
||||
with Image.open(Path("Tests/images/multipage-mmap.tiff")) as im:
|
||||
|
@ -120,13 +118,13 @@ class TestImage(PillowTestCase):
|
|||
assert im.mode == "RGB"
|
||||
assert im.size == (128, 128)
|
||||
|
||||
temp_file = self.tempfile("temp.jpg")
|
||||
temp_file = str(tmp_path / "temp.jpg")
|
||||
if os.path.exists(temp_file):
|
||||
os.remove(temp_file)
|
||||
im.save(Path(temp_file))
|
||||
|
||||
def test_fp_name(self):
|
||||
temp_file = self.tempfile("temp.jpg")
|
||||
def test_fp_name(self, tmp_path):
|
||||
temp_file = str(tmp_path / "temp.jpg")
|
||||
|
||||
class FP:
|
||||
def write(a, b):
|
||||
|
@ -148,9 +146,9 @@ class TestImage(PillowTestCase):
|
|||
with Image.open(fp) as reloaded:
|
||||
assert_image_similar(im, reloaded, 20)
|
||||
|
||||
def test_unknown_extension(self):
|
||||
def test_unknown_extension(self, tmp_path):
|
||||
im = hopper()
|
||||
temp_file = self.tempfile("temp.unknown")
|
||||
temp_file = str(tmp_path / "temp.unknown")
|
||||
with pytest.raises(ValueError):
|
||||
im.save(temp_file)
|
||||
|
||||
|
@ -164,25 +162,25 @@ class TestImage(PillowTestCase):
|
|||
im.paste(0, (0, 0, 100, 100))
|
||||
assert not im.readonly
|
||||
|
||||
@unittest.skipIf(is_win32(), "Test requires opening tempfile twice")
|
||||
def test_readonly_save(self):
|
||||
temp_file = self.tempfile("temp.bmp")
|
||||
@pytest.mark.skipif(is_win32(), reason="Test requires opening tempfile twice")
|
||||
def test_readonly_save(self, tmp_path):
|
||||
temp_file = str(tmp_path / "temp.bmp")
|
||||
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
|
||||
|
||||
with Image.open(temp_file) as im:
|
||||
assert im.readonly
|
||||
im.save(temp_file)
|
||||
|
||||
def test_dump(self):
|
||||
def test_dump(self, tmp_path):
|
||||
im = Image.new("L", (10, 10))
|
||||
im._dump(self.tempfile("temp_L.ppm"))
|
||||
im._dump(str(tmp_path / "temp_L.ppm"))
|
||||
|
||||
im = Image.new("RGB", (10, 10))
|
||||
im._dump(self.tempfile("temp_RGB.ppm"))
|
||||
im._dump(str(tmp_path / "temp_RGB.ppm"))
|
||||
|
||||
im = Image.new("HSV", (10, 10))
|
||||
with pytest.raises(ValueError):
|
||||
im._dump(self.tempfile("temp_HSV.ppm"))
|
||||
im._dump(str(tmp_path / "temp_HSV.ppm"))
|
||||
|
||||
def test_comparison_with_other_type(self):
|
||||
# Arrange
|
||||
|
@ -434,8 +432,7 @@ class TestImage(PillowTestCase):
|
|||
assert_image_similar(im2, im3, 110)
|
||||
|
||||
def test_check_size(self):
|
||||
# Checking that the _check_size function throws value errors
|
||||
# when we want it to.
|
||||
# Checking that the _check_size function throws value errors when we want it to
|
||||
with pytest.raises(ValueError):
|
||||
Image.new("RGB", 0) # not a tuple
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -587,11 +584,11 @@ class TestImage(PillowTestCase):
|
|||
expected = Image.new(mode, (100, 100), color)
|
||||
assert_image_equal(im.convert(mode), expected)
|
||||
|
||||
def test_no_resource_warning_on_save(self):
|
||||
def test_no_resource_warning_on_save(self, tmp_path):
|
||||
# https://github.com/python-pillow/Pillow/issues/835
|
||||
# Arrange
|
||||
test_file = "Tests/images/hopper.png"
|
||||
temp_file = self.tempfile("temp.jpg")
|
||||
temp_file = str(tmp_path / "temp.jpg")
|
||||
|
||||
# Act/Assert
|
||||
with Image.open(test_file) as im:
|
||||
|
@ -623,14 +620,14 @@ class TestImage(PillowTestCase):
|
|||
with Image.open(os.path.join("Tests/images", file)) as im:
|
||||
try:
|
||||
im.load()
|
||||
self.assertFail()
|
||||
assert False
|
||||
except OSError as e:
|
||||
assert str(e) == "buffer overrun when reading image file"
|
||||
|
||||
with Image.open("Tests/images/fli_overrun2.bin") as im:
|
||||
try:
|
||||
im.seek(1)
|
||||
self.assertFail()
|
||||
assert False
|
||||
except OSError as e:
|
||||
assert str(e) == "buffer overrun when reading image file"
|
||||
|
||||
|
@ -645,7 +642,7 @@ def mock_encode(*args):
|
|||
return encoder
|
||||
|
||||
|
||||
class TestRegistry(PillowTestCase):
|
||||
class TestRegistry:
|
||||
def test_encode_registry(self):
|
||||
|
||||
Image.register_encoder("MOCK", mock_encode)
|
||||
|
|
|
@ -228,9 +228,8 @@ class TestCffi(AccessTest):
|
|||
assert access[(x, y)] == caccess[(x, y)]
|
||||
|
||||
# Access an out-of-range pixel
|
||||
self.assertRaises(
|
||||
ValueError, lambda: access[(access.xsize + 1, access.ysize + 1)]
|
||||
)
|
||||
with pytest.raises(ValueError):
|
||||
access[(access.xsize + 1, access.ysize + 1)]
|
||||
|
||||
def test_get_vs_c(self):
|
||||
rgb = hopper("RGB")
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import unittest
|
||||
from contextlib import contextmanager
|
||||
|
||||
import pytest
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
from .helper import PillowTestCase, assert_image_equal, assert_image_similar, hopper
|
||||
from .helper import assert_image_equal, assert_image_similar, hopper
|
||||
|
||||
|
||||
class TestImagingResampleVulnerability(PillowTestCase):
|
||||
class TestImagingResampleVulnerability:
|
||||
# see https://github.com/python-pillow/Pillow/issues/1710
|
||||
def test_overflow(self):
|
||||
im = hopper("L")
|
||||
|
@ -43,7 +42,7 @@ class TestImagingResampleVulnerability(PillowTestCase):
|
|||
assert im.tobytes() != copy.tobytes()
|
||||
|
||||
|
||||
class TestImagingCoreResampleAccuracy(PillowTestCase):
|
||||
class TestImagingCoreResampleAccuracy:
|
||||
def make_case(self, mode, size, color):
|
||||
"""Makes a sample image with two dark and two bright squares.
|
||||
For example:
|
||||
|
@ -219,7 +218,7 @@ class TestImagingCoreResampleAccuracy(PillowTestCase):
|
|||
assert_image_equal(im, ref)
|
||||
|
||||
|
||||
class CoreResampleConsistencyTest(PillowTestCase):
|
||||
class CoreResampleConsistencyTest:
|
||||
def make_case(self, mode, fill):
|
||||
im = Image.new(mode, (512, 9), fill)
|
||||
return im.resize((9, 512), Image.LANCZOS), im.load()[0, 0]
|
||||
|
@ -254,7 +253,7 @@ class CoreResampleConsistencyTest(PillowTestCase):
|
|||
self.run_case(self.make_case("F", 1.192093e-07))
|
||||
|
||||
|
||||
class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||
class CoreResampleAlphaCorrectTest:
|
||||
def make_levels_case(self, mode):
|
||||
i = Image.new(mode, (256, 16))
|
||||
px = i.load()
|
||||
|
@ -275,7 +274,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
|||
len(used_colors), y
|
||||
)
|
||||
|
||||
@unittest.skip("current implementation isn't precise enough")
|
||||
@pytest.mark.skip("Current implementation isn't precise enough")
|
||||
def test_levels_rgba(self):
|
||||
case = self.make_levels_case("RGBA")
|
||||
self.run_levels_case(case.resize((512, 32), Image.BOX))
|
||||
|
@ -284,7 +283,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
|||
self.run_levels_case(case.resize((512, 32), Image.BICUBIC))
|
||||
self.run_levels_case(case.resize((512, 32), Image.LANCZOS))
|
||||
|
||||
@unittest.skip("current implementation isn't precise enough")
|
||||
@pytest.mark.skip("Current implementation isn't precise enough")
|
||||
def test_levels_la(self):
|
||||
case = self.make_levels_case("LA")
|
||||
self.run_levels_case(case.resize((512, 32), Image.BOX))
|
||||
|
@ -330,7 +329,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
|||
self.run_dirty_case(case.resize((20, 20), Image.LANCZOS), (255,))
|
||||
|
||||
|
||||
class CoreResamplePassesTest(PillowTestCase):
|
||||
class CoreResamplePassesTest:
|
||||
@contextmanager
|
||||
def count(self, diff):
|
||||
count = Image.core.get_stats()["new_count"]
|
||||
|
@ -373,7 +372,7 @@ class CoreResamplePassesTest(PillowTestCase):
|
|||
assert_image_similar(with_box, cropped, 0.1)
|
||||
|
||||
|
||||
class CoreResampleCoefficientsTest(PillowTestCase):
|
||||
class CoreResampleCoefficientsTest:
|
||||
def test_reduce(self):
|
||||
test_color = 254
|
||||
|
||||
|
@ -402,7 +401,7 @@ class CoreResampleCoefficientsTest(PillowTestCase):
|
|||
assert histogram[0x100 * 3 + 0xFF] == 0x10000
|
||||
|
||||
|
||||
class CoreResampleBoxTest(PillowTestCase):
|
||||
class CoreResampleBoxTest:
|
||||
def test_wrong_arguments(self):
|
||||
im = hopper()
|
||||
for resample in (
|
||||
|
@ -418,24 +417,24 @@ class CoreResampleBoxTest(PillowTestCase):
|
|||
im.resize((32, 32), resample, (20, 20, 20, 100))
|
||||
im.resize((32, 32), resample, (20, 20, 100, 20))
|
||||
|
||||
with self.assertRaisesRegex(TypeError, "must be sequence of length 4"):
|
||||
with pytest.raises(TypeError, match="must be sequence of length 4"):
|
||||
im.resize((32, 32), resample, (im.width, im.height))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "can't be negative"):
|
||||
with pytest.raises(ValueError, match="can't be negative"):
|
||||
im.resize((32, 32), resample, (-20, 20, 100, 100))
|
||||
with self.assertRaisesRegex(ValueError, "can't be negative"):
|
||||
with pytest.raises(ValueError, match="can't be negative"):
|
||||
im.resize((32, 32), resample, (20, -20, 100, 100))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "can't be empty"):
|
||||
with pytest.raises(ValueError, match="can't be empty"):
|
||||
im.resize((32, 32), resample, (20.1, 20, 20, 100))
|
||||
with self.assertRaisesRegex(ValueError, "can't be empty"):
|
||||
with pytest.raises(ValueError, match="can't be empty"):
|
||||
im.resize((32, 32), resample, (20, 20.1, 100, 20))
|
||||
with self.assertRaisesRegex(ValueError, "can't be empty"):
|
||||
with pytest.raises(ValueError, match="can't be empty"):
|
||||
im.resize((32, 32), resample, (20.1, 20.1, 20, 20))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "can't exceed"):
|
||||
with pytest.raises(ValueError, match="can't exceed"):
|
||||
im.resize((32, 32), resample, (0, 0, im.width + 1, im.height))
|
||||
with self.assertRaisesRegex(ValueError, "can't exceed"):
|
||||
with pytest.raises(ValueError, match="can't exceed"):
|
||||
im.resize((32, 32), resample, (0, 0, im.width, im.height + 1))
|
||||
|
||||
def resize_tiled(self, im, dst_size, xtiles, ytiles):
|
||||
|
@ -480,7 +479,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
|||
|
||||
# error with box should be much smaller than without
|
||||
assert_image_similar(reference, with_box, 6)
|
||||
with self.assertRaisesRegex(AssertionError, r"difference 29\."):
|
||||
with pytest.raises(AssertionError, match=r"difference 29\."):
|
||||
assert_image_similar(reference, without_box, 5)
|
||||
|
||||
def test_formats(self):
|
||||
|
@ -518,7 +517,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
|||
]:
|
||||
res = im.resize(size, Image.LANCZOS, box)
|
||||
assert res.size == size
|
||||
with self.assertRaisesRegex(AssertionError, r"difference \d"):
|
||||
with pytest.raises(AssertionError, match=r"difference \d"):
|
||||
# check that the difference at least that much
|
||||
assert_image_similar(
|
||||
res, im.crop(box), 20, ">>> {} {}".format(size, box)
|
||||
|
|
|
@ -66,7 +66,7 @@ class TestImageFont(PillowTestCase):
|
|||
)
|
||||
|
||||
def test_sanity(self):
|
||||
self.assertRegex(ImageFont.core.freetype2_version, r"\d+\.\d+\.\d+$")
|
||||
assert re.search(r"\d+\.\d+\.\d+$", ImageFont.core.freetype2_version)
|
||||
|
||||
def test_font_properties(self):
|
||||
ttf = self.get_font()
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import unittest
|
||||
|
||||
import pytest
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from .helper import PillowTestCase, assert_image_similar
|
||||
from .helper import assert_image_similar
|
||||
|
||||
image_font_installed = True
|
||||
try:
|
||||
|
@ -11,14 +10,11 @@ except ImportError:
|
|||
image_font_installed = False
|
||||
|
||||
|
||||
@unittest.skipUnless(image_font_installed, "image font not installed")
|
||||
class TestImageFontBitmap(PillowTestCase):
|
||||
def test_similar(self):
|
||||
@pytest.mark.skipif(not image_font_installed, reason="Image font not installed")
|
||||
def test_similar():
|
||||
text = "EmbeddedBitmap"
|
||||
font_outline = ImageFont.truetype(font="Tests/fonts/DejaVuSans.ttf", size=24)
|
||||
font_bitmap = ImageFont.truetype(
|
||||
font="Tests/fonts/DejaVuSans-bitmap.ttf", size=24
|
||||
)
|
||||
font_bitmap = ImageFont.truetype(font="Tests/fonts/DejaVuSans-bitmap.ttf", size=24)
|
||||
size_outline = font_outline.getsize(text)
|
||||
size_bitmap = font_bitmap.getsize(text)
|
||||
size_final = (
|
||||
|
@ -30,16 +26,13 @@ class TestImageFontBitmap(PillowTestCase):
|
|||
draw_bitmap = ImageDraw.Draw(im_bitmap)
|
||||
draw_outline = ImageDraw.Draw(im_outline)
|
||||
|
||||
# Metrics are different on the bitmap and ttf fonts,
|
||||
# more so on some platforms and versions of freetype than others.
|
||||
# Mac has a 1px difference, linux doesn't.
|
||||
# Metrics are different on the bitmap and TTF fonts,
|
||||
# more so on some platforms and versions of FreeType than others.
|
||||
# Mac has a 1px difference, Linux doesn't.
|
||||
draw_bitmap.text(
|
||||
(0, size_final[1] - size_bitmap[1]), text, fill=(0, 0, 0), font=font_bitmap
|
||||
)
|
||||
draw_outline.text(
|
||||
(0, size_final[1] - size_outline[1]),
|
||||
text,
|
||||
fill=(0, 0, 0),
|
||||
font=font_outline,
|
||||
(0, size_final[1] - size_outline[1]), text, fill=(0, 0, 0), font=font_outline,
|
||||
)
|
||||
assert_image_similar(im_bitmap, im_outline, 20)
|
||||
|
|
Loading…
Reference in New Issue
Block a user