Merge pull request #4419 from hugovk/pytest

Convert some tests to pytest style
This commit is contained in:
Hugo van Kemenade 2020-02-16 09:08:44 +02:00 committed by GitHub
commit a89156ab42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 4480 additions and 4240 deletions

View File

@ -1,7 +1,6 @@
import pytest
from PIL import Image, ImageFilter
from .helper import PillowTestCase
sample = Image.new("L", (7, 5))
# fmt: off
sample.putdata(sum([
@ -21,226 +20,244 @@ def test_imageops_box_blur():
assert isinstance(i, Image.Image)
class TestBoxBlur(PillowTestCase):
def box_blur(self, image, radius=1, n=1):
return image._new(image.im.box_blur(radius, n))
def box_blur(image, radius=1, n=1):
return image._new(image.im.box_blur(radius, n))
def assertImage(self, im, data, delta=0):
it = iter(im.getdata())
for data_row in data:
im_row = [next(it) for _ in range(im.size[0])]
if any(
abs(data_v - im_v) > delta for data_v, im_v in zip(data_row, im_row)
):
self.assertEqual(im_row, data_row)
self.assertRaises(StopIteration, next, it)
def assertBlur(self, im, radius, data, passes=1, delta=0):
# check grayscale image
self.assertImage(self.box_blur(im, radius, passes), data, delta)
rgba = Image.merge("RGBA", (im, im, im, im))
for band in self.box_blur(rgba, radius, passes).split():
self.assertImage(band, data, delta)
def assertImage(im, data, delta=0):
it = iter(im.getdata())
for data_row in data:
im_row = [next(it) for _ in range(im.size[0])]
if any(abs(data_v - im_v) > delta for data_v, im_v in zip(data_row, im_row)):
assert im_row == data_row
with pytest.raises(StopIteration):
next(it)
def test_color_modes(self):
self.assertRaises(ValueError, self.box_blur, sample.convert("1"))
self.assertRaises(ValueError, self.box_blur, sample.convert("P"))
self.box_blur(sample.convert("L"))
self.box_blur(sample.convert("LA"))
self.box_blur(sample.convert("LA").convert("La"))
self.assertRaises(ValueError, self.box_blur, sample.convert("I"))
self.assertRaises(ValueError, self.box_blur, sample.convert("F"))
self.box_blur(sample.convert("RGB"))
self.box_blur(sample.convert("RGBA"))
self.box_blur(sample.convert("RGBA").convert("RGBa"))
self.box_blur(sample.convert("CMYK"))
self.assertRaises(ValueError, self.box_blur, sample.convert("YCbCr"))
def test_radius_0(self):
self.assertBlur(
sample,
0,
[
# fmt: off
[210, 50, 20, 10, 220, 230, 80],
[190, 210, 20, 180, 170, 40, 110],
[120, 210, 250, 60, 220, 0, 220],
[220, 40, 230, 80, 130, 250, 40],
[250, 0, 80, 30, 60, 20, 110],
# fmt: on
],
)
def assertBlur(im, radius, data, passes=1, delta=0):
# check grayscale image
assertImage(box_blur(im, radius, passes), data, delta)
rgba = Image.merge("RGBA", (im, im, im, im))
for band in box_blur(rgba, radius, passes).split():
assertImage(band, data, delta)
def test_radius_0_02(self):
self.assertBlur(
sample,
0.02,
[
# fmt: off
[206, 55, 20, 17, 215, 223, 83],
[189, 203, 31, 171, 169, 46, 110],
[125, 206, 241, 69, 210, 13, 210],
[215, 49, 221, 82, 131, 235, 48],
[244, 7, 80, 32, 60, 27, 107],
# fmt: on
],
delta=2,
)
def test_radius_0_05(self):
self.assertBlur(
sample,
0.05,
[
# fmt: off
[202, 62, 22, 27, 209, 215, 88],
[188, 194, 44, 161, 168, 56, 111],
[131, 201, 229, 81, 198, 31, 198],
[209, 62, 209, 86, 133, 216, 59],
[237, 17, 80, 36, 60, 35, 103],
# fmt: on
],
delta=2,
)
def test_color_modes():
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_1(self):
self.assertBlur(
sample,
0.1,
[
# fmt: off
[196, 72, 24, 40, 200, 203, 93],
[187, 183, 62, 148, 166, 68, 111],
[139, 193, 213, 96, 182, 54, 182],
[201, 78, 193, 91, 133, 191, 73],
[227, 31, 80, 42, 61, 47, 99],
# fmt: on
],
delta=1,
)
def test_radius_0_5(self):
self.assertBlur(
sample,
0.5,
[
# fmt: off
[176, 101, 46, 83, 163, 165, 111],
[176, 149, 108, 122, 144, 120, 117],
[164, 171, 159, 141, 134, 119, 129],
[170, 136, 133, 114, 116, 124, 109],
[184, 95, 72, 70, 69, 81, 89],
# fmt: on
],
delta=1,
)
def test_radius_0():
assertBlur(
sample,
0,
[
# fmt: off
[210, 50, 20, 10, 220, 230, 80],
[190, 210, 20, 180, 170, 40, 110],
[120, 210, 250, 60, 220, 0, 220],
[220, 40, 230, 80, 130, 250, 40],
[250, 0, 80, 30, 60, 20, 110],
# fmt: on
],
)
def test_radius_1(self):
self.assertBlur(
sample,
1,
[
# fmt: off
[170, 109, 63, 97, 146, 153, 116],
[168, 142, 112, 128, 126, 143, 121],
[169, 166, 142, 149, 126, 131, 114],
[159, 156, 109, 127, 94, 117, 112],
[164, 128, 63, 87, 76, 89, 90],
# fmt: on
],
delta=1,
)
def test_radius_1_5(self):
self.assertBlur(
sample,
1.5,
[
# fmt: off
[155, 120, 105, 112, 124, 137, 130],
[160, 136, 124, 125, 127, 134, 130],
[166, 147, 130, 125, 120, 121, 119],
[168, 145, 119, 109, 103, 105, 110],
[168, 134, 96, 85, 85, 89, 97],
# fmt: on
],
delta=1,
)
def test_radius_0_02():
assertBlur(
sample,
0.02,
[
# fmt: off
[206, 55, 20, 17, 215, 223, 83],
[189, 203, 31, 171, 169, 46, 110],
[125, 206, 241, 69, 210, 13, 210],
[215, 49, 221, 82, 131, 235, 48],
[244, 7, 80, 32, 60, 27, 107],
# fmt: on
],
delta=2,
)
def test_radius_bigger_then_half(self):
self.assertBlur(
sample,
3,
[
# fmt: off
[144, 145, 142, 128, 114, 115, 117],
[148, 145, 137, 122, 109, 111, 112],
[152, 145, 131, 117, 103, 107, 108],
[156, 144, 126, 111, 97, 102, 103],
[160, 144, 121, 106, 92, 98, 99],
# fmt: on
],
delta=1,
)
def test_radius_bigger_then_width(self):
self.assertBlur(
sample,
10,
[
[158, 153, 147, 141, 135, 129, 123],
[159, 153, 147, 141, 136, 130, 124],
[159, 154, 148, 142, 136, 130, 124],
[160, 154, 148, 142, 137, 131, 125],
[160, 155, 149, 143, 137, 131, 125],
],
delta=0,
)
def test_radius_0_05():
assertBlur(
sample,
0.05,
[
# fmt: off
[202, 62, 22, 27, 209, 215, 88],
[188, 194, 44, 161, 168, 56, 111],
[131, 201, 229, 81, 198, 31, 198],
[209, 62, 209, 86, 133, 216, 59],
[237, 17, 80, 36, 60, 35, 103],
# fmt: on
],
delta=2,
)
def test_extreme_large_radius(self):
self.assertBlur(
sample,
600,
[
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
],
delta=1,
)
def test_two_passes(self):
self.assertBlur(
sample,
1,
[
# fmt: off
[153, 123, 102, 109, 132, 135, 129],
[159, 138, 123, 121, 133, 131, 126],
[162, 147, 136, 124, 127, 121, 121],
[159, 140, 125, 108, 111, 106, 108],
[154, 126, 105, 87, 94, 93, 97],
# fmt: on
],
passes=2,
delta=1,
)
def test_radius_0_1():
assertBlur(
sample,
0.1,
[
# fmt: off
[196, 72, 24, 40, 200, 203, 93],
[187, 183, 62, 148, 166, 68, 111],
[139, 193, 213, 96, 182, 54, 182],
[201, 78, 193, 91, 133, 191, 73],
[227, 31, 80, 42, 61, 47, 99],
# fmt: on
],
delta=1,
)
def test_three_passes(self):
self.assertBlur(
sample,
1,
[
# fmt: off
[146, 131, 116, 118, 126, 131, 130],
[151, 138, 125, 123, 126, 128, 127],
[154, 143, 129, 123, 120, 120, 119],
[152, 139, 122, 113, 108, 108, 108],
[148, 132, 112, 102, 97, 99, 100],
# fmt: on
],
passes=3,
delta=1,
)
def test_radius_0_5():
assertBlur(
sample,
0.5,
[
# fmt: off
[176, 101, 46, 83, 163, 165, 111],
[176, 149, 108, 122, 144, 120, 117],
[164, 171, 159, 141, 134, 119, 129],
[170, 136, 133, 114, 116, 124, 109],
[184, 95, 72, 70, 69, 81, 89],
# fmt: on
],
delta=1,
)
def test_radius_1():
assertBlur(
sample,
1,
[
# fmt: off
[170, 109, 63, 97, 146, 153, 116],
[168, 142, 112, 128, 126, 143, 121],
[169, 166, 142, 149, 126, 131, 114],
[159, 156, 109, 127, 94, 117, 112],
[164, 128, 63, 87, 76, 89, 90],
# fmt: on
],
delta=1,
)
def test_radius_1_5():
assertBlur(
sample,
1.5,
[
# fmt: off
[155, 120, 105, 112, 124, 137, 130],
[160, 136, 124, 125, 127, 134, 130],
[166, 147, 130, 125, 120, 121, 119],
[168, 145, 119, 109, 103, 105, 110],
[168, 134, 96, 85, 85, 89, 97],
# fmt: on
],
delta=1,
)
def test_radius_bigger_then_half():
assertBlur(
sample,
3,
[
# fmt: off
[144, 145, 142, 128, 114, 115, 117],
[148, 145, 137, 122, 109, 111, 112],
[152, 145, 131, 117, 103, 107, 108],
[156, 144, 126, 111, 97, 102, 103],
[160, 144, 121, 106, 92, 98, 99],
# fmt: on
],
delta=1,
)
def test_radius_bigger_then_width():
assertBlur(
sample,
10,
[
[158, 153, 147, 141, 135, 129, 123],
[159, 153, 147, 141, 136, 130, 124],
[159, 154, 148, 142, 136, 130, 124],
[160, 154, 148, 142, 137, 131, 125],
[160, 155, 149, 143, 137, 131, 125],
],
delta=0,
)
def test_extreme_large_radius():
assertBlur(
sample,
600,
[
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
[162, 162, 162, 162, 162, 162, 162],
],
delta=1,
)
def test_two_passes():
assertBlur(
sample,
1,
[
# fmt: off
[153, 123, 102, 109, 132, 135, 129],
[159, 138, 123, 121, 133, 131, 126],
[162, 147, 136, 124, 127, 121, 121],
[159, 140, 125, 108, 111, 106, 108],
[154, 126, 105, 87, 94, 93, 97],
# fmt: on
],
passes=2,
delta=1,
)
def test_three_passes():
assertBlur(
sample,
1,
[
# fmt: off
[146, 131, 116, 118, 126, 131, 130],
[151, 138, 125, 123, 126, 128, 127],
[154, 143, 129, 123, 120, 120, 119],
[152, 139, 122, 113, 108, 108, 108],
[148, 132, 112, 102, 97, 99, 100],
# fmt: on
],
passes=3,
delta=1,
)

View File

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

View File

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

View File

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

View File

@ -1,9 +1,7 @@
import unittest
import pytest
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
# save as...-> hopper.fli, default options.
@ -13,105 +11,115 @@ static_test_file = "Tests/images/hopper.fli"
animated_test_file = "Tests/images/a.fli"
class TestFileFli(PillowTestCase):
def test_sanity(self):
def test_sanity():
with Image.open(static_test_file) as im:
im.load()
assert im.mode == "P"
assert im.size == (128, 128)
assert im.format == "FLI"
assert not im.is_animated
with Image.open(animated_test_file) as im:
assert im.mode == "P"
assert im.size == (320, 200)
assert im.format == "FLI"
assert im.info["duration"] == 71
assert im.is_animated
@pytest.mark.skipif(is_pypy(), reason="Requires CPython")
def test_unclosed_file():
def open():
im = Image.open(static_test_file)
im.load()
pytest.warns(ResourceWarning, open)
def test_closed_file():
def open():
im = Image.open(static_test_file)
im.load()
im.close()
pytest.warns(None, open)
def test_context_manager():
def open():
with Image.open(static_test_file) as im:
im.load()
self.assertEqual(im.mode, "P")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "FLI")
self.assertFalse(im.is_animated)
with Image.open(animated_test_file) as im:
self.assertEqual(im.mode, "P")
self.assertEqual(im.size, (320, 200))
self.assertEqual(im.format, "FLI")
self.assertEqual(im.info["duration"], 71)
self.assertTrue(im.is_animated)
pytest.warns(None, open)
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self):
def open():
im = Image.open(static_test_file)
im.load()
pytest.warns(ResourceWarning, open)
def test_tell():
# Arrange
with Image.open(static_test_file) as im:
def test_closed_file(self):
def open():
im = Image.open(static_test_file)
im.load()
im.close()
# Act
frame = im.tell()
pytest.warns(None, open)
# Assert
assert frame == 0
def test_context_manager(self):
def open():
with Image.open(static_test_file) as im:
im.load()
pytest.warns(None, open)
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg"
def test_tell(self):
# Arrange
with Image.open(static_test_file) as im:
with pytest.raises(SyntaxError):
FliImagePlugin.FliImageFile(invalid_file)
# Act
frame = im.tell()
# Assert
self.assertEqual(frame, 0)
def test_n_frames():
with Image.open(static_test_file) as im:
assert im.n_frames == 1
assert not im.is_animated
def test_invalid_file(self):
invalid_file = "Tests/images/flower.jpg"
with Image.open(animated_test_file) as im:
assert im.n_frames == 384
assert im.is_animated
self.assertRaises(SyntaxError, FliImagePlugin.FliImageFile, invalid_file)
def test_n_frames(self):
with Image.open(static_test_file) as im:
self.assertEqual(im.n_frames, 1)
self.assertFalse(im.is_animated)
def test_eoferror():
with Image.open(animated_test_file) as im:
n_frames = im.n_frames
with Image.open(animated_test_file) as im:
self.assertEqual(im.n_frames, 384)
self.assertTrue(im.is_animated)
# Test seeking past the last frame
with pytest.raises(EOFError):
im.seek(n_frames)
assert im.tell() < n_frames
def test_eoferror(self):
with Image.open(animated_test_file) as im:
n_frames = im.n_frames
# Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1)
# Test seeking past the last frame
self.assertRaises(EOFError, im.seek, n_frames)
self.assertLess(im.tell(), n_frames)
# Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1)
def test_seek_tell():
with Image.open(animated_test_file) as im:
def test_seek_tell(self):
with Image.open(animated_test_file) as im:
layer_number = im.tell()
assert layer_number == 0
layer_number = im.tell()
self.assertEqual(layer_number, 0)
im.seek(0)
layer_number = im.tell()
assert layer_number == 0
im.seek(0)
layer_number = im.tell()
self.assertEqual(layer_number, 0)
im.seek(1)
layer_number = im.tell()
assert layer_number == 1
im.seek(1)
layer_number = im.tell()
self.assertEqual(layer_number, 1)
im.seek(2)
layer_number = im.tell()
assert layer_number == 2
im.seek(2)
layer_number = im.tell()
self.assertEqual(layer_number, 2)
im.seek(1)
layer_number = im.tell()
assert layer_number == 1
im.seek(1)
layer_number = im.tell()
self.assertEqual(layer_number, 1)
def test_seek(self):
with Image.open(animated_test_file) as im:
im.seek(50)
def test_seek():
with Image.open(animated_test_file) as im:
im.seek(50)
with Image.open("Tests/images/a_fli.png") as expected:
assert_image_equal(im, expected)
with Image.open("Tests/images/a_fli.png") as expected:
assert_image_equal(im, expected)

View File

@ -1,9 +1,6 @@
import unittest
import pytest
from PIL import Image
from .helper import PillowTestCase
try:
from PIL import FpxImagePlugin
except ImportError:
@ -11,18 +8,23 @@ except ImportError:
else:
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(self):
# Test an invalid OLE file
invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, invalid_file)
# Test a valid OLE file, but not an FPX file
ole_file = "Tests/images/test-ole-file.doc"
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file)
def test_invalid_file():
# Test an invalid OLE file
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
FpxImagePlugin.FpxImageFile(invalid_file)
def test_fpx_invalid_number_of_bands(self):
with self.assertRaisesRegex(IOError, "Invalid number of bands"):
Image.open("Tests/images/input_bw_five_bands.fpx")
# Test a valid OLE file, but not an FPX file
ole_file = "Tests/images/test-ole-file.doc"
with pytest.raises(SyntaxError):
FpxImagePlugin.FpxImageFile(ole_file)
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")

View File

@ -1,15 +1,17 @@
import pytest
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(self):
invalid_file = "Tests/images/flower.jpg"
def test_invalid_file():
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):
with Image.open("Tests/images/gbr.gbr") as im:
with Image.open("Tests/images/gbr.png") as target:
assert_image_equal(target, im)
def test_gbr_file():
with Image.open("Tests/images/gbr.gbr") as im:
with Image.open("Tests/images/gbr.png") as target:
assert_image_equal(target, im)

View File

@ -1,122 +1,128 @@
from PIL import GimpGradientFile
from .helper import PillowTestCase
def test_linear_pos_le_middle():
# Arrange
middle = 0.5
pos = 0.25
# Act
ret = GimpGradientFile.linear(middle, pos)
# Assert
assert ret == 0.25
class TestImage(PillowTestCase):
def test_linear_pos_le_middle(self):
# Arrange
middle = 0.5
pos = 0.25
def test_linear_pos_le_small_middle():
# Arrange
middle = 1e-11
pos = 1e-12
# Act
ret = GimpGradientFile.linear(middle, pos)
# Act
ret = GimpGradientFile.linear(middle, pos)
# Assert
self.assertEqual(ret, 0.25)
# Assert
assert ret == 0.0
def test_linear_pos_le_small_middle(self):
# Arrange
middle = 1e-11
pos = 1e-12
# Act
ret = GimpGradientFile.linear(middle, pos)
def test_linear_pos_gt_middle():
# Arrange
middle = 0.5
pos = 0.75
# Assert
self.assertEqual(ret, 0.0)
# Act
ret = GimpGradientFile.linear(middle, pos)
def test_linear_pos_gt_middle(self):
# Arrange
middle = 0.5
pos = 0.75
# Assert
assert ret == 0.75
# Act
ret = GimpGradientFile.linear(middle, pos)
# Assert
self.assertEqual(ret, 0.75)
def test_linear_pos_gt_small_middle():
# Arrange
middle = 1 - 1e-11
pos = 1 - 1e-12
def test_linear_pos_gt_small_middle(self):
# Arrange
middle = 1 - 1e-11
pos = 1 - 1e-12
# Act
ret = GimpGradientFile.linear(middle, pos)
# Act
ret = GimpGradientFile.linear(middle, pos)
# Assert
assert ret == 1.0
# Assert
self.assertEqual(ret, 1.0)
def test_curved(self):
# Arrange
middle = 0.5
pos = 0.75
def test_curved():
# Arrange
middle = 0.5
pos = 0.75
# Act
ret = GimpGradientFile.curved(middle, pos)
# Act
ret = GimpGradientFile.curved(middle, pos)
# Assert
self.assertEqual(ret, 0.75)
# Assert
assert ret == 0.75
def test_sine(self):
# Arrange
middle = 0.5
pos = 0.75
# Act
ret = GimpGradientFile.sine(middle, pos)
def test_sine():
# Arrange
middle = 0.5
pos = 0.75
# Assert
self.assertEqual(ret, 0.8535533905932737)
# Act
ret = GimpGradientFile.sine(middle, pos)
def test_sphere_increasing(self):
# Arrange
middle = 0.5
pos = 0.75
# Assert
assert ret == 0.8535533905932737
# Act
ret = GimpGradientFile.sphere_increasing(middle, pos)
# Assert
self.assertAlmostEqual(ret, 0.9682458365518543)
def test_sphere_increasing():
# Arrange
middle = 0.5
pos = 0.75
def test_sphere_decreasing(self):
# Arrange
middle = 0.5
pos = 0.75
# Act
ret = GimpGradientFile.sphere_increasing(middle, pos)
# Act
ret = GimpGradientFile.sphere_decreasing(middle, pos)
# Assert
assert round(abs(ret - 0.9682458365518543), 7) == 0
# Assert
self.assertEqual(ret, 0.3385621722338523)
def test_load_via_imagepalette(self):
# Arrange
from PIL import ImagePalette
def test_sphere_decreasing():
# Arrange
middle = 0.5
pos = 0.75
test_file = "Tests/images/gimp_gradient.ggr"
# Act
ret = GimpGradientFile.sphere_decreasing(middle, pos)
# Act
palette = ImagePalette.load(test_file)
# Assert
assert ret == 0.3385621722338523
# Assert
# load returns raw palette information
self.assertEqual(len(palette[0]), 1024)
self.assertEqual(palette[1], "RGBA")
def test_load_1_3_via_imagepalette(self):
# Arrange
from PIL import ImagePalette
def test_load_via_imagepalette():
# Arrange
from PIL import ImagePalette
# GIMP 1.3 gradient files contain a name field
test_file = "Tests/images/gimp_gradient_with_name.ggr"
test_file = "Tests/images/gimp_gradient.ggr"
# Act
palette = ImagePalette.load(test_file)
# Act
palette = ImagePalette.load(test_file)
# Assert
# load returns raw palette information
self.assertEqual(len(palette[0]), 1024)
self.assertEqual(palette[1], "RGBA")
# Assert
# load returns raw palette information
assert len(palette[0]) == 1024
assert palette[1] == "RGBA"
def test_load_1_3_via_imagepalette():
# Arrange
from PIL import ImagePalette
# GIMP 1.3 gradient files contain a name field
test_file = "Tests/images/gimp_gradient_with_name.ggr"
# Act
palette = ImagePalette.load(test_file)
# Assert
# load returns raw palette information
assert len(palette[0]) == 1024
assert palette[1] == "RGBA"

View File

@ -1,28 +1,30 @@
import pytest
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(self):
invalid_file = "Tests/images/flower.jpg"
def test_invalid_file():
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):
# Arrange
# https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8
# https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/
test_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.ara"
saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png"
# Act
with Image.open(test_file) as im:
im.load()
def test_valid_file():
# Arrange
# https://ghrc.nsstc.nasa.gov/hydro/details/cmx3g8
# https://ghrc.nsstc.nasa.gov/pub/fieldCampaigns/camex3/cmx3g8/browse/
test_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.ara"
saved_file = "Tests/images/cmx3g8_wv_1998.260_0745_mcidas.png"
# Assert
self.assertEqual(im.format, "MCIDAS")
self.assertEqual(im.mode, "I")
self.assertEqual(im.size, (1800, 400))
with Image.open(saved_file) as im2:
assert_image_equal(im, im2)
# Act
with Image.open(test_file) as im:
im.load()
# Assert
assert im.format == "MCIDAS"
assert im.mode == "I"
assert im.size == (1800, 400)
with Image.open(saved_file) as im2:
assert_image_equal(im, im2)

View File

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

View File

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

View File

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

View File

@ -1,116 +1,129 @@
import unittest
import pytest
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"
class TestImagePsd(PillowTestCase):
def test_sanity(self):
def test_sanity():
with Image.open(test_file) as im:
im.load()
assert im.mode == "RGB"
assert im.size == (128, 128)
assert im.format == "PSD"
im2 = hopper()
assert_image_similar(im, im2, 4.8)
@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():
def open():
im = Image.open(test_file)
im.load()
im.close()
pytest.warns(None, open)
def test_context_manager():
def open():
with Image.open(test_file) as im:
im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "PSD")
im2 = hopper()
assert_image_similar(im, im2, 4.8)
pytest.warns(None, open)
@unittest.skipIf(is_pypy(), "Requires CPython")
def test_unclosed_file(self):
def open():
im = Image.open(test_file)
im.load()
pytest.warns(ResourceWarning, open)
def test_invalid_file():
invalid_file = "Tests/images/flower.jpg"
def test_closed_file(self):
def open():
im = Image.open(test_file)
im.load()
im.close()
with pytest.raises(SyntaxError):
PsdImagePlugin.PsdImageFile(invalid_file)
pytest.warns(None, open)
def test_context_manager(self):
def open():
with Image.open(test_file) as im:
im.load()
def test_n_frames():
with Image.open("Tests/images/hopper_merged.psd") as im:
assert im.n_frames == 1
assert not im.is_animated
pytest.warns(None, open)
with Image.open(test_file) as im:
assert im.n_frames == 2
assert im.is_animated
def test_invalid_file(self):
invalid_file = "Tests/images/flower.jpg"
self.assertRaises(SyntaxError, PsdImagePlugin.PsdImageFile, invalid_file)
def test_eoferror():
with Image.open(test_file) as im:
# PSD seek index starts at 1 rather than 0
n_frames = im.n_frames + 1
def test_n_frames(self):
with Image.open("Tests/images/hopper_merged.psd") as im:
self.assertEqual(im.n_frames, 1)
self.assertFalse(im.is_animated)
# Test seeking past the last frame
with pytest.raises(EOFError):
im.seek(n_frames)
assert im.tell() < n_frames
with Image.open(test_file) as im:
self.assertEqual(im.n_frames, 2)
self.assertTrue(im.is_animated)
# Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1)
def test_eoferror(self):
with Image.open(test_file) as im:
# PSD seek index starts at 1 rather than 0
n_frames = im.n_frames + 1
# Test seeking past the last frame
self.assertRaises(EOFError, im.seek, n_frames)
self.assertLess(im.tell(), n_frames)
def test_seek_tell():
with Image.open(test_file) as im:
# Test that seeking to the last frame does not raise an error
im.seek(n_frames - 1)
layer_number = im.tell()
assert layer_number == 1
def test_seek_tell(self):
with Image.open(test_file) as im:
with pytest.raises(EOFError):
im.seek(0)
layer_number = im.tell()
self.assertEqual(layer_number, 1)
im.seek(1)
layer_number = im.tell()
assert layer_number == 1
self.assertRaises(EOFError, im.seek, 0)
im.seek(2)
layer_number = im.tell()
assert layer_number == 2
im.seek(1)
layer_number = im.tell()
self.assertEqual(layer_number, 1)
im.seek(2)
layer_number = im.tell()
self.assertEqual(layer_number, 2)
def test_seek_eoferror():
with Image.open(test_file) as im:
def test_seek_eoferror(self):
with Image.open(test_file) as im:
with pytest.raises(EOFError):
im.seek(-1)
self.assertRaises(EOFError, im.seek, -1)
def test_open_after_exclusive_load(self):
with Image.open(test_file) as im:
im.load()
im.seek(im.tell() + 1)
im.load()
def test_open_after_exclusive_load():
with Image.open(test_file) as im:
im.load()
im.seek(im.tell() + 1)
im.load()
def test_icc_profile(self):
with Image.open(test_file) as im:
self.assertIn("icc_profile", im.info)
icc_profile = im.info["icc_profile"]
self.assertEqual(len(icc_profile), 3144)
def test_icc_profile():
with Image.open(test_file) as im:
assert "icc_profile" in im.info
def test_no_icc_profile(self):
with Image.open("Tests/images/hopper_merged.psd") as im:
self.assertNotIn("icc_profile", im.info)
icc_profile = im.info["icc_profile"]
assert len(icc_profile) == 3144
def test_combined_larger_than_size(self):
# The 'combined' sizes of the individual parts is larger than the
# 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,
# then the seek can't be negative
with self.assertRaises(IOError):
Image.open("Tests/images/combined_larger_than_size.psd")
def test_no_icc_profile():
with Image.open("Tests/images/hopper_merged.psd") as im:
assert "icc_profile" not in im.info
def test_combined_larger_than_size():
# The 'combined' sizes of the individual parts is larger than the
# 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,
# then the seek can't be negative
with pytest.raises(IOError):
Image.open("Tests/images/combined_larger_than_size.psd")

View File

@ -1,47 +1,51 @@
import os
import unittest
import pytest
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"
class TestFileSun(PillowTestCase):
def test_sanity(self):
# Arrange
# Created with ImageMagick: convert hopper.jpg hopper.ras
test_file = "Tests/images/hopper.ras"
def test_sanity():
# Arrange
# Created with ImageMagick: convert hopper.jpg hopper.ras
test_file = "Tests/images/hopper.ras"
# Act
with Image.open(test_file) as im:
# Act
with Image.open(test_file) as im:
# Assert
self.assertEqual(im.size, (128, 128))
# Assert
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"
self.assertRaises(SyntaxError, SunImagePlugin.SunImageFile, invalid_file)
invalid_file = "Tests/images/flower.jpg"
with pytest.raises(SyntaxError):
SunImagePlugin.SunImageFile(invalid_file)
def test_im1(self):
with Image.open("Tests/images/sunraster.im1") as im:
with Image.open("Tests/images/sunraster.im1.png") as target:
def test_im1():
with Image.open("Tests/images/sunraster.im1") as im:
with Image.open("Tests/images/sunraster.im1.png") as target:
assert_image_equal(im, target)
@pytest.mark.skipif(
not os.path.exists(EXTRA_DIR), reason="Extra image files not installed"
)
def test_others():
files = (
os.path.join(EXTRA_DIR, f)
for f in os.listdir(EXTRA_DIR)
if os.path.splitext(f)[1] in (".sun", ".SUN", ".ras")
)
for path in files:
with Image.open(path) as im:
im.load()
assert isinstance(im, SunImagePlugin.SunImageFile)
target_path = "%s.png" % os.path.splitext(path)[0]
# im.save(target_file)
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_others(self):
files = (
os.path.join(EXTRA_DIR, f)
for f in os.listdir(EXTRA_DIR)
if os.path.splitext(f)[1] in (".sun", ".SUN", ".ras")
)
for path in files:
with Image.open(path) as im:
im.load()
self.assertIsInstance(im, SunImagePlugin.SunImageFile)
target_path = "%s.png" % os.path.splitext(path)[0]
# im.save(target_file)
with Image.open(target_path) as target:
assert_image_equal(im, target)

View File

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

View File

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

View File

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

View File

@ -1,103 +1,109 @@
import pytest
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(self):
def crop(mode):
im = hopper(mode)
assert_image_equal(im.crop(), im)
def test_crop():
def crop(mode):
im = hopper(mode)
assert_image_equal(im.crop(), im)
cropped = im.crop((50, 50, 100, 100))
self.assertEqual(cropped.mode, mode)
self.assertEqual(cropped.size, (50, 50))
cropped = im.crop((50, 50, 100, 100))
assert cropped.mode == mode
assert cropped.size == (50, 50)
for mode in "1", "P", "L", "RGB", "I", "F":
crop(mode)
for mode in "1", "P", "L", "RGB", "I", "F":
crop(mode)
def test_wide_crop(self):
def crop(*bbox):
i = im.crop(bbox)
h = i.histogram()
while h and not h[-1]:
del h[-1]
return tuple(h)
im = Image.new("L", (100, 100), 1)
def test_wide_crop():
def crop(*bbox):
i = im.crop(bbox)
h = i.histogram()
while h and not h[-1]:
del h[-1]
return tuple(h)
self.assertEqual(crop(0, 0, 100, 100), (0, 10000))
self.assertEqual(crop(25, 25, 75, 75), (0, 2500))
im = Image.new("L", (100, 100), 1)
# sides
self.assertEqual(crop(-25, 0, 25, 50), (1250, 1250))
self.assertEqual(crop(0, -25, 50, 25), (1250, 1250))
self.assertEqual(crop(75, 0, 125, 50), (1250, 1250))
self.assertEqual(crop(0, 75, 50, 125), (1250, 1250))
assert crop(0, 0, 100, 100) == (0, 10000)
assert crop(25, 25, 75, 75) == (0, 2500)
self.assertEqual(crop(-25, 25, 125, 75), (2500, 5000))
self.assertEqual(crop(25, -25, 75, 125), (2500, 5000))
# sides
assert crop(-25, 0, 25, 50) == (1250, 1250)
assert crop(0, -25, 50, 25) == (1250, 1250)
assert crop(75, 0, 125, 50) == (1250, 1250)
assert crop(0, 75, 50, 125) == (1250, 1250)
# corners
self.assertEqual(crop(-25, -25, 25, 25), (1875, 625))
self.assertEqual(crop(75, -25, 125, 25), (1875, 625))
self.assertEqual(crop(75, 75, 125, 125), (1875, 625))
self.assertEqual(crop(-25, 75, 25, 125), (1875, 625))
assert crop(-25, 25, 125, 75) == (2500, 5000)
assert crop(25, -25, 75, 125) == (2500, 5000)
def test_negative_crop(self):
# Check negative crop size (@PIL171)
# corners
assert crop(-25, -25, 25, 25) == (1875, 625)
assert crop(75, -25, 125, 25) == (1875, 625)
assert crop(75, 75, 125, 125) == (1875, 625)
assert crop(-25, 75, 25, 125) == (1875, 625)
im = Image.new("L", (512, 512))
im = im.crop((400, 400, 200, 200))
self.assertEqual(im.size, (0, 0))
self.assertEqual(len(im.getdata()), 0)
self.assertRaises(IndexError, lambda: im.getdata()[0])
def test_negative_crop():
# Check negative crop size (@PIL171)
def test_crop_float(self):
# Check cropping floats are rounded to nearest integer
# https://github.com/python-pillow/Pillow/issues/1744
im = Image.new("L", (512, 512))
im = im.crop((400, 400, 200, 200))
# Arrange
im = Image.new("RGB", (10, 10))
self.assertEqual(im.size, (10, 10))
assert im.size == (0, 0)
assert len(im.getdata()) == 0
with pytest.raises(IndexError):
im.getdata()[0]
# Act
cropped = im.crop((0.9, 1.1, 4.2, 5.8))
# Assert
self.assertEqual(cropped.size, (3, 5))
def test_crop_float():
# Check cropping floats are rounded to nearest integer
# https://github.com/python-pillow/Pillow/issues/1744
def test_crop_crash(self):
# Image.crop crashes prepatch with an access violation
# apparently a use after free on windows, see
# https://github.com/python-pillow/Pillow/issues/1077
# Arrange
im = Image.new("RGB", (10, 10))
assert im.size == (10, 10)
test_img = "Tests/images/bmp/g/pal8-0.bmp"
extents = (1, 1, 10, 10)
# works prepatch
with Image.open(test_img) as img:
img2 = img.crop(extents)
img2.load()
# Act
cropped = im.crop((0.9, 1.1, 4.2, 5.8))
# fail prepatch
with Image.open(test_img) as img:
img = img.crop(extents)
img.load()
# Assert
assert cropped.size == (3, 5)
def test_crop_zero(self):
im = Image.new("RGB", (0, 0), "white")
def test_crop_crash():
# Image.crop crashes prepatch with an access violation
# apparently a use after free on Windows, see
# https://github.com/python-pillow/Pillow/issues/1077
cropped = im.crop((0, 0, 0, 0))
self.assertEqual(cropped.size, (0, 0))
test_img = "Tests/images/bmp/g/pal8-0.bmp"
extents = (1, 1, 10, 10)
# works prepatch
with Image.open(test_img) as img:
img2 = img.crop(extents)
img2.load()
cropped = im.crop((10, 10, 20, 20))
self.assertEqual(cropped.size, (10, 10))
self.assertEqual(cropped.getdata()[0], (0, 0, 0))
# fail prepatch
with Image.open(test_img) as img:
img = img.crop(extents)
img.load()
im = Image.new("RGB", (0, 0))
cropped = im.crop((10, 10, 20, 20))
self.assertEqual(cropped.size, (10, 10))
self.assertEqual(cropped.getdata()[2], (0, 0, 0))
def test_crop_zero():
im = Image.new("RGB", (0, 0), "white")
cropped = im.crop((0, 0, 0, 0))
assert cropped.size == (0, 0)
cropped = im.crop((10, 10, 20, 20))
assert cropped.size == (10, 10)
assert cropped.getdata()[0] == (0, 0, 0)
im = Image.new("RGB", (0, 0))
cropped = im.crop((10, 10, 20, 20))
assert cropped.size == (10, 10)
assert cropped.getdata()[2] == (0, 0, 0)

View File

@ -1,73 +1,77 @@
import pytest
from PIL import Image
from .helper import PillowTestCase, fromstring, tostring
from .helper import fromstring, tostring
class TestImageDraft(PillowTestCase):
def setUp(self):
codecs = dir(Image.core)
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
self.skipTest("jpeg support not available")
def setup_module():
codecs = dir(Image.core)
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
pytest.skip("jpeg support not available")
def draft_roundtrip(self, in_mode, in_size, req_mode, req_size):
im = Image.new(in_mode, in_size)
data = tostring(im, "JPEG")
im = fromstring(data)
mode, box = im.draft(req_mode, req_size)
scale, _ = im.decoderconfig
self.assertEqual(box[:2], (0, 0))
self.assertTrue((im.width - scale) < box[2] <= im.width)
self.assertTrue((im.height - scale) < box[3] <= im.height)
return im
def test_size(self):
for in_size, req_size, out_size in [
((435, 361), (2048, 2048), (435, 361)), # bigger
((435, 361), (435, 361), (435, 361)), # same
((128, 128), (64, 64), (64, 64)),
((128, 128), (32, 32), (32, 32)),
((128, 128), (16, 16), (16, 16)),
# large requested width
((435, 361), (218, 128), (435, 361)), # almost 2x
((435, 361), (217, 128), (218, 181)), # more than 2x
((435, 361), (109, 64), (218, 181)), # almost 4x
((435, 361), (108, 64), (109, 91)), # more than 4x
((435, 361), (55, 32), (109, 91)), # almost 8x
((435, 361), (54, 32), (55, 46)), # more than 8x
((435, 361), (27, 16), (55, 46)), # more than 16x
# and vice versa
((435, 361), (128, 181), (435, 361)), # almost 2x
((435, 361), (128, 180), (218, 181)), # more than 2x
((435, 361), (64, 91), (218, 181)), # almost 4x
((435, 361), (64, 90), (109, 91)), # more than 4x
((435, 361), (32, 46), (109, 91)), # almost 8x
((435, 361), (32, 45), (55, 46)), # more than 8x
((435, 361), (16, 22), (55, 46)), # more than 16x
]:
im = self.draft_roundtrip("L", in_size, None, req_size)
im.load()
self.assertEqual(im.size, out_size)
def draft_roundtrip(in_mode, in_size, req_mode, req_size):
im = Image.new(in_mode, in_size)
data = tostring(im, "JPEG")
im = fromstring(data)
mode, box = im.draft(req_mode, req_size)
scale, _ = im.decoderconfig
assert box[:2] == (0, 0)
assert (im.width - scale) < box[2] <= im.width
assert (im.height - scale) < box[3] <= im.height
return im
def test_mode(self):
for in_mode, req_mode, out_mode in [
("RGB", "1", "RGB"),
("RGB", "L", "L"),
("RGB", "RGB", "RGB"),
("RGB", "YCbCr", "YCbCr"),
("L", "1", "L"),
("L", "L", "L"),
("L", "RGB", "L"),
("L", "YCbCr", "L"),
("CMYK", "1", "CMYK"),
("CMYK", "L", "CMYK"),
("CMYK", "RGB", "CMYK"),
("CMYK", "YCbCr", "CMYK"),
]:
im = self.draft_roundtrip(in_mode, (64, 64), req_mode, None)
im.load()
self.assertEqual(im.mode, out_mode)
def test_several_drafts(self):
im = self.draft_roundtrip("L", (128, 128), None, (64, 64))
im.draft(None, (64, 64))
def test_size():
for in_size, req_size, out_size in [
((435, 361), (2048, 2048), (435, 361)), # bigger
((435, 361), (435, 361), (435, 361)), # same
((128, 128), (64, 64), (64, 64)),
((128, 128), (32, 32), (32, 32)),
((128, 128), (16, 16), (16, 16)),
# large requested width
((435, 361), (218, 128), (435, 361)), # almost 2x
((435, 361), (217, 128), (218, 181)), # more than 2x
((435, 361), (109, 64), (218, 181)), # almost 4x
((435, 361), (108, 64), (109, 91)), # more than 4x
((435, 361), (55, 32), (109, 91)), # almost 8x
((435, 361), (54, 32), (55, 46)), # more than 8x
((435, 361), (27, 16), (55, 46)), # more than 16x
# and vice versa
((435, 361), (128, 181), (435, 361)), # almost 2x
((435, 361), (128, 180), (218, 181)), # more than 2x
((435, 361), (64, 91), (218, 181)), # almost 4x
((435, 361), (64, 90), (109, 91)), # more than 4x
((435, 361), (32, 46), (109, 91)), # almost 8x
((435, 361), (32, 45), (55, 46)), # more than 8x
((435, 361), (16, 22), (55, 46)), # more than 16x
]:
im = draft_roundtrip("L", in_size, None, req_size)
im.load()
assert im.size == out_size
def test_mode():
for in_mode, req_mode, out_mode in [
("RGB", "1", "RGB"),
("RGB", "L", "L"),
("RGB", "RGB", "RGB"),
("RGB", "YCbCr", "YCbCr"),
("L", "1", "L"),
("L", "L", "L"),
("L", "RGB", "L"),
("L", "YCbCr", "L"),
("CMYK", "1", "CMYK"),
("CMYK", "L", "CMYK"),
("CMYK", "RGB", "CMYK"),
("CMYK", "YCbCr", "CMYK"),
]:
im = draft_roundtrip(in_mode, (64, 64), req_mode, None)
im.load()
assert im.mode == out_mode
def test_several_drafts():
im = draft_roundtrip("L", (128, 128), None, (64, 64))
im.draft(None, (64, 64))
im.load()

View File

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

View File

@ -1,143 +1,155 @@
import pytest
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(self):
def filter(filter):
for mode in ["L", "RGB", "CMYK"]:
im = hopper(mode)
out = im.filter(filter)
self.assertEqual(out.mode, im.mode)
self.assertEqual(out.size, im.size)
def test_sanity():
def apply_filter(filter_to_apply):
for mode in ["L", "RGB", "CMYK"]:
im = hopper(mode)
out = im.filter(filter_to_apply)
assert out.mode == im.mode
assert out.size == im.size
filter(ImageFilter.BLUR)
filter(ImageFilter.CONTOUR)
filter(ImageFilter.DETAIL)
filter(ImageFilter.EDGE_ENHANCE)
filter(ImageFilter.EDGE_ENHANCE_MORE)
filter(ImageFilter.EMBOSS)
filter(ImageFilter.FIND_EDGES)
filter(ImageFilter.SMOOTH)
filter(ImageFilter.SMOOTH_MORE)
filter(ImageFilter.SHARPEN)
filter(ImageFilter.MaxFilter)
filter(ImageFilter.MedianFilter)
filter(ImageFilter.MinFilter)
filter(ImageFilter.ModeFilter)
filter(ImageFilter.GaussianBlur)
filter(ImageFilter.GaussianBlur(5))
filter(ImageFilter.BoxBlur(5))
filter(ImageFilter.UnsharpMask)
filter(ImageFilter.UnsharpMask(10))
apply_filter(ImageFilter.BLUR)
apply_filter(ImageFilter.CONTOUR)
apply_filter(ImageFilter.DETAIL)
apply_filter(ImageFilter.EDGE_ENHANCE)
apply_filter(ImageFilter.EDGE_ENHANCE_MORE)
apply_filter(ImageFilter.EMBOSS)
apply_filter(ImageFilter.FIND_EDGES)
apply_filter(ImageFilter.SMOOTH)
apply_filter(ImageFilter.SMOOTH_MORE)
apply_filter(ImageFilter.SHARPEN)
apply_filter(ImageFilter.MaxFilter)
apply_filter(ImageFilter.MedianFilter)
apply_filter(ImageFilter.MinFilter)
apply_filter(ImageFilter.ModeFilter)
apply_filter(ImageFilter.GaussianBlur)
apply_filter(ImageFilter.GaussianBlur(5))
apply_filter(ImageFilter.BoxBlur(5))
apply_filter(ImageFilter.UnsharpMask)
apply_filter(ImageFilter.UnsharpMask(10))
self.assertRaises(TypeError, filter, "hello")
with pytest.raises(TypeError):
apply_filter("hello")
def test_crash(self):
# crashes on small images
im = Image.new("RGB", (1, 1))
im.filter(ImageFilter.SMOOTH)
def test_crash():
im = Image.new("RGB", (2, 2))
im.filter(ImageFilter.SMOOTH)
# crashes on small images
im = Image.new("RGB", (1, 1))
im.filter(ImageFilter.SMOOTH)
im = Image.new("RGB", (3, 3))
im.filter(ImageFilter.SMOOTH)
im = Image.new("RGB", (2, 2))
im.filter(ImageFilter.SMOOTH)
def test_modefilter(self):
def modefilter(mode):
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
# 0 1 2
# 3 4 5
# 6 7 8
mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0]) # mode=0
mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
return mod, mod2
im = Image.new("RGB", (3, 3))
im.filter(ImageFilter.SMOOTH)
self.assertEqual(modefilter("1"), (4, 0))
self.assertEqual(modefilter("L"), (4, 0))
self.assertEqual(modefilter("P"), (4, 0))
self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0)))
def test_rankfilter(self):
def rankfilter(mode):
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
# 0 1 2
# 3 4 5
# 6 7 8
minimum = im.filter(ImageFilter.MinFilter).getpixel((1, 1))
med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1))
maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1))
return minimum, med, maximum
def test_modefilter():
def modefilter(mode):
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
# 0 1 2
# 3 4 5
# 6 7 8
mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0]) # mode=0
mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
return mod, mod2
self.assertEqual(rankfilter("1"), (0, 4, 8))
self.assertEqual(rankfilter("L"), (0, 4, 8))
self.assertRaises(ValueError, rankfilter, "P")
self.assertEqual(rankfilter("RGB"), ((0, 0, 0), (4, 0, 0), (8, 0, 0)))
self.assertEqual(rankfilter("I"), (0, 4, 8))
self.assertEqual(rankfilter("F"), (0.0, 4.0, 8.0))
assert modefilter("1") == (4, 0)
assert modefilter("L") == (4, 0)
assert modefilter("P") == (4, 0)
assert modefilter("RGB") == ((4, 0, 0), (0, 0, 0))
def test_rankfilter_properties(self):
rankfilter = ImageFilter.RankFilter(1, 2)
self.assertEqual(rankfilter.size, 1)
self.assertEqual(rankfilter.rank, 2)
def test_rankfilter():
def rankfilter(mode):
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
# 0 1 2
# 3 4 5
# 6 7 8
minimum = im.filter(ImageFilter.MinFilter).getpixel((1, 1))
med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1))
maximum = im.filter(ImageFilter.MaxFilter).getpixel((1, 1))
return minimum, med, maximum
def test_builtinfilter_p(self):
builtinFilter = ImageFilter.BuiltinFilter()
assert rankfilter("1") == (0, 4, 8)
assert rankfilter("L") == (0, 4, 8)
with pytest.raises(ValueError):
rankfilter("P")
assert rankfilter("RGB") == ((0, 0, 0), (4, 0, 0), (8, 0, 0))
assert rankfilter("I") == (0, 4, 8)
assert rankfilter("F") == (0.0, 4.0, 8.0)
self.assertRaises(ValueError, builtinFilter.filter, hopper("P"))
def test_kernel_not_enough_coefficients(self):
self.assertRaises(ValueError, lambda: ImageFilter.Kernel((3, 3), (0, 0)))
def test_rankfilter_properties():
rankfilter = ImageFilter.RankFilter(1, 2)
def test_consistency_3x3(self):
with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss.bmp") as reference:
kernel = ImageFilter.Kernel( # noqa: E127
(3, 3),
# fmt: off
(-1, -1, 0,
-1, 0, 1,
0, 1, 1),
# fmt: on
0.3,
assert rankfilter.size == 1
assert rankfilter.rank == 2
def test_builtinfilter_p():
builtinFilter = ImageFilter.BuiltinFilter()
with pytest.raises(ValueError):
builtinFilter.filter(hopper("P"))
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_emboss.bmp") as reference:
kernel = ImageFilter.Kernel( # noqa: E127
(3, 3),
# fmt: off
(-1, -1, 0,
-1, 0, 1,
0, 1, 1),
# fmt: on
0.3,
)
source = source.split() * 2
reference = reference.split() * 2
for mode in ["L", "LA", "RGB", "CMYK"]:
assert_image_equal(
Image.merge(mode, source[: len(mode)]).filter(kernel),
Image.merge(mode, reference[: len(mode)]),
)
source = source.split() * 2
reference = reference.split() * 2
for mode in ["L", "LA", "RGB", "CMYK"]:
assert_image_equal(
Image.merge(mode, source[: len(mode)]).filter(kernel),
Image.merge(mode, reference[: len(mode)]),
)
def test_consistency_5x5(self):
with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss_more.bmp") as reference:
kernel = ImageFilter.Kernel( # noqa: E127
(5, 5),
# fmt: off
(-1, -1, -1, -1, 0,
-1, -1, -1, 0, 1,
-1, -1, 0, 1, 1,
-1, 0, 1, 1, 1,
0, 1, 1, 1, 1),
# fmt: on
0.3,
def test_consistency_5x5():
with Image.open("Tests/images/hopper.bmp") as source:
with Image.open("Tests/images/hopper_emboss_more.bmp") as reference:
kernel = ImageFilter.Kernel( # noqa: E127
(5, 5),
# fmt: off
(-1, -1, -1, -1, 0,
-1, -1, -1, 0, 1,
-1, -1, 0, 1, 1,
-1, 0, 1, 1, 1,
0, 1, 1, 1, 1),
# fmt: on
0.3,
)
source = source.split() * 2
reference = reference.split() * 2
for mode in ["L", "LA", "RGB", "CMYK"]:
assert_image_equal(
Image.merge(mode, source[: len(mode)]).filter(kernel),
Image.merge(mode, reference[: len(mode)]),
)
source = source.split() * 2
reference = reference.split() * 2
for mode in ["L", "LA", "RGB", "CMYK"]:
assert_image_equal(
Image.merge(mode, source[: len(mode)]).filter(kernel),
Image.merge(mode, reference[: len(mode)]),
)

View File

@ -1,14 +1,16 @@
import pytest
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(self):
im1 = hopper()
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
def test_sanity():
im1 = hopper()
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,39 +1,48 @@
from .helper import PillowTestCase, assert_image_equal, hopper
import pytest
from .helper import assert_image_equal, hopper
class TestImagePoint(PillowTestCase):
def test_sanity(self):
im = hopper()
def test_sanity():
im = hopper()
self.assertRaises(ValueError, im.point, list(range(256)))
im.point(list(range(256)) * 3)
im.point(lambda x: x)
with pytest.raises(ValueError):
im.point(list(range(256)))
im.point(list(range(256)) * 3)
im.point(lambda x: x)
im = im.convert("I")
self.assertRaises(ValueError, im.point, list(range(256)))
im.point(lambda x: x * 1)
im.point(lambda x: x + 1)
im.point(lambda x: x * 1 + 1)
self.assertRaises(TypeError, im.point, lambda x: x - 1)
self.assertRaises(TypeError, im.point, lambda x: x / 1)
im = im.convert("I")
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 + 1)
with pytest.raises(TypeError):
im.point(lambda x: x - 1)
with pytest.raises(TypeError):
im.point(lambda x: x / 1)
def test_16bit_lut(self):
""" Tests for 16 bit -> 8 bit lut for converting I->L images
see https://github.com/python-pillow/Pillow/issues/440
"""
im = hopper("I")
im.point(list(range(256)) * 256, "L")
def test_f_lut(self):
""" Tests for floating point lut of 8bit gray image """
im = hopper("L")
lut = [0.5 * float(x) for x in range(256)]
def test_16bit_lut():
""" Tests for 16 bit -> 8 bit lut for converting I->L images
see https://github.com/python-pillow/Pillow/issues/440
"""
im = hopper("I")
im.point(list(range(256)) * 256, "L")
out = im.point(lut, "F")
int_lut = [x // 2 for x in range(256)]
assert_image_equal(out.convert("L"), im.point(int_lut, "L"))
def test_f_lut():
""" Tests for floating point lut of 8bit gray image """
im = hopper("L")
lut = [0.5 * float(x) for x in range(256)]
def test_f_mode(self):
im = hopper("F")
self.assertRaises(ValueError, im.point, None)
out = im.point(lut, "F")
int_lut = [x // 2 for x in range(256)]
assert_image_equal(out.convert("L"), im.point(int_lut, "L"))
def test_f_mode():
im = hopper("F")
with pytest.raises(ValueError):
im.point(None)

View File

@ -3,83 +3,87 @@ from array import array
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(self):
def test_sanity():
im1 = hopper()
im1 = hopper()
data = list(im1.getdata())
data = list(im1.getdata())
im2 = Image.new(im1.mode, im1.size, 0)
im2.putdata(data)
im2 = Image.new(im1.mode, im1.size, 0)
im2.putdata(data)
assert_image_equal(im1, im2)
assert_image_equal(im1, im2)
# readonly
im2 = Image.new(im1.mode, im2.size, 0)
im2.readonly = 1
im2.putdata(data)
# readonly
im2 = Image.new(im1.mode, im2.size, 0)
im2.readonly = 1
im2.putdata(data)
assert not im2.readonly
assert_image_equal(im1, im2)
self.assertFalse(im2.readonly)
assert_image_equal(im1, im2)
def test_long_integers(self):
# see bug-200802-systemerror
def put(value):
im = Image.new("RGBA", (1, 1))
im.putdata([value])
return im.getpixel((0, 0))
def test_long_integers():
# see bug-200802-systemerror
def put(value):
im = Image.new("RGBA", (1, 1))
im.putdata([value])
return im.getpixel((0, 0))
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
self.assertEqual(put(-1), (255, 255, 255, 255))
self.assertEqual(put(-1), (255, 255, 255, 255))
if sys.maxsize > 2 ** 32:
self.assertEqual(put(sys.maxsize), (255, 255, 255, 255))
else:
self.assertEqual(put(sys.maxsize), (255, 255, 255, 127))
assert put(0xFFFFFFFF) == (255, 255, 255, 255)
assert put(0xFFFFFFFF) == (255, 255, 255, 255)
assert put(-1) == (255, 255, 255, 255)
assert put(-1) == (255, 255, 255, 255)
if sys.maxsize > 2 ** 32:
assert put(sys.maxsize) == (255, 255, 255, 255)
else:
assert put(sys.maxsize) == (255, 255, 255, 127)
def test_pypy_performance(self):
im = Image.new("L", (256, 256))
im.putdata(list(range(256)) * 256)
def test_mode_i(self):
src = hopper("L")
data = list(src.getdata())
im = Image.new("I", src.size, 0)
im.putdata(data, 2, 256)
def test_pypy_performance():
im = Image.new("L", (256, 256))
im.putdata(list(range(256)) * 256)
target = [2 * elt + 256 for elt in data]
self.assertEqual(list(im.getdata()), target)
def test_mode_F(self):
src = hopper("L")
data = list(src.getdata())
im = Image.new("F", src.size, 0)
im.putdata(data, 2.0, 256.0)
def test_mode_i():
src = hopper("L")
data = list(src.getdata())
im = Image.new("I", src.size, 0)
im.putdata(data, 2, 256)
target = [2.0 * float(elt) + 256.0 for elt in data]
self.assertEqual(list(im.getdata()), target)
target = [2 * elt + 256 for elt in data]
assert list(im.getdata()) == target
def test_array_B(self):
# shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008
arr = array("B", [0]) * 15000
im = Image.new("L", (150, 100))
im.putdata(arr)
def test_mode_F():
src = hopper("L")
data = list(src.getdata())
im = Image.new("F", src.size, 0)
im.putdata(data, 2.0, 256.0)
self.assertEqual(len(im.getdata()), len(arr))
target = [2.0 * float(elt) + 256.0 for elt in data]
assert list(im.getdata()) == target
def test_array_F(self):
# shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008
im = Image.new("F", (150, 100))
arr = array("f", [0.0]) * 15000
im.putdata(arr)
def test_array_B():
# shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008
self.assertEqual(len(im.getdata()), len(arr))
arr = array("B", [0]) * 15000
im = Image.new("L", (150, 100))
im.putdata(arr)
assert len(im.getdata()) == len(arr)
def test_array_F():
# shouldn't segfault
# see https://github.com/python-pillow/Pillow/issues/1008
im = Image.new("F", (150, 100))
arr = array("f", [0.0]) * 15000
im.putdata(arr)
assert len(im.getdata()) == len(arr)

View File

@ -1,67 +1,74 @@
import pytest
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(self):
image = hopper()
converted = image.quantize()
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 10)
def test_sanity():
image = hopper()
converted = image.quantize()
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 10)
image = hopper()
converted = image.quantize(palette=hopper("P"))
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 60)
image = hopper()
converted = image.quantize(palette=hopper("P"))
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 60)
def test_libimagequant_quantize(self):
image = hopper()
try:
converted = image.quantize(100, Image.LIBIMAGEQUANT)
except ValueError as ex:
if "dependency" in str(ex).lower():
self.skipTest("libimagequant support not available")
else:
raise
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 15)
self.assertEqual(len(converted.getcolors()), 100)
def test_octree_quantize(self):
image = hopper()
converted = image.quantize(100, Image.FASTOCTREE)
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 20)
self.assertEqual(len(converted.getcolors()), 100)
def test_libimagequant_quantize():
image = hopper()
try:
converted = image.quantize(100, Image.LIBIMAGEQUANT)
except ValueError as ex:
if "dependency" in str(ex).lower():
pytest.skip("libimagequant support not available")
else:
raise
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 15)
assert len(converted.getcolors()) == 100
def test_rgba_quantize(self):
image = hopper("RGBA")
self.assertRaises(ValueError, image.quantize, method=0)
self.assertEqual(image.quantize().convert().mode, "RGBA")
def test_octree_quantize():
image = hopper()
converted = image.quantize(100, Image.FASTOCTREE)
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 20)
assert len(converted.getcolors()) == 100
def test_quantize(self):
with Image.open("Tests/images/caption_6_33_22.png") as image:
image = image.convert("RGB")
converted = image.quantize()
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 1)
def test_quantize_no_dither(self):
image = hopper()
with Image.open("Tests/images/caption_6_33_22.png") as palette:
palette = palette.convert("P")
def test_rgba_quantize():
image = hopper("RGBA")
with pytest.raises(ValueError):
image.quantize(method=0)
converted = image.quantize(dither=0, palette=palette)
assert_image(converted, "P", converted.size)
assert image.quantize().convert().mode == "RGBA"
def test_quantize_dither_diff(self):
image = hopper()
with Image.open("Tests/images/caption_6_33_22.png") as palette:
palette = palette.convert("P")
dither = image.quantize(dither=1, palette=palette)
nodither = image.quantize(dither=0, palette=palette)
def test_quantize():
with Image.open("Tests/images/caption_6_33_22.png") as image:
image = image.convert("RGB")
converted = image.quantize()
assert_image(converted, "P", converted.size)
assert_image_similar(converted.convert("RGB"), image, 1)
self.assertNotEqual(dither.tobytes(), nodither.tobytes())
def test_quantize_no_dither():
image = hopper()
with Image.open("Tests/images/caption_6_33_22.png") as palette:
palette = palette.convert("P")
converted = image.quantize(dither=0, palette=palette)
assert_image(converted, "P", converted.size)
def test_quantize_dither_diff():
image = hopper()
with Image.open("Tests/images/caption_6_33_22.png") as palette:
palette = palette.convert("P")
dither = image.quantize(dither=1, palette=palette)
nodither = image.quantize(dither=0, palette=palette)
assert dither.tobytes() != nodither.tobytes()

View File

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

View File

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

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(self):
def test_sanity():
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_image_equal(im1, fromstring(bitmap))
assert isinstance(bitmap, bytes)
assert_image_equal(im1, fromstring(bitmap))

View File

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

View File

@ -1,6 +1,6 @@
from PIL import Image, ImageChops
from .helper import PillowTestCase, assert_image_equal, hopper
from .helper import assert_image_equal, hopper
BLACK = (0, 0, 0)
BROWN = (127, 64, 0)
@ -13,352 +13,373 @@ WHITE = (255, 255, 255)
GREY = 128
class TestImageChops(PillowTestCase):
def test_sanity(self):
def test_sanity():
im = hopper("L")
im = hopper("L")
ImageChops.constant(im, 128)
ImageChops.duplicate(im)
ImageChops.invert(im)
ImageChops.lighter(im, im)
ImageChops.darker(im, im)
ImageChops.difference(im, im)
ImageChops.multiply(im, im)
ImageChops.screen(im, im)
ImageChops.constant(im, 128)
ImageChops.duplicate(im)
ImageChops.invert(im)
ImageChops.lighter(im, im)
ImageChops.darker(im, im)
ImageChops.difference(im, im)
ImageChops.multiply(im, im)
ImageChops.screen(im, im)
ImageChops.add(im, im)
ImageChops.add(im, im, 2.0)
ImageChops.add(im, im, 2.0, 128)
ImageChops.subtract(im, im)
ImageChops.subtract(im, im, 2.0)
ImageChops.subtract(im, im, 2.0, 128)
ImageChops.add(im, im)
ImageChops.add(im, im, 2.0)
ImageChops.add(im, im, 2.0, 128)
ImageChops.subtract(im, im)
ImageChops.subtract(im, im, 2.0)
ImageChops.subtract(im, im, 2.0, 128)
ImageChops.add_modulo(im, im)
ImageChops.subtract_modulo(im, im)
ImageChops.add_modulo(im, im)
ImageChops.subtract_modulo(im, im)
ImageChops.blend(im, im, 0.5)
ImageChops.composite(im, im, im)
ImageChops.blend(im, im, 0.5)
ImageChops.composite(im, im, im)
ImageChops.offset(im, 10)
ImageChops.offset(im, 10, 20)
ImageChops.offset(im, 10)
ImageChops.offset(im, 10, 20)
def test_add(self):
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
def test_add():
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.add(im1, im2)
# Act
new = ImageChops.add(im1, im2)
# Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76))
self.assertEqual(new.getpixel((50, 50)), ORANGE)
# Assert
assert new.getbbox() == (25, 25, 76, 76)
assert new.getpixel((50, 50)) == ORANGE
def test_add_scale_offset(self):
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.add(im1, im2, scale=2.5, offset=100)
def test_add_scale_offset():
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Assert
self.assertEqual(new.getbbox(), (0, 0, 100, 100))
self.assertEqual(new.getpixel((50, 50)), (202, 151, 100))
# Act
new = ImageChops.add(im1, im2, scale=2.5, offset=100)
def test_add_clip(self):
# Arrange
im = hopper()
# Assert
assert new.getbbox() == (0, 0, 100, 100)
assert new.getpixel((50, 50)) == (202, 151, 100)
# Act
new = ImageChops.add(im, im)
# Assert
self.assertEqual(new.getpixel((50, 50)), (255, 255, 254))
def test_add_clip():
# Arrange
im = hopper()
def test_add_modulo(self):
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.add(im, im)
# Act
new = ImageChops.add_modulo(im1, im2)
# Assert
assert new.getpixel((50, 50)) == (255, 255, 254)
# Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76))
self.assertEqual(new.getpixel((50, 50)), ORANGE)
def test_add_modulo_no_clip(self):
# Arrange
im = hopper()
def test_add_modulo():
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.add_modulo(im, im)
# Act
new = ImageChops.add_modulo(im1, im2)
# Assert
self.assertEqual(new.getpixel((50, 50)), (224, 76, 254))
# Assert
assert new.getbbox() == (25, 25, 76, 76)
assert new.getpixel((50, 50)) == ORANGE
def test_blend(self):
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.blend(im1, im2, 0.5)
def test_add_modulo_no_clip():
# Arrange
im = hopper()
# Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76))
self.assertEqual(new.getpixel((50, 50)), BROWN)
# Act
new = ImageChops.add_modulo(im, im)
def test_constant(self):
# Arrange
im = Image.new("RGB", (20, 10))
# Assert
assert new.getpixel((50, 50)) == (224, 76, 254)
# Act
new = ImageChops.constant(im, GREY)
# Assert
self.assertEqual(new.size, im.size)
self.assertEqual(new.getpixel((0, 0)), GREY)
self.assertEqual(new.getpixel((19, 9)), GREY)
def test_blend():
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
def test_darker_image(self):
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.blend(im1, im2, 0.5)
# Act
new = ImageChops.darker(im1, im2)
# Assert
assert new.getbbox() == (25, 25, 76, 76)
assert new.getpixel((50, 50)) == BROWN
# Assert
assert_image_equal(new, im2)
def test_darker_pixel(self):
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
def test_constant():
# Arrange
im = Image.new("RGB", (20, 10))
# Act
new = ImageChops.constant(im, GREY)
# Assert
assert new.size == im.size
assert new.getpixel((0, 0)) == GREY
assert new.getpixel((19, 9)) == GREY
def test_darker_image():
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.darker(im1, im2)
# Assert
self.assertEqual(new.getpixel((50, 50)), (240, 166, 0))
# Assert
assert_image_equal(new, im2)
def test_difference(self):
# Arrange
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:
# Act
new = ImageChops.difference(im1, im2)
def test_darker_pixel():
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
# Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76))
# Act
new = ImageChops.darker(im1, im2)
def test_difference_pixel(self):
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
# Assert
assert new.getpixel((50, 50)) == (240, 166, 0)
def test_difference():
# Arrange
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:
# Act
new = ImageChops.difference(im1, im2)
# Assert
self.assertEqual(new.getpixel((50, 50)), (240, 166, 128))
# Assert
assert new.getbbox() == (25, 25, 76, 76)
def test_duplicate(self):
# Arrange
im = hopper()
def test_difference_pixel():
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_polygon_kite_RGB.png") as im2:
# Act
new = ImageChops.duplicate(im)
new = ImageChops.difference(im1, im2)
# Assert
assert_image_equal(new, im)
# Assert
assert new.getpixel((50, 50)) == (240, 166, 128)
def test_invert(self):
# Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
# Act
new = ImageChops.invert(im)
def test_duplicate():
# Arrange
im = hopper()
# Assert
self.assertEqual(new.getbbox(), (0, 0, 100, 100))
self.assertEqual(new.getpixel((0, 0)), WHITE)
self.assertEqual(new.getpixel((50, 50)), CYAN)
# Act
new = ImageChops.duplicate(im)
def test_lighter_image(self):
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Assert
assert_image_equal(new, im)
# Act
new = ImageChops.lighter(im1, im2)
# Assert
assert_image_equal(new, im1)
def test_invert():
# Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
def test_lighter_pixel(self):
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
# Act
new = ImageChops.invert(im)
# Assert
assert new.getbbox() == (0, 0, 100, 100)
assert new.getpixel((0, 0)) == WHITE
assert new.getpixel((50, 50)) == CYAN
def test_lighter_image():
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.lighter(im1, im2)
# Assert
self.assertEqual(new.getpixel((50, 50)), (255, 255, 127))
# Assert
assert_image_equal(new, im1)
def test_multiply_black(self):
"""If you multiply an image with a solid black image,
the result is black."""
# Arrange
im1 = hopper()
black = Image.new("RGB", im1.size, "black")
def test_lighter_pixel():
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
# Act
new = ImageChops.multiply(im1, black)
new = ImageChops.lighter(im1, im2)
# Assert
assert_image_equal(new, black)
# Assert
assert new.getpixel((50, 50)) == (255, 255, 127)
def test_multiply_green(self):
# Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
green = Image.new("RGB", im.size, "green")
# Act
new = ImageChops.multiply(im, green)
def test_multiply_black():
"""If you multiply an image with a solid black image,
the result is black."""
# Arrange
im1 = hopper()
black = Image.new("RGB", im1.size, "black")
# Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76))
self.assertEqual(new.getpixel((25, 25)), DARK_GREEN)
self.assertEqual(new.getpixel((50, 50)), BLACK)
# Act
new = ImageChops.multiply(im1, black)
def test_multiply_white(self):
"""If you multiply with a solid white image,
the image is unaffected."""
# Arrange
im1 = hopper()
white = Image.new("RGB", im1.size, "white")
# Assert
assert_image_equal(new, black)
def test_multiply_green():
# Arrange
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im:
green = Image.new("RGB", im.size, "green")
# Act
new = ImageChops.multiply(im1, white)
new = ImageChops.multiply(im, green)
# Assert
assert_image_equal(new, im1)
# Assert
assert new.getbbox() == (25, 25, 76, 76)
assert new.getpixel((25, 25)) == DARK_GREEN
assert new.getpixel((50, 50)) == BLACK
def test_offset(self):
# Arrange
xoffset = 45
yoffset = 20
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im:
def test_multiply_white():
"""If you multiply with a solid white image, the image is unaffected."""
# Arrange
im1 = hopper()
white = Image.new("RGB", im1.size, "white")
# Act
new = ImageChops.multiply(im1, white)
# Assert
assert_image_equal(new, im1)
def test_offset():
# Arrange
xoffset = 45
yoffset = 20
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im:
# Act
new = ImageChops.offset(im, xoffset, yoffset)
# Assert
assert new.getbbox() == (0, 45, 100, 96)
assert new.getpixel((50, 50)) == BLACK
assert new.getpixel((50 + xoffset, 50 + yoffset)) == DARK_GREEN
# Test no yoffset
assert ImageChops.offset(im, xoffset) == ImageChops.offset(im, xoffset, xoffset)
def test_screen():
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.offset(im, xoffset, yoffset)
new = ImageChops.screen(im1, im2)
# Assert
self.assertEqual(new.getbbox(), (0, 45, 100, 96))
self.assertEqual(new.getpixel((50, 50)), BLACK)
self.assertEqual(new.getpixel((50 + xoffset, 50 + yoffset)), DARK_GREEN)
# Assert
assert new.getbbox() == (25, 25, 76, 76)
assert new.getpixel((50, 50)) == ORANGE
# Test no yoffset
self.assertEqual(
ImageChops.offset(im, xoffset), ImageChops.offset(im, xoffset, xoffset)
)
def test_screen(self):
# Arrange
with Image.open("Tests/images/imagedraw_ellipse_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_floodfill_RGB.png") as im2:
# Act
new = ImageChops.screen(im1, im2)
# Assert
self.assertEqual(new.getbbox(), (25, 25, 76, 76))
self.assertEqual(new.getpixel((50, 50)), ORANGE)
def test_subtract(self):
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.subtract(im1, im2)
# Assert
self.assertEqual(new.getbbox(), (25, 50, 76, 76))
self.assertEqual(new.getpixel((50, 50)), GREEN)
self.assertEqual(new.getpixel((50, 51)), BLACK)
def test_subtract_scale_offset(self):
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.subtract(im1, im2, scale=2.5, offset=100)
# Assert
self.assertEqual(new.getbbox(), (0, 0, 100, 100))
self.assertEqual(new.getpixel((50, 50)), (100, 202, 100))
def test_subtract_clip(self):
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
def test_subtract():
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.subtract(im1, im2)
# Assert
self.assertEqual(new.getpixel((50, 50)), (0, 0, 127))
# Assert
assert new.getbbox() == (25, 50, 76, 76)
assert new.getpixel((50, 50)) == GREEN
assert new.getpixel((50, 51)) == BLACK
def test_subtract_modulo(self):
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.subtract_modulo(im1, im2)
def test_subtract_scale_offset():
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Assert
self.assertEqual(new.getbbox(), (25, 50, 76, 76))
self.assertEqual(new.getpixel((50, 50)), GREEN)
self.assertEqual(new.getpixel((50, 51)), BLACK)
# Act
new = ImageChops.subtract(im1, im2, scale=2.5, offset=100)
def test_subtract_modulo_no_clip(self):
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
# Assert
assert new.getbbox() == (0, 0, 100, 100)
assert new.getpixel((50, 50)) == (100, 202, 100)
def test_subtract_clip():
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
# Act
new = ImageChops.subtract(im1, im2)
# Assert
assert new.getpixel((50, 50)) == (0, 0, 127)
def test_subtract_modulo():
# Arrange
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im1:
with Image.open("Tests/images/imagedraw_outline_chord_RGB.png") as im2:
# Act
new = ImageChops.subtract_modulo(im1, im2)
# Assert
self.assertEqual(new.getpixel((50, 50)), (241, 167, 127))
# Assert
assert new.getbbox() == (25, 50, 76, 76)
assert new.getpixel((50, 50)) == GREEN
assert new.getpixel((50, 51)) == BLACK
def test_logical(self):
def table(op, a, b):
out = []
for x in (a, b):
imx = Image.new("1", (1, 1), x)
for y in (a, b):
imy = Image.new("1", (1, 1), y)
out.append(op(imx, imy).getpixel((0, 0)))
return tuple(out)
self.assertEqual(table(ImageChops.logical_and, 0, 1), (0, 0, 0, 255))
self.assertEqual(table(ImageChops.logical_or, 0, 1), (0, 255, 255, 255))
self.assertEqual(table(ImageChops.logical_xor, 0, 1), (0, 255, 255, 0))
def test_subtract_modulo_no_clip():
# Arrange
im1 = hopper()
with Image.open("Tests/images/imagedraw_chord_RGB.png") as im2:
self.assertEqual(table(ImageChops.logical_and, 0, 128), (0, 0, 0, 255))
self.assertEqual(table(ImageChops.logical_or, 0, 128), (0, 255, 255, 255))
self.assertEqual(table(ImageChops.logical_xor, 0, 128), (0, 255, 255, 0))
# Act
new = ImageChops.subtract_modulo(im1, im2)
self.assertEqual(table(ImageChops.logical_and, 0, 255), (0, 0, 0, 255))
self.assertEqual(table(ImageChops.logical_or, 0, 255), (0, 255, 255, 255))
self.assertEqual(table(ImageChops.logical_xor, 0, 255), (0, 255, 255, 0))
# Assert
assert new.getpixel((50, 50)) == (241, 167, 127)
def test_logical():
def table(op, a, b):
out = []
for x in (a, b):
imx = Image.new("1", (1, 1), x)
for y in (a, b):
imy = Image.new("1", (1, 1), y)
out.append(op(imx, imy).getpixel((0, 0)))
return tuple(out)
assert table(ImageChops.logical_and, 0, 1) == (0, 0, 0, 255)
assert table(ImageChops.logical_or, 0, 1) == (0, 255, 255, 255)
assert table(ImageChops.logical_xor, 0, 1) == (0, 255, 255, 0)
assert table(ImageChops.logical_and, 0, 128) == (0, 0, 0, 255)
assert table(ImageChops.logical_or, 0, 128) == (0, 255, 255, 255)
assert table(ImageChops.logical_xor, 0, 128) == (0, 255, 255, 0)
assert table(ImageChops.logical_and, 0, 255) == (0, 0, 0, 255)
assert table(ImageChops.logical_or, 0, 255) == (0, 255, 255, 255)
assert table(ImageChops.logical_xor, 0, 255) == (0, 255, 255, 0)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
import os.path
import unittest
import pytest
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)
WHITE = (255, 255, 255)
@ -34,190 +34,206 @@ HAS_FREETYPE = features.check("freetype2")
FONT_PATH = "Tests/fonts/FreeMono.ttf"
class TestImageDraw(PillowTestCase):
def test_sanity(self):
im = hopper("RGB").copy()
def test_sanity():
im = hopper("RGB").copy()
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue", width=7)
draw.line(list(range(10)), pen)
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue", width=7)
draw.line(list(range(10)), pen)
from PIL import ImageDraw
from PIL import ImageDraw
draw, handler = ImageDraw.getdraw(im)
pen = ImageDraw2.Pen("blue", width=7)
draw.line(list(range(10)), pen)
draw, handler = ImageDraw.getdraw(im)
pen = ImageDraw2.Pen("blue", width=7)
draw.line(list(range(10)), pen)
def helper_ellipse(self, mode, bbox):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue", width=2)
brush = ImageDraw2.Brush("green")
expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode)
# Act
draw.ellipse(bbox, pen, brush)
def helper_ellipse(mode, bbox):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue", width=2)
brush = ImageDraw2.Brush("green")
expected = "Tests/images/imagedraw_ellipse_{}.png".format(mode)
# Assert
assert_image_similar(im, Image.open(expected), 1)
# Act
draw.ellipse(bbox, pen, brush)
def test_ellipse1(self):
self.helper_ellipse("RGB", BBOX1)
# Assert
assert_image_similar(im, Image.open(expected), 1)
def test_ellipse2(self):
self.helper_ellipse("RGB", BBOX2)
def test_ellipse_edge(self):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
brush = ImageDraw2.Brush("white")
def test_ellipse1():
helper_ellipse("RGB", BBOX1)
# Act
draw.ellipse(((0, 0), (W - 1, H)), brush)
# Assert
assert_image_similar(
im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1
)
def test_ellipse2():
helper_ellipse("RGB", BBOX2)
def helper_line(self, points):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("yellow", width=2)
# Act
draw.line(points, pen)
def test_ellipse_edge():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
brush = ImageDraw2.Brush("white")
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
# Act
draw.ellipse(((0, 0), (W - 1, H)), brush)
def test_line1_pen(self):
self.helper_line(POINTS1)
# Assert
assert_image_similar(im, Image.open("Tests/images/imagedraw_ellipse_edge.png"), 1)
def test_line2_pen(self):
self.helper_line(POINTS2)
def test_line_pen_as_brush(self):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = None
brush = ImageDraw2.Pen("yellow", width=2)
def helper_line(points):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("yellow", width=2)
# Act
# Pass in the pen as the brush parameter
draw.line(POINTS1, pen, brush)
# Act
draw.line(points, pen)
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
def helper_polygon(self, points):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue", width=2)
brush = ImageDraw2.Brush("red")
# Act
draw.polygon(points, pen, brush)
def test_line1_pen():
helper_line(POINTS1)
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png"))
def test_polygon1(self):
self.helper_polygon(POINTS1)
def test_line2_pen():
helper_line(POINTS2)
def test_polygon2(self):
self.helper_polygon(POINTS2)
def helper_rectangle(self, bbox):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("green", width=2)
brush = ImageDraw2.Brush("black")
def test_line_pen_as_brush():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = None
brush = ImageDraw2.Pen("yellow", width=2)
# Act
draw.rectangle(bbox, pen, brush)
# Act
# Pass in the pen as the brush parameter
draw.line(POINTS1, pen, brush)
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png"))
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_line.png"))
def test_rectangle1(self):
self.helper_rectangle(BBOX1)
def test_rectangle2(self):
self.helper_rectangle(BBOX2)
def helper_polygon(points):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("blue", width=2)
brush = ImageDraw2.Brush("red")
def test_big_rectangle(self):
# Test drawing a rectangle bigger than the image
# Arrange
im = Image.new("RGB", (W, H))
bbox = [(-1, -1), (W + 1, H + 1)]
brush = ImageDraw2.Brush("orange")
draw = ImageDraw2.Draw(im)
expected = "Tests/images/imagedraw_big_rectangle.png"
# Act
draw.polygon(points, pen, brush)
# Act
draw.rectangle(bbox, brush)
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_polygon.png"))
# Assert
assert_image_similar(im, Image.open(expected), 1)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_text(self):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
expected = "Tests/images/imagedraw2_text.png"
def test_polygon1():
helper_polygon(POINTS1)
# Act
draw.text((5, 5), "ImageDraw2", font)
# Assert
assert_image_similar(im, Image.open(expected), 13)
def test_polygon2():
helper_polygon(POINTS2)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_textsize(self):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
# Act
size = draw.textsize("ImageDraw2", font)
def helper_rectangle(bbox):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
pen = ImageDraw2.Pen("green", width=2)
brush = ImageDraw2.Brush("black")
# Assert
self.assertEqual(size[1], 12)
# Act
draw.rectangle(bbox, pen, brush)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_textsize_empty_string(self):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
# Assert
assert_image_equal(im, Image.open("Tests/images/imagedraw_rectangle.png"))
# Act
# Should not cause 'SystemError: <built-in method getsize of
# ImagingFont object at 0x...> returned NULL without setting an error'
draw.textsize("", font)
draw.textsize("\n", font)
draw.textsize("test\n", font)
@unittest.skipUnless(HAS_FREETYPE, "ImageFont not available")
def test_flush(self):
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
def test_rectangle1():
helper_rectangle(BBOX1)
# Act
draw.text((5, 5), "ImageDraw2", font)
im2 = draw.flush()
# Assert
assert_image_equal(im, im2)
def test_rectangle2():
helper_rectangle(BBOX2)
def test_big_rectangle():
# Test drawing a rectangle bigger than the image
# Arrange
im = Image.new("RGB", (W, H))
bbox = [(-1, -1), (W + 1, H + 1)]
brush = ImageDraw2.Brush("orange")
draw = ImageDraw2.Draw(im)
expected = "Tests/images/imagedraw_big_rectangle.png"
# Act
draw.rectangle(bbox, brush)
# Assert
assert_image_similar(im, Image.open(expected), 1)
@pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_text():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
expected = "Tests/images/imagedraw2_text.png"
# Act
draw.text((5, 5), "ImageDraw2", font)
# Assert
assert_image_similar(im, Image.open(expected), 13)
@pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_textsize():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
# Act
size = draw.textsize("ImageDraw2", font)
# Assert
assert size[1] == 12
@pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_textsize_empty_string():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
# Act
# Should not cause 'SystemError: <built-in method getsize of
# ImagingFont object at 0x...> returned NULL without setting an error'
draw.textsize("", font)
draw.textsize("\n", font)
draw.textsize("test\n", font)
@pytest.mark.skipif(not HAS_FREETYPE, reason="ImageFont not available")
def test_flush():
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw2.Draw(im)
font = ImageDraw2.Font("white", FONT_PATH)
# Act
draw.text((5, 5), "ImageDraw2", font)
im2 = draw.flush()
# Assert
assert_image_equal(im, im2)

View File

@ -1,54 +1,55 @@
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(self):
def test_sanity():
# FIXME: assert_image
# Implicit asserts no exception:
ImageEnhance.Color(hopper()).enhance(0.5)
ImageEnhance.Contrast(hopper()).enhance(0.5)
ImageEnhance.Brightness(hopper()).enhance(0.5)
ImageEnhance.Sharpness(hopper()).enhance(0.5)
# FIXME: assert_image
# Implicit asserts no exception:
ImageEnhance.Color(hopper()).enhance(0.5)
ImageEnhance.Contrast(hopper()).enhance(0.5)
ImageEnhance.Brightness(hopper()).enhance(0.5)
ImageEnhance.Sharpness(hopper()).enhance(0.5)
def test_crash(self):
def test_crash():
# crashes on small images
im = Image.new("RGB", (1, 1))
ImageEnhance.Sharpness(im).enhance(0.5)
# crashes on small images
im = Image.new("RGB", (1, 1))
ImageEnhance.Sharpness(im).enhance(0.5)
def _half_transparent_image(self):
# returns an image, half transparent, half solid
im = hopper("RGB")
def _half_transparent_image():
# returns an image, half transparent, half solid
im = hopper("RGB")
transparent = Image.new("L", im.size, 0)
solid = Image.new("L", (im.size[0] // 2, im.size[1]), 255)
transparent.paste(solid, (0, 0))
im.putalpha(transparent)
transparent = Image.new("L", im.size, 0)
solid = Image.new("L", (im.size[0] // 2, im.size[1]), 255)
transparent.paste(solid, (0, 0))
im.putalpha(transparent)
return im
return im
def _check_alpha(self, im, original, op, amount):
self.assertEqual(im.getbands(), original.getbands())
assert_image_equal(
im.getchannel("A"),
original.getchannel("A"),
"Diff on {}: {}".format(op, amount),
)
def test_alpha(self):
# Issue https://github.com/python-pillow/Pillow/issues/899
# Is alpha preserved through image enhancement?
def _check_alpha(im, original, op, amount):
assert im.getbands() == original.getbands()
assert_image_equal(
im.getchannel("A"),
original.getchannel("A"),
"Diff on {}: {}".format(op, amount),
)
original = self._half_transparent_image()
for op in ["Color", "Brightness", "Contrast", "Sharpness"]:
for amount in [0, 0.5, 1.0]:
self._check_alpha(
getattr(ImageEnhance, op)(original).enhance(amount),
original,
op,
amount,
)
def test_alpha():
# Issue https://github.com/python-pillow/Pillow/issues/899
# Is alpha preserved through image enhancement?
original = _half_transparent_image()
for op in ["Color", "Brightness", "Contrast", "Sharpness"]:
for amount in [0, 0.5, 1.0]:
_check_alpha(
getattr(ImageEnhance, op)(original).enhance(amount),
original,
op,
amount,
)

View File

@ -1,7 +1,7 @@
import pytest
from PIL import Image, ImageOps
from .helper import (
PillowTestCase,
assert_image_equal,
assert_image_similar,
assert_tuple_approx_equal,
@ -16,287 +16,294 @@ except ImportError:
HAVE_WEBP = False
class TestImageOps(PillowTestCase):
class Deformer:
def getmesh(self, im):
x, y = im.size
return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))]
class Deformer:
def getmesh(self, im):
x, y = im.size
return [((0, 0, x, y), (0, 0, x, 0, x, y, y, 0))]
deformer = Deformer()
def test_sanity(self):
deformer = Deformer()
ImageOps.autocontrast(hopper("L"))
ImageOps.autocontrast(hopper("RGB"))
ImageOps.autocontrast(hopper("L"), cutoff=10)
ImageOps.autocontrast(hopper("L"), ignore=[0, 255])
def test_sanity():
ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255))
ImageOps.colorize(hopper("L"), "black", "white")
ImageOps.autocontrast(hopper("L"))
ImageOps.autocontrast(hopper("RGB"))
ImageOps.pad(hopper("L"), (128, 128))
ImageOps.pad(hopper("RGB"), (128, 128))
ImageOps.autocontrast(hopper("L"), cutoff=10)
ImageOps.autocontrast(hopper("L"), ignore=[0, 255])
ImageOps.crop(hopper("L"), 1)
ImageOps.crop(hopper("RGB"), 1)
ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255))
ImageOps.colorize(hopper("L"), "black", "white")
ImageOps.deform(hopper("L"), self.deformer)
ImageOps.deform(hopper("RGB"), self.deformer)
ImageOps.pad(hopper("L"), (128, 128))
ImageOps.pad(hopper("RGB"), (128, 128))
ImageOps.equalize(hopper("L"))
ImageOps.equalize(hopper("RGB"))
ImageOps.crop(hopper("L"), 1)
ImageOps.crop(hopper("RGB"), 1)
ImageOps.expand(hopper("L"), 1)
ImageOps.expand(hopper("RGB"), 1)
ImageOps.expand(hopper("L"), 2, "blue")
ImageOps.expand(hopper("RGB"), 2, "blue")
ImageOps.deform(hopper("L"), deformer)
ImageOps.deform(hopper("RGB"), deformer)
ImageOps.fit(hopper("L"), (128, 128))
ImageOps.fit(hopper("RGB"), (128, 128))
ImageOps.equalize(hopper("L"))
ImageOps.equalize(hopper("RGB"))
ImageOps.flip(hopper("L"))
ImageOps.flip(hopper("RGB"))
ImageOps.expand(hopper("L"), 1)
ImageOps.expand(hopper("RGB"), 1)
ImageOps.expand(hopper("L"), 2, "blue")
ImageOps.expand(hopper("RGB"), 2, "blue")
ImageOps.grayscale(hopper("L"))
ImageOps.grayscale(hopper("RGB"))
ImageOps.fit(hopper("L"), (128, 128))
ImageOps.fit(hopper("RGB"), (128, 128))
ImageOps.invert(hopper("L"))
ImageOps.invert(hopper("RGB"))
ImageOps.flip(hopper("L"))
ImageOps.flip(hopper("RGB"))
ImageOps.mirror(hopper("L"))
ImageOps.mirror(hopper("RGB"))
ImageOps.grayscale(hopper("L"))
ImageOps.grayscale(hopper("RGB"))
ImageOps.posterize(hopper("L"), 4)
ImageOps.posterize(hopper("RGB"), 4)
ImageOps.invert(hopper("L"))
ImageOps.invert(hopper("RGB"))
ImageOps.solarize(hopper("L"))
ImageOps.solarize(hopper("RGB"))
ImageOps.mirror(hopper("L"))
ImageOps.mirror(hopper("RGB"))
ImageOps.exif_transpose(hopper("L"))
ImageOps.exif_transpose(hopper("RGB"))
ImageOps.posterize(hopper("L"), 4)
ImageOps.posterize(hopper("RGB"), 4)
def test_1pxfit(self):
# Division by zero in equalize if image is 1 pixel high
newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
self.assertEqual(newimg.size, (35, 35))
ImageOps.solarize(hopper("L"))
ImageOps.solarize(hopper("RGB"))
newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35))
self.assertEqual(newimg.size, (35, 35))
ImageOps.exif_transpose(hopper("L"))
ImageOps.exif_transpose(hopper("RGB"))
newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35))
self.assertEqual(newimg.size, (35, 35))
def test_fit_same_ratio(self):
# The ratio for this image is 1000.0 / 755 = 1.3245033112582782
# If the ratios are not acknowledged to be the same,
# and Pillow attempts to adjust the width to
# 1.3245033112582782 * 755 = 1000.0000000000001
# then centering this greater width causes a negative x offset when cropping
with Image.new("RGB", (1000, 755)) as im:
new_im = ImageOps.fit(im, (1000, 755))
self.assertEqual(new_im.size, (1000, 755))
def test_1pxfit():
# Division by zero in equalize if image is 1 pixel high
newimg = ImageOps.fit(hopper("RGB").resize((1, 1)), (35, 35))
assert newimg.size == (35, 35)
def test_pad(self):
# Same ratio
im = hopper()
new_size = (im.width * 2, im.height * 2)
new_im = ImageOps.pad(im, new_size)
self.assertEqual(new_im.size, new_size)
newimg = ImageOps.fit(hopper("RGB").resize((1, 100)), (35, 35))
assert newimg.size == (35, 35)
for label, color, new_size in [
("h", None, (im.width * 4, im.height * 2)),
("v", "#f00", (im.width * 2, im.height * 4)),
]:
for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]):
new_im = ImageOps.pad(im, new_size, color=color, centering=centering)
self.assertEqual(new_im.size, new_size)
newimg = ImageOps.fit(hopper("RGB").resize((100, 1)), (35, 35))
assert newimg.size == (35, 35)
def test_fit_same_ratio():
# The ratio for this image is 1000.0 / 755 = 1.3245033112582782
# If the ratios are not acknowledged to be the same,
# and Pillow attempts to adjust the width to
# 1.3245033112582782 * 755 = 1000.0000000000001
# then centering this greater width causes a negative x offset when cropping
with Image.new("RGB", (1000, 755)) as im:
new_im = ImageOps.fit(im, (1000, 755))
assert new_im.size == (1000, 755)
def test_pad():
# Same ratio
im = hopper()
new_size = (im.width * 2, im.height * 2)
new_im = ImageOps.pad(im, new_size)
assert new_im.size == new_size
for label, color, new_size in [
("h", None, (im.width * 4, im.height * 2)),
("v", "#f00", (im.width * 2, im.height * 4)),
]:
for i, centering in enumerate([(0, 0), (0.5, 0.5), (1, 1)]):
new_im = ImageOps.pad(im, new_size, color=color, centering=centering)
assert new_im.size == new_size
with Image.open(
"Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg"
) as target:
assert_image_similar(new_im, target, 6)
def test_pil163():
# Division by zero in equalize if < 255 pixels in image (@PIL163)
i = hopper("RGB").resize((15, 16))
ImageOps.equalize(i.convert("L"))
ImageOps.equalize(i.convert("P"))
ImageOps.equalize(i.convert("RGB"))
def test_scale():
# Test the scaling function
i = hopper("L").resize((50, 50))
with pytest.raises(ValueError):
ImageOps.scale(i, -1)
newimg = ImageOps.scale(i, 1)
assert newimg.size == (50, 50)
newimg = ImageOps.scale(i, 2)
assert newimg.size == (100, 100)
newimg = ImageOps.scale(i, 0.5)
assert newimg.size == (25, 25)
def test_colorize_2color():
# Test the colorizing function with 2-color functionality
# Open test image (256px by 10px, black to white)
with Image.open("Tests/images/bw_gradient.png") as im:
im = im.convert("L")
# Create image with original 2-color functionality
im_test = ImageOps.colorize(im, "red", "green")
# Test output image (2-color)
left = (0, 1)
middle = (127, 1)
right = (255, 1)
assert_tuple_approx_equal(
im_test.getpixel(left),
(255, 0, 0),
threshold=1,
msg="black test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(middle),
(127, 63, 0),
threshold=1,
msg="mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(right),
(0, 127, 0),
threshold=1,
msg="white test pixel incorrect",
)
def test_colorize_2color_offset():
# Test the colorizing function with 2-color functionality and offset
# Open test image (256px by 10px, black to white)
with Image.open("Tests/images/bw_gradient.png") as im:
im = im.convert("L")
# Create image with original 2-color functionality with offsets
im_test = ImageOps.colorize(
im, black="red", white="green", blackpoint=50, whitepoint=100
)
# Test output image (2-color) with offsets
left = (25, 1)
middle = (75, 1)
right = (125, 1)
assert_tuple_approx_equal(
im_test.getpixel(left),
(255, 0, 0),
threshold=1,
msg="black test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(middle),
(127, 63, 0),
threshold=1,
msg="mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(right),
(0, 127, 0),
threshold=1,
msg="white test pixel incorrect",
)
def test_colorize_3color_offset():
# Test the colorizing function with 3-color functionality and offset
# Open test image (256px by 10px, black to white)
with Image.open("Tests/images/bw_gradient.png") as im:
im = im.convert("L")
# Create image with new three color functionality with offsets
im_test = ImageOps.colorize(
im,
black="red",
white="green",
mid="blue",
blackpoint=50,
whitepoint=200,
midpoint=100,
)
# Test output image (3-color) with offsets
left = (25, 1)
left_middle = (75, 1)
middle = (100, 1)
right_middle = (150, 1)
right = (225, 1)
assert_tuple_approx_equal(
im_test.getpixel(left),
(255, 0, 0),
threshold=1,
msg="black test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(left_middle),
(127, 0, 127),
threshold=1,
msg="low-mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(middle), (0, 0, 255), threshold=1, msg="mid incorrect"
)
assert_tuple_approx_equal(
im_test.getpixel(right_middle),
(0, 63, 127),
threshold=1,
msg="high-mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(right),
(0, 127, 0),
threshold=1,
msg="white test pixel incorrect",
)
def test_exif_transpose():
exts = [".jpg"]
if HAVE_WEBP and _webp.HAVE_WEBPANIM:
exts.append(".webp")
for ext in exts:
with Image.open("Tests/images/hopper" + ext) as base_im:
def check(orientation_im):
for im in [
orientation_im,
orientation_im.copy(),
]: # ImageFile # Image
if orientation_im is base_im:
assert "exif" not in im.info
else:
original_exif = im.info["exif"]
transposed_im = ImageOps.exif_transpose(im)
assert_image_similar(base_im, transposed_im, 17)
if orientation_im is base_im:
assert "exif" not in im.info
else:
assert transposed_im.info["exif"] != original_exif
assert 0x0112 not in transposed_im.getexif()
# Repeat the operation to test that it does not keep transposing
transposed_im2 = ImageOps.exif_transpose(transposed_im)
assert_image_equal(transposed_im2, transposed_im)
check(base_im)
for i in range(2, 9):
with Image.open(
"Tests/images/imageops_pad_" + label + "_" + str(i) + ".jpg"
) as target:
assert_image_similar(new_im, target, 6)
def test_pil163(self):
# Division by zero in equalize if < 255 pixels in image (@PIL163)
i = hopper("RGB").resize((15, 16))
ImageOps.equalize(i.convert("L"))
ImageOps.equalize(i.convert("P"))
ImageOps.equalize(i.convert("RGB"))
def test_scale(self):
# Test the scaling function
i = hopper("L").resize((50, 50))
with self.assertRaises(ValueError):
ImageOps.scale(i, -1)
newimg = ImageOps.scale(i, 1)
self.assertEqual(newimg.size, (50, 50))
newimg = ImageOps.scale(i, 2)
self.assertEqual(newimg.size, (100, 100))
newimg = ImageOps.scale(i, 0.5)
self.assertEqual(newimg.size, (25, 25))
def test_colorize_2color(self):
# Test the colorizing function with 2-color functionality
# Open test image (256px by 10px, black to white)
with Image.open("Tests/images/bw_gradient.png") as im:
im = im.convert("L")
# Create image with original 2-color functionality
im_test = ImageOps.colorize(im, "red", "green")
# Test output image (2-color)
left = (0, 1)
middle = (127, 1)
right = (255, 1)
assert_tuple_approx_equal(
im_test.getpixel(left),
(255, 0, 0),
threshold=1,
msg="black test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(middle),
(127, 63, 0),
threshold=1,
msg="mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(right),
(0, 127, 0),
threshold=1,
msg="white test pixel incorrect",
)
def test_colorize_2color_offset(self):
# Test the colorizing function with 2-color functionality and offset
# Open test image (256px by 10px, black to white)
with Image.open("Tests/images/bw_gradient.png") as im:
im = im.convert("L")
# Create image with original 2-color functionality with offsets
im_test = ImageOps.colorize(
im, black="red", white="green", blackpoint=50, whitepoint=100
)
# Test output image (2-color) with offsets
left = (25, 1)
middle = (75, 1)
right = (125, 1)
assert_tuple_approx_equal(
im_test.getpixel(left),
(255, 0, 0),
threshold=1,
msg="black test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(middle),
(127, 63, 0),
threshold=1,
msg="mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(right),
(0, 127, 0),
threshold=1,
msg="white test pixel incorrect",
)
def test_colorize_3color_offset(self):
# Test the colorizing function with 3-color functionality and offset
# Open test image (256px by 10px, black to white)
with Image.open("Tests/images/bw_gradient.png") as im:
im = im.convert("L")
# Create image with new three color functionality with offsets
im_test = ImageOps.colorize(
im,
black="red",
white="green",
mid="blue",
blackpoint=50,
whitepoint=200,
midpoint=100,
)
# Test output image (3-color) with offsets
left = (25, 1)
left_middle = (75, 1)
middle = (100, 1)
right_middle = (150, 1)
right = (225, 1)
assert_tuple_approx_equal(
im_test.getpixel(left),
(255, 0, 0),
threshold=1,
msg="black test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(left_middle),
(127, 0, 127),
threshold=1,
msg="low-mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(middle), (0, 0, 255), threshold=1, msg="mid incorrect"
)
assert_tuple_approx_equal(
im_test.getpixel(right_middle),
(0, 63, 127),
threshold=1,
msg="high-mid test pixel incorrect",
)
assert_tuple_approx_equal(
im_test.getpixel(right),
(0, 127, 0),
threshold=1,
msg="white test pixel incorrect",
)
def test_exif_transpose(self):
exts = [".jpg"]
if HAVE_WEBP and _webp.HAVE_WEBPANIM:
exts.append(".webp")
for ext in exts:
with Image.open("Tests/images/hopper" + ext) as base_im:
def check(orientation_im):
for im in [
orientation_im,
orientation_im.copy(),
]: # ImageFile # Image
if orientation_im is base_im:
self.assertNotIn("exif", im.info)
else:
original_exif = im.info["exif"]
transposed_im = ImageOps.exif_transpose(im)
assert_image_similar(base_im, transposed_im, 17)
if orientation_im is base_im:
self.assertNotIn("exif", im.info)
else:
self.assertNotEqual(
transposed_im.info["exif"], original_exif
)
self.assertNotIn(0x0112, transposed_im.getexif())
# Repeat the operation
# to test that it does not keep transposing
transposed_im2 = ImageOps.exif_transpose(transposed_im)
assert_image_equal(transposed_im2, transposed_im)
check(base_im)
for i in range(2, 9):
with Image.open(
"Tests/images/hopper_orientation_" + str(i) + ext
) as orientation_im:
check(orientation_im)
"Tests/images/hopper_orientation_" + str(i) + ext
) as orientation_im:
check(orientation_im)

View File

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

View File

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

View File

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

View File

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