mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 09:26:16 +03:00
Format with Black
This commit is contained in:
parent
a986fed5b4
commit
d08475442b
|
@ -4,5 +4,5 @@ from PIL import Image
|
|||
import sys
|
||||
|
||||
|
||||
if sys.maxsize < 2**32:
|
||||
im = Image.new('L', (999999, 999999), 0)
|
||||
if sys.maxsize < 2 ** 32:
|
||||
im = Image.new("L", (999999, 999999), 0)
|
||||
|
|
|
@ -26,18 +26,21 @@ def timer(func, label, *args):
|
|||
starttime = time.time()
|
||||
for x in range(iterations):
|
||||
func(*args)
|
||||
if time.time()-starttime > 10:
|
||||
print("%s: breaking at %s iterations, %.6f per iteration" % (
|
||||
label, x+1, (time.time()-starttime)/(x+1.0)))
|
||||
if time.time() - starttime > 10:
|
||||
print(
|
||||
"%s: breaking at %s iterations, %.6f per iteration"
|
||||
% (label, x + 1, (time.time() - starttime) / (x + 1.0))
|
||||
)
|
||||
break
|
||||
if x == iterations-1:
|
||||
if x == iterations - 1:
|
||||
endtime = time.time()
|
||||
print("%s: %.4f s %.6f per iteration" % (
|
||||
label, endtime-starttime, (endtime-starttime)/(x+1.0)))
|
||||
print(
|
||||
"%s: %.4f s %.6f per iteration"
|
||||
% (label, endtime - starttime, (endtime - starttime) / (x + 1.0))
|
||||
)
|
||||
|
||||
|
||||
class BenchCffiAccess(PillowTestCase):
|
||||
|
||||
def test_direct(self):
|
||||
im = hopper()
|
||||
im.load()
|
||||
|
@ -48,11 +51,11 @@ class BenchCffiAccess(PillowTestCase):
|
|||
self.assertEqual(caccess[(0, 0)], access[(0, 0)])
|
||||
|
||||
print("Size: %sx%s" % im.size)
|
||||
timer(iterate_get, 'PyAccess - get', im.size, access)
|
||||
timer(iterate_set, 'PyAccess - set', im.size, access)
|
||||
timer(iterate_get, 'C-api - get', im.size, caccess)
|
||||
timer(iterate_set, 'C-api - set', im.size, caccess)
|
||||
timer(iterate_get, "PyAccess - get", im.size, access)
|
||||
timer(iterate_set, "PyAccess - set", im.size, access)
|
||||
timer(iterate_get, "C-api - get", im.size, caccess)
|
||||
timer(iterate_set, "C-api - set", im.size, caccess)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -2,6 +2,7 @@ from . import helper
|
|||
import timeit
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
|
||||
|
|
|
@ -12,5 +12,5 @@ class TestFliOverflow(PillowTestCase):
|
|||
im.load()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -6,7 +6,6 @@ from PIL._util import py3
|
|||
from io import BytesIO
|
||||
|
||||
if py3:
|
||||
Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00',
|
||||
'latin-1')))
|
||||
Image.open(BytesIO(bytes("icns\x00\x00\x00\x10hang\x00\x00\x00\x00", "latin-1")))
|
||||
else:
|
||||
Image.open(BytesIO(bytes('icns\x00\x00\x00\x10hang\x00\x00\x00\x00')))
|
||||
Image.open(BytesIO(bytes("icns\x00\x00\x00\x10hang\x00\x00\x00\x00")))
|
||||
|
|
|
@ -9,11 +9,11 @@ min_iterations = 100
|
|||
max_iterations = 10000
|
||||
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS")
|
||||
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
|
||||
class TestImagingLeaks(PillowTestCase):
|
||||
|
||||
def _get_mem_usage(self):
|
||||
from resource import getpagesize, getrusage, RUSAGE_SELF
|
||||
|
||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
||||
return mem * getpagesize() / 1024 / 1024
|
||||
|
||||
|
@ -25,20 +25,22 @@ class TestImagingLeaks(PillowTestCase):
|
|||
if i < min_iterations:
|
||||
mem_limit = mem + 1
|
||||
continue
|
||||
msg = 'memory usage limit exceeded after %d iterations' % (i + 1)
|
||||
msg = "memory usage limit exceeded after %d iterations" % (i + 1)
|
||||
self.assertLessEqual(mem, mem_limit, msg)
|
||||
|
||||
def test_leak_putdata(self):
|
||||
im = Image.new('RGB', (25, 25))
|
||||
self._test_leak(min_iterations, max_iterations,
|
||||
im.putdata, im.getdata())
|
||||
im = Image.new("RGB", (25, 25))
|
||||
self._test_leak(min_iterations, max_iterations, im.putdata, im.getdata())
|
||||
|
||||
def test_leak_getlist(self):
|
||||
im = Image.new('P', (25, 25))
|
||||
self._test_leak(min_iterations, max_iterations,
|
||||
im = Image.new("P", (25, 25))
|
||||
self._test_leak(
|
||||
min_iterations,
|
||||
max_iterations,
|
||||
# Pass a new list at each iteration.
|
||||
lambda: im.point(range(256)))
|
||||
lambda: im.point(range(256)),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -6,10 +6,16 @@ from PIL._util import py3
|
|||
from io import BytesIO
|
||||
|
||||
if py3:
|
||||
Image.open(BytesIO(bytes(
|
||||
'\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang',
|
||||
'latin-1')))
|
||||
Image.open(
|
||||
BytesIO(
|
||||
bytes(
|
||||
"\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang",
|
||||
"latin-1",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
Image.open(BytesIO(bytes(
|
||||
'\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang')))
|
||||
Image.open(
|
||||
BytesIO(bytes("\x00\x00\x00\x0cjP\x20\x20\x0d\x0a\x87\x0a\x00\x00\x00\x00hang"))
|
||||
)
|
||||
|
|
|
@ -4,21 +4,22 @@ from PIL import Image
|
|||
from io import BytesIO
|
||||
|
||||
# Limits for testing the leak
|
||||
mem_limit = 1024*1048576
|
||||
stack_size = 8*1048576
|
||||
iterations = int((mem_limit/stack_size)*2)
|
||||
mem_limit = 1024 * 1048576
|
||||
stack_size = 8 * 1048576
|
||||
iterations = int((mem_limit / stack_size) * 2)
|
||||
codecs = dir(Image.core)
|
||||
test_file = "Tests/images/rgb_trns_ycbc.jp2"
|
||||
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS")
|
||||
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
|
||||
class TestJpegLeaks(PillowTestCase):
|
||||
def setUp(self):
|
||||
if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs:
|
||||
self.skipTest('JPEG 2000 support not available')
|
||||
self.skipTest("JPEG 2000 support not available")
|
||||
|
||||
def test_leak_load(self):
|
||||
from resource import setrlimit, RLIMIT_AS, RLIMIT_STACK
|
||||
|
||||
setrlimit(RLIMIT_STACK, (stack_size, stack_size))
|
||||
setrlimit(RLIMIT_AS, (mem_limit, mem_limit))
|
||||
for _ in range(iterations):
|
||||
|
@ -27,6 +28,7 @@ class TestJpegLeaks(PillowTestCase):
|
|||
|
||||
def test_leak_save(self):
|
||||
from resource import setrlimit, RLIMIT_AS, RLIMIT_STACK
|
||||
|
||||
setrlimit(RLIMIT_STACK, (stack_size, stack_size))
|
||||
setrlimit(RLIMIT_AS, (mem_limit, mem_limit))
|
||||
for _ in range(iterations):
|
||||
|
@ -38,5 +40,5 @@ class TestJpegLeaks(PillowTestCase):
|
|||
test_output.read()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -5,11 +5,11 @@ from .helper import unittest, PillowTestCase
|
|||
class TestJ2kEncodeOverflow(PillowTestCase):
|
||||
def test_j2k_overflow(self):
|
||||
|
||||
im = Image.new('RGBA', (1024, 131584))
|
||||
target = self.tempfile('temp.jpc')
|
||||
im = Image.new("RGBA", (1024, 131584))
|
||||
target = self.tempfile("temp.jpc")
|
||||
with self.assertRaises(IOError):
|
||||
im.save(target)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -14,7 +14,7 @@ valgrind --tool=massif python test-installed.py -s -v Tests/check_jpeg_leaks.py
|
|||
"""
|
||||
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS")
|
||||
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
|
||||
class TestJpegLeaks(PillowTestCase):
|
||||
|
||||
"""
|
||||
|
@ -74,9 +74,11 @@ post-patch:
|
|||
"""
|
||||
|
||||
def test_qtables_leak(self):
|
||||
im = hopper('RGB')
|
||||
im = hopper("RGB")
|
||||
|
||||
standard_l_qtable = [int(s) for s in """
|
||||
standard_l_qtable = [
|
||||
int(s)
|
||||
for s in """
|
||||
16 11 10 16 24 40 51 61
|
||||
12 12 14 19 26 58 60 55
|
||||
14 13 16 24 40 57 69 56
|
||||
|
@ -85,9 +87,14 @@ post-patch:
|
|||
24 35 55 64 81 104 113 92
|
||||
49 64 78 87 103 121 120 101
|
||||
72 92 95 98 112 100 103 99
|
||||
""".split(None)]
|
||||
""".split(
|
||||
None
|
||||
)
|
||||
]
|
||||
|
||||
standard_chrominance_qtable = [int(s) for s in """
|
||||
standard_chrominance_qtable = [
|
||||
int(s)
|
||||
for s in """
|
||||
17 18 24 47 99 99 99 99
|
||||
18 21 26 66 99 99 99 99
|
||||
24 26 56 99 99 99 99 99
|
||||
|
@ -96,10 +103,12 @@ post-patch:
|
|||
99 99 99 99 99 99 99 99
|
||||
99 99 99 99 99 99 99 99
|
||||
99 99 99 99 99 99 99 99
|
||||
""".split(None)]
|
||||
""".split(
|
||||
None
|
||||
)
|
||||
]
|
||||
|
||||
qtables = [standard_l_qtable,
|
||||
standard_chrominance_qtable]
|
||||
qtables = [standard_l_qtable, standard_chrominance_qtable]
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
|
@ -161,8 +170,8 @@ post patch:
|
|||
0 11.33
|
||||
|
||||
"""
|
||||
im = hopper('RGB')
|
||||
exif = b'12345678'*4096
|
||||
im = hopper("RGB")
|
||||
exif = b"12345678" * 4096
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
|
@ -195,12 +204,12 @@ base case:
|
|||
0 +----------------------------------------------------------------------->Gi
|
||||
0 7.882
|
||||
"""
|
||||
im = hopper('RGB')
|
||||
im = hopper("RGB")
|
||||
|
||||
for _ in range(iterations):
|
||||
test_output = BytesIO()
|
||||
im.save(test_output, "JPEG")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -22,12 +22,11 @@ YDIM = 32769
|
|||
XDIM = 48000
|
||||
|
||||
|
||||
@unittest.skipIf(sys.maxsize <= 2**32, "requires 64-bit system")
|
||||
@unittest.skipIf(sys.maxsize <= 2 ** 32, "requires 64-bit system")
|
||||
class LargeMemoryTest(PillowTestCase):
|
||||
|
||||
def _write_png(self, xdim, ydim):
|
||||
f = self.tempfile('temp.png')
|
||||
im = Image.new('L', (xdim, ydim), 0)
|
||||
f = self.tempfile("temp.png")
|
||||
im = Image.new("L", (xdim, ydim), 0)
|
||||
im.save(f)
|
||||
|
||||
def test_large(self):
|
||||
|
@ -44,5 +43,5 @@ class LargeMemoryTest(PillowTestCase):
|
|||
Image.fromarray(arr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -11,6 +11,7 @@ from .helper import unittest, PillowTestCase
|
|||
# Raspberry Pis).
|
||||
|
||||
from PIL import Image
|
||||
|
||||
try:
|
||||
import numpy as np
|
||||
except ImportError:
|
||||
|
@ -20,14 +21,13 @@ YDIM = 32769
|
|||
XDIM = 48000
|
||||
|
||||
|
||||
@unittest.skipIf(sys.maxsize <= 2**32, "requires 64-bit system")
|
||||
@unittest.skipIf(sys.maxsize <= 2 ** 32, "requires 64-bit system")
|
||||
class LargeMemoryNumpyTest(PillowTestCase):
|
||||
|
||||
def _write_png(self, xdim, ydim):
|
||||
dtype = np.uint8
|
||||
a = np.zeros((xdim, ydim), dtype=dtype)
|
||||
f = self.tempfile('temp.png')
|
||||
im = Image.fromarray(a, 'L')
|
||||
f = self.tempfile("temp.png")
|
||||
im = Image.fromarray(a, "L")
|
||||
im.save(f)
|
||||
|
||||
def test_large(self):
|
||||
|
@ -39,5 +39,5 @@ class LargeMemoryNumpyTest(PillowTestCase):
|
|||
self._write_png(XDIM, XDIM)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -15,5 +15,5 @@ class TestLibtiffSegfault(PillowTestCase):
|
|||
im.load()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -17,10 +17,10 @@ class TestPngDos(PillowTestCase):
|
|||
ImageFile.LOAD_TRUNCATED_IMAGES = False
|
||||
|
||||
for s in im.text.values():
|
||||
self.assertLess(len(s), 1024*1024, "Text chunk larger than 1M")
|
||||
self.assertLess(len(s), 1024 * 1024, "Text chunk larger than 1M")
|
||||
|
||||
for s in im.info.values():
|
||||
self.assertLess(len(s), 1024*1024, "Text chunk larger than 1M")
|
||||
self.assertLess(len(s), 1024 * 1024, "Text chunk larger than 1M")
|
||||
|
||||
def test_dos_text(self):
|
||||
|
||||
|
@ -32,20 +32,20 @@ class TestPngDos(PillowTestCase):
|
|||
return
|
||||
|
||||
for s in im.text.values():
|
||||
self.assertLess(len(s), 1024*1024, "Text chunk larger than 1M")
|
||||
self.assertLess(len(s), 1024 * 1024, "Text chunk larger than 1M")
|
||||
|
||||
def test_dos_total_memory(self):
|
||||
im = Image.new('L', (1, 1))
|
||||
compressed_data = zlib.compress(b'a'*1024*1023)
|
||||
im = Image.new("L", (1, 1))
|
||||
compressed_data = zlib.compress(b"a" * 1024 * 1023)
|
||||
|
||||
info = PngImagePlugin.PngInfo()
|
||||
|
||||
for x in range(64):
|
||||
info.add_text('t%s' % x, compressed_data, zip=True)
|
||||
info.add_itxt('i%s' % x, compressed_data, zip=True)
|
||||
info.add_text("t%s" % x, compressed_data, zip=True)
|
||||
info.add_itxt("i%s" % x, compressed_data, zip=True)
|
||||
|
||||
b = BytesIO()
|
||||
im.save(b, 'PNG', pnginfo=info)
|
||||
im.save(b, "PNG", pnginfo=info)
|
||||
b.seek(0)
|
||||
|
||||
try:
|
||||
|
@ -57,9 +57,10 @@ class TestPngDos(PillowTestCase):
|
|||
total_len = 0
|
||||
for txt in im2.text.values():
|
||||
total_len += len(txt)
|
||||
self.assertLess(total_len, 64*1024*1024,
|
||||
"Total text chunks greater than 64M")
|
||||
self.assertLess(
|
||||
total_len, 64 * 1024 * 1024, "Total text chunks greater than 64M"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
136
Tests/helper.py
136
Tests/helper.py
|
@ -11,12 +11,13 @@ from PIL import Image, ImageMath
|
|||
from PIL._util import py3
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
HAS_UPLOADER = False
|
||||
|
||||
if os.environ.get('SHOW_ERRORS', None):
|
||||
if os.environ.get("SHOW_ERRORS", None):
|
||||
# local img.show for errors.
|
||||
HAS_UPLOADER = True
|
||||
|
||||
|
@ -25,9 +26,12 @@ if os.environ.get('SHOW_ERRORS', None):
|
|||
def upload(self, a, b):
|
||||
a.show()
|
||||
b.show()
|
||||
|
||||
|
||||
else:
|
||||
try:
|
||||
import test_image_results
|
||||
|
||||
HAS_UPLOADER = True
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -35,19 +39,18 @@ else:
|
|||
|
||||
def convert_to_comparable(a, b):
|
||||
new_a, new_b = a, b
|
||||
if a.mode == 'P':
|
||||
new_a = Image.new('L', a.size)
|
||||
new_b = Image.new('L', b.size)
|
||||
if a.mode == "P":
|
||||
new_a = Image.new("L", a.size)
|
||||
new_b = Image.new("L", b.size)
|
||||
new_a.putdata(a.getdata())
|
||||
new_b.putdata(b.getdata())
|
||||
elif a.mode == 'I;16':
|
||||
new_a = a.convert('I')
|
||||
new_b = b.convert('I')
|
||||
elif a.mode == "I;16":
|
||||
new_a = a.convert("I")
|
||||
new_b = b.convert("I")
|
||||
return new_a, new_b
|
||||
|
||||
|
||||
class PillowTestCase(unittest.TestCase):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
unittest.TestCase.__init__(self, *args, **kwargs)
|
||||
# holds last result object passed to run method:
|
||||
|
@ -75,32 +78,32 @@ class PillowTestCase(unittest.TestCase):
|
|||
def assert_deep_equal(self, a, b, msg=None):
|
||||
try:
|
||||
self.assertEqual(
|
||||
len(a), len(b),
|
||||
msg or "got length %s, expected %s" % (len(a), len(b)))
|
||||
len(a), len(b), msg or "got length %s, expected %s" % (len(a), len(b))
|
||||
)
|
||||
self.assertTrue(
|
||||
all(x == y for x, y in zip(a, b)),
|
||||
msg or "got %s, expected %s" % (a, b))
|
||||
all(x == y for x, y in zip(a, b)), msg or "got %s, expected %s" % (a, b)
|
||||
)
|
||||
except Exception:
|
||||
self.assertEqual(a, b, msg)
|
||||
|
||||
def assert_image(self, im, mode, size, msg=None):
|
||||
if mode is not None:
|
||||
self.assertEqual(
|
||||
im.mode, mode,
|
||||
msg or "got mode %r, expected %r" % (im.mode, mode))
|
||||
im.mode, mode, msg or "got mode %r, expected %r" % (im.mode, mode)
|
||||
)
|
||||
|
||||
if size is not None:
|
||||
self.assertEqual(
|
||||
im.size, size,
|
||||
msg or "got size %r, expected %r" % (im.size, size))
|
||||
im.size, size, msg or "got size %r, expected %r" % (im.size, size)
|
||||
)
|
||||
|
||||
def assert_image_equal(self, a, b, msg=None):
|
||||
self.assertEqual(
|
||||
a.mode, b.mode,
|
||||
msg or "got mode %r, expected %r" % (a.mode, b.mode))
|
||||
a.mode, b.mode, msg or "got mode %r, expected %r" % (a.mode, b.mode)
|
||||
)
|
||||
self.assertEqual(
|
||||
a.size, b.size,
|
||||
msg or "got size %r, expected %r" % (a.size, b.size))
|
||||
a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size)
|
||||
)
|
||||
if a.tobytes() != b.tobytes():
|
||||
if HAS_UPLOADER:
|
||||
try:
|
||||
|
@ -120,26 +123,28 @@ class PillowTestCase(unittest.TestCase):
|
|||
def assert_image_similar(self, a, b, epsilon, msg=None):
|
||||
epsilon = float(epsilon)
|
||||
self.assertEqual(
|
||||
a.mode, b.mode,
|
||||
msg or "got mode %r, expected %r" % (a.mode, b.mode))
|
||||
a.mode, b.mode, msg or "got mode %r, expected %r" % (a.mode, b.mode)
|
||||
)
|
||||
self.assertEqual(
|
||||
a.size, b.size,
|
||||
msg or "got size %r, expected %r" % (a.size, b.size))
|
||||
a.size, b.size, msg or "got size %r, expected %r" % (a.size, b.size)
|
||||
)
|
||||
|
||||
a, b = convert_to_comparable(a, b)
|
||||
|
||||
diff = 0
|
||||
for ach, bch in zip(a.split(), b.split()):
|
||||
chdiff = ImageMath.eval("abs(a - b)", a=ach, b=bch).convert('L')
|
||||
chdiff = ImageMath.eval("abs(a - b)", a=ach, b=bch).convert("L")
|
||||
diff += sum(i * num for i, num in enumerate(chdiff.histogram()))
|
||||
|
||||
ave_diff = float(diff)/(a.size[0]*a.size[1])
|
||||
ave_diff = float(diff) / (a.size[0] * a.size[1])
|
||||
try:
|
||||
self.assertGreaterEqual(
|
||||
epsilon, ave_diff,
|
||||
(msg or '') +
|
||||
" average pixel value difference %.4f > epsilon %.4f" % (
|
||||
ave_diff, epsilon))
|
||||
epsilon,
|
||||
ave_diff,
|
||||
(msg or "")
|
||||
+ " average pixel value difference %.4f > epsilon %.4f"
|
||||
% (ave_diff, epsilon),
|
||||
)
|
||||
except Exception as e:
|
||||
if HAS_UPLOADER:
|
||||
try:
|
||||
|
@ -149,8 +154,7 @@ class PillowTestCase(unittest.TestCase):
|
|||
pass
|
||||
raise e
|
||||
|
||||
def assert_image_similar_tofile(self, a, filename, epsilon, msg=None,
|
||||
mode=None):
|
||||
def assert_image_similar_tofile(self, a, filename, epsilon, msg=None, mode=None):
|
||||
with Image.open(filename) as img:
|
||||
if mode:
|
||||
img = img.convert(mode)
|
||||
|
@ -168,9 +172,9 @@ class PillowTestCase(unittest.TestCase):
|
|||
|
||||
# Verify some things.
|
||||
if warn_class is None:
|
||||
self.assertEqual(len(w), 0,
|
||||
"Expected no warnings, got %s" %
|
||||
[v.category for v in w])
|
||||
self.assertEqual(
|
||||
len(w), 0, "Expected no warnings, got %s" % [v.category for v in w]
|
||||
)
|
||||
else:
|
||||
self.assertGreaterEqual(len(w), 1)
|
||||
found = False
|
||||
|
@ -192,27 +196,26 @@ class PillowTestCase(unittest.TestCase):
|
|||
|
||||
value = True
|
||||
for i, target in enumerate(targets):
|
||||
value *= (target - threshold <= actuals[i] <= target + threshold)
|
||||
value *= target - threshold <= actuals[i] <= target + threshold
|
||||
|
||||
self.assertTrue(value,
|
||||
msg + ': ' + repr(actuals) + ' != ' + repr(targets))
|
||||
self.assertTrue(value, msg + ": " + repr(actuals) + " != " + repr(targets))
|
||||
|
||||
def skipKnownBadTest(self, msg=None, platform=None,
|
||||
travis=None, interpreter=None):
|
||||
def skipKnownBadTest(self, msg=None, platform=None, travis=None, interpreter=None):
|
||||
# Skip if platform/travis matches, and
|
||||
# PILLOW_RUN_KNOWN_BAD is not true in the environment.
|
||||
if os.environ.get('PILLOW_RUN_KNOWN_BAD', False):
|
||||
print(os.environ.get('PILLOW_RUN_KNOWN_BAD', False))
|
||||
if os.environ.get("PILLOW_RUN_KNOWN_BAD", False):
|
||||
print(os.environ.get("PILLOW_RUN_KNOWN_BAD", False))
|
||||
return
|
||||
|
||||
skip = True
|
||||
if platform is not None:
|
||||
skip = sys.platform.startswith(platform)
|
||||
if travis is not None:
|
||||
skip = skip and (travis == bool(os.environ.get('TRAVIS', False)))
|
||||
skip = skip and (travis == bool(os.environ.get("TRAVIS", False)))
|
||||
if interpreter is not None:
|
||||
skip = skip and (interpreter == 'pypy' and
|
||||
hasattr(sys, 'pypy_version_info'))
|
||||
skip = skip and (
|
||||
interpreter == "pypy" and hasattr(sys, "pypy_version_info")
|
||||
)
|
||||
if skip:
|
||||
self.skipTest(msg or "Known Bad Test")
|
||||
|
||||
|
@ -234,7 +237,7 @@ class PillowTestCase(unittest.TestCase):
|
|||
raise IOError()
|
||||
|
||||
|
||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS")
|
||||
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
|
||||
class PillowLeakTestCase(PillowTestCase):
|
||||
# requires unix/macOS
|
||||
iterations = 100 # count
|
||||
|
@ -249,8 +252,9 @@ class PillowLeakTestCase(PillowTestCase):
|
|||
"""
|
||||
|
||||
from resource import getrusage, RUSAGE_SELF
|
||||
|
||||
mem = getrusage(RUSAGE_SELF).ru_maxrss
|
||||
if sys.platform == 'darwin':
|
||||
if sys.platform == "darwin":
|
||||
# man 2 getrusage:
|
||||
# ru_maxrss
|
||||
# This is the maximum resident set size utilized (in bytes).
|
||||
|
@ -266,8 +270,8 @@ class PillowLeakTestCase(PillowTestCase):
|
|||
start_mem = self._get_mem_usage()
|
||||
for cycle in range(self.iterations):
|
||||
core()
|
||||
mem = (self._get_mem_usage() - start_mem)
|
||||
msg = 'memory usage limit exceeded in iteration %d' % cycle
|
||||
mem = self._get_mem_usage() - start_mem
|
||||
msg = "memory usage limit exceeded in iteration %d" % cycle
|
||||
self.assertLess(mem, self.mem_limit, msg)
|
||||
|
||||
|
||||
|
@ -281,11 +285,13 @@ if not py3:
|
|||
|
||||
def fromstring(data):
|
||||
from io import BytesIO
|
||||
|
||||
return Image.open(BytesIO(data))
|
||||
|
||||
|
||||
def tostring(im, string_format, **options):
|
||||
from io import BytesIO
|
||||
|
||||
out = BytesIO()
|
||||
im.save(out, string_format, **options)
|
||||
return out.getvalue()
|
||||
|
@ -318,7 +324,8 @@ def command_succeeds(cmd):
|
|||
command succeeds, or False if an OSError was raised by subprocess.Popen.
|
||||
"""
|
||||
import subprocess
|
||||
with open(os.devnull, 'wb') as f:
|
||||
|
||||
with open(os.devnull, "wb") as f:
|
||||
try:
|
||||
subprocess.call(cmd, stdout=f, stderr=subprocess.STDOUT)
|
||||
except OSError:
|
||||
|
@ -327,40 +334,41 @@ def command_succeeds(cmd):
|
|||
|
||||
|
||||
def djpeg_available():
|
||||
return command_succeeds(['djpeg', '-version'])
|
||||
return command_succeeds(["djpeg", "-version"])
|
||||
|
||||
|
||||
def cjpeg_available():
|
||||
return command_succeeds(['cjpeg', '-version'])
|
||||
return command_succeeds(["cjpeg", "-version"])
|
||||
|
||||
|
||||
def netpbm_available():
|
||||
return (command_succeeds(["ppmquant", "--version"]) and
|
||||
command_succeeds(["ppmtogif", "--version"]))
|
||||
return command_succeeds(["ppmquant", "--version"]) and command_succeeds(
|
||||
["ppmtogif", "--version"]
|
||||
)
|
||||
|
||||
|
||||
def imagemagick_available():
|
||||
return IMCONVERT and command_succeeds([IMCONVERT, '-version'])
|
||||
return IMCONVERT and command_succeeds([IMCONVERT, "-version"])
|
||||
|
||||
|
||||
def on_appveyor():
|
||||
return 'APPVEYOR' in os.environ
|
||||
return "APPVEYOR" in os.environ
|
||||
|
||||
|
||||
if sys.platform == 'win32':
|
||||
IMCONVERT = os.environ.get('MAGICK_HOME', '')
|
||||
if sys.platform == "win32":
|
||||
IMCONVERT = os.environ.get("MAGICK_HOME", "")
|
||||
if IMCONVERT:
|
||||
IMCONVERT = os.path.join(IMCONVERT, 'convert.exe')
|
||||
IMCONVERT = os.path.join(IMCONVERT, "convert.exe")
|
||||
else:
|
||||
IMCONVERT = 'convert'
|
||||
IMCONVERT = "convert"
|
||||
|
||||
|
||||
def distro():
|
||||
if os.path.exists('/etc/os-release'):
|
||||
with open('/etc/os-release', 'r') as f:
|
||||
if os.path.exists("/etc/os-release"):
|
||||
with open("/etc/os-release", "r") as f:
|
||||
for line in f:
|
||||
if 'ID=' in line:
|
||||
return line.strip().split('=')[1]
|
||||
if "ID=" in line:
|
||||
return line.strip().split("=")[1]
|
||||
|
||||
|
||||
class cached_property(object):
|
||||
|
|
|
@ -5,6 +5,7 @@ import os
|
|||
import traceback
|
||||
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
for file in glob.glob("src/PIL/*.py"):
|
||||
|
|
|
@ -4,21 +4,33 @@ from __future__ import print_function
|
|||
|
||||
modes = [
|
||||
"1",
|
||||
"L", "LA", "La",
|
||||
"I", "I;16", "I;16L", "I;16B", "I;32L", "I;32B",
|
||||
"L",
|
||||
"LA",
|
||||
"La",
|
||||
"I",
|
||||
"I;16",
|
||||
"I;16L",
|
||||
"I;16B",
|
||||
"I;32L",
|
||||
"I;32B",
|
||||
"F",
|
||||
"P", "PA",
|
||||
"RGB", "RGBA", "RGBa", "RGBX",
|
||||
"P",
|
||||
"PA",
|
||||
"RGB",
|
||||
"RGBA",
|
||||
"RGBa",
|
||||
"RGBX",
|
||||
"CMYK",
|
||||
"YCbCr",
|
||||
"LAB", "HSV",
|
||||
]
|
||||
"LAB",
|
||||
"HSV",
|
||||
]
|
||||
|
||||
|
||||
def hash(s, i):
|
||||
# djb2 hash: multiply by 33 and xor character
|
||||
for c in s:
|
||||
i = (((i << 5) + i) ^ ord(c)) & 0xffffffff
|
||||
i = (((i << 5) + i) ^ ord(c)) & 0xFFFFFFFF
|
||||
return i
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import PIL.Image
|
|||
|
||||
|
||||
class TestSanity(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
|
||||
# Make sure we have the binary extension
|
||||
|
@ -13,7 +12,7 @@ class TestSanity(PillowTestCase):
|
|||
|
||||
# Create an image and do stuff with it.
|
||||
im = PIL.Image.new("1", (100, 100))
|
||||
self.assertEqual((im.mode, im.size), ('1', (100, 100)))
|
||||
self.assertEqual((im.mode, im.size), ("1", (100, 100)))
|
||||
self.assertEqual(len(im.tobytes()), 1300)
|
||||
|
||||
# Create images in all remaining major modes.
|
||||
|
|
|
@ -4,21 +4,20 @@ from PIL import _binary
|
|||
|
||||
|
||||
class TestBinary(PillowTestCase):
|
||||
|
||||
def test_standard(self):
|
||||
self.assertEqual(_binary.i8(b'*'), 42)
|
||||
self.assertEqual(_binary.o8(42), b'*')
|
||||
self.assertEqual(_binary.i8(b"*"), 42)
|
||||
self.assertEqual(_binary.o8(42), b"*")
|
||||
|
||||
def test_little_endian(self):
|
||||
self.assertEqual(_binary.i16le(b'\xff\xff\x00\x00'), 65535)
|
||||
self.assertEqual(_binary.i32le(b'\xff\xff\x00\x00'), 65535)
|
||||
self.assertEqual(_binary.i16le(b"\xff\xff\x00\x00"), 65535)
|
||||
self.assertEqual(_binary.i32le(b"\xff\xff\x00\x00"), 65535)
|
||||
|
||||
self.assertEqual(_binary.o16le(65535), b'\xff\xff')
|
||||
self.assertEqual(_binary.o32le(65535), b'\xff\xff\x00\x00')
|
||||
self.assertEqual(_binary.o16le(65535), b"\xff\xff")
|
||||
self.assertEqual(_binary.o32le(65535), b"\xff\xff\x00\x00")
|
||||
|
||||
def test_big_endian(self):
|
||||
self.assertEqual(_binary.i16be(b'\x00\x00\xff\xff'), 0)
|
||||
self.assertEqual(_binary.i32be(b'\x00\x00\xff\xff'), 65535)
|
||||
self.assertEqual(_binary.i16be(b"\x00\x00\xff\xff"), 0)
|
||||
self.assertEqual(_binary.i32be(b"\x00\x00\xff\xff"), 65535)
|
||||
|
||||
self.assertEqual(_binary.o16be(65535), b'\xff\xff')
|
||||
self.assertEqual(_binary.o32be(65535), b'\x00\x00\xff\xff')
|
||||
self.assertEqual(_binary.o16be(65535), b"\xff\xff")
|
||||
self.assertEqual(_binary.o32be(65535), b"\x00\x00\xff\xff")
|
||||
|
|
|
@ -4,19 +4,22 @@ from .helper import PillowTestCase
|
|||
from PIL import Image
|
||||
import os
|
||||
|
||||
base = os.path.join('Tests', 'images', 'bmp')
|
||||
base = os.path.join("Tests", "images", "bmp")
|
||||
|
||||
|
||||
class TestBmpReference(PillowTestCase):
|
||||
|
||||
def get_files(self, d, ext='.bmp'):
|
||||
return [os.path.join(base, d, f) for f
|
||||
in os.listdir(os.path.join(base, d)) if ext in f]
|
||||
def get_files(self, d, ext=".bmp"):
|
||||
return [
|
||||
os.path.join(base, d, f)
|
||||
for f in os.listdir(os.path.join(base, d))
|
||||
if ext in f
|
||||
]
|
||||
|
||||
def test_bad(self):
|
||||
""" These shouldn't crash/dos, but they shouldn't return anything
|
||||
either """
|
||||
for f in self.get_files('b'):
|
||||
for f in self.get_files("b"):
|
||||
|
||||
def open(f):
|
||||
try:
|
||||
im = Image.open(f)
|
||||
|
@ -41,13 +44,12 @@ class TestBmpReference(PillowTestCase):
|
|||
"pal8os2sp.bmp",
|
||||
"rgb32bf-xbgr.bmp",
|
||||
]
|
||||
for f in self.get_files('q'):
|
||||
for f in self.get_files("q"):
|
||||
try:
|
||||
im = Image.open(f)
|
||||
im.load()
|
||||
if os.path.basename(f) not in supported:
|
||||
print("Please add %s to the partially supported"
|
||||
" bmp specs." % f)
|
||||
print("Please add %s to the partially supported bmp specs." % f)
|
||||
except Exception: # as msg:
|
||||
if os.path.basename(f) in supported:
|
||||
raise
|
||||
|
@ -57,49 +59,52 @@ class TestBmpReference(PillowTestCase):
|
|||
html directory that we can compare against. """
|
||||
|
||||
# Target files, if they're not just replacing the extension
|
||||
file_map = {'pal1wb.bmp': 'pal1.png',
|
||||
'pal4rle.bmp': 'pal4.png',
|
||||
'pal8-0.bmp': 'pal8.png',
|
||||
'pal8rle.bmp': 'pal8.png',
|
||||
'pal8topdown.bmp': 'pal8.png',
|
||||
'pal8nonsquare.bmp': 'pal8nonsquare-v.png',
|
||||
'pal8os2.bmp': 'pal8.png',
|
||||
'pal8os2sp.bmp': 'pal8.png',
|
||||
'pal8os2v2.bmp': 'pal8.png',
|
||||
'pal8os2v2-16.bmp': 'pal8.png',
|
||||
'pal8v4.bmp': 'pal8.png',
|
||||
'pal8v5.bmp': 'pal8.png',
|
||||
'rgb16-565pal.bmp': 'rgb16-565.png',
|
||||
'rgb24pal.bmp': 'rgb24.png',
|
||||
'rgb32.bmp': 'rgb24.png',
|
||||
'rgb32bf.bmp': 'rgb24.png'
|
||||
file_map = {
|
||||
"pal1wb.bmp": "pal1.png",
|
||||
"pal4rle.bmp": "pal4.png",
|
||||
"pal8-0.bmp": "pal8.png",
|
||||
"pal8rle.bmp": "pal8.png",
|
||||
"pal8topdown.bmp": "pal8.png",
|
||||
"pal8nonsquare.bmp": "pal8nonsquare-v.png",
|
||||
"pal8os2.bmp": "pal8.png",
|
||||
"pal8os2sp.bmp": "pal8.png",
|
||||
"pal8os2v2.bmp": "pal8.png",
|
||||
"pal8os2v2-16.bmp": "pal8.png",
|
||||
"pal8v4.bmp": "pal8.png",
|
||||
"pal8v5.bmp": "pal8.png",
|
||||
"rgb16-565pal.bmp": "rgb16-565.png",
|
||||
"rgb24pal.bmp": "rgb24.png",
|
||||
"rgb32.bmp": "rgb24.png",
|
||||
"rgb32bf.bmp": "rgb24.png",
|
||||
}
|
||||
|
||||
def get_compare(f):
|
||||
name = os.path.split(f)[1]
|
||||
if name in file_map:
|
||||
return os.path.join(base, 'html', file_map[name])
|
||||
return os.path.join(base, "html", file_map[name])
|
||||
name = os.path.splitext(name)[0]
|
||||
return os.path.join(base, 'html', "%s.png" % name)
|
||||
return os.path.join(base, "html", "%s.png" % name)
|
||||
|
||||
for f in self.get_files('g'):
|
||||
for f in self.get_files("g"):
|
||||
try:
|
||||
im = Image.open(f)
|
||||
im.load()
|
||||
compare = Image.open(get_compare(f))
|
||||
compare.load()
|
||||
if im.mode == 'P':
|
||||
if im.mode == "P":
|
||||
# assert image similar doesn't really work
|
||||
# with paletized image, since the palette might
|
||||
# be differently ordered for an equivalent image.
|
||||
im = im.convert('RGBA')
|
||||
compare = im.convert('RGBA')
|
||||
im = im.convert("RGBA")
|
||||
compare = im.convert("RGBA")
|
||||
self.assert_image_similar(im, compare, 5)
|
||||
|
||||
except Exception as msg:
|
||||
# there are three here that are unsupported:
|
||||
unsupported = (os.path.join(base, 'g', 'rgb32bf.bmp'),
|
||||
os.path.join(base, 'g', 'pal8rle.bmp'),
|
||||
os.path.join(base, 'g', 'pal4rle.bmp'))
|
||||
unsupported = (
|
||||
os.path.join(base, "g", "rgb32bf.bmp"),
|
||||
os.path.join(base, "g", "pal8rle.bmp"),
|
||||
os.path.join(base, "g", "pal4rle.bmp"),
|
||||
)
|
||||
if f not in unsupported:
|
||||
self.fail("Unsupported Image %s: %s" % (f, msg))
|
||||
|
|
|
@ -4,6 +4,7 @@ from PIL import Image, ImageFilter
|
|||
|
||||
|
||||
sample = Image.new("L", (7, 5))
|
||||
# fmt: off
|
||||
sample.putdata(sum([
|
||||
[210, 50, 20, 10, 220, 230, 80],
|
||||
[190, 210, 20, 180, 170, 40, 110],
|
||||
|
@ -11,10 +12,10 @@ sample.putdata(sum([
|
|||
[220, 40, 230, 80, 130, 250, 40],
|
||||
[250, 0, 80, 30, 60, 20, 110],
|
||||
], []))
|
||||
# fmt: on
|
||||
|
||||
|
||||
class TestBoxBlurApi(PillowTestCase):
|
||||
|
||||
def test_imageops_box_blur(self):
|
||||
i = sample.filter(ImageFilter.BoxBlur(1))
|
||||
self.assertEqual(i.mode, sample.mode)
|
||||
|
@ -23,7 +24,6 @@ class TestBoxBlurApi(PillowTestCase):
|
|||
|
||||
|
||||
class TestBoxBlur(PillowTestCase):
|
||||
|
||||
def box_blur(self, image, radius=1, n=1):
|
||||
return image._new(image.im.box_blur(radius, n))
|
||||
|
||||
|
@ -32,8 +32,7 @@ class TestBoxBlur(PillowTestCase):
|
|||
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)
|
||||
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)
|
||||
|
@ -41,7 +40,7 @@ class TestBoxBlur(PillowTestCase):
|
|||
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))
|
||||
rgba = Image.merge("RGBA", (im, im, im, im))
|
||||
for band in self.box_blur(rgba, radius, passes).split():
|
||||
self.assertImage(band, data, delta)
|
||||
|
||||
|
@ -61,110 +60,135 @@ class TestBoxBlur(PillowTestCase):
|
|||
|
||||
def test_radius_0(self):
|
||||
self.assertBlur(
|
||||
sample, 0,
|
||||
sample,
|
||||
0,
|
||||
[
|
||||
# fmt: off
|
||||
[210, 50, 20, 10, 220, 230, 80],
|
||||
[190, 210, 20, 180, 170, 40, 110],
|
||||
[120, 210, 250, 60, 220, 0, 220],
|
||||
[220, 40, 230, 80, 130, 250, 40],
|
||||
[250, 0, 80, 30, 60, 20, 110],
|
||||
]
|
||||
# fmt: on
|
||||
],
|
||||
)
|
||||
|
||||
def test_radius_0_02(self):
|
||||
self.assertBlur(
|
||||
sample, 0.02,
|
||||
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,
|
||||
sample,
|
||||
0.05,
|
||||
[
|
||||
# fmt: off
|
||||
[202, 62, 22, 27, 209, 215, 88],
|
||||
[188, 194, 44, 161, 168, 56, 111],
|
||||
[131, 201, 229, 81, 198, 31, 198],
|
||||
[209, 62, 209, 86, 133, 216, 59],
|
||||
[237, 17, 80, 36, 60, 35, 103],
|
||||
# fmt: on
|
||||
],
|
||||
delta=2,
|
||||
)
|
||||
|
||||
def test_radius_0_1(self):
|
||||
self.assertBlur(
|
||||
sample, 0.1,
|
||||
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,
|
||||
sample,
|
||||
0.5,
|
||||
[
|
||||
# fmt: off
|
||||
[176, 101, 46, 83, 163, 165, 111],
|
||||
[176, 149, 108, 122, 144, 120, 117],
|
||||
[164, 171, 159, 141, 134, 119, 129],
|
||||
[170, 136, 133, 114, 116, 124, 109],
|
||||
[184, 95, 72, 70, 69, 81, 89],
|
||||
# fmt: on
|
||||
],
|
||||
delta=1,
|
||||
)
|
||||
|
||||
def test_radius_1(self):
|
||||
self.assertBlur(
|
||||
sample, 1,
|
||||
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,
|
||||
sample,
|
||||
1.5,
|
||||
[
|
||||
# fmt: off
|
||||
[155, 120, 105, 112, 124, 137, 130],
|
||||
[160, 136, 124, 125, 127, 134, 130],
|
||||
[166, 147, 130, 125, 120, 121, 119],
|
||||
[168, 145, 119, 109, 103, 105, 110],
|
||||
[168, 134, 96, 85, 85, 89, 97],
|
||||
# fmt: on
|
||||
],
|
||||
delta=1,
|
||||
)
|
||||
|
||||
def test_radius_bigger_then_half(self):
|
||||
self.assertBlur(
|
||||
sample, 3,
|
||||
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,
|
||||
sample,
|
||||
10,
|
||||
[
|
||||
[158, 153, 147, 141, 135, 129, 123],
|
||||
[159, 153, 147, 141, 136, 130, 124],
|
||||
|
@ -177,7 +201,8 @@ class TestBoxBlur(PillowTestCase):
|
|||
|
||||
def test_extreme_large_radius(self):
|
||||
self.assertBlur(
|
||||
sample, 600,
|
||||
sample,
|
||||
600,
|
||||
[
|
||||
[162, 162, 162, 162, 162, 162, 162],
|
||||
[162, 162, 162, 162, 162, 162, 162],
|
||||
|
@ -190,13 +215,16 @@ class TestBoxBlur(PillowTestCase):
|
|||
|
||||
def test_two_passes(self):
|
||||
self.assertBlur(
|
||||
sample, 1,
|
||||
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,
|
||||
|
@ -204,13 +232,16 @@ class TestBoxBlur(PillowTestCase):
|
|||
|
||||
def test_three_passes(self):
|
||||
self.assertBlur(
|
||||
sample, 1,
|
||||
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,
|
||||
|
|
|
@ -20,185 +20,197 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
|
||||
table = [
|
||||
[
|
||||
r / float(size1D-1) if size1D != 1 else 0,
|
||||
g / float(size2D-1) if size2D != 1 else 0,
|
||||
b / float(size3D-1) if size3D != 1 else 0,
|
||||
r / float(size1D-1) if size1D != 1 else 0,
|
||||
g / float(size2D-1) if size2D != 1 else 0,
|
||||
r / float(size1D - 1) if size1D != 1 else 0,
|
||||
g / float(size2D - 1) if size2D != 1 else 0,
|
||||
b / float(size3D - 1) if size3D != 1 else 0,
|
||||
r / float(size1D - 1) if size1D != 1 else 0,
|
||||
g / float(size2D - 1) if size2D != 1 else 0,
|
||||
][:channels]
|
||||
for b in range(size3D)
|
||||
for g in range(size2D)
|
||||
for r in range(size1D)
|
||||
]
|
||||
return (
|
||||
channels, size1D, size2D, size3D,
|
||||
[item for sublist in table for item in sublist])
|
||||
channels,
|
||||
size1D,
|
||||
size2D,
|
||||
size3D,
|
||||
[item for sublist in table for item in sublist],
|
||||
)
|
||||
|
||||
def test_wrong_args(self):
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "filter"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.CUBIC,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im.im.color_lut_3d("RGB", Image.CUBIC, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "image mode"):
|
||||
im.im.color_lut_3d('wrong',
|
||||
Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im.im.color_lut_3d(
|
||||
"wrong", Image.LINEAR, *self.generate_identity_table(3, 3)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table_channels"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
*self.generate_identity_table(5, 3))
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(5, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table_channels"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
*self.generate_identity_table(1, 3))
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(1, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "table_channels"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
*self.generate_identity_table(2, 3))
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(2, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "Table size"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
*self.generate_identity_table(3, (1, 3, 3)))
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (1, 3, 3))
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "Table size"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
*self.generate_identity_table(3, (66, 3, 3)))
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (66, 3, 3))
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
3, 2, 2, 2, [0, 0, 0] * 7)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 7)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, r"size1D \* size2D \* size3D"):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
3, 2, 2, 2, [0, 0, 0] * 9)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, 0] * 9)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
3, 2, 2, 2, [0, 0, "0"] * 8)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, [0, 0, "0"] * 8)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
im.im.color_lut_3d('RGB',
|
||||
Image.LINEAR,
|
||||
3, 2, 2, 2, 16)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, 3, 2, 2, 2, 16)
|
||||
|
||||
def test_correct_args(self):
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
im.im.color_lut_3d('CMYK', Image.LINEAR,
|
||||
*self.generate_identity_table(4, 3))
|
||||
im.im.color_lut_3d("CMYK", Image.LINEAR, *self.generate_identity_table(4, 3))
|
||||
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, (2, 3, 3)))
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (2, 3, 3))
|
||||
)
|
||||
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, (65, 3, 3)))
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (65, 3, 3))
|
||||
)
|
||||
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, (3, 65, 3)))
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (3, 65, 3))
|
||||
)
|
||||
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, (3, 3, 65)))
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (3, 3, 65))
|
||||
)
|
||||
|
||||
def test_wrong_mode(self):
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
im = Image.new('L', (10, 10), 0)
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im = Image.new("L", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im.im.color_lut_3d('L', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
im = Image.new('L', (10, 10), 0)
|
||||
im.im.color_lut_3d('L', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im = Image.new("L", (10, 10), 0)
|
||||
im.im.color_lut_3d("L", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im.im.color_lut_3d('RGBA', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d(
|
||||
"RGBA", Image.LINEAR, *self.generate_identity_table(3, 3)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "wrong mode"):
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(4, 3))
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGB", Image.LINEAR, *self.generate_identity_table(4, 3))
|
||||
|
||||
def test_correct_mode(self):
|
||||
im = Image.new('RGBA', (10, 10), 0)
|
||||
im.im.color_lut_3d('RGBA', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im = Image.new("RGBA", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
im = Image.new('RGBA', (10, 10), 0)
|
||||
im.im.color_lut_3d('RGBA', Image.LINEAR,
|
||||
*self.generate_identity_table(4, 3))
|
||||
im = Image.new("RGBA", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(4, 3))
|
||||
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im.im.color_lut_3d('HSV', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 3))
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d("HSV", Image.LINEAR, *self.generate_identity_table(3, 3))
|
||||
|
||||
im = Image.new('RGB', (10, 10), 0)
|
||||
im.im.color_lut_3d('RGBA', Image.LINEAR,
|
||||
*self.generate_identity_table(4, 3))
|
||||
im = Image.new("RGB", (10, 10), 0)
|
||||
im.im.color_lut_3d("RGBA", Image.LINEAR, *self.generate_identity_table(4, 3))
|
||||
|
||||
def test_identities(self):
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)]
|
||||
)
|
||||
|
||||
# Fast test with small cubes
|
||||
for size in [2, 3, 5, 7, 11, 16, 17]:
|
||||
self.assert_image_equal(im, im._new(
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, size))))
|
||||
self.assert_image_equal(
|
||||
im,
|
||||
im._new(
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, size)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
# Not so fast
|
||||
self.assert_image_equal(im, im._new(
|
||||
im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
*self.generate_identity_table(3, (2, 2, 65)))))
|
||||
self.assert_image_equal(
|
||||
im,
|
||||
im._new(
|
||||
im.im.color_lut_3d(
|
||||
"RGB", Image.LINEAR, *self.generate_identity_table(3, (2, 2, 65))
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_identities_4_channels(self):
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)]
|
||||
)
|
||||
|
||||
# Red channel copied to alpha
|
||||
self.assert_image_equal(
|
||||
Image.merge('RGBA', (im.split()*2)[:4]),
|
||||
im._new(im.im.color_lut_3d('RGBA', Image.LINEAR,
|
||||
*self.generate_identity_table(4, 17))))
|
||||
Image.merge("RGBA", (im.split() * 2)[:4]),
|
||||
im._new(
|
||||
im.im.color_lut_3d(
|
||||
"RGBA", Image.LINEAR, *self.generate_identity_table(4, 17)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_copy_alpha_channel(self):
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGBA', [g, g.transpose(Image.ROTATE_90),
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGBA",
|
||||
[
|
||||
g,
|
||||
g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180),
|
||||
g.transpose(Image.ROTATE_270)])
|
||||
g.transpose(Image.ROTATE_270),
|
||||
],
|
||||
)
|
||||
|
||||
self.assert_image_equal(im, im._new(
|
||||
im.im.color_lut_3d('RGBA', Image.LINEAR,
|
||||
*self.generate_identity_table(3, 17))))
|
||||
self.assert_image_equal(
|
||||
im,
|
||||
im._new(
|
||||
im.im.color_lut_3d(
|
||||
"RGBA", Image.LINEAR, *self.generate_identity_table(3, 17)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def test_channels_order(self):
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)]
|
||||
)
|
||||
|
||||
# Reverse channels by splitting and using table
|
||||
# fmt: off
|
||||
self.assert_image_equal(
|
||||
Image.merge('RGB', im.split()[::-1]),
|
||||
im._new(im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
|
@ -209,12 +221,15 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
1, 0, 0, 1, 0, 1,
|
||||
1, 1, 0, 1, 1, 1,
|
||||
])))
|
||||
# fmt: on
|
||||
|
||||
def test_overflow(self):
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)]
|
||||
)
|
||||
|
||||
# fmt: off
|
||||
transformed = im._new(im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
3, 2, 2, 2,
|
||||
[
|
||||
|
@ -224,6 +239,7 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
-1, -1, 2, 2, -1, 2,
|
||||
-1, 2, 2, 2, 2, 2,
|
||||
])).load()
|
||||
# fmt: on
|
||||
self.assertEqual(transformed[0, 0], (0, 0, 255))
|
||||
self.assertEqual(transformed[50, 50], (0, 0, 255))
|
||||
self.assertEqual(transformed[255, 0], (0, 255, 255))
|
||||
|
@ -233,6 +249,7 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
self.assertEqual(transformed[255, 255], (255, 255, 0))
|
||||
self.assertEqual(transformed[205, 205], (255, 255, 0))
|
||||
|
||||
# fmt: off
|
||||
transformed = im._new(im.im.color_lut_3d('RGB', Image.LINEAR,
|
||||
3, 2, 2, 2,
|
||||
[
|
||||
|
@ -242,6 +259,7 @@ class TestColorLut3DCoreAPI(PillowTestCase):
|
|||
-3, -3, 5, 5, -3, 5,
|
||||
-3, 5, 5, 5, 5, 5,
|
||||
])).load()
|
||||
# fmt: on
|
||||
self.assertEqual(transformed[0, 0], (0, 0, 255))
|
||||
self.assertEqual(transformed[50, 50], (0, 0, 255))
|
||||
self.assertEqual(transformed[255, 0], (0, 255, 255))
|
||||
|
@ -286,14 +304,15 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
self.assertEqual(tuple(lut.size), (2, 2, 2))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
|
||||
# fmt: off
|
||||
lut = ImageFilter.Color3DLUT((2, 2, 2), [
|
||||
(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11),
|
||||
(12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23)])
|
||||
# fmt: on
|
||||
self.assertEqual(tuple(lut.size), (2, 2, 2))
|
||||
self.assertEqual(lut.table, list(range(24)))
|
||||
|
||||
lut = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8,
|
||||
channels=4)
|
||||
lut = ImageFilter.Color3DLUT((2, 2, 2), [(0, 1, 2, 3)] * 8, channels=4)
|
||||
self.assertEqual(tuple(lut.size), (2, 2, 2))
|
||||
self.assertEqual(lut.table, list(range(4)) * 8)
|
||||
|
||||
|
@ -318,7 +337,7 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
self.assertEqual(lut.table.shape, (table.size,))
|
||||
|
||||
# Check application
|
||||
Image.new('RGB', (10, 10), 0).filter(lut)
|
||||
Image.new("RGB", (10, 10), 0).filter(lut)
|
||||
|
||||
# Check copy
|
||||
table[0] = 33
|
||||
|
@ -332,40 +351,34 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
|
||||
@unittest.skipIf(numpy is None, "Numpy is not installed")
|
||||
def test_numpy_formats(self):
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)]
|
||||
)
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
|
||||
lambda r, g, b: (r, g, b))
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float32)[:-1]
|
||||
with self.assertRaisesRegex(ValueError, "should have table_channels"):
|
||||
im.filter(lut)
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
|
||||
lambda r, g, b: (r, g, b))
|
||||
lut.table = (numpy.array(lut.table, dtype=numpy.float32)
|
||||
.reshape((7 * 9 * 11), 3))
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float32).reshape((7 * 9 * 11), 3)
|
||||
with self.assertRaisesRegex(ValueError, "should have table_channels"):
|
||||
im.filter(lut)
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
|
||||
lambda r, g, b: (r, g, b))
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float16)
|
||||
self.assert_image_equal(im, im.filter(lut))
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
|
||||
lambda r, g, b: (r, g, b))
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float32)
|
||||
self.assert_image_equal(im, im.filter(lut))
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
|
||||
lambda r, g, b: (r, g, b))
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.float64)
|
||||
self.assert_image_equal(im, im.filter(lut))
|
||||
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
|
||||
lambda r, g, b: (r, g, b))
|
||||
lut = ImageFilter.Color3DLUT.generate((7, 9, 11), lambda r, g, b: (r, g, b))
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.int32)
|
||||
im.filter(lut)
|
||||
lut.table = numpy.array(lut.table, dtype=numpy.int8)
|
||||
|
@ -373,54 +386,65 @@ class TestColorLut3DFilter(PillowTestCase):
|
|||
|
||||
def test_repr(self):
|
||||
lut = ImageFilter.Color3DLUT(2, [0, 1, 2] * 8)
|
||||
self.assertEqual(repr(lut),
|
||||
"<Color3DLUT from list size=2x2x2 channels=3>")
|
||||
self.assertEqual(repr(lut), "<Color3DLUT from list size=2x2x2 channels=3>")
|
||||
|
||||
lut = ImageFilter.Color3DLUT(
|
||||
(3, 4, 5), array('f', [0, 0, 0, 0] * (3 * 4 * 5)),
|
||||
channels=4, target_mode='YCbCr', _copy_table=False)
|
||||
(3, 4, 5),
|
||||
array("f", [0, 0, 0, 0] * (3 * 4 * 5)),
|
||||
channels=4,
|
||||
target_mode="YCbCr",
|
||||
_copy_table=False,
|
||||
)
|
||||
self.assertEqual(
|
||||
repr(lut),
|
||||
"<Color3DLUT from array size=3x4x5 channels=4 target_mode=YCbCr>")
|
||||
repr(lut), "<Color3DLUT from array size=3x4x5 channels=4 target_mode=YCbCr>"
|
||||
)
|
||||
|
||||
|
||||
class TestGenerateColorLut3D(PillowTestCase):
|
||||
def test_wrong_channels_count(self):
|
||||
with self.assertRaisesRegex(ValueError, "3 or 4 output channels"):
|
||||
ImageFilter.Color3DLUT.generate(
|
||||
5, channels=2, callback=lambda r, g, b: (r, g, b))
|
||||
5, channels=2, callback=lambda r, g, b: (r, g, b)
|
||||
)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b, r))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "should have either channels"):
|
||||
ImageFilter.Color3DLUT.generate(
|
||||
5, channels=4, callback=lambda r, g, b: (r, g, b))
|
||||
5, channels=4, callback=lambda r, g, b: (r, g, b)
|
||||
)
|
||||
|
||||
def test_3_channels(self):
|
||||
lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
|
||||
self.assertEqual(tuple(lut.size), (5, 5, 5))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[:24], [
|
||||
0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.75, 0.0, 0.0,
|
||||
1.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, 0.25, 0.0, 0.5, 0.25, 0.0])
|
||||
# fmt: on
|
||||
|
||||
def test_4_channels(self):
|
||||
lut = ImageFilter.Color3DLUT.generate(
|
||||
5, channels=4, callback=lambda r, g, b: (b, r, g, (r+g+b) / 2))
|
||||
5, channels=4, callback=lambda r, g, b: (b, r, g, (r + g + b) / 2)
|
||||
)
|
||||
self.assertEqual(tuple(lut.size), (5, 5, 5))
|
||||
self.assertEqual(lut.name, "Color 3D LUT")
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[:24], [
|
||||
0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.125, 0.0, 0.5, 0.0, 0.25,
|
||||
0.0, 0.75, 0.0, 0.375, 0.0, 1.0, 0.0, 0.5, 0.0, 0.0, 0.25, 0.125
|
||||
])
|
||||
# fmt: on
|
||||
|
||||
def test_apply(self):
|
||||
lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))
|
||||
|
||||
g = Image.linear_gradient('L')
|
||||
im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
|
||||
g.transpose(Image.ROTATE_180)])
|
||||
g = Image.linear_gradient("L")
|
||||
im = Image.merge(
|
||||
"RGB", [g, g.transpose(Image.ROTATE_90), g.transpose(Image.ROTATE_180)]
|
||||
)
|
||||
self.assertEqual(im, im.filter(lut))
|
||||
|
||||
|
||||
|
@ -442,80 +466,96 @@ class TestTransformColorLut3D(PillowTestCase):
|
|||
|
||||
def test_target_mode(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
2, lambda r, g, b: (r, g, b), target_mode='HSV')
|
||||
2, lambda r, g, b: (r, g, b), target_mode="HSV"
|
||||
)
|
||||
|
||||
lut = source.transform(lambda r, g, b: (r, g, b))
|
||||
self.assertEqual(lut.mode, 'HSV')
|
||||
self.assertEqual(lut.mode, "HSV")
|
||||
|
||||
lut = source.transform(lambda r, g, b: (r, g, b), target_mode='RGB')
|
||||
self.assertEqual(lut.mode, 'RGB')
|
||||
lut = source.transform(lambda r, g, b: (r, g, b), target_mode="RGB")
|
||||
self.assertEqual(lut.mode, "RGB")
|
||||
|
||||
def test_3_to_3_channels(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
(3, 4, 5), lambda r, g, b: (r, g, b))
|
||||
lut = source.transform(lambda r, g, b: (r*r, g*g, b*b))
|
||||
source = ImageFilter.Color3DLUT.generate((3, 4, 5), lambda r, g, b: (r, g, b))
|
||||
lut = source.transform(lambda r, g, b: (r * r, g * g, b * b))
|
||||
self.assertEqual(tuple(lut.size), tuple(source.size))
|
||||
self.assertEqual(len(lut.table), len(source.table))
|
||||
self.assertNotEqual(lut.table, source.table)
|
||||
self.assertEqual(lut.table[0:10], [
|
||||
0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0])
|
||||
self.assertEqual(
|
||||
lut.table[0:10], [0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
|
||||
)
|
||||
|
||||
def test_3_to_4_channels(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
(6, 5, 4), lambda r, g, b: (r, g, b))
|
||||
lut = source.transform(lambda r, g, b: (r*r, g*g, b*b, 1), channels=4)
|
||||
source = ImageFilter.Color3DLUT.generate((6, 5, 4), lambda r, g, b: (r, g, b))
|
||||
lut = source.transform(lambda r, g, b: (r * r, g * g, b * b, 1), channels=4)
|
||||
self.assertEqual(tuple(lut.size), tuple(source.size))
|
||||
self.assertNotEqual(len(lut.table), len(source.table))
|
||||
self.assertNotEqual(lut.table, source.table)
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[0:16], [
|
||||
0.0, 0.0, 0.0, 1, 0.2**2, 0.0, 0.0, 1,
|
||||
0.4**2, 0.0, 0.0, 1, 0.6**2, 0.0, 0.0, 1])
|
||||
# fmt: on
|
||||
|
||||
def test_4_to_3_channels(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
(3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4)
|
||||
lut = source.transform(lambda r, g, b, a: (a - r*r, a - g*g, a - b*b),
|
||||
channels=3)
|
||||
(3, 6, 5), lambda r, g, b: (r, g, b, 1), channels=4
|
||||
)
|
||||
lut = source.transform(
|
||||
lambda r, g, b, a: (a - r * r, a - g * g, a - b * b), channels=3
|
||||
)
|
||||
self.assertEqual(tuple(lut.size), tuple(source.size))
|
||||
self.assertNotEqual(len(lut.table), len(source.table))
|
||||
self.assertNotEqual(lut.table, source.table)
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[0:18], [
|
||||
1.0, 1.0, 1.0, 0.75, 1.0, 1.0, 0.0, 1.0, 1.0,
|
||||
1.0, 0.96, 1.0, 0.75, 0.96, 1.0, 0.0, 0.96, 1.0])
|
||||
# fmt: on
|
||||
|
||||
def test_4_to_4_channels(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
(6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4)
|
||||
lut = source.transform(lambda r, g, b, a: (r*r, g*g, b*b, a - 0.5))
|
||||
(6, 5, 4), lambda r, g, b: (r, g, b, 1), channels=4
|
||||
)
|
||||
lut = source.transform(lambda r, g, b, a: (r * r, g * g, b * b, a - 0.5))
|
||||
self.assertEqual(tuple(lut.size), tuple(source.size))
|
||||
self.assertEqual(len(lut.table), len(source.table))
|
||||
self.assertNotEqual(lut.table, source.table)
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[0:16], [
|
||||
0.0, 0.0, 0.0, 0.5, 0.2**2, 0.0, 0.0, 0.5,
|
||||
0.4**2, 0.0, 0.0, 0.5, 0.6**2, 0.0, 0.0, 0.5])
|
||||
# fmt: on
|
||||
|
||||
def test_with_normals_3_channels(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
(6, 5, 4), lambda r, g, b: (r*r, g*g, b*b))
|
||||
(6, 5, 4), lambda r, g, b: (r * r, g * g, b * b)
|
||||
)
|
||||
lut = source.transform(
|
||||
lambda nr, ng, nb, r, g, b: (nr - r, ng - g, nb - b),
|
||||
with_normals=True)
|
||||
lambda nr, ng, nb, r, g, b: (nr - r, ng - g, nb - b), with_normals=True
|
||||
)
|
||||
self.assertEqual(tuple(lut.size), tuple(source.size))
|
||||
self.assertEqual(len(lut.table), len(source.table))
|
||||
self.assertNotEqual(lut.table, source.table)
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[0:18], [
|
||||
0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.24, 0.0, 0.0,
|
||||
0.24, 0.0, 0.0, 0.8 - (0.8**2), 0, 0, 0, 0, 0])
|
||||
# fmt: on
|
||||
|
||||
def test_with_normals_4_channels(self):
|
||||
source = ImageFilter.Color3DLUT.generate(
|
||||
(3, 6, 5), lambda r, g, b: (r*r, g*g, b*b, 1), channels=4)
|
||||
(3, 6, 5), lambda r, g, b: (r * r, g * g, b * b, 1), channels=4
|
||||
)
|
||||
lut = source.transform(
|
||||
lambda nr, ng, nb, r, g, b, a: (nr - r, ng - g, nb - b, a-0.5),
|
||||
with_normals=True)
|
||||
lambda nr, ng, nb, r, g, b, a: (nr - r, ng - g, nb - b, a - 0.5),
|
||||
with_normals=True,
|
||||
)
|
||||
self.assertEqual(tuple(lut.size), tuple(source.size))
|
||||
self.assertEqual(len(lut.table), len(source.table))
|
||||
self.assertNotEqual(lut.table, source.table)
|
||||
# fmt: off
|
||||
self.assertEqual(lut.table[0:16], [
|
||||
0.0, 0.0, 0.0, 0.5, 0.25, 0.0, 0.0, 0.5,
|
||||
0.0, 0.0, 0.0, 0.5, 0.0, 0.16, 0.0, 0.5])
|
||||
# fmt: on
|
||||
|
|
|
@ -6,39 +6,39 @@ from .helper import unittest, PillowTestCase
|
|||
from PIL import Image
|
||||
|
||||
|
||||
is_pypy = hasattr(sys, 'pypy_version_info')
|
||||
is_pypy = hasattr(sys, "pypy_version_info")
|
||||
|
||||
|
||||
class TestCoreStats(PillowTestCase):
|
||||
def test_get_stats(self):
|
||||
# Create at least one image
|
||||
Image.new('RGB', (10, 10))
|
||||
Image.new("RGB", (10, 10))
|
||||
|
||||
stats = Image.core.get_stats()
|
||||
self.assertIn('new_count', stats)
|
||||
self.assertIn('reused_blocks', stats)
|
||||
self.assertIn('freed_blocks', stats)
|
||||
self.assertIn('allocated_blocks', stats)
|
||||
self.assertIn('reallocated_blocks', stats)
|
||||
self.assertIn('blocks_cached', stats)
|
||||
self.assertIn("new_count", stats)
|
||||
self.assertIn("reused_blocks", stats)
|
||||
self.assertIn("freed_blocks", stats)
|
||||
self.assertIn("allocated_blocks", stats)
|
||||
self.assertIn("reallocated_blocks", stats)
|
||||
self.assertIn("blocks_cached", stats)
|
||||
|
||||
def test_reset_stats(self):
|
||||
Image.core.reset_stats()
|
||||
|
||||
stats = Image.core.get_stats()
|
||||
self.assertEqual(stats['new_count'], 0)
|
||||
self.assertEqual(stats['reused_blocks'], 0)
|
||||
self.assertEqual(stats['freed_blocks'], 0)
|
||||
self.assertEqual(stats['allocated_blocks'], 0)
|
||||
self.assertEqual(stats['reallocated_blocks'], 0)
|
||||
self.assertEqual(stats['blocks_cached'], 0)
|
||||
self.assertEqual(stats["new_count"], 0)
|
||||
self.assertEqual(stats["reused_blocks"], 0)
|
||||
self.assertEqual(stats["freed_blocks"], 0)
|
||||
self.assertEqual(stats["allocated_blocks"], 0)
|
||||
self.assertEqual(stats["reallocated_blocks"], 0)
|
||||
self.assertEqual(stats["blocks_cached"], 0)
|
||||
|
||||
|
||||
class TestCoreMemory(PillowTestCase):
|
||||
def tearDown(self):
|
||||
# Restore default values
|
||||
Image.core.set_alignment(1)
|
||||
Image.core.set_block_size(1024*1024)
|
||||
Image.core.set_block_size(1024 * 1024)
|
||||
Image.core.set_blocks_max(0)
|
||||
Image.core.clear_cache()
|
||||
|
||||
|
@ -54,7 +54,7 @@ class TestCoreMemory(PillowTestCase):
|
|||
self.assertEqual(alignment, i)
|
||||
|
||||
# Try to construct new image
|
||||
Image.new('RGB', (10, 10))
|
||||
Image.new("RGB", (10, 10))
|
||||
|
||||
self.assertRaises(ValueError, Image.core.set_alignment, 0)
|
||||
self.assertRaises(ValueError, Image.core.set_alignment, -1)
|
||||
|
@ -66,13 +66,13 @@ class TestCoreMemory(PillowTestCase):
|
|||
self.assertGreaterEqual(block_size, 4096)
|
||||
|
||||
def test_set_block_size(self):
|
||||
for i in [4096, 2*4096, 3*4096]:
|
||||
for i in [4096, 2 * 4096, 3 * 4096]:
|
||||
Image.core.set_block_size(i)
|
||||
block_size = Image.core.get_block_size()
|
||||
self.assertEqual(block_size, i)
|
||||
|
||||
# Try to construct new image
|
||||
Image.new('RGB', (10, 10))
|
||||
Image.new("RGB", (10, 10))
|
||||
|
||||
self.assertRaises(ValueError, Image.core.set_block_size, 0)
|
||||
self.assertRaises(ValueError, Image.core.set_block_size, -1)
|
||||
|
@ -82,13 +82,13 @@ class TestCoreMemory(PillowTestCase):
|
|||
Image.core.reset_stats()
|
||||
Image.core.set_blocks_max(0)
|
||||
Image.core.set_block_size(4096)
|
||||
Image.new('RGB', (256, 256))
|
||||
Image.new("RGB", (256, 256))
|
||||
|
||||
stats = Image.core.get_stats()
|
||||
self.assertGreaterEqual(stats['new_count'], 1)
|
||||
self.assertGreaterEqual(stats['allocated_blocks'], 64)
|
||||
self.assertGreaterEqual(stats["new_count"], 1)
|
||||
self.assertGreaterEqual(stats["allocated_blocks"], 64)
|
||||
if not is_pypy:
|
||||
self.assertGreaterEqual(stats['freed_blocks'], 64)
|
||||
self.assertGreaterEqual(stats["freed_blocks"], 64)
|
||||
|
||||
def test_get_blocks_max(self):
|
||||
blocks_max = Image.core.get_blocks_max()
|
||||
|
@ -102,7 +102,7 @@ class TestCoreMemory(PillowTestCase):
|
|||
self.assertEqual(blocks_max, i)
|
||||
|
||||
# Try to construct new image
|
||||
Image.new('RGB', (10, 10))
|
||||
Image.new("RGB", (10, 10))
|
||||
|
||||
self.assertRaises(ValueError, Image.core.set_blocks_max, -1)
|
||||
|
||||
|
@ -111,15 +111,15 @@ class TestCoreMemory(PillowTestCase):
|
|||
Image.core.reset_stats()
|
||||
Image.core.set_blocks_max(128)
|
||||
Image.core.set_block_size(4096)
|
||||
Image.new('RGB', (256, 256))
|
||||
Image.new('RGB', (256, 256))
|
||||
Image.new("RGB", (256, 256))
|
||||
Image.new("RGB", (256, 256))
|
||||
|
||||
stats = Image.core.get_stats()
|
||||
self.assertGreaterEqual(stats['new_count'], 2)
|
||||
self.assertGreaterEqual(stats['allocated_blocks'], 64)
|
||||
self.assertGreaterEqual(stats['reused_blocks'], 64)
|
||||
self.assertEqual(stats['freed_blocks'], 0)
|
||||
self.assertEqual(stats['blocks_cached'], 64)
|
||||
self.assertGreaterEqual(stats["new_count"], 2)
|
||||
self.assertGreaterEqual(stats["allocated_blocks"], 64)
|
||||
self.assertGreaterEqual(stats["reused_blocks"], 64)
|
||||
self.assertEqual(stats["freed_blocks"], 0)
|
||||
self.assertEqual(stats["blocks_cached"], 64)
|
||||
|
||||
@unittest.skipIf(is_pypy, "images are not collected")
|
||||
def test_clear_cache_stats(self):
|
||||
|
@ -127,55 +127,55 @@ class TestCoreMemory(PillowTestCase):
|
|||
Image.core.clear_cache()
|
||||
Image.core.set_blocks_max(128)
|
||||
Image.core.set_block_size(4096)
|
||||
Image.new('RGB', (256, 256))
|
||||
Image.new('RGB', (256, 256))
|
||||
Image.new("RGB", (256, 256))
|
||||
Image.new("RGB", (256, 256))
|
||||
# Keep 16 blocks in cache
|
||||
Image.core.clear_cache(16)
|
||||
|
||||
stats = Image.core.get_stats()
|
||||
self.assertGreaterEqual(stats['new_count'], 2)
|
||||
self.assertGreaterEqual(stats['allocated_blocks'], 64)
|
||||
self.assertGreaterEqual(stats['reused_blocks'], 64)
|
||||
self.assertGreaterEqual(stats['freed_blocks'], 48)
|
||||
self.assertEqual(stats['blocks_cached'], 16)
|
||||
self.assertGreaterEqual(stats["new_count"], 2)
|
||||
self.assertGreaterEqual(stats["allocated_blocks"], 64)
|
||||
self.assertGreaterEqual(stats["reused_blocks"], 64)
|
||||
self.assertGreaterEqual(stats["freed_blocks"], 48)
|
||||
self.assertEqual(stats["blocks_cached"], 16)
|
||||
|
||||
def test_large_images(self):
|
||||
Image.core.reset_stats()
|
||||
Image.core.set_blocks_max(0)
|
||||
Image.core.set_block_size(4096)
|
||||
Image.new('RGB', (2048, 16))
|
||||
Image.new("RGB", (2048, 16))
|
||||
Image.core.clear_cache()
|
||||
|
||||
stats = Image.core.get_stats()
|
||||
self.assertGreaterEqual(stats['new_count'], 1)
|
||||
self.assertGreaterEqual(stats['allocated_blocks'], 16)
|
||||
self.assertGreaterEqual(stats['reused_blocks'], 0)
|
||||
self.assertEqual(stats['blocks_cached'], 0)
|
||||
self.assertGreaterEqual(stats["new_count"], 1)
|
||||
self.assertGreaterEqual(stats["allocated_blocks"], 16)
|
||||
self.assertGreaterEqual(stats["reused_blocks"], 0)
|
||||
self.assertEqual(stats["blocks_cached"], 0)
|
||||
if not is_pypy:
|
||||
self.assertGreaterEqual(stats['freed_blocks'], 16)
|
||||
self.assertGreaterEqual(stats["freed_blocks"], 16)
|
||||
|
||||
|
||||
class TestEnvVars(PillowTestCase):
|
||||
def tearDown(self):
|
||||
# Restore default values
|
||||
Image.core.set_alignment(1)
|
||||
Image.core.set_block_size(1024*1024)
|
||||
Image.core.set_block_size(1024 * 1024)
|
||||
Image.core.set_blocks_max(0)
|
||||
Image.core.clear_cache()
|
||||
|
||||
def test_units(self):
|
||||
Image._apply_env_variables({'PILLOW_BLOCKS_MAX': '2K'})
|
||||
self.assertEqual(Image.core.get_blocks_max(), 2*1024)
|
||||
Image._apply_env_variables({'PILLOW_BLOCK_SIZE': '2m'})
|
||||
self.assertEqual(Image.core.get_block_size(), 2*1024*1024)
|
||||
Image._apply_env_variables({"PILLOW_BLOCKS_MAX": "2K"})
|
||||
self.assertEqual(Image.core.get_blocks_max(), 2 * 1024)
|
||||
Image._apply_env_variables({"PILLOW_BLOCK_SIZE": "2m"})
|
||||
self.assertEqual(Image.core.get_block_size(), 2 * 1024 * 1024)
|
||||
|
||||
def test_warnings(self):
|
||||
self.assert_warning(
|
||||
UserWarning, Image._apply_env_variables,
|
||||
{'PILLOW_ALIGNMENT': '15'})
|
||||
UserWarning, Image._apply_env_variables, {"PILLOW_ALIGNMENT": "15"}
|
||||
)
|
||||
self.assert_warning(
|
||||
UserWarning, Image._apply_env_variables,
|
||||
{'PILLOW_BLOCK_SIZE': '1024'})
|
||||
UserWarning, Image._apply_env_variables, {"PILLOW_BLOCK_SIZE": "1024"}
|
||||
)
|
||||
self.assert_warning(
|
||||
UserWarning, Image._apply_env_variables,
|
||||
{'PILLOW_BLOCKS_MAX': 'wat'})
|
||||
UserWarning, Image._apply_env_variables, {"PILLOW_BLOCKS_MAX": "wat"}
|
||||
)
|
||||
|
|
|
@ -8,7 +8,6 @@ ORIGINAL_LIMIT = Image.MAX_IMAGE_PIXELS
|
|||
|
||||
|
||||
class TestDecompressionBomb(PillowTestCase):
|
||||
|
||||
def tearDown(self):
|
||||
Image.MAX_IMAGE_PIXELS = ORIGINAL_LIMIT
|
||||
|
||||
|
@ -33,20 +32,17 @@ class TestDecompressionBomb(PillowTestCase):
|
|||
Image.MAX_IMAGE_PIXELS = 128 * 128 - 1
|
||||
self.assertEqual(Image.MAX_IMAGE_PIXELS, 128 * 128 - 1)
|
||||
|
||||
self.assert_warning(Image.DecompressionBombWarning,
|
||||
Image.open, TEST_FILE)
|
||||
self.assert_warning(Image.DecompressionBombWarning, Image.open, TEST_FILE)
|
||||
|
||||
def test_exception(self):
|
||||
# Set limit to trigger exception on the test file
|
||||
Image.MAX_IMAGE_PIXELS = 64 * 128 - 1
|
||||
self.assertEqual(Image.MAX_IMAGE_PIXELS, 64 * 128 - 1)
|
||||
|
||||
self.assertRaises(Image.DecompressionBombError,
|
||||
lambda: Image.open(TEST_FILE))
|
||||
self.assertRaises(Image.DecompressionBombError, lambda: Image.open(TEST_FILE))
|
||||
|
||||
|
||||
class TestDecompressionCrop(PillowTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.src = hopper()
|
||||
Image.MAX_IMAGE_PIXELS = self.src.height * self.src.width * 4 - 1
|
||||
|
@ -58,21 +54,17 @@ class TestDecompressionCrop(PillowTestCase):
|
|||
# Crops can extend the extents, therefore we should have the
|
||||
# same decompression bomb warnings on them.
|
||||
box = (0, 0, self.src.width * 2, self.src.height * 2)
|
||||
self.assert_warning(Image.DecompressionBombWarning,
|
||||
self.src.crop, box)
|
||||
self.assert_warning(Image.DecompressionBombWarning, self.src.crop, box)
|
||||
|
||||
def test_crop_decompression_checks(self):
|
||||
|
||||
im = Image.new("RGB", (100, 100))
|
||||
|
||||
good_values = ((-9999, -9999, -9990, -9990),
|
||||
(-999, -999, -990, -990))
|
||||
good_values = ((-9999, -9999, -9990, -9990), (-999, -999, -990, -990))
|
||||
|
||||
warning_values = ((-160, -160, 99, 99),
|
||||
(160, 160, -99, -99))
|
||||
warning_values = ((-160, -160, 99, 99), (160, 160, -99, -99))
|
||||
|
||||
error_values = ((-99909, -99990, 99999, 99999),
|
||||
(99909, 99990, -99999, -99999))
|
||||
error_values = ((-99909, -99990, 99999, 99999), (99909, 99990, -99999, -99999))
|
||||
|
||||
for value in good_values:
|
||||
self.assertEqual(im.crop(value).size, (9, 9))
|
||||
|
|
|
@ -4,41 +4,36 @@ from PIL import features
|
|||
|
||||
try:
|
||||
from PIL import _webp
|
||||
|
||||
HAVE_WEBP = True
|
||||
except ImportError:
|
||||
HAVE_WEBP = False
|
||||
|
||||
|
||||
class TestFeatures(PillowTestCase):
|
||||
|
||||
def test_check(self):
|
||||
# Check the correctness of the convenience function
|
||||
for module in features.modules:
|
||||
self.assertEqual(features.check_module(module),
|
||||
features.check(module))
|
||||
self.assertEqual(features.check_module(module), features.check(module))
|
||||
for codec in features.codecs:
|
||||
self.assertEqual(features.check_codec(codec),
|
||||
features.check(codec))
|
||||
self.assertEqual(features.check_codec(codec), features.check(codec))
|
||||
for feature in features.features:
|
||||
self.assertEqual(features.check_feature(feature),
|
||||
features.check(feature))
|
||||
self.assertEqual(features.check_feature(feature), features.check(feature))
|
||||
|
||||
@unittest.skipUnless(HAVE_WEBP, "WebP not available")
|
||||
def test_webp_transparency(self):
|
||||
self.assertEqual(features.check('transp_webp'),
|
||||
not _webp.WebPDecoderBuggyAlpha())
|
||||
self.assertEqual(features.check('transp_webp'),
|
||||
_webp.HAVE_TRANSPARENCY)
|
||||
self.assertEqual(
|
||||
features.check("transp_webp"), not _webp.WebPDecoderBuggyAlpha()
|
||||
)
|
||||
self.assertEqual(features.check("transp_webp"), _webp.HAVE_TRANSPARENCY)
|
||||
|
||||
@unittest.skipUnless(HAVE_WEBP, "WebP not available")
|
||||
def test_webp_mux(self):
|
||||
self.assertEqual(features.check('webp_mux'),
|
||||
_webp.HAVE_WEBPMUX)
|
||||
self.assertEqual(features.check("webp_mux"), _webp.HAVE_WEBPMUX)
|
||||
|
||||
@unittest.skipUnless(HAVE_WEBP, "WebP not available")
|
||||
def test_webp_anim(self):
|
||||
self.assertEqual(features.check('webp_anim'),
|
||||
_webp.HAVE_WEBPANIM)
|
||||
self.assertEqual(features.check("webp_anim"), _webp.HAVE_WEBPANIM)
|
||||
|
||||
def test_check_modules(self):
|
||||
for feature in features.modules:
|
||||
|
|
|
@ -5,11 +5,10 @@ import io
|
|||
|
||||
|
||||
class TestFileBmp(PillowTestCase):
|
||||
|
||||
def roundtrip(self, im):
|
||||
outfile = self.tempfile("temp.bmp")
|
||||
|
||||
im.save(outfile, 'BMP')
|
||||
im.save(outfile, "BMP")
|
||||
|
||||
reloaded = Image.open(outfile)
|
||||
reloaded.load()
|
||||
|
@ -28,8 +27,7 @@ class TestFileBmp(PillowTestCase):
|
|||
|
||||
def test_invalid_file(self):
|
||||
with open("Tests/images/flower.jpg", "rb") as fp:
|
||||
self.assertRaises(SyntaxError,
|
||||
BmpImagePlugin.BmpImageFile, fp)
|
||||
self.assertRaises(SyntaxError, BmpImagePlugin.BmpImageFile, fp)
|
||||
|
||||
def test_save_to_bytes(self):
|
||||
output = io.BytesIO()
|
||||
|
@ -62,27 +60,27 @@ class TestFileBmp(PillowTestCase):
|
|||
im = Image.open("Tests/images/hopper.bmp")
|
||||
|
||||
# Act
|
||||
im.save(outfile, 'JPEG', dpi=im.info['dpi'])
|
||||
im.save(outfile, "JPEG", dpi=im.info["dpi"])
|
||||
|
||||
# Assert
|
||||
reloaded = Image.open(outfile)
|
||||
reloaded.load()
|
||||
self.assertEqual(im.info['dpi'], reloaded.info['dpi'])
|
||||
self.assertEqual(im.info["dpi"], reloaded.info["dpi"])
|
||||
self.assertEqual(im.size, reloaded.size)
|
||||
self.assertEqual(reloaded.format, "JPEG")
|
||||
|
||||
def test_load_dpi_rounding(self):
|
||||
# Round up
|
||||
im = Image.open('Tests/images/hopper.bmp')
|
||||
im = Image.open("Tests/images/hopper.bmp")
|
||||
self.assertEqual(im.info["dpi"], (96, 96))
|
||||
|
||||
# Round down
|
||||
im = Image.open('Tests/images/hopper_roundDown.bmp')
|
||||
im = Image.open("Tests/images/hopper_roundDown.bmp")
|
||||
self.assertEqual(im.info["dpi"], (72, 72))
|
||||
|
||||
def test_save_dpi_rounding(self):
|
||||
outfile = self.tempfile("temp.bmp")
|
||||
im = Image.open('Tests/images/hopper.bmp')
|
||||
im = Image.open("Tests/images/hopper.bmp")
|
||||
|
||||
im.save(outfile, dpi=(72.2, 72.2))
|
||||
reloaded = Image.open(outfile)
|
||||
|
@ -94,17 +92,17 @@ class TestFileBmp(PillowTestCase):
|
|||
|
||||
def test_load_dib(self):
|
||||
# test for #1293, Imagegrab returning Unsupported Bitfields Format
|
||||
im = Image.open('Tests/images/clipboard.dib')
|
||||
im = Image.open("Tests/images/clipboard.dib")
|
||||
self.assertEqual(im.format, "DIB")
|
||||
self.assertEqual(im.get_format_mimetype(), "image/bmp")
|
||||
|
||||
target = Image.open('Tests/images/clipboard_target.png')
|
||||
target = Image.open("Tests/images/clipboard_target.png")
|
||||
self.assert_image_equal(im, target)
|
||||
|
||||
def test_save_dib(self):
|
||||
outfile = self.tempfile("temp.dib")
|
||||
|
||||
im = Image.open('Tests/images/clipboard.dib')
|
||||
im = Image.open("Tests/images/clipboard.dib")
|
||||
im.save(outfile)
|
||||
|
||||
reloaded = Image.open(outfile)
|
||||
|
|
|
@ -6,7 +6,6 @@ TEST_FILE = "Tests/images/gfs.t06z.rassda.tm00.bufr_d"
|
|||
|
||||
|
||||
class TestFileBufrStub(PillowTestCase):
|
||||
|
||||
def test_open(self):
|
||||
# Act
|
||||
im = Image.open(TEST_FILE)
|
||||
|
@ -23,8 +22,9 @@ class TestFileBufrStub(PillowTestCase):
|
|||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
# Act / Assert
|
||||
self.assertRaises(SyntaxError,
|
||||
BufrStubImagePlugin.BufrStubImageFile, invalid_file)
|
||||
self.assertRaises(
|
||||
SyntaxError, BufrStubImagePlugin.BufrStubImageFile, invalid_file
|
||||
)
|
||||
|
||||
def test_load(self):
|
||||
# Arrange
|
||||
|
|
|
@ -7,7 +7,6 @@ TEST_FILE = "Tests/images/dummy.container"
|
|||
|
||||
|
||||
class TestFileContainer(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
dir(Image)
|
||||
dir(ContainerIO)
|
||||
|
@ -106,14 +105,16 @@ class TestFileContainer(PillowTestCase):
|
|||
|
||||
def test_readlines(self):
|
||||
# Arrange
|
||||
expected = ["This is line 1\n",
|
||||
expected = [
|
||||
"This is line 1\n",
|
||||
"This is line 2\n",
|
||||
"This is line 3\n",
|
||||
"This is line 4\n",
|
||||
"This is line 5\n",
|
||||
"This is line 6\n",
|
||||
"This is line 7\n",
|
||||
"This is line 8\n"]
|
||||
"This is line 8\n",
|
||||
]
|
||||
with open(TEST_FILE) as fh:
|
||||
container = ContainerIO.ContainerIO(fh, 0, 120)
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ TEST_FILE = "Tests/images/deerstalker.cur"
|
|||
|
||||
|
||||
class TestFileCur(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
im = Image.open(TEST_FILE)
|
||||
|
||||
|
@ -20,8 +19,7 @@ class TestFileCur(PillowTestCase):
|
|||
def test_invalid_file(self):
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
self.assertRaises(SyntaxError,
|
||||
CurImagePlugin.CurImageFile, invalid_file)
|
||||
self.assertRaises(SyntaxError, CurImagePlugin.CurImageFile, invalid_file)
|
||||
|
||||
no_cursors_file = "Tests/images/no_cursors.cur"
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ TEST_FILE = "Tests/images/hopper.dcx"
|
|||
|
||||
|
||||
class TestFileDcx(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
# Arrange
|
||||
|
||||
|
@ -24,12 +23,12 @@ class TestFileDcx(PillowTestCase):
|
|||
def open():
|
||||
im = Image.open(TEST_FILE)
|
||||
im.load()
|
||||
|
||||
self.assert_warning(None, open)
|
||||
|
||||
def test_invalid_file(self):
|
||||
with open("Tests/images/flower.jpg", "rb") as fp:
|
||||
self.assertRaises(SyntaxError,
|
||||
DcxImagePlugin.DcxImageFile, fp)
|
||||
self.assertRaises(SyntaxError, DcxImagePlugin.DcxImageFile, fp)
|
||||
|
||||
def test_tell(self):
|
||||
# Arrange
|
||||
|
@ -55,7 +54,7 @@ class TestFileDcx(PillowTestCase):
|
|||
self.assertLess(im.tell(), n_frames)
|
||||
|
||||
# Test that seeking to the last frame does not raise an error
|
||||
im.seek(n_frames-1)
|
||||
im.seek(n_frames - 1)
|
||||
|
||||
def test_seek_too_far(self):
|
||||
# Arrange
|
||||
|
|
|
@ -15,7 +15,7 @@ class TestFileDds(PillowTestCase):
|
|||
|
||||
def test_sanity_dxt1(self):
|
||||
"""Check DXT1 images can be opened"""
|
||||
target = Image.open(TEST_FILE_DXT1.replace('.dds', '.png'))
|
||||
target = Image.open(TEST_FILE_DXT1.replace(".dds", ".png"))
|
||||
|
||||
im = Image.open(TEST_FILE_DXT1)
|
||||
im.load()
|
||||
|
@ -24,12 +24,12 @@ class TestFileDds(PillowTestCase):
|
|||
self.assertEqual(im.mode, "RGBA")
|
||||
self.assertEqual(im.size, (256, 256))
|
||||
|
||||
self.assert_image_equal(target.convert('RGBA'), im)
|
||||
self.assert_image_equal(target.convert("RGBA"), im)
|
||||
|
||||
def test_sanity_dxt5(self):
|
||||
"""Check DXT5 images can be opened"""
|
||||
|
||||
target = Image.open(TEST_FILE_DXT5.replace('.dds', '.png'))
|
||||
target = Image.open(TEST_FILE_DXT5.replace(".dds", ".png"))
|
||||
|
||||
im = Image.open(TEST_FILE_DXT5)
|
||||
im.load()
|
||||
|
@ -43,7 +43,7 @@ class TestFileDds(PillowTestCase):
|
|||
def test_sanity_dxt3(self):
|
||||
"""Check DXT3 images can be opened"""
|
||||
|
||||
target = Image.open(TEST_FILE_DXT3.replace('.dds', '.png'))
|
||||
target = Image.open(TEST_FILE_DXT3.replace(".dds", ".png"))
|
||||
|
||||
im = Image.open(TEST_FILE_DXT3)
|
||||
im.load()
|
||||
|
@ -57,7 +57,7 @@ class TestFileDds(PillowTestCase):
|
|||
def test_dx10_bc7(self):
|
||||
"""Check DX10 images can be opened"""
|
||||
|
||||
target = Image.open(TEST_FILE_DX10_BC7.replace('.dds', '.png'))
|
||||
target = Image.open(TEST_FILE_DX10_BC7.replace(".dds", ".png"))
|
||||
|
||||
im = Image.open(TEST_FILE_DX10_BC7)
|
||||
im.load()
|
||||
|
@ -69,13 +69,16 @@ class TestFileDds(PillowTestCase):
|
|||
self.assert_image_equal(target, im)
|
||||
|
||||
def test_unimplemented_dxgi_format(self):
|
||||
self.assertRaises(NotImplementedError, Image.open,
|
||||
"Tests/images/unimplemented_dxgi_format.dds")
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
Image.open,
|
||||
"Tests/images/unimplemented_dxgi_format.dds",
|
||||
)
|
||||
|
||||
def test_uncompressed_rgb(self):
|
||||
"""Check uncompressed RGB images can be opened"""
|
||||
|
||||
target = Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace('.dds', '.png'))
|
||||
target = Image.open(TEST_FILE_UNCOMPRESSED_RGB.replace(".dds", ".png"))
|
||||
|
||||
im = Image.open(TEST_FILE_UNCOMPRESSED_RGB)
|
||||
im.load()
|
||||
|
@ -110,7 +113,7 @@ class TestFileDds(PillowTestCase):
|
|||
|
||||
def test_short_header(self):
|
||||
""" Check a short header"""
|
||||
with open(TEST_FILE_DXT5, 'rb') as f:
|
||||
with open(TEST_FILE_DXT5, "rb") as f:
|
||||
img_file = f.read()
|
||||
|
||||
def short_header():
|
||||
|
@ -121,7 +124,7 @@ class TestFileDds(PillowTestCase):
|
|||
def test_short_file(self):
|
||||
""" Check that the appropriate error is thrown for a short file"""
|
||||
|
||||
with open(TEST_FILE_DXT5, 'rb') as f:
|
||||
with open(TEST_FILE_DXT5, "rb") as f:
|
||||
img_file = f.read()
|
||||
|
||||
def short_file():
|
||||
|
@ -131,5 +134,8 @@ class TestFileDds(PillowTestCase):
|
|||
self.assertRaises(IOError, short_file)
|
||||
|
||||
def test_unimplemented_pixel_format(self):
|
||||
self.assertRaises(NotImplementedError, Image.open,
|
||||
"Tests/images/unimplemented_pixel_format.dds")
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
Image.open,
|
||||
"Tests/images/unimplemented_pixel_format.dds",
|
||||
)
|
||||
|
|
|
@ -21,7 +21,6 @@ file3 = "Tests/images/binary_preview_map.eps"
|
|||
|
||||
|
||||
class TestFileEps(PillowTestCase):
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_sanity(self):
|
||||
# Regular scale
|
||||
|
@ -53,8 +52,7 @@ class TestFileEps(PillowTestCase):
|
|||
def test_invalid_file(self):
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
self.assertRaises(SyntaxError,
|
||||
EpsImagePlugin.EpsImageFile, invalid_file)
|
||||
self.assertRaises(SyntaxError, EpsImagePlugin.EpsImageFile, invalid_file)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_cmyk(self):
|
||||
|
@ -67,8 +65,8 @@ class TestFileEps(PillowTestCase):
|
|||
cmyk_image.load()
|
||||
self.assertEqual(cmyk_image.mode, "RGB")
|
||||
|
||||
if 'jpeg_decoder' in dir(Image.core):
|
||||
target = Image.open('Tests/images/pil_sample_rgb.jpg')
|
||||
if "jpeg_decoder" in dir(Image.core):
|
||||
target = Image.open("Tests/images/pil_sample_rgb.jpg")
|
||||
self.assert_image_similar(cmyk_image, target, 10)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
|
@ -86,19 +84,19 @@ class TestFileEps(PillowTestCase):
|
|||
def test_file_object(self):
|
||||
# issue 479
|
||||
image1 = Image.open(file1)
|
||||
with open(self.tempfile('temp_file.eps'), 'wb') as fh:
|
||||
image1.save(fh, 'EPS')
|
||||
with open(self.tempfile("temp_file.eps"), "wb") as fh:
|
||||
image1.save(fh, "EPS")
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_iobase_object(self):
|
||||
# issue 479
|
||||
image1 = Image.open(file1)
|
||||
with io.open(self.tempfile('temp_iobase.eps'), 'wb') as fh:
|
||||
image1.save(fh, 'EPS')
|
||||
with io.open(self.tempfile("temp_iobase.eps"), "wb") as fh:
|
||||
image1.save(fh, "EPS")
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
def test_bytesio_object(self):
|
||||
with open(file1, 'rb') as f:
|
||||
with open(file1, "rb") as f:
|
||||
img_bytes = io.BytesIO(f.read())
|
||||
|
||||
img = Image.open(img_bytes)
|
||||
|
@ -110,7 +108,7 @@ class TestFileEps(PillowTestCase):
|
|||
|
||||
def test_image_mode_not_supported(self):
|
||||
im = hopper("RGBA")
|
||||
tmpfile = self.tempfile('temp.eps')
|
||||
tmpfile = self.tempfile("temp.eps")
|
||||
self.assertRaises(ValueError, im.save, tmpfile)
|
||||
|
||||
@unittest.skipUnless(HAS_GHOSTSCRIPT, "Ghostscript not available")
|
||||
|
@ -195,33 +193,33 @@ class TestFileEps(PillowTestCase):
|
|||
Image.open(file3)
|
||||
|
||||
def _test_readline(self, t, ending):
|
||||
ending = "Failure with line ending: %s" % ("".join(
|
||||
"%s" % ord(s)
|
||||
for s in ending))
|
||||
self.assertEqual(t.readline().strip('\r\n'), 'something', ending)
|
||||
self.assertEqual(t.readline().strip('\r\n'), 'else', ending)
|
||||
self.assertEqual(t.readline().strip('\r\n'), 'baz', ending)
|
||||
self.assertEqual(t.readline().strip('\r\n'), 'bif', ending)
|
||||
ending = "Failure with line ending: %s" % (
|
||||
"".join("%s" % ord(s) for s in ending)
|
||||
)
|
||||
self.assertEqual(t.readline().strip("\r\n"), "something", ending)
|
||||
self.assertEqual(t.readline().strip("\r\n"), "else", ending)
|
||||
self.assertEqual(t.readline().strip("\r\n"), "baz", ending)
|
||||
self.assertEqual(t.readline().strip("\r\n"), "bif", ending)
|
||||
|
||||
def _test_readline_io_psfile(self, test_string, ending):
|
||||
f = io.BytesIO(test_string.encode('latin-1'))
|
||||
f = io.BytesIO(test_string.encode("latin-1"))
|
||||
t = EpsImagePlugin.PSFile(f)
|
||||
self._test_readline(t, ending)
|
||||
|
||||
def _test_readline_file_psfile(self, test_string, ending):
|
||||
f = self.tempfile('temp.txt')
|
||||
with open(f, 'wb') as w:
|
||||
w.write(test_string.encode('latin-1'))
|
||||
f = self.tempfile("temp.txt")
|
||||
with open(f, "wb") as w:
|
||||
w.write(test_string.encode("latin-1"))
|
||||
|
||||
with open(f, 'rb') as r:
|
||||
with open(f, "rb") as r:
|
||||
t = EpsImagePlugin.PSFile(r)
|
||||
self._test_readline(t, ending)
|
||||
|
||||
def test_readline(self):
|
||||
# check all the freaking line endings possible from the spec
|
||||
# test_string = u'something\r\nelse\n\rbaz\rbif\n'
|
||||
line_endings = ['\r\n', '\n', '\n\r', '\r']
|
||||
strings = ['something', 'else', 'baz', 'bif']
|
||||
line_endings = ["\r\n", "\n", "\n\r", "\r"]
|
||||
strings = ["something", "else", "baz", "bif"]
|
||||
|
||||
for ending in line_endings:
|
||||
s = ending.join(strings)
|
||||
|
@ -231,10 +229,12 @@ class TestFileEps(PillowTestCase):
|
|||
def test_open_eps(self):
|
||||
# https://github.com/python-pillow/Pillow/issues/1104
|
||||
# Arrange
|
||||
FILES = ["Tests/images/illu10_no_preview.eps",
|
||||
FILES = [
|
||||
"Tests/images/illu10_no_preview.eps",
|
||||
"Tests/images/illu10_preview.eps",
|
||||
"Tests/images/illuCS6_no_preview.eps",
|
||||
"Tests/images/illuCS6_preview.eps"]
|
||||
"Tests/images/illuCS6_preview.eps",
|
||||
]
|
||||
|
||||
# Act / Assert
|
||||
for filename in FILES:
|
||||
|
|
|
@ -6,7 +6,6 @@ TEST_FILE = "Tests/images/hopper.fits"
|
|||
|
||||
|
||||
class TestFileFitsStub(PillowTestCase):
|
||||
|
||||
def test_open(self):
|
||||
# Act
|
||||
im = Image.open(TEST_FILE)
|
||||
|
@ -23,8 +22,9 @@ class TestFileFitsStub(PillowTestCase):
|
|||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
# Act / Assert
|
||||
self.assertRaises(SyntaxError,
|
||||
FitsStubImagePlugin.FITSStubImageFile, invalid_file)
|
||||
self.assertRaises(
|
||||
SyntaxError, FitsStubImagePlugin.FITSStubImageFile, invalid_file
|
||||
)
|
||||
|
||||
def test_load(self):
|
||||
# Arrange
|
||||
|
@ -42,5 +42,5 @@ class TestFileFitsStub(PillowTestCase):
|
|||
# Act / Assert: stub cannot save without an implemented handler
|
||||
self.assertRaises(IOError, im.save, dummy_filename)
|
||||
self.assertRaises(
|
||||
IOError,
|
||||
FitsStubImagePlugin._save, im, dummy_fp, dummy_filename)
|
||||
IOError, FitsStubImagePlugin._save, im, dummy_fp, dummy_filename
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ animated_test_file = "Tests/images/a.fli"
|
|||
|
||||
|
||||
class TestFileFli(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
im = Image.open(static_test_file)
|
||||
im.load()
|
||||
|
@ -31,6 +30,7 @@ class TestFileFli(PillowTestCase):
|
|||
def open():
|
||||
im = Image.open(static_test_file)
|
||||
im.load()
|
||||
|
||||
self.assert_warning(None, open)
|
||||
|
||||
def test_tell(self):
|
||||
|
@ -46,8 +46,7 @@ class TestFileFli(PillowTestCase):
|
|||
def test_invalid_file(self):
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
self.assertRaises(SyntaxError,
|
||||
FliImagePlugin.FliImageFile, invalid_file)
|
||||
self.assertRaises(SyntaxError, FliImagePlugin.FliImageFile, invalid_file)
|
||||
|
||||
def test_n_frames(self):
|
||||
im = Image.open(static_test_file)
|
||||
|
@ -67,7 +66,7 @@ class TestFileFli(PillowTestCase):
|
|||
self.assertLess(im.tell(), n_frames)
|
||||
|
||||
# Test that seeking to the last frame does not raise an error
|
||||
im.seek(n_frames-1)
|
||||
im.seek(n_frames - 1)
|
||||
|
||||
def test_seek_tell(self):
|
||||
im = Image.open(animated_test_file)
|
||||
|
|
|
@ -10,14 +10,11 @@ else:
|
|||
|
||||
@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)
|
||||
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)
|
||||
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file)
|
||||
|
|
|
@ -3,14 +3,13 @@ from PIL import Image
|
|||
|
||||
|
||||
class TestFileFtex(PillowTestCase):
|
||||
|
||||
def test_load_raw(self):
|
||||
im = Image.open('Tests/images/ftex_uncompressed.ftu')
|
||||
target = Image.open('Tests/images/ftex_uncompressed.png')
|
||||
im = Image.open("Tests/images/ftex_uncompressed.ftu")
|
||||
target = Image.open("Tests/images/ftex_uncompressed.png")
|
||||
|
||||
self.assert_image_equal(im, target)
|
||||
|
||||
def test_load_dxt1(self):
|
||||
im = Image.open('Tests/images/ftex_dxt1.ftc')
|
||||
target = Image.open('Tests/images/ftex_dxt1.png')
|
||||
self.assert_image_similar(im, target.convert('RGBA'), 15)
|
||||
im = Image.open("Tests/images/ftex_dxt1.ftc")
|
||||
target = Image.open("Tests/images/ftex_dxt1.png")
|
||||
self.assert_image_similar(im, target.convert("RGBA"), 15)
|
||||
|
|
|
@ -4,16 +4,14 @@ from PIL import Image, GbrImagePlugin
|
|||
|
||||
|
||||
class TestFileGbr(PillowTestCase):
|
||||
|
||||
def test_invalid_file(self):
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
self.assertRaises(SyntaxError,
|
||||
GbrImagePlugin.GbrImageFile, invalid_file)
|
||||
self.assertRaises(SyntaxError, GbrImagePlugin.GbrImageFile, invalid_file)
|
||||
|
||||
def test_gbr_file(self):
|
||||
im = Image.open('Tests/images/gbr.gbr')
|
||||
im = Image.open("Tests/images/gbr.gbr")
|
||||
|
||||
target = Image.open('Tests/images/gbr.png')
|
||||
target = Image.open("Tests/images/gbr.png")
|
||||
|
||||
self.assert_image_equal(target, im)
|
||||
|
|
|
@ -6,15 +6,13 @@ TEST_GD_FILE = "Tests/images/hopper.gd"
|
|||
|
||||
|
||||
class TestFileGd(PillowTestCase):
|
||||
|
||||
def test_sanity(self):
|
||||
im = GdImageFile.open(TEST_GD_FILE)
|
||||
self.assertEqual(im.size, (128, 128))
|
||||
self.assertEqual(im.format, "GD")
|
||||
|
||||
def test_bad_mode(self):
|
||||
self.assertRaises(ValueError,
|
||||
GdImageFile.open, TEST_GD_FILE, 'bad mode')
|
||||
self.assertRaises(ValueError, GdImageFile.open, TEST_GD_FILE, "bad mode")
|
||||
|
||||
def test_invalid_file(self):
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
|
|
@ -6,6 +6,7 @@ from io import BytesIO
|
|||
|
||||
try:
|
||||
from PIL import _webp
|
||||
|
||||
HAVE_WEBP = True
|
||||
except ImportError:
|
||||
HAVE_WEBP = False
|
||||
|
@ -20,7 +21,6 @@ with open(TEST_GIF, "rb") as f:
|
|||
|
||||
|
||||
class TestFileGif(PillowTestCase):
|
||||
|
||||
def setUp(self):
|
||||
if "gif_encoder" not in codecs or "gif_decoder" not in codecs:
|
||||
self.skipTest("gif support not available") # can this happen?
|
||||
|
@ -37,13 +37,13 @@ class TestFileGif(PillowTestCase):
|
|||
def open():
|
||||
im = Image.open(TEST_GIF)
|
||||
im.load()
|
||||
|
||||
self.assert_warning(None, open)
|
||||
|
||||
def test_invalid_file(self):
|
||||
invalid_file = "Tests/images/flower.jpg"
|
||||
|
||||
self.assertRaises(SyntaxError,
|
||||
GifImagePlugin.GifImageFile, invalid_file)
|
||||
self.assertRaises(SyntaxError, GifImagePlugin.GifImageFile, invalid_file)
|
||||
|
||||
def test_optimize(self):
|
||||
def test_grayscale(optimize):
|
||||
|
@ -70,19 +70,22 @@ class TestFileGif(PillowTestCase):
|
|||
# Check for correctness after conversion back to RGB
|
||||
def check(colors, size, expected_palette_length):
|
||||
# make an image with empty colors in the start of the palette range
|
||||
im = Image.frombytes('P', (colors, colors),
|
||||
bytes(bytearray(range(256-colors, 256))*colors))
|
||||
im = Image.frombytes(
|
||||
"P",
|
||||
(colors, colors),
|
||||
bytes(bytearray(range(256 - colors, 256)) * colors),
|
||||
)
|
||||
im = im.resize((size, size))
|
||||
outfile = BytesIO()
|
||||
im.save(outfile, 'GIF')
|
||||
im.save(outfile, "GIF")
|
||||
outfile.seek(0)
|
||||
reloaded = Image.open(outfile)
|
||||
|
||||
# check palette length
|
||||
palette_length = max(i+1 for i, v in enumerate(reloaded.histogram()) if v)
|
||||
palette_length = max(i + 1 for i, v in enumerate(reloaded.histogram()) if v)
|
||||
self.assertEqual(expected_palette_length, palette_length)
|
||||
|
||||
self.assert_image_equal(im.convert('RGB'), reloaded.convert('RGB'))
|
||||
self.assert_image_equal(im.convert("RGB"), reloaded.convert("RGB"))
|
||||
|
||||
# These do optimize the palette
|
||||
check(128, 511, 128)
|
||||
|
@ -106,79 +109,76 @@ class TestFileGif(PillowTestCase):
|
|||
self.assertEqual(im.mode, "L")
|
||||
|
||||
def test_roundtrip(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im = hopper()
|
||||
im.save(out)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assert_image_similar(reread.convert('RGB'), im, 50)
|
||||
self.assert_image_similar(reread.convert("RGB"), im, 50)
|
||||
|
||||
def test_roundtrip2(self):
|
||||
# see https://github.com/python-pillow/Pillow/issues/403
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im = Image.open(TEST_GIF)
|
||||
im2 = im.copy()
|
||||
im2.save(out)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assert_image_similar(reread.convert('RGB'), hopper(), 50)
|
||||
self.assert_image_similar(reread.convert("RGB"), hopper(), 50)
|
||||
|
||||
def test_roundtrip_save_all(self):
|
||||
# Single frame image
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im = hopper()
|
||||
im.save(out, save_all=True)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assert_image_similar(reread.convert('RGB'), im, 50)
|
||||
self.assert_image_similar(reread.convert("RGB"), im, 50)
|
||||
|
||||
# Multiframe image
|
||||
im = Image.open("Tests/images/dispose_bgnd.gif")
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.save(out, save_all=True)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assertEqual(reread.n_frames, 5)
|
||||
|
||||
def test_headers_saving_for_animated_gifs(self):
|
||||
important_headers = ['background', 'version', 'duration', 'loop']
|
||||
important_headers = ["background", "version", "duration", "loop"]
|
||||
# Multiframe image
|
||||
im = Image.open("Tests/images/dispose_bgnd.gif")
|
||||
|
||||
info = im.info.copy()
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.save(out, save_all=True)
|
||||
reread = Image.open(out)
|
||||
|
||||
for header in important_headers:
|
||||
self.assertEqual(
|
||||
info[header],
|
||||
reread.info[header]
|
||||
)
|
||||
self.assertEqual(info[header], reread.info[header])
|
||||
|
||||
def test_palette_handling(self):
|
||||
# see https://github.com/python-pillow/Pillow/issues/513
|
||||
|
||||
im = Image.open(TEST_GIF)
|
||||
im = im.convert('RGB')
|
||||
im = im.convert("RGB")
|
||||
|
||||
im = im.resize((100, 100), Image.LANCZOS)
|
||||
im2 = im.convert('P', palette=Image.ADAPTIVE, colors=256)
|
||||
im2 = im.convert("P", palette=Image.ADAPTIVE, colors=256)
|
||||
|
||||
f = self.tempfile('temp.gif')
|
||||
f = self.tempfile("temp.gif")
|
||||
im2.save(f, optimize=True)
|
||||
|
||||
reloaded = Image.open(f)
|
||||
|
||||
self.assert_image_similar(im, reloaded.convert('RGB'), 10)
|
||||
self.assert_image_similar(im, reloaded.convert("RGB"), 10)
|
||||
|
||||
def test_palette_434(self):
|
||||
# see https://github.com/python-pillow/Pillow/issues/434
|
||||
|
||||
def roundtrip(im, *args, **kwargs):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.copy().save(out, *args, **kwargs)
|
||||
reloaded = Image.open(out)
|
||||
|
||||
|
@ -192,7 +192,7 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
im = im.convert("RGB")
|
||||
# check automatic P conversion
|
||||
reloaded = roundtrip(im).convert('RGB')
|
||||
reloaded = roundtrip(im).convert("RGB")
|
||||
self.assert_image_equal(im, reloaded)
|
||||
|
||||
@unittest.skipUnless(netpbm_available(), "netpbm not available")
|
||||
|
@ -240,10 +240,7 @@ class TestFileGif(PillowTestCase):
|
|||
self.assert_image_equal(im, expected)
|
||||
|
||||
def test_n_frames(self):
|
||||
for path, n_frames in [
|
||||
[TEST_GIF, 1],
|
||||
['Tests/images/iss634.gif', 42]
|
||||
]:
|
||||
for path, n_frames in [[TEST_GIF, 1], ["Tests/images/iss634.gif", 42]]:
|
||||
# Test is_animated before n_frames
|
||||
im = Image.open(path)
|
||||
self.assertEqual(im.is_animated, n_frames != 1)
|
||||
|
@ -262,7 +259,7 @@ class TestFileGif(PillowTestCase):
|
|||
self.assertLess(im.tell(), n_frames)
|
||||
|
||||
# Test that seeking to the last frame does not raise an error
|
||||
im.seek(n_frames-1)
|
||||
im.seek(n_frames - 1)
|
||||
|
||||
def test_dispose_none(self):
|
||||
img = Image.open("Tests/images/dispose_none.gif")
|
||||
|
@ -292,18 +289,15 @@ class TestFileGif(PillowTestCase):
|
|||
pass
|
||||
|
||||
def test_save_dispose(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im_list = [
|
||||
Image.new('L', (100, 100), '#000'),
|
||||
Image.new('L', (100, 100), '#111'),
|
||||
Image.new('L', (100, 100), '#222'),
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#111"),
|
||||
Image.new("L", (100, 100), "#222"),
|
||||
]
|
||||
for method in range(0, 4):
|
||||
im_list[0].save(
|
||||
out,
|
||||
save_all=True,
|
||||
append_images=im_list[1:],
|
||||
disposal=method
|
||||
out, save_all=True, append_images=im_list[1:], disposal=method
|
||||
)
|
||||
img = Image.open(out)
|
||||
for _ in range(2):
|
||||
|
@ -315,14 +309,14 @@ class TestFileGif(PillowTestCase):
|
|||
out,
|
||||
save_all=True,
|
||||
append_images=im_list[1:],
|
||||
disposal=tuple(range(len(im_list)))
|
||||
disposal=tuple(range(len(im_list))),
|
||||
)
|
||||
|
||||
img = Image.open(out)
|
||||
|
||||
for i in range(2):
|
||||
img.seek(img.tell() + 1)
|
||||
self.assertEqual(img.disposal_method, i+1)
|
||||
self.assertEqual(img.disposal_method, i + 1)
|
||||
|
||||
def test_iss634(self):
|
||||
img = Image.open("Tests/images/iss634.gif")
|
||||
|
@ -330,42 +324,39 @@ class TestFileGif(PillowTestCase):
|
|||
img.seek(img.tell() + 1)
|
||||
# all transparent pixels should be replaced with the color from the
|
||||
# first frame
|
||||
self.assertEqual(img.histogram()[img.info['transparency']], 0)
|
||||
self.assertEqual(img.histogram()[img.info["transparency"]], 0)
|
||||
|
||||
def test_duration(self):
|
||||
duration = 1000
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
out = self.tempfile("temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
|
||||
# Check that the argument has priority over the info settings
|
||||
im.info['duration'] = 100
|
||||
im.info["duration"] = 100
|
||||
im.save(out, duration=duration)
|
||||
|
||||
reread = Image.open(out)
|
||||
self.assertEqual(reread.info['duration'], duration)
|
||||
self.assertEqual(reread.info["duration"], duration)
|
||||
|
||||
def test_multiple_duration(self):
|
||||
duration_list = [1000, 2000, 3000]
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im_list = [
|
||||
Image.new('L', (100, 100), '#000'),
|
||||
Image.new('L', (100, 100), '#111'),
|
||||
Image.new('L', (100, 100), '#222')
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#111"),
|
||||
Image.new("L", (100, 100), "#222"),
|
||||
]
|
||||
|
||||
# duration as list
|
||||
im_list[0].save(
|
||||
out,
|
||||
save_all=True,
|
||||
append_images=im_list[1:],
|
||||
duration=duration_list
|
||||
out, save_all=True, append_images=im_list[1:], duration=duration_list
|
||||
)
|
||||
reread = Image.open(out)
|
||||
|
||||
for duration in duration_list:
|
||||
self.assertEqual(reread.info['duration'], duration)
|
||||
self.assertEqual(reread.info["duration"], duration)
|
||||
try:
|
||||
reread.seek(reread.tell() + 1)
|
||||
except EOFError:
|
||||
|
@ -373,15 +364,12 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
# duration as tuple
|
||||
im_list[0].save(
|
||||
out,
|
||||
save_all=True,
|
||||
append_images=im_list[1:],
|
||||
duration=tuple(duration_list)
|
||||
out, save_all=True, append_images=im_list[1:], duration=tuple(duration_list)
|
||||
)
|
||||
reread = Image.open(out)
|
||||
|
||||
for duration in duration_list:
|
||||
self.assertEqual(reread.info['duration'], duration)
|
||||
self.assertEqual(reread.info["duration"], duration)
|
||||
try:
|
||||
reread.seek(reread.tell() + 1)
|
||||
except EOFError:
|
||||
|
@ -390,20 +378,17 @@ class TestFileGif(PillowTestCase):
|
|||
def test_identical_frames(self):
|
||||
duration_list = [1000, 1500, 2000, 4000]
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im_list = [
|
||||
Image.new('L', (100, 100), '#000'),
|
||||
Image.new('L', (100, 100), '#000'),
|
||||
Image.new('L', (100, 100), '#000'),
|
||||
Image.new('L', (100, 100), '#111')
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#000"),
|
||||
Image.new("L", (100, 100), "#111"),
|
||||
]
|
||||
|
||||
# duration as list
|
||||
im_list[0].save(
|
||||
out,
|
||||
save_all=True,
|
||||
append_images=im_list[1:],
|
||||
duration=duration_list
|
||||
out, save_all=True, append_images=im_list[1:], duration=duration_list
|
||||
)
|
||||
reread = Image.open(out)
|
||||
|
||||
|
@ -411,64 +396,63 @@ class TestFileGif(PillowTestCase):
|
|||
self.assertEqual(reread.n_frames, 2)
|
||||
|
||||
# Assert that the new duration is the total of the identical frames
|
||||
self.assertEqual(reread.info['duration'], 4500)
|
||||
self.assertEqual(reread.info["duration"], 4500)
|
||||
|
||||
def test_number_of_loops(self):
|
||||
number_of_loops = 2
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
out = self.tempfile("temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.save(out, loop=number_of_loops)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assertEqual(reread.info['loop'], number_of_loops)
|
||||
self.assertEqual(reread.info["loop"], number_of_loops)
|
||||
|
||||
def test_background(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
im.info['background'] = 1
|
||||
out = self.tempfile("temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.info["background"] = 1
|
||||
im.save(out)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assertEqual(reread.info['background'], im.info['background'])
|
||||
self.assertEqual(reread.info["background"], im.info["background"])
|
||||
|
||||
if HAVE_WEBP and _webp.HAVE_WEBPANIM:
|
||||
im = Image.open("Tests/images/hopper.webp")
|
||||
self.assertIsInstance(im.info['background'], tuple)
|
||||
self.assertIsInstance(im.info["background"], tuple)
|
||||
im.save(out)
|
||||
|
||||
def test_comment(self):
|
||||
im = Image.open(TEST_GIF)
|
||||
self.assertEqual(im.info['comment'],
|
||||
b"File written by Adobe Photoshop\xa8 4.0")
|
||||
self.assertEqual(im.info["comment"], b"File written by Adobe Photoshop\xa8 4.0")
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
im.info['comment'] = b"Test comment text"
|
||||
out = self.tempfile("temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.info["comment"] = b"Test comment text"
|
||||
im.save(out)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assertEqual(reread.info['comment'], im.info['comment'])
|
||||
self.assertEqual(reread.info["comment"], im.info["comment"])
|
||||
|
||||
def test_comment_over_255(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
out = self.tempfile("temp.gif")
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
comment = b"Test comment text"
|
||||
while len(comment) < 256:
|
||||
comment += comment
|
||||
im.info['comment'] = comment
|
||||
im.info["comment"] = comment
|
||||
im.save(out)
|
||||
reread = Image.open(out)
|
||||
|
||||
self.assertEqual(reread.info['comment'], comment)
|
||||
self.assertEqual(reread.info["comment"], comment)
|
||||
|
||||
def test_zero_comment_subblocks(self):
|
||||
im = Image.open('Tests/images/hopper_zero_comment_subblocks.gif')
|
||||
im = Image.open("Tests/images/hopper_zero_comment_subblocks.gif")
|
||||
expected = Image.open(TEST_GIF)
|
||||
self.assert_image_equal(im, expected)
|
||||
|
||||
def test_version(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
def assertVersionAfterSave(im, version):
|
||||
im.save(out)
|
||||
|
@ -476,11 +460,11 @@ class TestFileGif(PillowTestCase):
|
|||
self.assertEqual(reread.info["version"], version)
|
||||
|
||||
# Test that GIF87a is used by default
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
assertVersionAfterSave(im, b"GIF87a")
|
||||
|
||||
# Test setting the version to 89a
|
||||
im = Image.new('L', (100, 100), '#000')
|
||||
im = Image.new("L", (100, 100), "#000")
|
||||
im.info["version"] = b"89a"
|
||||
assertVersionAfterSave(im, b"GIF89a")
|
||||
|
||||
|
@ -497,12 +481,11 @@ class TestFileGif(PillowTestCase):
|
|||
assertVersionAfterSave(im, b"GIF87a")
|
||||
|
||||
def test_append_images(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
# Test appending single frame images
|
||||
im = Image.new('RGB', (100, 100), '#f00')
|
||||
ims = [Image.new('RGB', (100, 100), color) for color
|
||||
in ['#0f0', '#00f']]
|
||||
im = Image.new("RGB", (100, 100), "#f00")
|
||||
ims = [Image.new("RGB", (100, 100), color) for color in ["#0f0", "#00f"]]
|
||||
im.copy().save(out, save_all=True, append_images=ims)
|
||||
|
||||
reread = Image.open(out)
|
||||
|
@ -512,6 +495,7 @@ class TestFileGif(PillowTestCase):
|
|||
def imGenerator(ims):
|
||||
for im in ims:
|
||||
yield im
|
||||
|
||||
im.save(out, save_all=True, append_images=imGenerator(ims))
|
||||
|
||||
reread = Image.open(out)
|
||||
|
@ -533,44 +517,43 @@ class TestFileGif(PillowTestCase):
|
|||
# the top palette entry to trigger the bug.
|
||||
|
||||
data = bytes(bytearray(range(1, 254)))
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256))*3)
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)
|
||||
|
||||
im = Image.new('L', (253, 1))
|
||||
im = Image.new("L", (253, 1))
|
||||
im.frombytes(data)
|
||||
im.putpalette(palette)
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.save(out, transparency=253)
|
||||
reloaded = Image.open(out)
|
||||
|
||||
self.assertEqual(reloaded.info['transparency'], 253)
|
||||
self.assertEqual(reloaded.info["transparency"], 253)
|
||||
|
||||
def test_rgb_transparency(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
# Single frame
|
||||
im = Image.new('RGB', (1, 1))
|
||||
im.info['transparency'] = (255, 0, 0)
|
||||
im = Image.new("RGB", (1, 1))
|
||||
im.info["transparency"] = (255, 0, 0)
|
||||
self.assert_warning(UserWarning, im.save, out)
|
||||
|
||||
reloaded = Image.open(out)
|
||||
self.assertNotIn('transparency', reloaded.info)
|
||||
self.assertNotIn("transparency", reloaded.info)
|
||||
|
||||
# Multiple frames
|
||||
im = Image.new('RGB', (1, 1))
|
||||
im.info['transparency'] = b""
|
||||
ims = [Image.new('RGB', (1, 1))]
|
||||
self.assert_warning(UserWarning,
|
||||
im.save, out, save_all=True, append_images=ims)
|
||||
im = Image.new("RGB", (1, 1))
|
||||
im.info["transparency"] = b""
|
||||
ims = [Image.new("RGB", (1, 1))]
|
||||
self.assert_warning(UserWarning, im.save, out, save_all=True, append_images=ims)
|
||||
|
||||
reloaded = Image.open(out)
|
||||
self.assertNotIn('transparency', reloaded.info)
|
||||
self.assertNotIn("transparency", reloaded.info)
|
||||
|
||||
def test_bbox(self):
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
|
||||
im = Image.new('RGB', (100, 100), '#fff')
|
||||
ims = [Image.new("RGB", (100, 100), '#000')]
|
||||
im = Image.new("RGB", (100, 100), "#fff")
|
||||
ims = [Image.new("RGB", (100, 100), "#000")]
|
||||
im.save(out, save_all=True, append_images=ims)
|
||||
|
||||
reread = Image.open(out)
|
||||
|
@ -579,26 +562,26 @@ class TestFileGif(PillowTestCase):
|
|||
def test_palette_save_L(self):
|
||||
# generate an L mode image with a separate palette
|
||||
|
||||
im = hopper('P')
|
||||
im_l = Image.frombytes('L', im.size, im.tobytes())
|
||||
im = hopper("P")
|
||||
im_l = Image.frombytes("L", im.size, im.tobytes())
|
||||
palette = bytes(bytearray(im.getpalette()))
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im_l.save(out, palette=palette)
|
||||
|
||||
reloaded = Image.open(out)
|
||||
|
||||
self.assert_image_equal(reloaded.convert('RGB'), im.convert('RGB'))
|
||||
self.assert_image_equal(reloaded.convert("RGB"), im.convert("RGB"))
|
||||
|
||||
def test_palette_save_P(self):
|
||||
# pass in a different palette, then construct what the image
|
||||
# would look like.
|
||||
# Forcing a non-straight grayscale palette.
|
||||
|
||||
im = hopper('P')
|
||||
palette = bytes(bytearray([255-i//3 for i in range(768)]))
|
||||
im = hopper("P")
|
||||
palette = bytes(bytearray([255 - i // 3 for i in range(768)]))
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.save(out, palette=palette)
|
||||
|
||||
reloaded = Image.open(out)
|
||||
|
@ -609,10 +592,10 @@ class TestFileGif(PillowTestCase):
|
|||
# pass in a different palette, as an ImagePalette.ImagePalette
|
||||
# effectively the same as test_palette_save_P
|
||||
|
||||
im = hopper('P')
|
||||
palette = ImagePalette.ImagePalette('RGB', list(range(256))[::-1]*3)
|
||||
im = hopper("P")
|
||||
palette = ImagePalette.ImagePalette("RGB", list(range(256))[::-1] * 3)
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.save(out, palette=palette)
|
||||
|
||||
reloaded = Image.open(out)
|
||||
|
@ -622,22 +605,22 @@ class TestFileGif(PillowTestCase):
|
|||
def test_save_I(self):
|
||||
# Test saving something that would trigger the auto-convert to 'L'
|
||||
|
||||
im = hopper('I')
|
||||
im = hopper("I")
|
||||
|
||||
out = self.tempfile('temp.gif')
|
||||
out = self.tempfile("temp.gif")
|
||||
im.save(out)
|
||||
|
||||
reloaded = Image.open(out)
|
||||
self.assert_image_equal(reloaded.convert('L'), im.convert('L'))
|
||||
self.assert_image_equal(reloaded.convert("L"), im.convert("L"))
|
||||
|
||||
def test_getdata(self):
|
||||
# test getheader/getdata against legacy values
|
||||
# Create a 'P' image with holes in the palette
|
||||
im = Image._wedge().resize((16, 16))
|
||||
im.putpalette(ImagePalette.ImagePalette('RGB'))
|
||||
im.info = {'background': 0}
|
||||
im.putpalette(ImagePalette.ImagePalette("RGB"))
|
||||
im.info = {"background": 0}
|
||||
|
||||
passed_palette = bytes(bytearray([255-i//3 for i in range(768)]))
|
||||
passed_palette = bytes(bytearray([255 - i // 3 for i in range(768)]))
|
||||
|
||||
GifImagePlugin._FORCE_OPTIMIZE = True
|
||||
try:
|
||||
|
@ -645,10 +628,11 @@ class TestFileGif(PillowTestCase):
|
|||
d = GifImagePlugin.getdata(im)
|
||||
|
||||
import pickle
|
||||
|
||||
# Enable to get target values on pre-refactor version
|
||||
# with open('Tests/images/gif_header_data.pkl', 'wb') as f:
|
||||
# pickle.dump((h, d), f, 1)
|
||||
with open('Tests/images/gif_header_data.pkl', 'rb') as f:
|
||||
with open("Tests/images/gif_header_data.pkl", "rb") as f:
|
||||
(h_target, d_target) = pickle.load(f)
|
||||
|
||||
self.assertEqual(h, h_target)
|
||||
|
@ -658,14 +642,14 @@ class TestFileGif(PillowTestCase):
|
|||
|
||||
def test_lzw_bits(self):
|
||||
# see https://github.com/python-pillow/Pillow/issues/2811
|
||||
im = Image.open('Tests/images/issue_2811.gif')
|
||||
im = Image.open("Tests/images/issue_2811.gif")
|
||||
|
||||
self.assertEqual(im.tile[0][3][0], 11) # LZW bits
|
||||
# codec error prepatch
|
||||
im.load()
|
||||
|
||||
def test_extents(self):
|
||||
im = Image.open('Tests/images/test_extents.gif')
|
||||
im = Image.open("Tests/images/test_extents.gif")
|
||||
self.assertEqual(im.size, (100, 100))
|
||||
im.seek(1)
|
||||
self.assertEqual(im.size, (150, 150))
|
||||
|
|
|
@ -4,7 +4,6 @@ from PIL import GimpGradientFile
|
|||
|
||||
|
||||
class TestImage(PillowTestCase):
|
||||
|
||||
def test_linear_pos_le_middle(self):
|
||||
# Arrange
|
||||
middle = 0.5
|
||||
|
@ -96,6 +95,7 @@ class TestImage(PillowTestCase):
|
|||
def test_load_via_imagepalette(self):
|
||||
# Arrange
|
||||
from PIL import ImagePalette
|
||||
|
||||
test_file = "Tests/images/gimp_gradient.ggr"
|
||||
|
||||
# Act
|
||||
|
@ -109,6 +109,7 @@ class TestImage(PillowTestCase):
|
|||
def test_load_1_3_via_imagepalette(self):
|
||||
# Arrange
|
||||
from PIL import ImagePalette
|
||||
|
||||
# GIMP 1.3 gradient files contain a name field
|
||||
test_file = "Tests/images/gimp_gradient_with_name.ggr"
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user