mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-04 11:53:32 +03:00
Format with Black
This commit is contained in:
parent
f87821e010
commit
77f946d8bc
|
@ -4,22 +4,24 @@ import sys
|
||||||
from PIL import Image, features, ImageDraw, ImageFont
|
from PIL import Image, features, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform.startswith('win32'), "requires Unix or macOS")
|
@unittest.skipIf(sys.platform.startswith("win32"), "requires Unix or macOS")
|
||||||
class TestTTypeFontLeak(PillowLeakTestCase):
|
class TestTTypeFontLeak(PillowLeakTestCase):
|
||||||
# fails at iteration 3 in master
|
# fails at iteration 3 in master
|
||||||
iterations = 10
|
iterations = 10
|
||||||
mem_limit = 4096 # k
|
mem_limit = 4096 # k
|
||||||
|
|
||||||
def _test_font(self, font):
|
def _test_font(self, font):
|
||||||
im = Image.new('RGB', (255, 255), 'white')
|
im = Image.new("RGB", (255, 255), "white")
|
||||||
draw = ImageDraw.ImageDraw(im)
|
draw = ImageDraw.ImageDraw(im)
|
||||||
self._test_leak(lambda: draw.text((0, 0), "some text "*1024, # ~10k
|
self._test_leak(
|
||||||
font=font, fill="black"))
|
lambda: draw.text(
|
||||||
|
(0, 0), "some text " * 1024, font=font, fill="black" # ~10k
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@unittest.skipIf(not features.check('freetype2'),
|
@unittest.skipIf(not features.check("freetype2"), "Test requires freetype2")
|
||||||
"Test requires freetype2")
|
|
||||||
def test_leak(self):
|
def test_leak(self):
|
||||||
ttype = ImageFont.truetype('Tests/fonts/FreeMono.ttf', 20)
|
ttype = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 20)
|
||||||
self._test_font(ttype)
|
self._test_font(ttype)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ message = "hello, world"
|
||||||
|
|
||||||
|
|
||||||
class TestFontPcf(PillowTestCase):
|
class TestFontPcf(PillowTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
|
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
|
||||||
self.skipTest("zlib support not available")
|
self.skipTest("zlib support not available")
|
||||||
|
@ -25,15 +24,15 @@ class TestFontPcf(PillowTestCase):
|
||||||
self.assertEqual(len([_f for _f in font.glyph if _f]), 223)
|
self.assertEqual(len([_f for _f in font.glyph if _f]), 223)
|
||||||
|
|
||||||
tempname = self.tempfile("temp.pil")
|
tempname = self.tempfile("temp.pil")
|
||||||
self.addCleanup(self.delete_tempfile, tempname[:-4]+'.pbm')
|
self.addCleanup(self.delete_tempfile, tempname[:-4] + ".pbm")
|
||||||
font.save(tempname)
|
font.save(tempname)
|
||||||
|
|
||||||
with Image.open(tempname.replace('.pil', '.pbm')) as loaded:
|
with Image.open(tempname.replace(".pil", ".pbm")) as loaded:
|
||||||
with Image.open('Tests/fonts/10x20.pbm') as target:
|
with Image.open("Tests/fonts/10x20.pbm") as target:
|
||||||
self.assert_image_equal(loaded, target)
|
self.assert_image_equal(loaded, target)
|
||||||
|
|
||||||
with open(tempname, 'rb') as f_loaded:
|
with open(tempname, "rb") as f_loaded:
|
||||||
with open('Tests/fonts/10x20.pil', 'rb') as f_target:
|
with open("Tests/fonts/10x20.pil", "rb") as f_target:
|
||||||
self.assertEqual(f_loaded.read(), f_target.read())
|
self.assertEqual(f_loaded.read(), f_target.read())
|
||||||
return tempname
|
return tempname
|
||||||
|
|
||||||
|
@ -49,8 +48,8 @@ class TestFontPcf(PillowTestCase):
|
||||||
font = ImageFont.load(tempname)
|
font = ImageFont.load(tempname)
|
||||||
im = Image.new("L", (130, 30), "white")
|
im = Image.new("L", (130, 30), "white")
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
draw.text((0, 0), message, 'black', font=font)
|
draw.text((0, 0), message, "black", font=font)
|
||||||
with Image.open('Tests/images/test_draw_pbm_target.png') as target:
|
with Image.open("Tests/images/test_draw_pbm_target.png") as target:
|
||||||
self.assert_image_similar(im, target, 0)
|
self.assert_image_similar(im, target, 0)
|
||||||
|
|
||||||
def test_textsize(self):
|
def test_textsize(self):
|
||||||
|
@ -61,8 +60,8 @@ class TestFontPcf(PillowTestCase):
|
||||||
self.assertEqual(dy, 20)
|
self.assertEqual(dy, 20)
|
||||||
self.assertIn(dx, (0, 10))
|
self.assertIn(dx, (0, 10))
|
||||||
for l in range(len(message)):
|
for l in range(len(message)):
|
||||||
msg = message[:l+1]
|
msg = message[: l + 1]
|
||||||
self.assertEqual(font.getsize(msg), (len(msg)*10, 20))
|
self.assertEqual(font.getsize(msg), (len(msg) * 10, 20))
|
||||||
|
|
||||||
def _test_high_characters(self, message):
|
def _test_high_characters(self, message):
|
||||||
tempname = self.save_font()
|
tempname = self.save_font()
|
||||||
|
@ -70,12 +69,12 @@ class TestFontPcf(PillowTestCase):
|
||||||
im = Image.new("L", (750, 30), "white")
|
im = Image.new("L", (750, 30), "white")
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
draw.text((0, 0), message, "black", font=font)
|
draw.text((0, 0), message, "black", font=font)
|
||||||
with Image.open('Tests/images/high_ascii_chars.png') as target:
|
with Image.open("Tests/images/high_ascii_chars.png") as target:
|
||||||
self.assert_image_similar(im, target, 0)
|
self.assert_image_similar(im, target, 0)
|
||||||
|
|
||||||
def test_high_characters(self):
|
def test_high_characters(self):
|
||||||
message = "".join(chr(i+1) for i in range(140, 232))
|
message = "".join(chr(i + 1) for i in range(140, 232))
|
||||||
self._test_high_characters(message)
|
self._test_high_characters(message)
|
||||||
# accept bytes instances in Py3.
|
# accept bytes instances in Py3.
|
||||||
if py3:
|
if py3:
|
||||||
self._test_high_characters(message.encode('latin1'))
|
self._test_high_characters(message.encode("latin1"))
|
||||||
|
|
|
@ -8,19 +8,18 @@ import itertools
|
||||||
|
|
||||||
|
|
||||||
class TestFormatHSV(PillowTestCase):
|
class TestFormatHSV(PillowTestCase):
|
||||||
|
|
||||||
def int_to_float(self, i):
|
def int_to_float(self, i):
|
||||||
return float(i)/255.0
|
return float(i) / 255.0
|
||||||
|
|
||||||
def str_to_float(self, i):
|
def str_to_float(self, i):
|
||||||
return float(ord(i))/255.0
|
return float(ord(i)) / 255.0
|
||||||
|
|
||||||
def tuple_to_ints(self, tp):
|
def tuple_to_ints(self, tp):
|
||||||
x, y, z = tp
|
x, y, z = tp
|
||||||
return int(x*255.0), int(y*255.0), int(z*255.0)
|
return int(x * 255.0), int(y * 255.0), int(z * 255.0)
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
Image.new('HSV', (100, 100))
|
Image.new("HSV", (100, 100))
|
||||||
|
|
||||||
def wedge(self):
|
def wedge(self):
|
||||||
w = Image._wedge()
|
w = Image._wedge()
|
||||||
|
@ -28,7 +27,7 @@ class TestFormatHSV(PillowTestCase):
|
||||||
|
|
||||||
(px, h) = w.size
|
(px, h) = w.size
|
||||||
|
|
||||||
r = Image.new('L', (px*3, h))
|
r = Image.new("L", (px * 3, h))
|
||||||
g = r.copy()
|
g = r.copy()
|
||||||
b = r.copy()
|
b = r.copy()
|
||||||
|
|
||||||
|
@ -36,12 +35,12 @@ class TestFormatHSV(PillowTestCase):
|
||||||
r.paste(w90, (px, 0))
|
r.paste(w90, (px, 0))
|
||||||
|
|
||||||
g.paste(w90, (0, 0))
|
g.paste(w90, (0, 0))
|
||||||
g.paste(w, (2*px, 0))
|
g.paste(w, (2 * px, 0))
|
||||||
|
|
||||||
b.paste(w, (px, 0))
|
b.paste(w, (px, 0))
|
||||||
b.paste(w90, (2*px, 0))
|
b.paste(w90, (2 * px, 0))
|
||||||
|
|
||||||
img = Image.merge('RGB', (r, g, b))
|
img = Image.merge("RGB", (r, g, b))
|
||||||
|
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
@ -55,77 +54,101 @@ class TestFormatHSV(PillowTestCase):
|
||||||
else:
|
else:
|
||||||
conv_func = self.str_to_float
|
conv_func = self.str_to_float
|
||||||
|
|
||||||
if hasattr(itertools, 'izip'):
|
if hasattr(itertools, "izip"):
|
||||||
iter_helper = itertools.izip
|
iter_helper = itertools.izip
|
||||||
else:
|
else:
|
||||||
iter_helper = itertools.zip_longest
|
iter_helper = itertools.zip_longest
|
||||||
|
|
||||||
converted = [self.tuple_to_ints(func(conv_func(_r), conv_func(_g),
|
converted = [
|
||||||
conv_func(_b)))
|
self.tuple_to_ints(func(conv_func(_r), conv_func(_g), conv_func(_b)))
|
||||||
for (_r, _g, _b) in iter_helper(r.tobytes(), g.tobytes(),
|
for (_r, _g, _b) in iter_helper(r.tobytes(), g.tobytes(), b.tobytes())
|
||||||
b.tobytes())]
|
]
|
||||||
|
|
||||||
if py3:
|
if py3:
|
||||||
new_bytes = b''.join(bytes(chr(h)+chr(s)+chr(v), 'latin-1') for (
|
new_bytes = b"".join(
|
||||||
h, s, v) in converted)
|
bytes(chr(h) + chr(s) + chr(v), "latin-1") for (h, s, v) in converted
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
new_bytes = b''.join(chr(h)+chr(s)+chr(v) for (
|
new_bytes = b"".join(chr(h) + chr(s) + chr(v) for (h, s, v) in converted)
|
||||||
h, s, v) in converted)
|
|
||||||
|
|
||||||
hsv = Image.frombytes(mode, r.size, new_bytes)
|
hsv = Image.frombytes(mode, r.size, new_bytes)
|
||||||
|
|
||||||
return hsv
|
return hsv
|
||||||
|
|
||||||
def to_hsv_colorsys(self, im):
|
def to_hsv_colorsys(self, im):
|
||||||
return self.to_xxx_colorsys(im, colorsys.rgb_to_hsv, 'HSV')
|
return self.to_xxx_colorsys(im, colorsys.rgb_to_hsv, "HSV")
|
||||||
|
|
||||||
def to_rgb_colorsys(self, im):
|
def to_rgb_colorsys(self, im):
|
||||||
return self.to_xxx_colorsys(im, colorsys.hsv_to_rgb, 'RGB')
|
return self.to_xxx_colorsys(im, colorsys.hsv_to_rgb, "RGB")
|
||||||
|
|
||||||
def test_wedge(self):
|
def test_wedge(self):
|
||||||
src = self.wedge().resize((3*32, 32), Image.BILINEAR)
|
src = self.wedge().resize((3 * 32, 32), Image.BILINEAR)
|
||||||
im = src.convert('HSV')
|
im = src.convert("HSV")
|
||||||
comparable = self.to_hsv_colorsys(src)
|
comparable = self.to_hsv_colorsys(src)
|
||||||
|
|
||||||
self.assert_image_similar(im.getchannel(0), comparable.getchannel(0),
|
self.assert_image_similar(
|
||||||
1, "Hue conversion is wrong")
|
im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong"
|
||||||
self.assert_image_similar(im.getchannel(1), comparable.getchannel(1),
|
)
|
||||||
1, "Saturation conversion is wrong")
|
self.assert_image_similar(
|
||||||
self.assert_image_similar(im.getchannel(2), comparable.getchannel(2),
|
im.getchannel(1),
|
||||||
1, "Value conversion is wrong")
|
comparable.getchannel(1),
|
||||||
|
1,
|
||||||
|
"Saturation conversion is wrong",
|
||||||
|
)
|
||||||
|
self.assert_image_similar(
|
||||||
|
im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong"
|
||||||
|
)
|
||||||
|
|
||||||
comparable = src
|
comparable = src
|
||||||
im = im.convert('RGB')
|
im = im.convert("RGB")
|
||||||
|
|
||||||
self.assert_image_similar(im.getchannel(0), comparable.getchannel(0),
|
self.assert_image_similar(
|
||||||
3, "R conversion is wrong")
|
im.getchannel(0), comparable.getchannel(0), 3, "R conversion is wrong"
|
||||||
self.assert_image_similar(im.getchannel(1), comparable.getchannel(1),
|
)
|
||||||
3, "G conversion is wrong")
|
self.assert_image_similar(
|
||||||
self.assert_image_similar(im.getchannel(2), comparable.getchannel(2),
|
im.getchannel(1), comparable.getchannel(1), 3, "G conversion is wrong"
|
||||||
3, "B conversion is wrong")
|
)
|
||||||
|
self.assert_image_similar(
|
||||||
|
im.getchannel(2), comparable.getchannel(2), 3, "B conversion is wrong"
|
||||||
|
)
|
||||||
|
|
||||||
def test_convert(self):
|
def test_convert(self):
|
||||||
im = hopper('RGB').convert('HSV')
|
im = hopper("RGB").convert("HSV")
|
||||||
comparable = self.to_hsv_colorsys(hopper('RGB'))
|
comparable = self.to_hsv_colorsys(hopper("RGB"))
|
||||||
|
|
||||||
self.assert_image_similar(im.getchannel(0), comparable.getchannel(0),
|
self.assert_image_similar(
|
||||||
1, "Hue conversion is wrong")
|
im.getchannel(0), comparable.getchannel(0), 1, "Hue conversion is wrong"
|
||||||
self.assert_image_similar(im.getchannel(1), comparable.getchannel(1),
|
)
|
||||||
1, "Saturation conversion is wrong")
|
self.assert_image_similar(
|
||||||
self.assert_image_similar(im.getchannel(2), comparable.getchannel(2),
|
im.getchannel(1),
|
||||||
1, "Value conversion is wrong")
|
comparable.getchannel(1),
|
||||||
|
1,
|
||||||
|
"Saturation conversion is wrong",
|
||||||
|
)
|
||||||
|
self.assert_image_similar(
|
||||||
|
im.getchannel(2), comparable.getchannel(2), 1, "Value conversion is wrong"
|
||||||
|
)
|
||||||
|
|
||||||
def test_hsv_to_rgb(self):
|
def test_hsv_to_rgb(self):
|
||||||
comparable = self.to_hsv_colorsys(hopper('RGB'))
|
comparable = self.to_hsv_colorsys(hopper("RGB"))
|
||||||
converted = comparable.convert('RGB')
|
converted = comparable.convert("RGB")
|
||||||
comparable = self.to_rgb_colorsys(comparable)
|
comparable = self.to_rgb_colorsys(comparable)
|
||||||
|
|
||||||
self.assert_image_similar(converted.getchannel(0),
|
self.assert_image_similar(
|
||||||
comparable.getchannel(0),
|
converted.getchannel(0),
|
||||||
3, "R conversion is wrong")
|
comparable.getchannel(0),
|
||||||
self.assert_image_similar(converted.getchannel(1),
|
3,
|
||||||
comparable.getchannel(1),
|
"R conversion is wrong",
|
||||||
3, "G conversion is wrong")
|
)
|
||||||
self.assert_image_similar(converted.getchannel(2),
|
self.assert_image_similar(
|
||||||
comparable.getchannel(2),
|
converted.getchannel(1),
|
||||||
3, "B conversion is wrong")
|
comparable.getchannel(1),
|
||||||
|
3,
|
||||||
|
"G conversion is wrong",
|
||||||
|
)
|
||||||
|
self.assert_image_similar(
|
||||||
|
converted.getchannel(2),
|
||||||
|
comparable.getchannel(2),
|
||||||
|
3,
|
||||||
|
"B conversion is wrong",
|
||||||
|
)
|
||||||
|
|
|
@ -4,15 +4,14 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestFormatLab(PillowTestCase):
|
class TestFormatLab(PillowTestCase):
|
||||||
|
|
||||||
def test_white(self):
|
def test_white(self):
|
||||||
i = Image.open('Tests/images/lab.tif')
|
i = Image.open("Tests/images/lab.tif")
|
||||||
|
|
||||||
i.load()
|
i.load()
|
||||||
|
|
||||||
self.assertEqual(i.mode, 'LAB')
|
self.assertEqual(i.mode, "LAB")
|
||||||
|
|
||||||
self.assertEqual(i.getbands(), ('L', 'A', 'B'))
|
self.assertEqual(i.getbands(), ("L", "A", "B"))
|
||||||
|
|
||||||
k = i.getpixel((0, 0))
|
k = i.getpixel((0, 0))
|
||||||
self.assertEqual(k, (255, 128, 128))
|
self.assertEqual(k, (255, 128, 128))
|
||||||
|
@ -21,14 +20,14 @@ class TestFormatLab(PillowTestCase):
|
||||||
a = i.getdata(1)
|
a = i.getdata(1)
|
||||||
b = i.getdata(2)
|
b = i.getdata(2)
|
||||||
|
|
||||||
self.assertEqual(list(L), [255]*100)
|
self.assertEqual(list(L), [255] * 100)
|
||||||
self.assertEqual(list(a), [128]*100)
|
self.assertEqual(list(a), [128] * 100)
|
||||||
self.assertEqual(list(b), [128]*100)
|
self.assertEqual(list(b), [128] * 100)
|
||||||
|
|
||||||
def test_green(self):
|
def test_green(self):
|
||||||
# l= 50 (/100), a = -100 (-128 .. 128) b=0 in PS
|
# l= 50 (/100), a = -100 (-128 .. 128) b=0 in PS
|
||||||
# == RGB: 0, 152, 117
|
# == RGB: 0, 152, 117
|
||||||
i = Image.open('Tests/images/lab-green.tif')
|
i = Image.open("Tests/images/lab-green.tif")
|
||||||
|
|
||||||
k = i.getpixel((0, 0))
|
k = i.getpixel((0, 0))
|
||||||
self.assertEqual(k, (128, 28, 128))
|
self.assertEqual(k, (128, 28, 128))
|
||||||
|
@ -36,7 +35,7 @@ class TestFormatLab(PillowTestCase):
|
||||||
def test_red(self):
|
def test_red(self):
|
||||||
# l= 50 (/100), a = 100 (-128 .. 128) b=0 in PS
|
# l= 50 (/100), a = 100 (-128 .. 128) b=0 in PS
|
||||||
# == RGB: 255, 0, 124
|
# == RGB: 255, 0, 124
|
||||||
i = Image.open('Tests/images/lab-red.tif')
|
i = Image.open("Tests/images/lab-red.tif")
|
||||||
|
|
||||||
k = i.getpixel((0, 0))
|
k = i.getpixel((0, 0))
|
||||||
self.assertEqual(k, (128, 228, 128))
|
self.assertEqual(k, (128, 228, 128))
|
||||||
|
|
|
@ -8,37 +8,54 @@ import shutil
|
||||||
|
|
||||||
|
|
||||||
class TestImage(PillowTestCase):
|
class TestImage(PillowTestCase):
|
||||||
|
|
||||||
def test_image_modes_success(self):
|
def test_image_modes_success(self):
|
||||||
for mode in [
|
for mode in [
|
||||||
'1', 'P', 'PA',
|
"1",
|
||||||
'L', 'LA', 'La',
|
"P",
|
||||||
'F', 'I', 'I;16', 'I;16L', 'I;16B', 'I;16N',
|
"PA",
|
||||||
'RGB', 'RGBX', 'RGBA', 'RGBa',
|
"L",
|
||||||
'CMYK', 'YCbCr', 'LAB', 'HSV',
|
"LA",
|
||||||
|
"La",
|
||||||
|
"F",
|
||||||
|
"I",
|
||||||
|
"I;16",
|
||||||
|
"I;16L",
|
||||||
|
"I;16B",
|
||||||
|
"I;16N",
|
||||||
|
"RGB",
|
||||||
|
"RGBX",
|
||||||
|
"RGBA",
|
||||||
|
"RGBa",
|
||||||
|
"CMYK",
|
||||||
|
"YCbCr",
|
||||||
|
"LAB",
|
||||||
|
"HSV",
|
||||||
]:
|
]:
|
||||||
Image.new(mode, (1, 1))
|
Image.new(mode, (1, 1))
|
||||||
|
|
||||||
def test_image_modes_fail(self):
|
def test_image_modes_fail(self):
|
||||||
for mode in [
|
for mode in [
|
||||||
'', 'bad', 'very very long',
|
"",
|
||||||
'BGR;15', 'BGR;16', 'BGR;24', 'BGR;32'
|
"bad",
|
||||||
|
"very very long",
|
||||||
|
"BGR;15",
|
||||||
|
"BGR;16",
|
||||||
|
"BGR;24",
|
||||||
|
"BGR;32",
|
||||||
]:
|
]:
|
||||||
with self.assertRaises(ValueError) as e:
|
with self.assertRaises(ValueError) as e:
|
||||||
Image.new(mode, (1, 1))
|
Image.new(mode, (1, 1))
|
||||||
self.assertEqual(str(e.exception), 'unrecognized image mode')
|
self.assertEqual(str(e.exception), "unrecognized image mode")
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
im = Image.new("L", (100, 100))
|
im = Image.new("L", (100, 100))
|
||||||
self.assertEqual(
|
self.assertEqual(repr(im)[:45], "<PIL.Image.Image image mode=L size=100x100 at")
|
||||||
repr(im)[:45], "<PIL.Image.Image image mode=L size=100x100 at")
|
|
||||||
self.assertEqual(im.mode, "L")
|
self.assertEqual(im.mode, "L")
|
||||||
self.assertEqual(im.size, (100, 100))
|
self.assertEqual(im.size, (100, 100))
|
||||||
|
|
||||||
im = Image.new("RGB", (100, 100))
|
im = Image.new("RGB", (100, 100))
|
||||||
self.assertEqual(
|
self.assertEqual(repr(im)[:45], "<PIL.Image.Image image mode=RGB size=100x100 ")
|
||||||
repr(im)[:45], "<PIL.Image.Image image mode=RGB size=100x100 ")
|
|
||||||
self.assertEqual(im.mode, "RGB")
|
self.assertEqual(im.mode, "RGB")
|
||||||
self.assertEqual(im.size, (100, 100))
|
self.assertEqual(im.size, (100, 100))
|
||||||
|
|
||||||
|
@ -64,10 +81,12 @@ class TestImage(PillowTestCase):
|
||||||
def test_invalid_image(self):
|
def test_invalid_image(self):
|
||||||
if py3:
|
if py3:
|
||||||
import io
|
import io
|
||||||
im = io.BytesIO(b'')
|
|
||||||
|
im = io.BytesIO(b"")
|
||||||
else:
|
else:
|
||||||
import StringIO
|
import StringIO
|
||||||
im = StringIO.StringIO('')
|
|
||||||
|
im = StringIO.StringIO("")
|
||||||
self.assertRaises(IOError, Image.open, im)
|
self.assertRaises(IOError, Image.open, im)
|
||||||
|
|
||||||
def test_bad_mode(self):
|
def test_bad_mode(self):
|
||||||
|
@ -76,6 +95,7 @@ class TestImage(PillowTestCase):
|
||||||
@unittest.skipUnless(Image.HAS_PATHLIB, "requires pathlib/pathlib2")
|
@unittest.skipUnless(Image.HAS_PATHLIB, "requires pathlib/pathlib2")
|
||||||
def test_pathlib(self):
|
def test_pathlib(self):
|
||||||
from PIL.Image import Path
|
from PIL.Image import Path
|
||||||
|
|
||||||
im = Image.open(Path("Tests/images/multipage-mmap.tiff"))
|
im = Image.open(Path("Tests/images/multipage-mmap.tiff"))
|
||||||
self.assertEqual(im.mode, "P")
|
self.assertEqual(im.mode, "P")
|
||||||
self.assertEqual(im.size, (10, 10))
|
self.assertEqual(im.size, (10, 10))
|
||||||
|
@ -95,6 +115,7 @@ class TestImage(PillowTestCase):
|
||||||
class FP(object):
|
class FP(object):
|
||||||
def write(a, b):
|
def write(a, b):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
fp = FP()
|
fp = FP()
|
||||||
fp.name = temp_file
|
fp.name = temp_file
|
||||||
|
|
||||||
|
@ -105,9 +126,10 @@ class TestImage(PillowTestCase):
|
||||||
# see #1460, pathlib support breaks tempfile.TemporaryFile on py27
|
# see #1460, pathlib support breaks tempfile.TemporaryFile on py27
|
||||||
# Will error out on save on 3.0.0
|
# Will error out on save on 3.0.0
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
im = hopper()
|
im = hopper()
|
||||||
with tempfile.TemporaryFile() as fp:
|
with tempfile.TemporaryFile() as fp:
|
||||||
im.save(fp, 'JPEG')
|
im.save(fp, "JPEG")
|
||||||
fp.seek(0)
|
fp.seek(0)
|
||||||
reloaded = Image.open(fp)
|
reloaded = Image.open(fp)
|
||||||
self.assert_image_similar(im, reloaded, 20)
|
self.assert_image_similar(im, reloaded, 20)
|
||||||
|
@ -127,8 +149,9 @@ class TestImage(PillowTestCase):
|
||||||
im.paste(0, (0, 0, 100, 100))
|
im.paste(0, (0, 0, 100, 100))
|
||||||
self.assertFalse(im.readonly)
|
self.assertFalse(im.readonly)
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform.startswith('win32'),
|
@unittest.skipIf(
|
||||||
"Test requires opening tempfile twice")
|
sys.platform.startswith("win32"), "Test requires opening tempfile twice"
|
||||||
|
)
|
||||||
def test_readonly_save(self):
|
def test_readonly_save(self):
|
||||||
temp_file = self.tempfile("temp.bmp")
|
temp_file = self.tempfile("temp.bmp")
|
||||||
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
|
shutil.copy("Tests/images/rgb32bf-rgba.bmp", temp_file)
|
||||||
|
@ -149,7 +172,7 @@ class TestImage(PillowTestCase):
|
||||||
|
|
||||||
def test_comparison_with_other_type(self):
|
def test_comparison_with_other_type(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
item = Image.new('RGB', (25, 25), '#000')
|
item = Image.new("RGB", (25, 25), "#000")
|
||||||
num = 12
|
num = 12
|
||||||
|
|
||||||
# Act/Assert
|
# Act/Assert
|
||||||
|
@ -167,8 +190,8 @@ class TestImage(PillowTestCase):
|
||||||
im = im._expand(xmargin)
|
im = im._expand(xmargin)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(im.size[0], orig_size[0] + 2*xmargin)
|
self.assertEqual(im.size[0], orig_size[0] + 2 * xmargin)
|
||||||
self.assertEqual(im.size[1], orig_size[1] + 2*xmargin)
|
self.assertEqual(im.size[1], orig_size[1] + 2 * xmargin)
|
||||||
|
|
||||||
def test_expand_xy(self):
|
def test_expand_xy(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
@ -181,32 +204,32 @@ class TestImage(PillowTestCase):
|
||||||
im = im._expand(xmargin, ymargin)
|
im = im._expand(xmargin, ymargin)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(im.size[0], orig_size[0] + 2*xmargin)
|
self.assertEqual(im.size[0], orig_size[0] + 2 * xmargin)
|
||||||
self.assertEqual(im.size[1], orig_size[1] + 2*ymargin)
|
self.assertEqual(im.size[1], orig_size[1] + 2 * ymargin)
|
||||||
|
|
||||||
def test_getbands(self):
|
def test_getbands(self):
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(hopper('RGB').getbands(), ('R', 'G', 'B'))
|
self.assertEqual(hopper("RGB").getbands(), ("R", "G", "B"))
|
||||||
self.assertEqual(hopper('YCbCr').getbands(), ('Y', 'Cb', 'Cr'))
|
self.assertEqual(hopper("YCbCr").getbands(), ("Y", "Cb", "Cr"))
|
||||||
|
|
||||||
def test_getchannel_wrong_params(self):
|
def test_getchannel_wrong_params(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
||||||
self.assertRaises(ValueError, im.getchannel, -1)
|
self.assertRaises(ValueError, im.getchannel, -1)
|
||||||
self.assertRaises(ValueError, im.getchannel, 3)
|
self.assertRaises(ValueError, im.getchannel, 3)
|
||||||
self.assertRaises(ValueError, im.getchannel, 'Z')
|
self.assertRaises(ValueError, im.getchannel, "Z")
|
||||||
self.assertRaises(ValueError, im.getchannel, '1')
|
self.assertRaises(ValueError, im.getchannel, "1")
|
||||||
|
|
||||||
def test_getchannel(self):
|
def test_getchannel(self):
|
||||||
im = hopper('YCbCr')
|
im = hopper("YCbCr")
|
||||||
Y, Cb, Cr = im.split()
|
Y, Cb, Cr = im.split()
|
||||||
|
|
||||||
self.assert_image_equal(Y, im.getchannel(0))
|
self.assert_image_equal(Y, im.getchannel(0))
|
||||||
self.assert_image_equal(Y, im.getchannel('Y'))
|
self.assert_image_equal(Y, im.getchannel("Y"))
|
||||||
self.assert_image_equal(Cb, im.getchannel(1))
|
self.assert_image_equal(Cb, im.getchannel(1))
|
||||||
self.assert_image_equal(Cb, im.getchannel('Cb'))
|
self.assert_image_equal(Cb, im.getchannel("Cb"))
|
||||||
self.assert_image_equal(Cr, im.getchannel(2))
|
self.assert_image_equal(Cr, im.getchannel(2))
|
||||||
self.assert_image_equal(Cr, im.getchannel('Cr'))
|
self.assert_image_equal(Cr, im.getchannel("Cr"))
|
||||||
|
|
||||||
def test_getbbox(self):
|
def test_getbbox(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
@ -220,8 +243,8 @@ class TestImage(PillowTestCase):
|
||||||
|
|
||||||
def test_ne(self):
|
def test_ne(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
im1 = Image.new('RGB', (25, 25), 'black')
|
im1 = Image.new("RGB", (25, 25), "black")
|
||||||
im2 = Image.new('RGB', (25, 25), 'white')
|
im2 = Image.new("RGB", (25, 25), "white")
|
||||||
|
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertNotEqual(im1, im2)
|
self.assertNotEqual(im1, im2)
|
||||||
|
@ -231,20 +254,23 @@ class TestImage(PillowTestCase):
|
||||||
# Arrange
|
# Arrange
|
||||||
from PIL import ImageDraw
|
from PIL import ImageDraw
|
||||||
|
|
||||||
expected_colors = sorted([
|
expected_colors = sorted(
|
||||||
(1122, (128, 127, 0, 255)),
|
[
|
||||||
(1089, (0, 255, 0, 255)),
|
(1122, (128, 127, 0, 255)),
|
||||||
(3300, (255, 0, 0, 255)),
|
(1089, (0, 255, 0, 255)),
|
||||||
(1156, (170, 85, 0, 192)),
|
(3300, (255, 0, 0, 255)),
|
||||||
(1122, (0, 255, 0, 128)),
|
(1156, (170, 85, 0, 192)),
|
||||||
(1122, (255, 0, 0, 128)),
|
(1122, (0, 255, 0, 128)),
|
||||||
(1089, (0, 255, 0, 0))])
|
(1122, (255, 0, 0, 128)),
|
||||||
|
(1089, (0, 255, 0, 0)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
dst = Image.new('RGBA', size=(100, 100), color=(0, 255, 0, 255))
|
dst = Image.new("RGBA", size=(100, 100), color=(0, 255, 0, 255))
|
||||||
draw = ImageDraw.Draw(dst)
|
draw = ImageDraw.Draw(dst)
|
||||||
draw.rectangle((0, 33, 100, 66), fill=(0, 255, 0, 128))
|
draw.rectangle((0, 33, 100, 66), fill=(0, 255, 0, 128))
|
||||||
draw.rectangle((0, 67, 100, 100), fill=(0, 255, 0, 0))
|
draw.rectangle((0, 67, 100, 100), fill=(0, 255, 0, 0))
|
||||||
src = Image.new('RGBA', size=(100, 100), color=(255, 0, 0, 255))
|
src = Image.new("RGBA", size=(100, 100), color=(255, 0, 0, 255))
|
||||||
draw = ImageDraw.Draw(src)
|
draw = ImageDraw.Draw(src)
|
||||||
draw.rectangle((33, 0, 66, 100), fill=(255, 0, 0, 128))
|
draw.rectangle((33, 0, 66, 100), fill=(255, 0, 0, 128))
|
||||||
draw.rectangle((67, 0, 100, 100), fill=(255, 0, 0, 0))
|
draw.rectangle((67, 0, 100, 100), fill=(255, 0, 0, 0))
|
||||||
|
@ -257,10 +283,10 @@ class TestImage(PillowTestCase):
|
||||||
self.assertEqual(img_colors, expected_colors)
|
self.assertEqual(img_colors, expected_colors)
|
||||||
|
|
||||||
def test_alpha_inplace(self):
|
def test_alpha_inplace(self):
|
||||||
src = Image.new('RGBA', (128, 128), 'blue')
|
src = Image.new("RGBA", (128, 128), "blue")
|
||||||
|
|
||||||
over = Image.new('RGBA', (128, 128), 'red')
|
over = Image.new("RGBA", (128, 128), "red")
|
||||||
mask = hopper('L')
|
mask = hopper("L")
|
||||||
over.putalpha(mask)
|
over.putalpha(mask)
|
||||||
|
|
||||||
target = Image.alpha_composite(src, over)
|
target = Image.alpha_composite(src, over)
|
||||||
|
@ -273,41 +299,36 @@ class TestImage(PillowTestCase):
|
||||||
# with offset down to right
|
# with offset down to right
|
||||||
offset = src.copy()
|
offset = src.copy()
|
||||||
offset.alpha_composite(over, (64, 64))
|
offset.alpha_composite(over, (64, 64))
|
||||||
self.assert_image_equal(offset.crop((64, 64, 127, 127)),
|
self.assert_image_equal(
|
||||||
target.crop((0, 0, 63, 63)))
|
offset.crop((64, 64, 127, 127)), target.crop((0, 0, 63, 63))
|
||||||
|
)
|
||||||
self.assertEqual(offset.size, (128, 128))
|
self.assertEqual(offset.size, (128, 128))
|
||||||
|
|
||||||
# offset and crop
|
# offset and crop
|
||||||
box = src.copy()
|
box = src.copy()
|
||||||
box.alpha_composite(over, (64, 64), (0, 0, 32, 32))
|
box.alpha_composite(over, (64, 64), (0, 0, 32, 32))
|
||||||
self.assert_image_equal(box.crop((64, 64, 96, 96)),
|
self.assert_image_equal(box.crop((64, 64, 96, 96)), target.crop((0, 0, 32, 32)))
|
||||||
target.crop((0, 0, 32, 32)))
|
self.assert_image_equal(box.crop((96, 96, 128, 128)), src.crop((0, 0, 32, 32)))
|
||||||
self.assert_image_equal(box.crop((96, 96, 128, 128)),
|
|
||||||
src.crop((0, 0, 32, 32)))
|
|
||||||
self.assertEqual(box.size, (128, 128))
|
self.assertEqual(box.size, (128, 128))
|
||||||
|
|
||||||
# source point
|
# source point
|
||||||
source = src.copy()
|
source = src.copy()
|
||||||
source.alpha_composite(over, (32, 32), (32, 32, 96, 96))
|
source.alpha_composite(over, (32, 32), (32, 32, 96, 96))
|
||||||
|
|
||||||
self.assert_image_equal(source.crop((32, 32, 96, 96)),
|
self.assert_image_equal(
|
||||||
target.crop((32, 32, 96, 96)))
|
source.crop((32, 32, 96, 96)), target.crop((32, 32, 96, 96))
|
||||||
|
)
|
||||||
self.assertEqual(source.size, (128, 128))
|
self.assertEqual(source.size, (128, 128))
|
||||||
|
|
||||||
# errors
|
# errors
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, source.alpha_composite, over, "invalid source")
|
||||||
source.alpha_composite, over, "invalid source")
|
self.assertRaises(
|
||||||
self.assertRaises(ValueError,
|
ValueError, source.alpha_composite, over, (0, 0), "invalid destination"
|
||||||
source.alpha_composite, over, (0, 0),
|
)
|
||||||
"invalid destination")
|
self.assertRaises(ValueError, source.alpha_composite, over, 0)
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, source.alpha_composite, over, (0, 0), 0)
|
||||||
source.alpha_composite, over, 0)
|
self.assertRaises(ValueError, source.alpha_composite, over, (0, -1))
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, source.alpha_composite, over, (0, 0), (0, -1))
|
||||||
source.alpha_composite, over, (0, 0), 0)
|
|
||||||
self.assertRaises(ValueError,
|
|
||||||
source.alpha_composite, over, (0, -1))
|
|
||||||
self.assertRaises(ValueError,
|
|
||||||
source.alpha_composite, over, (0, 0), (0, -1))
|
|
||||||
|
|
||||||
def test_registered_extensions_uninitialized(self):
|
def test_registered_extensions_uninitialized(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
@ -328,14 +349,14 @@ class TestImage(PillowTestCase):
|
||||||
def test_registered_extensions(self):
|
def test_registered_extensions(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
# Open an image to trigger plugin registration
|
# Open an image to trigger plugin registration
|
||||||
Image.open('Tests/images/rgb.jpg')
|
Image.open("Tests/images/rgb.jpg")
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
extensions = Image.registered_extensions()
|
extensions = Image.registered_extensions()
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertTrue(extensions)
|
self.assertTrue(extensions)
|
||||||
for ext in ['.cur', '.icns', '.tif', '.tiff']:
|
for ext in [".cur", ".icns", ".tif", ".tiff"]:
|
||||||
self.assertIn(ext, extensions)
|
self.assertIn(ext, extensions)
|
||||||
|
|
||||||
def test_effect_mandelbrot(self):
|
def test_effect_mandelbrot(self):
|
||||||
|
@ -349,7 +370,7 @@ class TestImage(PillowTestCase):
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(im.size, (512, 512))
|
self.assertEqual(im.size, (512, 512))
|
||||||
im2 = Image.open('Tests/images/effect_mandelbrot.png')
|
im2 = Image.open("Tests/images/effect_mandelbrot.png")
|
||||||
self.assert_image_equal(im, im2)
|
self.assert_image_equal(im, im2)
|
||||||
|
|
||||||
def test_effect_mandelbrot_bad_arguments(self):
|
def test_effect_mandelbrot_bad_arguments(self):
|
||||||
|
@ -361,9 +382,7 @@ class TestImage(PillowTestCase):
|
||||||
quality = 1
|
quality = 1
|
||||||
|
|
||||||
# Act/Assert
|
# Act/Assert
|
||||||
self.assertRaises(
|
self.assertRaises(ValueError, Image.effect_mandelbrot, size, extent, quality)
|
||||||
ValueError,
|
|
||||||
Image.effect_mandelbrot, size, extent, quality)
|
|
||||||
|
|
||||||
def test_effect_noise(self):
|
def test_effect_noise(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
@ -393,32 +412,32 @@ class TestImage(PillowTestCase):
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(im.size, (128, 128))
|
self.assertEqual(im.size, (128, 128))
|
||||||
im3 = Image.open('Tests/images/effect_spread.png')
|
im3 = Image.open("Tests/images/effect_spread.png")
|
||||||
self.assert_image_similar(im2, im3, 110)
|
self.assert_image_similar(im2, im3, 110)
|
||||||
|
|
||||||
def test_check_size(self):
|
def test_check_size(self):
|
||||||
# Checking that the _check_size function throws value errors
|
# Checking that the _check_size function throws value errors
|
||||||
# when we want it to.
|
# when we want it to.
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
Image.new('RGB', 0) # not a tuple
|
Image.new("RGB", 0) # not a tuple
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
Image.new('RGB', (0,)) # Tuple too short
|
Image.new("RGB", (0,)) # Tuple too short
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
Image.new('RGB', (-1, -1)) # w,h < 0
|
Image.new("RGB", (-1, -1)) # w,h < 0
|
||||||
|
|
||||||
# this should pass with 0 sized images, #2259
|
# this should pass with 0 sized images, #2259
|
||||||
im = Image.new('L', (0, 0))
|
im = Image.new("L", (0, 0))
|
||||||
self.assertEqual(im.size, (0, 0))
|
self.assertEqual(im.size, (0, 0))
|
||||||
|
|
||||||
im = Image.new('L', (0, 100))
|
im = Image.new("L", (0, 100))
|
||||||
self.assertEqual(im.size, (0, 100))
|
self.assertEqual(im.size, (0, 100))
|
||||||
|
|
||||||
im = Image.new('L', (100, 0))
|
im = Image.new("L", (100, 0))
|
||||||
self.assertEqual(im.size, (100, 0))
|
self.assertEqual(im.size, (100, 0))
|
||||||
|
|
||||||
self.assertTrue(Image.new('RGB', (1, 1)))
|
self.assertTrue(Image.new("RGB", (1, 1)))
|
||||||
# Should pass lists too
|
# Should pass lists too
|
||||||
i = Image.new('RGB', [1, 1])
|
i = Image.new("RGB", [1, 1])
|
||||||
self.assertIsInstance(i.size, tuple)
|
self.assertIsInstance(i.size, tuple)
|
||||||
|
|
||||||
def test_storage_neg(self):
|
def test_storage_neg(self):
|
||||||
|
@ -428,7 +447,7 @@ class TestImage(PillowTestCase):
|
||||||
# Storage.c, rather than the size check above
|
# Storage.c, rather than the size check above
|
||||||
|
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
Image.core.fill('RGB', (2, -2), (0, 0, 0))
|
Image.core.fill("RGB", (2, -2), (0, 0, 0))
|
||||||
|
|
||||||
def test_offset_not_implemented(self):
|
def test_offset_not_implemented(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
|
@ -445,8 +464,7 @@ class TestImage(PillowTestCase):
|
||||||
wrong_mode = "RGB"
|
wrong_mode = "RGB"
|
||||||
|
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, Image.linear_gradient, wrong_mode)
|
||||||
Image.linear_gradient, wrong_mode)
|
|
||||||
|
|
||||||
def test_linear_gradient(self):
|
def test_linear_gradient(self):
|
||||||
|
|
||||||
|
@ -470,8 +488,7 @@ class TestImage(PillowTestCase):
|
||||||
wrong_mode = "RGB"
|
wrong_mode = "RGB"
|
||||||
|
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, Image.radial_gradient, wrong_mode)
|
||||||
Image.radial_gradient, wrong_mode)
|
|
||||||
|
|
||||||
def test_radial_gradient(self):
|
def test_radial_gradient(self):
|
||||||
|
|
||||||
|
@ -514,11 +531,11 @@ class TestImage(PillowTestCase):
|
||||||
def test__new(self):
|
def test__new(self):
|
||||||
from PIL import ImagePalette
|
from PIL import ImagePalette
|
||||||
|
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
im_p = hopper('P')
|
im_p = hopper("P")
|
||||||
|
|
||||||
blank_p = Image.new('P', (10, 10))
|
blank_p = Image.new("P", (10, 10))
|
||||||
blank_pa = Image.new('PA', (10, 10))
|
blank_pa = Image.new("PA", (10, 10))
|
||||||
blank_p.palette = None
|
blank_p.palette = None
|
||||||
blank_pa.palette = None
|
blank_pa.palette = None
|
||||||
|
|
||||||
|
@ -528,8 +545,7 @@ class TestImage(PillowTestCase):
|
||||||
self.assertEqual(new_im.size, im.size)
|
self.assertEqual(new_im.size, im.size)
|
||||||
self.assertEqual(new_im.info, base_image.info)
|
self.assertEqual(new_im.info, base_image.info)
|
||||||
if palette_result is not None:
|
if palette_result is not None:
|
||||||
self.assertEqual(new_im.palette.tobytes(),
|
self.assertEqual(new_im.palette.tobytes(), palette_result.tobytes())
|
||||||
palette_result.tobytes())
|
|
||||||
else:
|
else:
|
||||||
self.assertIsNone(new_im.palette)
|
self.assertIsNone(new_im.palette)
|
||||||
|
|
||||||
|
@ -540,9 +556,9 @@ class TestImage(PillowTestCase):
|
||||||
|
|
||||||
def test_p_from_rgb_rgba(self):
|
def test_p_from_rgb_rgba(self):
|
||||||
for mode, color in [
|
for mode, color in [
|
||||||
("RGB", '#DDEEFF'),
|
("RGB", "#DDEEFF"),
|
||||||
("RGB", (221, 238, 255)),
|
("RGB", (221, 238, 255)),
|
||||||
("RGBA", (221, 238, 255, 255))
|
("RGBA", (221, 238, 255, 255)),
|
||||||
]:
|
]:
|
||||||
im = Image.new("P", (100, 100), color)
|
im = Image.new("P", (100, 100), color)
|
||||||
expected = Image.new(mode, (100, 100), color)
|
expected = Image.new(mode, (100, 100), color)
|
||||||
|
@ -551,7 +567,7 @@ class TestImage(PillowTestCase):
|
||||||
def test_no_resource_warning_on_save(self):
|
def test_no_resource_warning_on_save(self):
|
||||||
# https://github.com/python-pillow/Pillow/issues/835
|
# https://github.com/python-pillow/Pillow/issues/835
|
||||||
# Arrange
|
# Arrange
|
||||||
test_file = 'Tests/images/hopper.png'
|
test_file = "Tests/images/hopper.png"
|
||||||
temp_file = self.tempfile("temp.jpg")
|
temp_file = self.tempfile("temp.jpg")
|
||||||
|
|
||||||
# Act/Assert
|
# Act/Assert
|
||||||
|
@ -560,9 +576,11 @@ class TestImage(PillowTestCase):
|
||||||
|
|
||||||
def test_load_on_nonexclusive_multiframe(self):
|
def test_load_on_nonexclusive_multiframe(self):
|
||||||
with open("Tests/images/frozenpond.mpo", "rb") as fp:
|
with open("Tests/images/frozenpond.mpo", "rb") as fp:
|
||||||
|
|
||||||
def act(fp):
|
def act(fp):
|
||||||
im = Image.open(fp)
|
im = Image.open(fp)
|
||||||
im.load()
|
im.load()
|
||||||
|
|
||||||
act(fp)
|
act(fp)
|
||||||
|
|
||||||
with Image.open(fp) as im:
|
with Image.open(fp) as im:
|
||||||
|
@ -582,19 +600,22 @@ def mock_encode(*args):
|
||||||
|
|
||||||
|
|
||||||
class TestRegistry(PillowTestCase):
|
class TestRegistry(PillowTestCase):
|
||||||
|
|
||||||
def test_encode_registry(self):
|
def test_encode_registry(self):
|
||||||
|
|
||||||
Image.register_encoder('MOCK', mock_encode)
|
Image.register_encoder("MOCK", mock_encode)
|
||||||
self.assertIn('MOCK', Image.ENCODERS)
|
self.assertIn("MOCK", Image.ENCODERS)
|
||||||
|
|
||||||
enc = Image._getencoder('RGB', 'MOCK', ('args',), extra=('extra',))
|
enc = Image._getencoder("RGB", "MOCK", ("args",), extra=("extra",))
|
||||||
|
|
||||||
self.assertIsInstance(enc, MockEncoder)
|
self.assertIsInstance(enc, MockEncoder)
|
||||||
self.assertEqual(enc.args, ('RGB', 'args', 'extra'))
|
self.assertEqual(enc.args, ("RGB", "args", "extra"))
|
||||||
|
|
||||||
def test_encode_registry_fail(self):
|
def test_encode_registry_fail(self):
|
||||||
self.assertRaises(IOError, Image._getencoder, 'RGB',
|
self.assertRaises(
|
||||||
'DoesNotExist',
|
IOError,
|
||||||
('args',),
|
Image._getencoder,
|
||||||
extra=('extra',))
|
"RGB",
|
||||||
|
"DoesNotExist",
|
||||||
|
("args",),
|
||||||
|
extra=("extra",),
|
||||||
|
)
|
||||||
|
|
|
@ -70,11 +70,10 @@ class TestImagePutPixel(AccessTest):
|
||||||
|
|
||||||
width, height = im1.size
|
width, height = im1.size
|
||||||
self.assertEqual(im1.getpixel((0, 0)), im1.getpixel((-width, -height)))
|
self.assertEqual(im1.getpixel((0, 0)), im1.getpixel((-width, -height)))
|
||||||
self.assertEqual(im1.getpixel((-1, -1)),
|
self.assertEqual(im1.getpixel((-1, -1)), im1.getpixel((width - 1, height - 1)))
|
||||||
im1.getpixel((width-1, height-1)))
|
|
||||||
|
|
||||||
for y in range(-1, -im1.size[1]-1, -1):
|
for y in range(-1, -im1.size[1] - 1, -1):
|
||||||
for x in range(-1, -im1.size[0]-1, -1):
|
for x in range(-1, -im1.size[0] - 1, -1):
|
||||||
pos = x, y
|
pos = x, y
|
||||||
im2.putpixel(pos, im1.getpixel(pos))
|
im2.putpixel(pos, im1.getpixel(pos))
|
||||||
|
|
||||||
|
@ -83,8 +82,8 @@ class TestImagePutPixel(AccessTest):
|
||||||
im2 = Image.new(im1.mode, im1.size, 0)
|
im2 = Image.new(im1.mode, im1.size, 0)
|
||||||
im2.readonly = 1
|
im2.readonly = 1
|
||||||
|
|
||||||
for y in range(-1, -im1.size[1]-1, -1):
|
for y in range(-1, -im1.size[1] - 1, -1):
|
||||||
for x in range(-1, -im1.size[0]-1, -1):
|
for x in range(-1, -im1.size[0] - 1, -1):
|
||||||
pos = x, y
|
pos = x, y
|
||||||
im2.putpixel(pos, im1.getpixel(pos))
|
im2.putpixel(pos, im1.getpixel(pos))
|
||||||
|
|
||||||
|
@ -96,8 +95,8 @@ class TestImagePutPixel(AccessTest):
|
||||||
pix1 = im1.load()
|
pix1 = im1.load()
|
||||||
pix2 = im2.load()
|
pix2 = im2.load()
|
||||||
|
|
||||||
for y in range(-1, -im1.size[1]-1, -1):
|
for y in range(-1, -im1.size[1] - 1, -1):
|
||||||
for x in range(-1, -im1.size[0]-1, -1):
|
for x in range(-1, -im1.size[0] - 1, -1):
|
||||||
pix2[x, y] = pix1[x, y]
|
pix2[x, y] = pix1[x, y]
|
||||||
|
|
||||||
self.assert_image_equal(im1, im2)
|
self.assert_image_equal(im1, im2)
|
||||||
|
@ -120,15 +119,19 @@ class TestImageGetPixel(AccessTest):
|
||||||
im = Image.new(mode, (1, 1), None)
|
im = Image.new(mode, (1, 1), None)
|
||||||
im.putpixel((0, 0), c)
|
im.putpixel((0, 0), c)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
im.getpixel((0, 0)), c,
|
im.getpixel((0, 0)),
|
||||||
"put/getpixel roundtrip failed for mode %s, color %s" % (mode, c))
|
c,
|
||||||
|
"put/getpixel roundtrip failed for mode %s, color %s" % (mode, c),
|
||||||
|
)
|
||||||
|
|
||||||
# check putpixel negative index
|
# check putpixel negative index
|
||||||
im.putpixel((-1, -1), c)
|
im.putpixel((-1, -1), c)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
im.getpixel((-1, -1)), c,
|
im.getpixel((-1, -1)),
|
||||||
|
c,
|
||||||
"put/getpixel roundtrip negative index failed"
|
"put/getpixel roundtrip negative index failed"
|
||||||
" for mode %s, color %s" % (mode, c))
|
" for mode %s, color %s" % (mode, c),
|
||||||
|
)
|
||||||
|
|
||||||
# Check 0
|
# Check 0
|
||||||
im = Image.new(mode, (0, 0), None)
|
im = Image.new(mode, (0, 0), None)
|
||||||
|
@ -145,13 +148,17 @@ class TestImageGetPixel(AccessTest):
|
||||||
# check initial color
|
# check initial color
|
||||||
im = Image.new(mode, (1, 1), c)
|
im = Image.new(mode, (1, 1), c)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
im.getpixel((0, 0)), c,
|
im.getpixel((0, 0)),
|
||||||
"initial color failed for mode %s, color %s " % (mode, c))
|
c,
|
||||||
|
"initial color failed for mode %s, color %s " % (mode, c),
|
||||||
|
)
|
||||||
# check initial color negative index
|
# check initial color negative index
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
im.getpixel((-1, -1)), c,
|
im.getpixel((-1, -1)),
|
||||||
|
c,
|
||||||
"initial color failed with negative index"
|
"initial color failed with negative index"
|
||||||
"for mode %s, color %s " % (mode, c))
|
"for mode %s, color %s " % (mode, c),
|
||||||
|
)
|
||||||
|
|
||||||
# Check 0
|
# Check 0
|
||||||
im = Image.new(mode, (0, 0), c)
|
im = Image.new(mode, (0, 0), c)
|
||||||
|
@ -162,18 +169,32 @@ class TestImageGetPixel(AccessTest):
|
||||||
im.getpixel((-1, -1))
|
im.getpixel((-1, -1))
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
for mode in ("1", "L", "LA", "I", "I;16", "I;16B", "F",
|
for mode in (
|
||||||
"P", "PA", "RGB", "RGBA", "RGBX", "CMYK", "YCbCr"):
|
"1",
|
||||||
|
"L",
|
||||||
|
"LA",
|
||||||
|
"I",
|
||||||
|
"I;16",
|
||||||
|
"I;16B",
|
||||||
|
"F",
|
||||||
|
"P",
|
||||||
|
"PA",
|
||||||
|
"RGB",
|
||||||
|
"RGBA",
|
||||||
|
"RGBX",
|
||||||
|
"CMYK",
|
||||||
|
"YCbCr",
|
||||||
|
):
|
||||||
self.check(mode)
|
self.check(mode)
|
||||||
|
|
||||||
def test_signedness(self):
|
def test_signedness(self):
|
||||||
# see https://github.com/python-pillow/Pillow/issues/452
|
# see https://github.com/python-pillow/Pillow/issues/452
|
||||||
# pixelaccess is using signed int* instead of uint*
|
# pixelaccess is using signed int* instead of uint*
|
||||||
for mode in ("I;16", "I;16B"):
|
for mode in ("I;16", "I;16B"):
|
||||||
self.check(mode, 2**15-1)
|
self.check(mode, 2 ** 15 - 1)
|
||||||
self.check(mode, 2**15)
|
self.check(mode, 2 ** 15)
|
||||||
self.check(mode, 2**15+1)
|
self.check(mode, 2 ** 15 + 1)
|
||||||
self.check(mode, 2**16-1)
|
self.check(mode, 2 ** 16 - 1)
|
||||||
|
|
||||||
def test_p_putpixel_rgb_rgba(self):
|
def test_p_putpixel_rgb_rgba(self):
|
||||||
for color in [(255, 0, 0), (255, 0, 0, 255)]:
|
for color in [(255, 0, 0), (255, 0, 0, 255)]:
|
||||||
|
@ -210,29 +231,30 @@ class TestCffi(AccessTest):
|
||||||
self.assertEqual(access[(x, y)], caccess[(x, y)])
|
self.assertEqual(access[(x, y)], caccess[(x, y)])
|
||||||
|
|
||||||
# Access an out-of-range pixel
|
# Access an out-of-range pixel
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(
|
||||||
lambda: access[(access.xsize+1, access.ysize+1)])
|
ValueError, lambda: access[(access.xsize + 1, access.ysize + 1)]
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_vs_c(self):
|
def test_get_vs_c(self):
|
||||||
rgb = hopper('RGB')
|
rgb = hopper("RGB")
|
||||||
rgb.load()
|
rgb.load()
|
||||||
self._test_get_access(rgb)
|
self._test_get_access(rgb)
|
||||||
self._test_get_access(hopper('RGBA'))
|
self._test_get_access(hopper("RGBA"))
|
||||||
self._test_get_access(hopper('L'))
|
self._test_get_access(hopper("L"))
|
||||||
self._test_get_access(hopper('LA'))
|
self._test_get_access(hopper("LA"))
|
||||||
self._test_get_access(hopper('1'))
|
self._test_get_access(hopper("1"))
|
||||||
self._test_get_access(hopper('P'))
|
self._test_get_access(hopper("P"))
|
||||||
# self._test_get_access(hopper('PA')) # PA -- how do I make a PA image?
|
# self._test_get_access(hopper('PA')) # PA -- how do I make a PA image?
|
||||||
self._test_get_access(hopper('F'))
|
self._test_get_access(hopper("F"))
|
||||||
|
|
||||||
im = Image.new('I;16', (10, 10), 40000)
|
im = Image.new("I;16", (10, 10), 40000)
|
||||||
self._test_get_access(im)
|
self._test_get_access(im)
|
||||||
im = Image.new('I;16L', (10, 10), 40000)
|
im = Image.new("I;16L", (10, 10), 40000)
|
||||||
self._test_get_access(im)
|
self._test_get_access(im)
|
||||||
im = Image.new('I;16B', (10, 10), 40000)
|
im = Image.new("I;16B", (10, 10), 40000)
|
||||||
self._test_get_access(im)
|
self._test_get_access(im)
|
||||||
|
|
||||||
im = Image.new('I', (10, 10), 40000)
|
im = Image.new("I", (10, 10), 40000)
|
||||||
self._test_get_access(im)
|
self._test_get_access(im)
|
||||||
# These don't actually appear to be modes that I can actually make,
|
# These don't actually appear to be modes that I can actually make,
|
||||||
# as unpack sets them directly into the I mode.
|
# as unpack sets them directly into the I mode.
|
||||||
|
@ -261,25 +283,25 @@ class TestCffi(AccessTest):
|
||||||
access[(0, 0)] = color
|
access[(0, 0)] = color
|
||||||
|
|
||||||
def test_set_vs_c(self):
|
def test_set_vs_c(self):
|
||||||
rgb = hopper('RGB')
|
rgb = hopper("RGB")
|
||||||
rgb.load()
|
rgb.load()
|
||||||
self._test_set_access(rgb, (255, 128, 0))
|
self._test_set_access(rgb, (255, 128, 0))
|
||||||
self._test_set_access(hopper('RGBA'), (255, 192, 128, 0))
|
self._test_set_access(hopper("RGBA"), (255, 192, 128, 0))
|
||||||
self._test_set_access(hopper('L'), 128)
|
self._test_set_access(hopper("L"), 128)
|
||||||
self._test_set_access(hopper('LA'), (128, 128))
|
self._test_set_access(hopper("LA"), (128, 128))
|
||||||
self._test_set_access(hopper('1'), 255)
|
self._test_set_access(hopper("1"), 255)
|
||||||
self._test_set_access(hopper('P'), 128)
|
self._test_set_access(hopper("P"), 128)
|
||||||
# self._test_set_access(i, (128, 128)) #PA -- undone how to make
|
# self._test_set_access(i, (128, 128)) #PA -- undone how to make
|
||||||
self._test_set_access(hopper('F'), 1024.0)
|
self._test_set_access(hopper("F"), 1024.0)
|
||||||
|
|
||||||
im = Image.new('I;16', (10, 10), 40000)
|
im = Image.new("I;16", (10, 10), 40000)
|
||||||
self._test_set_access(im, 45000)
|
self._test_set_access(im, 45000)
|
||||||
im = Image.new('I;16L', (10, 10), 40000)
|
im = Image.new("I;16L", (10, 10), 40000)
|
||||||
self._test_set_access(im, 45000)
|
self._test_set_access(im, 45000)
|
||||||
im = Image.new('I;16B', (10, 10), 40000)
|
im = Image.new("I;16B", (10, 10), 40000)
|
||||||
self._test_set_access(im, 45000)
|
self._test_set_access(im, 45000)
|
||||||
|
|
||||||
im = Image.new('I', (10, 10), 40000)
|
im = Image.new("I", (10, 10), 40000)
|
||||||
self._test_set_access(im, 45000)
|
self._test_set_access(im, 45000)
|
||||||
# im = Image.new('I;32L', (10, 10), -(2**10))
|
# im = Image.new('I;32L', (10, 10), -(2**10))
|
||||||
# self._test_set_access(im, -(2**13)+1)
|
# self._test_set_access(im, -(2**13)+1)
|
||||||
|
@ -295,7 +317,7 @@ class TestCffi(AccessTest):
|
||||||
|
|
||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
# Do not save references to the image, only to the access object
|
# Do not save references to the image, only to the access object
|
||||||
px = Image.new('L', (size, 1), 0).load()
|
px = Image.new("L", (size, 1), 0).load()
|
||||||
for i in range(size):
|
for i in range(size):
|
||||||
# pixels can contain garbage if image is released
|
# pixels can contain garbage if image is released
|
||||||
self.assertEqual(px[i, 0], 0)
|
self.assertEqual(px[i, 0], 0)
|
||||||
|
@ -309,16 +331,18 @@ class TestCffi(AccessTest):
|
||||||
|
|
||||||
|
|
||||||
class TestEmbeddable(unittest.TestCase):
|
class TestEmbeddable(unittest.TestCase):
|
||||||
@unittest.skipIf(not sys.platform.startswith('win32') or
|
@unittest.skipIf(
|
||||||
on_appveyor(),
|
not sys.platform.startswith("win32") or on_appveyor(),
|
||||||
"Failing on AppVeyor when run from subprocess, not from shell")
|
"Failing on AppVeyor when run from subprocess, not from shell",
|
||||||
|
)
|
||||||
def test_embeddable(self):
|
def test_embeddable(self):
|
||||||
import subprocess
|
import subprocess
|
||||||
import ctypes
|
import ctypes
|
||||||
from distutils import ccompiler, sysconfig
|
from distutils import ccompiler, sysconfig
|
||||||
|
|
||||||
with open('embed_pil.c', 'w') as fh:
|
with open("embed_pil.c", "w") as fh:
|
||||||
fh.write("""
|
fh.write(
|
||||||
|
"""
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
|
@ -345,24 +369,27 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
""" % sys.prefix.replace('\\', '\\\\'))
|
"""
|
||||||
|
% sys.prefix.replace("\\", "\\\\")
|
||||||
|
)
|
||||||
|
|
||||||
compiler = ccompiler.new_compiler()
|
compiler = ccompiler.new_compiler()
|
||||||
compiler.add_include_dir(sysconfig.get_python_inc())
|
compiler.add_include_dir(sysconfig.get_python_inc())
|
||||||
|
|
||||||
libdir = (sysconfig.get_config_var('LIBDIR') or
|
libdir = sysconfig.get_config_var(
|
||||||
sysconfig.get_python_inc().replace('include', 'libs'))
|
"LIBDIR"
|
||||||
|
) or sysconfig.get_python_inc().replace("include", "libs")
|
||||||
print(libdir)
|
print(libdir)
|
||||||
compiler.add_library_dir(libdir)
|
compiler.add_library_dir(libdir)
|
||||||
objects = compiler.compile(['embed_pil.c'])
|
objects = compiler.compile(["embed_pil.c"])
|
||||||
compiler.link_executable(objects, 'embed_pil')
|
compiler.link_executable(objects, "embed_pil")
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env["PATH"] = sys.prefix + ';' + env["PATH"]
|
env["PATH"] = sys.prefix + ";" + env["PATH"]
|
||||||
|
|
||||||
# do not display the Windows Error Reporting dialog
|
# do not display the Windows Error Reporting dialog
|
||||||
ctypes.windll.kernel32.SetErrorMode(0x0002)
|
ctypes.windll.kernel32.SetErrorMode(0x0002)
|
||||||
|
|
||||||
process = subprocess.Popen(['embed_pil.exe'], env=env)
|
process = subprocess.Popen(["embed_pil.exe"], env=env)
|
||||||
process.communicate()
|
process.communicate()
|
||||||
self.assertEqual(process.returncode, 0)
|
self.assertEqual(process.returncode, 0)
|
||||||
|
|
|
@ -6,28 +6,25 @@ im = hopper().resize((128, 100))
|
||||||
|
|
||||||
|
|
||||||
class TestImageArray(PillowTestCase):
|
class TestImageArray(PillowTestCase):
|
||||||
|
|
||||||
def test_toarray(self):
|
def test_toarray(self):
|
||||||
def test(mode):
|
def test(mode):
|
||||||
ai = im.convert(mode).__array_interface__
|
ai = im.convert(mode).__array_interface__
|
||||||
return ai['version'], ai["shape"], ai["typestr"], len(ai["data"])
|
return ai["version"], ai["shape"], ai["typestr"], len(ai["data"])
|
||||||
|
|
||||||
# self.assertEqual(test("1"), (3, (100, 128), '|b1', 1600))
|
# self.assertEqual(test("1"), (3, (100, 128), '|b1', 1600))
|
||||||
self.assertEqual(test("L"), (3, (100, 128), '|u1', 12800))
|
self.assertEqual(test("L"), (3, (100, 128), "|u1", 12800))
|
||||||
|
|
||||||
# FIXME: wrong?
|
# FIXME: wrong?
|
||||||
self.assertEqual(test("I"), (3, (100, 128),
|
self.assertEqual(test("I"), (3, (100, 128), Image._ENDIAN + "i4", 51200))
|
||||||
Image._ENDIAN + 'i4', 51200))
|
|
||||||
# FIXME: wrong?
|
# FIXME: wrong?
|
||||||
self.assertEqual(test("F"), (3, (100, 128),
|
self.assertEqual(test("F"), (3, (100, 128), Image._ENDIAN + "f4", 51200))
|
||||||
Image._ENDIAN + 'f4', 51200))
|
|
||||||
|
|
||||||
self.assertEqual(test("LA"), (3, (100, 128, 2), '|u1', 25600))
|
self.assertEqual(test("LA"), (3, (100, 128, 2), "|u1", 25600))
|
||||||
self.assertEqual(test("RGB"), (3, (100, 128, 3), '|u1', 38400))
|
self.assertEqual(test("RGB"), (3, (100, 128, 3), "|u1", 38400))
|
||||||
self.assertEqual(test("RGBA"), (3, (100, 128, 4), '|u1', 51200))
|
self.assertEqual(test("RGBA"), (3, (100, 128, 4), "|u1", 51200))
|
||||||
self.assertEqual(test("RGBX"), (3, (100, 128, 4), '|u1', 51200))
|
self.assertEqual(test("RGBX"), (3, (100, 128, 4), "|u1", 51200))
|
||||||
|
|
||||||
def test_fromarray(self):
|
def test_fromarray(self):
|
||||||
|
|
||||||
class Wrapper(object):
|
class Wrapper(object):
|
||||||
""" Class with API matching Image.fromarray """
|
""" Class with API matching Image.fromarray """
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,26 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageConvert(PillowTestCase):
|
class TestImageConvert(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
def convert(im, mode):
|
def convert(im, mode):
|
||||||
out = im.convert(mode)
|
out = im.convert(mode)
|
||||||
self.assertEqual(out.mode, mode)
|
self.assertEqual(out.mode, mode)
|
||||||
self.assertEqual(out.size, im.size)
|
self.assertEqual(out.size, im.size)
|
||||||
|
|
||||||
modes = ("1", "L", "LA", "P", "PA", "I", "F",
|
modes = (
|
||||||
"RGB", "RGBA", "RGBX", "CMYK", "YCbCr")
|
"1",
|
||||||
|
"L",
|
||||||
|
"LA",
|
||||||
|
"P",
|
||||||
|
"PA",
|
||||||
|
"I",
|
||||||
|
"F",
|
||||||
|
"RGB",
|
||||||
|
"RGBA",
|
||||||
|
"RGBX",
|
||||||
|
"CMYK",
|
||||||
|
"YCbCr",
|
||||||
|
)
|
||||||
|
|
||||||
for mode in modes:
|
for mode in modes:
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
|
@ -38,162 +48,159 @@ class TestImageConvert(PillowTestCase):
|
||||||
|
|
||||||
def _test_float_conversion(self, im):
|
def _test_float_conversion(self, im):
|
||||||
orig = im.getpixel((5, 5))
|
orig = im.getpixel((5, 5))
|
||||||
converted = im.convert('F').getpixel((5, 5))
|
converted = im.convert("F").getpixel((5, 5))
|
||||||
self.assertEqual(orig, converted)
|
self.assertEqual(orig, converted)
|
||||||
|
|
||||||
def test_8bit(self):
|
def test_8bit(self):
|
||||||
im = Image.open('Tests/images/hopper.jpg')
|
im = Image.open("Tests/images/hopper.jpg")
|
||||||
self._test_float_conversion(im.convert('L'))
|
self._test_float_conversion(im.convert("L"))
|
||||||
|
|
||||||
def test_16bit(self):
|
def test_16bit(self):
|
||||||
im = Image.open('Tests/images/16bit.cropped.tif')
|
im = Image.open("Tests/images/16bit.cropped.tif")
|
||||||
self._test_float_conversion(im)
|
self._test_float_conversion(im)
|
||||||
|
|
||||||
def test_16bit_workaround(self):
|
def test_16bit_workaround(self):
|
||||||
im = Image.open('Tests/images/16bit.cropped.tif')
|
im = Image.open("Tests/images/16bit.cropped.tif")
|
||||||
self._test_float_conversion(im.convert('I'))
|
self._test_float_conversion(im.convert("I"))
|
||||||
|
|
||||||
def test_rgba_p(self):
|
def test_rgba_p(self):
|
||||||
im = hopper('RGBA')
|
im = hopper("RGBA")
|
||||||
im.putalpha(hopper('L'))
|
im.putalpha(hopper("L"))
|
||||||
|
|
||||||
converted = im.convert('P')
|
converted = im.convert("P")
|
||||||
comparable = converted.convert('RGBA')
|
comparable = converted.convert("RGBA")
|
||||||
|
|
||||||
self.assert_image_similar(im, comparable, 20)
|
self.assert_image_similar(im, comparable, 20)
|
||||||
|
|
||||||
def test_trns_p(self):
|
def test_trns_p(self):
|
||||||
im = hopper('P')
|
im = hopper("P")
|
||||||
im.info['transparency'] = 0
|
im.info["transparency"] = 0
|
||||||
|
|
||||||
f = self.tempfile('temp.png')
|
f = self.tempfile("temp.png")
|
||||||
|
|
||||||
im_l = im.convert('L')
|
im_l = im.convert("L")
|
||||||
self.assertEqual(im_l.info['transparency'], 0) # undone
|
self.assertEqual(im_l.info["transparency"], 0) # undone
|
||||||
im_l.save(f)
|
im_l.save(f)
|
||||||
|
|
||||||
im_rgb = im.convert('RGB')
|
im_rgb = im.convert("RGB")
|
||||||
self.assertEqual(im_rgb.info['transparency'], (0, 0, 0)) # undone
|
self.assertEqual(im_rgb.info["transparency"], (0, 0, 0)) # undone
|
||||||
im_rgb.save(f)
|
im_rgb.save(f)
|
||||||
|
|
||||||
# ref https://github.com/python-pillow/Pillow/issues/664
|
# ref https://github.com/python-pillow/Pillow/issues/664
|
||||||
|
|
||||||
def test_trns_p_rgba(self):
|
def test_trns_p_rgba(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
im = hopper('P')
|
im = hopper("P")
|
||||||
im.info['transparency'] = 128
|
im.info["transparency"] = 128
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
im_rgba = im.convert('RGBA')
|
im_rgba = im.convert("RGBA")
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
self.assertNotIn('transparency', im_rgba.info)
|
self.assertNotIn("transparency", im_rgba.info)
|
||||||
# https://github.com/python-pillow/Pillow/issues/2702
|
# https://github.com/python-pillow/Pillow/issues/2702
|
||||||
self.assertIsNone(im_rgba.palette)
|
self.assertIsNone(im_rgba.palette)
|
||||||
|
|
||||||
def test_trns_l(self):
|
def test_trns_l(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
im.info['transparency'] = 128
|
im.info["transparency"] = 128
|
||||||
|
|
||||||
f = self.tempfile('temp.png')
|
f = self.tempfile("temp.png")
|
||||||
|
|
||||||
im_rgb = im.convert('RGB')
|
im_rgb = im.convert("RGB")
|
||||||
self.assertEqual(im_rgb.info['transparency'],
|
self.assertEqual(im_rgb.info["transparency"], (128, 128, 128)) # undone
|
||||||
(128, 128, 128)) # undone
|
|
||||||
im_rgb.save(f)
|
im_rgb.save(f)
|
||||||
|
|
||||||
im_p = im.convert('P')
|
im_p = im.convert("P")
|
||||||
self.assertIn('transparency', im_p.info)
|
self.assertIn("transparency", im_p.info)
|
||||||
im_p.save(f)
|
im_p.save(f)
|
||||||
|
|
||||||
im_p = self.assert_warning(
|
im_p = self.assert_warning(UserWarning, im.convert, "P", palette=Image.ADAPTIVE)
|
||||||
UserWarning,
|
self.assertNotIn("transparency", im_p.info)
|
||||||
im.convert, 'P', palette=Image.ADAPTIVE)
|
|
||||||
self.assertNotIn('transparency', im_p.info)
|
|
||||||
im_p.save(f)
|
im_p.save(f)
|
||||||
|
|
||||||
def test_trns_RGB(self):
|
def test_trns_RGB(self):
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
im.info['transparency'] = im.getpixel((0, 0))
|
im.info["transparency"] = im.getpixel((0, 0))
|
||||||
|
|
||||||
f = self.tempfile('temp.png')
|
f = self.tempfile("temp.png")
|
||||||
|
|
||||||
im_l = im.convert('L')
|
im_l = im.convert("L")
|
||||||
self.assertEqual(im_l.info['transparency'],
|
self.assertEqual(im_l.info["transparency"], im_l.getpixel((0, 0))) # undone
|
||||||
im_l.getpixel((0, 0))) # undone
|
|
||||||
im_l.save(f)
|
im_l.save(f)
|
||||||
|
|
||||||
im_p = im.convert('P')
|
im_p = im.convert("P")
|
||||||
self.assertIn('transparency', im_p.info)
|
self.assertIn("transparency", im_p.info)
|
||||||
im_p.save(f)
|
im_p.save(f)
|
||||||
|
|
||||||
im_rgba = im.convert('RGBA')
|
im_rgba = im.convert("RGBA")
|
||||||
self.assertNotIn('transparency', im_rgba.info)
|
self.assertNotIn("transparency", im_rgba.info)
|
||||||
im_rgba.save(f)
|
im_rgba.save(f)
|
||||||
|
|
||||||
im_p = self.assert_warning(
|
im_p = self.assert_warning(UserWarning, im.convert, "P", palette=Image.ADAPTIVE)
|
||||||
UserWarning,
|
self.assertNotIn("transparency", im_p.info)
|
||||||
im.convert, 'P', palette=Image.ADAPTIVE)
|
|
||||||
self.assertNotIn('transparency', im_p.info)
|
|
||||||
im_p.save(f)
|
im_p.save(f)
|
||||||
|
|
||||||
def test_gif_with_rgba_palette_to_p(self):
|
def test_gif_with_rgba_palette_to_p(self):
|
||||||
# See https://github.com/python-pillow/Pillow/issues/2433
|
# See https://github.com/python-pillow/Pillow/issues/2433
|
||||||
im = Image.open('Tests/images/hopper.gif')
|
im = Image.open("Tests/images/hopper.gif")
|
||||||
im.info['transparency'] = 255
|
im.info["transparency"] = 255
|
||||||
im.load()
|
im.load()
|
||||||
self.assertEqual(im.palette.mode, 'RGBA')
|
self.assertEqual(im.palette.mode, "RGBA")
|
||||||
im_p = im.convert('P')
|
im_p = im.convert("P")
|
||||||
|
|
||||||
# Should not raise ValueError: unrecognized raw mode
|
# Should not raise ValueError: unrecognized raw mode
|
||||||
im_p.load()
|
im_p.load()
|
||||||
|
|
||||||
def test_p_la(self):
|
def test_p_la(self):
|
||||||
im = hopper('RGBA')
|
im = hopper("RGBA")
|
||||||
alpha = hopper('L')
|
alpha = hopper("L")
|
||||||
im.putalpha(alpha)
|
im.putalpha(alpha)
|
||||||
|
|
||||||
comparable = im.convert('P').convert('LA').getchannel('A')
|
comparable = im.convert("P").convert("LA").getchannel("A")
|
||||||
|
|
||||||
self.assert_image_similar(alpha, comparable, 5)
|
self.assert_image_similar(alpha, comparable, 5)
|
||||||
|
|
||||||
def test_matrix_illegal_conversion(self):
|
def test_matrix_illegal_conversion(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
im = hopper('CMYK')
|
im = hopper("CMYK")
|
||||||
|
# fmt: off
|
||||||
matrix = (
|
matrix = (
|
||||||
0.412453, 0.357580, 0.180423, 0,
|
0.412453, 0.357580, 0.180423, 0,
|
||||||
0.212671, 0.715160, 0.072169, 0,
|
0.212671, 0.715160, 0.072169, 0,
|
||||||
0.019334, 0.119193, 0.950227, 0)
|
0.019334, 0.119193, 0.950227, 0)
|
||||||
self.assertNotEqual(im.mode, 'RGB')
|
# fmt: on
|
||||||
|
self.assertNotEqual(im.mode, "RGB")
|
||||||
|
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, im.convert, mode="CMYK", matrix=matrix)
|
||||||
im.convert, mode='CMYK', matrix=matrix)
|
|
||||||
|
|
||||||
def test_matrix_wrong_mode(self):
|
def test_matrix_wrong_mode(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
|
# fmt: off
|
||||||
matrix = (
|
matrix = (
|
||||||
0.412453, 0.357580, 0.180423, 0,
|
0.412453, 0.357580, 0.180423, 0,
|
||||||
0.212671, 0.715160, 0.072169, 0,
|
0.212671, 0.715160, 0.072169, 0,
|
||||||
0.019334, 0.119193, 0.950227, 0)
|
0.019334, 0.119193, 0.950227, 0)
|
||||||
self.assertEqual(im.mode, 'L')
|
# fmt: on
|
||||||
|
self.assertEqual(im.mode, "L")
|
||||||
|
|
||||||
# Act / Assert
|
# Act / Assert
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, im.convert, mode="L", matrix=matrix)
|
||||||
im.convert, mode='L', matrix=matrix)
|
|
||||||
|
|
||||||
def test_matrix_xyz(self):
|
def test_matrix_xyz(self):
|
||||||
|
|
||||||
def matrix_convert(mode):
|
def matrix_convert(mode):
|
||||||
# Arrange
|
# Arrange
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
im.info['transparency'] = (255, 0, 0)
|
im.info["transparency"] = (255, 0, 0)
|
||||||
|
# fmt: off
|
||||||
matrix = (
|
matrix = (
|
||||||
0.412453, 0.357580, 0.180423, 0,
|
0.412453, 0.357580, 0.180423, 0,
|
||||||
0.212671, 0.715160, 0.072169, 0,
|
0.212671, 0.715160, 0.072169, 0,
|
||||||
0.019334, 0.119193, 0.950227, 0)
|
0.019334, 0.119193, 0.950227, 0)
|
||||||
self.assertEqual(im.mode, 'RGB')
|
# fmt: on
|
||||||
|
self.assertEqual(im.mode, "RGB")
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
# Convert an RGB image to the CIE XYZ colour space
|
# Convert an RGB image to the CIE XYZ colour space
|
||||||
|
@ -202,31 +209,31 @@ class TestImageConvert(PillowTestCase):
|
||||||
# Assert
|
# Assert
|
||||||
self.assertEqual(converted_im.mode, mode)
|
self.assertEqual(converted_im.mode, mode)
|
||||||
self.assertEqual(converted_im.size, im.size)
|
self.assertEqual(converted_im.size, im.size)
|
||||||
target = Image.open('Tests/images/hopper-XYZ.png')
|
target = Image.open("Tests/images/hopper-XYZ.png")
|
||||||
if converted_im.mode == 'RGB':
|
if converted_im.mode == "RGB":
|
||||||
self.assert_image_similar(converted_im, target, 3)
|
self.assert_image_similar(converted_im, target, 3)
|
||||||
self.assertEqual(converted_im.info['transparency'],
|
self.assertEqual(converted_im.info["transparency"], (105, 54, 4))
|
||||||
(105, 54, 4))
|
|
||||||
else:
|
else:
|
||||||
self.assert_image_similar(converted_im,
|
self.assert_image_similar(converted_im, target.getchannel(0), 1)
|
||||||
target.getchannel(0), 1)
|
self.assertEqual(converted_im.info["transparency"], 105)
|
||||||
self.assertEqual(converted_im.info['transparency'], 105)
|
|
||||||
|
|
||||||
matrix_convert('RGB')
|
matrix_convert("RGB")
|
||||||
matrix_convert('L')
|
matrix_convert("L")
|
||||||
|
|
||||||
def test_matrix_identity(self):
|
def test_matrix_identity(self):
|
||||||
# Arrange
|
# Arrange
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
|
# fmt: off
|
||||||
identity_matrix = (
|
identity_matrix = (
|
||||||
1, 0, 0, 0,
|
1, 0, 0, 0,
|
||||||
0, 1, 0, 0,
|
0, 1, 0, 0,
|
||||||
0, 0, 1, 0)
|
0, 0, 1, 0)
|
||||||
self.assertEqual(im.mode, 'RGB')
|
# fmt: on
|
||||||
|
self.assertEqual(im.mode, "RGB")
|
||||||
|
|
||||||
# Act
|
# Act
|
||||||
# Convert with an identity matrix
|
# Convert with an identity matrix
|
||||||
converted_im = im.convert(mode='RGB', matrix=identity_matrix)
|
converted_im = im.convert(mode="RGB", matrix=identity_matrix)
|
||||||
|
|
||||||
# Assert
|
# Assert
|
||||||
# No change
|
# No change
|
||||||
|
|
|
@ -6,7 +6,6 @@ import copy
|
||||||
|
|
||||||
|
|
||||||
class TestImageCopy(PillowTestCase):
|
class TestImageCopy(PillowTestCase):
|
||||||
|
|
||||||
def test_copy(self):
|
def test_copy(self):
|
||||||
croppedCoordinates = (10, 10, 20, 20)
|
croppedCoordinates = (10, 10, 20, 20)
|
||||||
croppedSize = (10, 10)
|
croppedSize = (10, 10)
|
||||||
|
@ -36,7 +35,7 @@ class TestImageCopy(PillowTestCase):
|
||||||
self.assertEqual(out.size, croppedSize)
|
self.assertEqual(out.size, croppedSize)
|
||||||
|
|
||||||
def test_copy_zero(self):
|
def test_copy_zero(self):
|
||||||
im = Image.new('RGB', (0, 0))
|
im = Image.new("RGB", (0, 0))
|
||||||
out = im.copy()
|
out = im.copy()
|
||||||
self.assertEqual(out.mode, im.mode)
|
self.assertEqual(out.mode, im.mode)
|
||||||
self.assertEqual(out.size, im.size)
|
self.assertEqual(out.size, im.size)
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageCrop(PillowTestCase):
|
class TestImageCrop(PillowTestCase):
|
||||||
|
|
||||||
def test_crop(self):
|
def test_crop(self):
|
||||||
def crop(mode):
|
def crop(mode):
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
|
@ -13,11 +12,11 @@ class TestImageCrop(PillowTestCase):
|
||||||
cropped = im.crop((50, 50, 100, 100))
|
cropped = im.crop((50, 50, 100, 100))
|
||||||
self.assertEqual(cropped.mode, mode)
|
self.assertEqual(cropped.mode, mode)
|
||||||
self.assertEqual(cropped.size, (50, 50))
|
self.assertEqual(cropped.size, (50, 50))
|
||||||
|
|
||||||
for mode in "1", "P", "L", "RGB", "I", "F":
|
for mode in "1", "P", "L", "RGB", "I", "F":
|
||||||
crop(mode)
|
crop(mode)
|
||||||
|
|
||||||
def test_wide_crop(self):
|
def test_wide_crop(self):
|
||||||
|
|
||||||
def crop(*bbox):
|
def crop(*bbox):
|
||||||
i = im.crop(bbox)
|
i = im.crop(bbox)
|
||||||
h = i.histogram()
|
h = i.histogram()
|
||||||
|
@ -74,7 +73,7 @@ class TestImageCrop(PillowTestCase):
|
||||||
# apparently a use after free on windows, see
|
# apparently a use after free on windows, see
|
||||||
# https://github.com/python-pillow/Pillow/issues/1077
|
# https://github.com/python-pillow/Pillow/issues/1077
|
||||||
|
|
||||||
test_img = 'Tests/images/bmp/g/pal8-0.bmp'
|
test_img = "Tests/images/bmp/g/pal8-0.bmp"
|
||||||
extents = (1, 1, 10, 10)
|
extents = (1, 1, 10, 10)
|
||||||
# works prepatch
|
# works prepatch
|
||||||
img = Image.open(test_img)
|
img = Image.open(test_img)
|
||||||
|
@ -88,7 +87,7 @@ class TestImageCrop(PillowTestCase):
|
||||||
|
|
||||||
def test_crop_zero(self):
|
def test_crop_zero(self):
|
||||||
|
|
||||||
im = Image.new('RGB', (0, 0), 'white')
|
im = Image.new("RGB", (0, 0), "white")
|
||||||
|
|
||||||
cropped = im.crop((0, 0, 0, 0))
|
cropped = im.crop((0, 0, 0, 0))
|
||||||
self.assertEqual(cropped.size, (0, 0))
|
self.assertEqual(cropped.size, (0, 0))
|
||||||
|
@ -97,7 +96,7 @@ class TestImageCrop(PillowTestCase):
|
||||||
self.assertEqual(cropped.size, (10, 10))
|
self.assertEqual(cropped.size, (10, 10))
|
||||||
self.assertEqual(cropped.getdata()[0], (0, 0, 0))
|
self.assertEqual(cropped.getdata()[0], (0, 0, 0))
|
||||||
|
|
||||||
im = Image.new('RGB', (0, 0))
|
im = Image.new("RGB", (0, 0))
|
||||||
|
|
||||||
cropped = im.crop((10, 10, 20, 20))
|
cropped = im.crop((10, 10, 20, 20))
|
||||||
self.assertEqual(cropped.size, (10, 10))
|
self.assertEqual(cropped.size, (10, 10))
|
||||||
|
|
|
@ -11,7 +11,7 @@ class TestImageDraft(PillowTestCase):
|
||||||
|
|
||||||
def draft_roundtrip(self, in_mode, in_size, req_mode, req_size):
|
def draft_roundtrip(self, in_mode, in_size, req_mode, req_size):
|
||||||
im = Image.new(in_mode, in_size)
|
im = Image.new(in_mode, in_size)
|
||||||
data = tostring(im, 'JPEG')
|
data = tostring(im, "JPEG")
|
||||||
im = fromstring(data)
|
im = fromstring(data)
|
||||||
im.draft(req_mode, req_size)
|
im.draft(req_mode, req_size)
|
||||||
return im
|
return im
|
||||||
|
@ -23,7 +23,6 @@ class TestImageDraft(PillowTestCase):
|
||||||
((128, 128), (64, 64), (64, 64)),
|
((128, 128), (64, 64), (64, 64)),
|
||||||
((128, 128), (32, 32), (32, 32)),
|
((128, 128), (32, 32), (32, 32)),
|
||||||
((128, 128), (16, 16), (16, 16)),
|
((128, 128), (16, 16), (16, 16)),
|
||||||
|
|
||||||
# large requested width
|
# large requested width
|
||||||
((435, 361), (218, 128), (435, 361)), # almost 2x
|
((435, 361), (218, 128), (435, 361)), # almost 2x
|
||||||
((435, 361), (217, 128), (218, 181)), # more than 2x
|
((435, 361), (217, 128), (218, 181)), # more than 2x
|
||||||
|
@ -32,7 +31,6 @@ class TestImageDraft(PillowTestCase):
|
||||||
((435, 361), (55, 32), (109, 91)), # almost 8x
|
((435, 361), (55, 32), (109, 91)), # almost 8x
|
||||||
((435, 361), (54, 32), (55, 46)), # more than 8x
|
((435, 361), (54, 32), (55, 46)), # more than 8x
|
||||||
((435, 361), (27, 16), (55, 46)), # more than 16x
|
((435, 361), (27, 16), (55, 46)), # more than 16x
|
||||||
|
|
||||||
# and vice versa
|
# and vice versa
|
||||||
((435, 361), (128, 181), (435, 361)), # almost 2x
|
((435, 361), (128, 181), (435, 361)), # almost 2x
|
||||||
((435, 361), (128, 180), (218, 181)), # more than 2x
|
((435, 361), (128, 180), (218, 181)), # more than 2x
|
||||||
|
@ -42,7 +40,7 @@ class TestImageDraft(PillowTestCase):
|
||||||
((435, 361), (32, 45), (55, 46)), # more than 8x
|
((435, 361), (32, 45), (55, 46)), # more than 8x
|
||||||
((435, 361), (16, 22), (55, 46)), # more than 16x
|
((435, 361), (16, 22), (55, 46)), # more than 16x
|
||||||
]:
|
]:
|
||||||
im = self.draft_roundtrip('L', in_size, None, req_size)
|
im = self.draft_roundtrip("L", in_size, None, req_size)
|
||||||
im.load()
|
im.load()
|
||||||
self.assertEqual(im.size, out_size)
|
self.assertEqual(im.size, out_size)
|
||||||
|
|
||||||
|
@ -66,6 +64,6 @@ class TestImageDraft(PillowTestCase):
|
||||||
self.assertEqual(im.mode, out_mode)
|
self.assertEqual(im.mode, out_mode)
|
||||||
|
|
||||||
def test_several_drafts(self):
|
def test_several_drafts(self):
|
||||||
im = self.draft_roundtrip('L', (128, 128), None, (64, 64))
|
im = self.draft_roundtrip("L", (128, 128), None, (64, 64))
|
||||||
im.draft(None, (64, 64))
|
im.draft(None, (64, 64))
|
||||||
im.load()
|
im.load()
|
||||||
|
|
|
@ -4,9 +4,7 @@ from PIL import Image, ImageFilter
|
||||||
|
|
||||||
|
|
||||||
class TestImageFilter(PillowTestCase):
|
class TestImageFilter(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
def filter(filter):
|
def filter(filter):
|
||||||
for mode in ["L", "RGB", "CMYK"]:
|
for mode in ["L", "RGB", "CMYK"]:
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
|
@ -49,7 +47,6 @@ class TestImageFilter(PillowTestCase):
|
||||||
im.filter(ImageFilter.SMOOTH)
|
im.filter(ImageFilter.SMOOTH)
|
||||||
|
|
||||||
def test_modefilter(self):
|
def test_modefilter(self):
|
||||||
|
|
||||||
def modefilter(mode):
|
def modefilter(mode):
|
||||||
im = Image.new(mode, (3, 3), None)
|
im = Image.new(mode, (3, 3), None)
|
||||||
im.putdata(list(range(9)))
|
im.putdata(list(range(9)))
|
||||||
|
@ -68,7 +65,6 @@ class TestImageFilter(PillowTestCase):
|
||||||
self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0)))
|
self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0)))
|
||||||
|
|
||||||
def test_rankfilter(self):
|
def test_rankfilter(self):
|
||||||
|
|
||||||
def rankfilter(mode):
|
def rankfilter(mode):
|
||||||
im = Image.new(mode, (3, 3), None)
|
im = Image.new(mode, (3, 3), None)
|
||||||
im.putdata(list(range(9)))
|
im.putdata(list(range(9)))
|
||||||
|
@ -100,39 +96,48 @@ class TestImageFilter(PillowTestCase):
|
||||||
self.assertRaises(ValueError, builtinFilter.filter, hopper("P"))
|
self.assertRaises(ValueError, builtinFilter.filter, hopper("P"))
|
||||||
|
|
||||||
def test_kernel_not_enough_coefficients(self):
|
def test_kernel_not_enough_coefficients(self):
|
||||||
self.assertRaises(ValueError,
|
self.assertRaises(ValueError, lambda: ImageFilter.Kernel((3, 3), (0, 0)))
|
||||||
lambda: ImageFilter.Kernel((3, 3), (0, 0)))
|
|
||||||
|
|
||||||
def test_consistency_3x3(self):
|
def test_consistency_3x3(self):
|
||||||
source = Image.open("Tests/images/hopper.bmp")
|
source = Image.open("Tests/images/hopper.bmp")
|
||||||
reference = Image.open("Tests/images/hopper_emboss.bmp")
|
reference = Image.open("Tests/images/hopper_emboss.bmp")
|
||||||
kernel = ImageFilter.Kernel((3, 3), # noqa: E127
|
kernel = ImageFilter.Kernel( # noqa: E127
|
||||||
(-1, -1, 0,
|
(3, 3),
|
||||||
-1, 0, 1,
|
# fmt: off
|
||||||
0, 1, 1), .3)
|
(-1, -1, 0,
|
||||||
|
-1, 0, 1,
|
||||||
|
0, 1, 1),
|
||||||
|
# fmt: on
|
||||||
|
0.3,
|
||||||
|
)
|
||||||
source = source.split() * 2
|
source = source.split() * 2
|
||||||
reference = reference.split() * 2
|
reference = reference.split() * 2
|
||||||
|
|
||||||
for mode in ['L', 'LA', 'RGB', 'CMYK']:
|
for mode in ["L", "LA", "RGB", "CMYK"]:
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
Image.merge(mode, source[:len(mode)]).filter(kernel),
|
Image.merge(mode, source[: len(mode)]).filter(kernel),
|
||||||
Image.merge(mode, reference[:len(mode)]),
|
Image.merge(mode, reference[: len(mode)]),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_consistency_5x5(self):
|
def test_consistency_5x5(self):
|
||||||
source = Image.open("Tests/images/hopper.bmp")
|
source = Image.open("Tests/images/hopper.bmp")
|
||||||
reference = Image.open("Tests/images/hopper_emboss_more.bmp")
|
reference = Image.open("Tests/images/hopper_emboss_more.bmp")
|
||||||
kernel = ImageFilter.Kernel((5, 5), # noqa: E127
|
kernel = ImageFilter.Kernel( # noqa: E127
|
||||||
(-1, -1, -1, -1, 0,
|
(5, 5),
|
||||||
-1, -1, -1, 0, 1,
|
# fmt: off
|
||||||
-1, -1, 0, 1, 1,
|
(-1, -1, -1, -1, 0,
|
||||||
-1, 0, 1, 1, 1,
|
-1, -1, -1, 0, 1,
|
||||||
0, 1, 1, 1, 1), 0.3)
|
-1, -1, 0, 1, 1,
|
||||||
|
-1, 0, 1, 1, 1,
|
||||||
|
0, 1, 1, 1, 1),
|
||||||
|
# fmt: on
|
||||||
|
0.3,
|
||||||
|
)
|
||||||
source = source.split() * 2
|
source = source.split() * 2
|
||||||
reference = reference.split() * 2
|
reference = reference.split() * 2
|
||||||
|
|
||||||
for mode in ['L', 'LA', 'RGB', 'CMYK']:
|
for mode in ["L", "LA", "RGB", "CMYK"]:
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
Image.merge(mode, source[:len(mode)]).filter(kernel),
|
Image.merge(mode, source[: len(mode)]).filter(kernel),
|
||||||
Image.merge(mode, reference[:len(mode)]),
|
Image.merge(mode, reference[: len(mode)]),
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageFromBytes(PillowTestCase):
|
class TestImageFromBytes(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
im1 = hopper()
|
im1 = hopper()
|
||||||
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
|
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
|
||||||
|
|
|
@ -8,8 +8,8 @@ class TestFromQImage(PillowQtTestCase, PillowTestCase):
|
||||||
|
|
||||||
files_to_test = [
|
files_to_test = [
|
||||||
hopper(),
|
hopper(),
|
||||||
Image.open('Tests/images/transparent.png'),
|
Image.open("Tests/images/transparent.png"),
|
||||||
Image.open('Tests/images/7x13.png'),
|
Image.open("Tests/images/7x13.png"),
|
||||||
]
|
]
|
||||||
|
|
||||||
def roundtrip(self, expected):
|
def roundtrip(self, expected):
|
||||||
|
@ -19,26 +19,26 @@ class TestFromQImage(PillowQtTestCase, PillowTestCase):
|
||||||
result = ImageQt.fromqimage(intermediate)
|
result = ImageQt.fromqimage(intermediate)
|
||||||
|
|
||||||
if intermediate.hasAlphaChannel():
|
if intermediate.hasAlphaChannel():
|
||||||
self.assert_image_equal(result, expected.convert('RGBA'))
|
self.assert_image_equal(result, expected.convert("RGBA"))
|
||||||
else:
|
else:
|
||||||
self.assert_image_equal(result, expected.convert('RGB'))
|
self.assert_image_equal(result, expected.convert("RGB"))
|
||||||
|
|
||||||
def test_sanity_1(self):
|
def test_sanity_1(self):
|
||||||
for im in self.files_to_test:
|
for im in self.files_to_test:
|
||||||
self.roundtrip(im.convert('1'))
|
self.roundtrip(im.convert("1"))
|
||||||
|
|
||||||
def test_sanity_rgb(self):
|
def test_sanity_rgb(self):
|
||||||
for im in self.files_to_test:
|
for im in self.files_to_test:
|
||||||
self.roundtrip(im.convert('RGB'))
|
self.roundtrip(im.convert("RGB"))
|
||||||
|
|
||||||
def test_sanity_rgba(self):
|
def test_sanity_rgba(self):
|
||||||
for im in self.files_to_test:
|
for im in self.files_to_test:
|
||||||
self.roundtrip(im.convert('RGBA'))
|
self.roundtrip(im.convert("RGBA"))
|
||||||
|
|
||||||
def test_sanity_l(self):
|
def test_sanity_l(self):
|
||||||
for im in self.files_to_test:
|
for im in self.files_to_test:
|
||||||
self.roundtrip(im.convert('L'))
|
self.roundtrip(im.convert("L"))
|
||||||
|
|
||||||
def test_sanity_p(self):
|
def test_sanity_p(self):
|
||||||
for im in self.files_to_test:
|
for im in self.files_to_test:
|
||||||
self.roundtrip(im.convert('P'))
|
self.roundtrip(im.convert("P"))
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetBands(PillowTestCase):
|
class TestImageGetBands(PillowTestCase):
|
||||||
|
|
||||||
def test_getbands(self):
|
def test_getbands(self):
|
||||||
self.assertEqual(Image.new("1", (1, 1)).getbands(), ("1",))
|
self.assertEqual(Image.new("1", (1, 1)).getbands(), ("1",))
|
||||||
self.assertEqual(Image.new("L", (1, 1)).getbands(), ("L",))
|
self.assertEqual(Image.new("L", (1, 1)).getbands(), ("L",))
|
||||||
|
@ -12,9 +11,6 @@ class TestImageGetBands(PillowTestCase):
|
||||||
self.assertEqual(Image.new("F", (1, 1)).getbands(), ("F",))
|
self.assertEqual(Image.new("F", (1, 1)).getbands(), ("F",))
|
||||||
self.assertEqual(Image.new("P", (1, 1)).getbands(), ("P",))
|
self.assertEqual(Image.new("P", (1, 1)).getbands(), ("P",))
|
||||||
self.assertEqual(Image.new("RGB", (1, 1)).getbands(), ("R", "G", "B"))
|
self.assertEqual(Image.new("RGB", (1, 1)).getbands(), ("R", "G", "B"))
|
||||||
self.assertEqual(
|
self.assertEqual(Image.new("RGBA", (1, 1)).getbands(), ("R", "G", "B", "A"))
|
||||||
Image.new("RGBA", (1, 1)).getbands(), ("R", "G", "B", "A"))
|
self.assertEqual(Image.new("CMYK", (1, 1)).getbands(), ("C", "M", "Y", "K"))
|
||||||
self.assertEqual(
|
self.assertEqual(Image.new("YCbCr", (1, 1)).getbands(), ("Y", "Cb", "Cr"))
|
||||||
Image.new("CMYK", (1, 1)).getbands(), ("C", "M", "Y", "K"))
|
|
||||||
self.assertEqual(
|
|
||||||
Image.new("YCbCr", (1, 1)).getbands(), ("Y", "Cb", "Cr"))
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetBbox(PillowTestCase):
|
class TestImageGetBbox(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
bbox = hopper().getbbox()
|
bbox = hopper().getbbox()
|
||||||
|
|
|
@ -2,9 +2,7 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetColors(PillowTestCase):
|
class TestImageGetColors(PillowTestCase):
|
||||||
|
|
||||||
def test_getcolors(self):
|
def test_getcolors(self):
|
||||||
|
|
||||||
def getcolors(mode, limit=None):
|
def getcolors(mode, limit=None):
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
if limit:
|
if limit:
|
||||||
|
@ -43,9 +41,11 @@ class TestImageGetColors(PillowTestCase):
|
||||||
|
|
||||||
im = hopper().quantize(3).convert("RGB")
|
im = hopper().quantize(3).convert("RGB")
|
||||||
|
|
||||||
expected = [(4039, (172, 166, 181)),
|
expected = [
|
||||||
(4385, (124, 113, 134)),
|
(4039, (172, 166, 181)),
|
||||||
(7960, (31, 20, 33))]
|
(4385, (124, 113, 134)),
|
||||||
|
(7960, (31, 20, 33)),
|
||||||
|
]
|
||||||
|
|
||||||
A = im.getcolors(maxcolors=2)
|
A = im.getcolors(maxcolors=2)
|
||||||
self.assertIsNone(A)
|
self.assertIsNone(A)
|
||||||
|
|
|
@ -2,7 +2,6 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetData(PillowTestCase):
|
class TestImageGetData(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
data = hopper().getdata()
|
data = hopper().getdata()
|
||||||
|
@ -13,7 +12,6 @@ class TestImageGetData(PillowTestCase):
|
||||||
self.assertEqual(data[0], (20, 20, 70))
|
self.assertEqual(data[0], (20, 20, 70))
|
||||||
|
|
||||||
def test_roundtrip(self):
|
def test_roundtrip(self):
|
||||||
|
|
||||||
def getdata(mode):
|
def getdata(mode):
|
||||||
im = hopper(mode).resize((32, 30))
|
im = hopper(mode).resize((32, 30))
|
||||||
data = im.getdata()
|
data = im.getdata()
|
||||||
|
|
|
@ -3,9 +3,7 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetExtrema(PillowTestCase):
|
class TestImageGetExtrema(PillowTestCase):
|
||||||
|
|
||||||
def test_extrema(self):
|
def test_extrema(self):
|
||||||
|
|
||||||
def extrema(mode):
|
def extrema(mode):
|
||||||
return hopper(mode).getextrema()
|
return hopper(mode).getextrema()
|
||||||
|
|
||||||
|
@ -14,16 +12,13 @@ class TestImageGetExtrema(PillowTestCase):
|
||||||
self.assertEqual(extrema("I"), (0, 255))
|
self.assertEqual(extrema("I"), (0, 255))
|
||||||
self.assertEqual(extrema("F"), (0, 255))
|
self.assertEqual(extrema("F"), (0, 255))
|
||||||
self.assertEqual(extrema("P"), (0, 225)) # fixed palette
|
self.assertEqual(extrema("P"), (0, 225)) # fixed palette
|
||||||
self.assertEqual(
|
self.assertEqual(extrema("RGB"), ((0, 255), (0, 255), (0, 255)))
|
||||||
extrema("RGB"), ((0, 255), (0, 255), (0, 255)))
|
self.assertEqual(extrema("RGBA"), ((0, 255), (0, 255), (0, 255), (255, 255)))
|
||||||
self.assertEqual(
|
self.assertEqual(extrema("CMYK"), ((0, 255), (0, 255), (0, 255), (0, 0)))
|
||||||
extrema("RGBA"), ((0, 255), (0, 255), (0, 255), (255, 255)))
|
|
||||||
self.assertEqual(
|
|
||||||
extrema("CMYK"), ((0, 255), (0, 255), (0, 255), (0, 0)))
|
|
||||||
self.assertEqual(extrema("I;16"), (0, 255))
|
self.assertEqual(extrema("I;16"), (0, 255))
|
||||||
|
|
||||||
def test_true_16(self):
|
def test_true_16(self):
|
||||||
im = Image.open("Tests/images/16_bit_noise.tif")
|
im = Image.open("Tests/images/16_bit_noise.tif")
|
||||||
self.assertEqual(im.mode, 'I;16')
|
self.assertEqual(im.mode, "I;16")
|
||||||
extrema = im.getextrema()
|
extrema = im.getextrema()
|
||||||
self.assertEqual(extrema, (106, 285))
|
self.assertEqual(extrema, (106, 285))
|
||||||
|
|
|
@ -3,7 +3,6 @@ from PIL._util import py3
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetIm(PillowTestCase):
|
class TestImageGetIm(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
type_repr = repr(type(im.getim()))
|
type_repr = repr(type(im.getim()))
|
||||||
|
|
|
@ -2,13 +2,13 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetPalette(PillowTestCase):
|
class TestImageGetPalette(PillowTestCase):
|
||||||
|
|
||||||
def test_palette(self):
|
def test_palette(self):
|
||||||
def palette(mode):
|
def palette(mode):
|
||||||
p = hopper(mode).getpalette()
|
p = hopper(mode).getpalette()
|
||||||
if p:
|
if p:
|
||||||
return p[:10]
|
return p[:10]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self.assertIsNone(palette("1"))
|
self.assertIsNone(palette("1"))
|
||||||
self.assertIsNone(palette("L"))
|
self.assertIsNone(palette("L"))
|
||||||
self.assertIsNone(palette("I"))
|
self.assertIsNone(palette("I"))
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageGetProjection(PillowTestCase):
|
class TestImageGetProjection(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
|
@ -2,9 +2,7 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImageHistogram(PillowTestCase):
|
class TestImageHistogram(PillowTestCase):
|
||||||
|
|
||||||
def test_histogram(self):
|
def test_histogram(self):
|
||||||
|
|
||||||
def histogram(mode):
|
def histogram(mode):
|
||||||
h = hopper(mode).histogram()
|
h = hopper(mode).histogram()
|
||||||
return len(h), min(h), max(h)
|
return len(h), min(h), max(h)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import os
|
||||||
|
|
||||||
|
|
||||||
class TestImageLoad(PillowTestCase):
|
class TestImageLoad(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageMode(PillowTestCase):
|
class TestImageMode(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
@ -36,10 +35,13 @@ class TestImageMode(PillowTestCase):
|
||||||
def test_properties(self):
|
def test_properties(self):
|
||||||
def check(mode, *result):
|
def check(mode, *result):
|
||||||
signature = (
|
signature = (
|
||||||
Image.getmodebase(mode), Image.getmodetype(mode),
|
Image.getmodebase(mode),
|
||||||
Image.getmodebands(mode), Image.getmodebandnames(mode),
|
Image.getmodetype(mode),
|
||||||
)
|
Image.getmodebands(mode),
|
||||||
|
Image.getmodebandnames(mode),
|
||||||
|
)
|
||||||
self.assertEqual(signature, result)
|
self.assertEqual(signature, result)
|
||||||
|
|
||||||
check("1", "L", "L", 1, ("1",))
|
check("1", "L", "L", 1, ("1",))
|
||||||
check("L", "L", "L", 1, ("L",))
|
check("L", "L", "L", 1, ("L",))
|
||||||
check("P", "P", "L", 1, ("P",))
|
check("P", "P", "L", 1, ("P",))
|
||||||
|
|
|
@ -9,10 +9,7 @@ class TestImagingPaste(PillowTestCase):
|
||||||
|
|
||||||
def assert_9points_image(self, im, expected):
|
def assert_9points_image(self, im, expected):
|
||||||
expected = [
|
expected = [
|
||||||
point[0]
|
point[0] if im.mode == "L" else point[: len(im.mode)] for point in expected
|
||||||
if im.mode == 'L' else
|
|
||||||
point[:len(im.mode)]
|
|
||||||
for point in expected
|
|
||||||
]
|
]
|
||||||
px = im.load()
|
px = im.load()
|
||||||
actual = [
|
actual = [
|
||||||
|
@ -39,7 +36,7 @@ class TestImagingPaste(PillowTestCase):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def mask_1(self):
|
def mask_1(self):
|
||||||
mask = Image.new('1', (self.size, self.size))
|
mask = Image.new("1", (self.size, self.size))
|
||||||
px = mask.load()
|
px = mask.load()
|
||||||
for y in range(mask.height):
|
for y in range(mask.height):
|
||||||
for x in range(mask.width):
|
for x in range(mask.width):
|
||||||
|
@ -52,7 +49,7 @@ class TestImagingPaste(PillowTestCase):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def gradient_L(self):
|
def gradient_L(self):
|
||||||
gradient = Image.new('L', (self.size, self.size))
|
gradient = Image.new("L", (self.size, self.size))
|
||||||
px = gradient.load()
|
px = gradient.load()
|
||||||
for y in range(gradient.height):
|
for y in range(gradient.height):
|
||||||
for x in range(gradient.width):
|
for x in range(gradient.width):
|
||||||
|
@ -61,34 +58,43 @@ class TestImagingPaste(PillowTestCase):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def gradient_RGB(self):
|
def gradient_RGB(self):
|
||||||
return Image.merge('RGB', [
|
return Image.merge(
|
||||||
self.gradient_L,
|
"RGB",
|
||||||
self.gradient_L.transpose(Image.ROTATE_90),
|
[
|
||||||
self.gradient_L.transpose(Image.ROTATE_180),
|
self.gradient_L,
|
||||||
])
|
self.gradient_L.transpose(Image.ROTATE_90),
|
||||||
|
self.gradient_L.transpose(Image.ROTATE_180),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def gradient_RGBA(self):
|
def gradient_RGBA(self):
|
||||||
return Image.merge('RGBA', [
|
return Image.merge(
|
||||||
self.gradient_L,
|
"RGBA",
|
||||||
self.gradient_L.transpose(Image.ROTATE_90),
|
[
|
||||||
self.gradient_L.transpose(Image.ROTATE_180),
|
self.gradient_L,
|
||||||
self.gradient_L.transpose(Image.ROTATE_270),
|
self.gradient_L.transpose(Image.ROTATE_90),
|
||||||
])
|
self.gradient_L.transpose(Image.ROTATE_180),
|
||||||
|
self.gradient_L.transpose(Image.ROTATE_270),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def gradient_RGBa(self):
|
def gradient_RGBa(self):
|
||||||
return Image.merge('RGBa', [
|
return Image.merge(
|
||||||
self.gradient_L,
|
"RGBa",
|
||||||
self.gradient_L.transpose(Image.ROTATE_90),
|
[
|
||||||
self.gradient_L.transpose(Image.ROTATE_180),
|
self.gradient_L,
|
||||||
self.gradient_L.transpose(Image.ROTATE_270),
|
self.gradient_L.transpose(Image.ROTATE_90),
|
||||||
])
|
self.gradient_L.transpose(Image.ROTATE_180),
|
||||||
|
self.gradient_L.transpose(Image.ROTATE_270),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_image_solid(self):
|
def test_image_solid(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), 'red')
|
im = Image.new(mode, (200, 200), "red")
|
||||||
im2 = getattr(self, 'gradient_' + mode)
|
im2 = getattr(self, "gradient_" + mode)
|
||||||
|
|
||||||
im.paste(im2, (12, 23))
|
im.paste(im2, (12, 23))
|
||||||
|
|
||||||
|
@ -96,79 +102,99 @@ class TestImagingPaste(PillowTestCase):
|
||||||
self.assert_image_equal(im, im2)
|
self.assert_image_equal(im, im2)
|
||||||
|
|
||||||
def test_image_mask_1(self):
|
def test_image_mask_1(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), 'white')
|
im = Image.new(mode, (200, 200), "white")
|
||||||
im2 = getattr(self, 'gradient_' + mode)
|
im2 = getattr(self, "gradient_" + mode)
|
||||||
|
|
||||||
self.assert_9points_paste(im, im2, self.mask_1, [
|
self.assert_9points_paste(
|
||||||
(255, 255, 255, 255),
|
im,
|
||||||
(255, 255, 255, 255),
|
im2,
|
||||||
(127, 254, 127, 0),
|
self.mask_1,
|
||||||
(255, 255, 255, 255),
|
[
|
||||||
(255, 255, 255, 255),
|
(255, 255, 255, 255),
|
||||||
(191, 190, 63, 64),
|
(255, 255, 255, 255),
|
||||||
(127, 0, 127, 254),
|
(127, 254, 127, 0),
|
||||||
(191, 64, 63, 190),
|
(255, 255, 255, 255),
|
||||||
(255, 255, 255, 255),
|
(255, 255, 255, 255),
|
||||||
])
|
(191, 190, 63, 64),
|
||||||
|
(127, 0, 127, 254),
|
||||||
|
(191, 64, 63, 190),
|
||||||
|
(255, 255, 255, 255),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_image_mask_L(self):
|
def test_image_mask_L(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), 'white')
|
im = Image.new(mode, (200, 200), "white")
|
||||||
im2 = getattr(self, 'gradient_' + mode)
|
im2 = getattr(self, "gradient_" + mode)
|
||||||
|
|
||||||
self.assert_9points_paste(im, im2, self.mask_L, [
|
self.assert_9points_paste(
|
||||||
(128, 191, 255, 191),
|
im,
|
||||||
(208, 239, 239, 208),
|
im2,
|
||||||
(255, 255, 255, 255),
|
self.mask_L,
|
||||||
(112, 111, 206, 207),
|
[
|
||||||
(192, 191, 191, 191),
|
(128, 191, 255, 191),
|
||||||
(239, 239, 207, 207),
|
(208, 239, 239, 208),
|
||||||
(128, 1, 128, 254),
|
(255, 255, 255, 255),
|
||||||
(207, 113, 112, 207),
|
(112, 111, 206, 207),
|
||||||
(255, 191, 128, 191),
|
(192, 191, 191, 191),
|
||||||
])
|
(239, 239, 207, 207),
|
||||||
|
(128, 1, 128, 254),
|
||||||
|
(207, 113, 112, 207),
|
||||||
|
(255, 191, 128, 191),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_image_mask_RGBA(self):
|
def test_image_mask_RGBA(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), 'white')
|
im = Image.new(mode, (200, 200), "white")
|
||||||
im2 = getattr(self, 'gradient_' + mode)
|
im2 = getattr(self, "gradient_" + mode)
|
||||||
|
|
||||||
self.assert_9points_paste(im, im2, self.gradient_RGBA, [
|
self.assert_9points_paste(
|
||||||
(128, 191, 255, 191),
|
im,
|
||||||
(208, 239, 239, 208),
|
im2,
|
||||||
(255, 255, 255, 255),
|
self.gradient_RGBA,
|
||||||
(112, 111, 206, 207),
|
[
|
||||||
(192, 191, 191, 191),
|
(128, 191, 255, 191),
|
||||||
(239, 239, 207, 207),
|
(208, 239, 239, 208),
|
||||||
(128, 1, 128, 254),
|
(255, 255, 255, 255),
|
||||||
(207, 113, 112, 207),
|
(112, 111, 206, 207),
|
||||||
(255, 191, 128, 191),
|
(192, 191, 191, 191),
|
||||||
])
|
(239, 239, 207, 207),
|
||||||
|
(128, 1, 128, 254),
|
||||||
|
(207, 113, 112, 207),
|
||||||
|
(255, 191, 128, 191),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_image_mask_RGBa(self):
|
def test_image_mask_RGBa(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), 'white')
|
im = Image.new(mode, (200, 200), "white")
|
||||||
im2 = getattr(self, 'gradient_' + mode)
|
im2 = getattr(self, "gradient_" + mode)
|
||||||
|
|
||||||
self.assert_9points_paste(im, im2, self.gradient_RGBa, [
|
self.assert_9points_paste(
|
||||||
(128, 255, 126, 255),
|
im,
|
||||||
(0, 127, 126, 255),
|
im2,
|
||||||
(126, 253, 126, 255),
|
self.gradient_RGBa,
|
||||||
(128, 127, 254, 255),
|
[
|
||||||
(0, 255, 254, 255),
|
(128, 255, 126, 255),
|
||||||
(126, 125, 254, 255),
|
(0, 127, 126, 255),
|
||||||
(128, 1, 128, 255),
|
(126, 253, 126, 255),
|
||||||
(0, 129, 128, 255),
|
(128, 127, 254, 255),
|
||||||
(126, 255, 128, 255),
|
(0, 255, 254, 255),
|
||||||
])
|
(126, 125, 254, 255),
|
||||||
|
(128, 1, 128, 255),
|
||||||
|
(0, 129, 128, 255),
|
||||||
|
(126, 255, 128, 255),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_color_solid(self):
|
def test_color_solid(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), 'black')
|
im = Image.new(mode, (200, 200), "black")
|
||||||
|
|
||||||
rect = (12, 23, 128 + 12, 128 + 23)
|
rect = (12, 23, 128 + 12, 128 + 23)
|
||||||
im.paste('white', rect)
|
im.paste("white", rect)
|
||||||
|
|
||||||
hist = im.crop(rect).histogram()
|
hist = im.crop(rect).histogram()
|
||||||
while hist:
|
while hist:
|
||||||
|
@ -177,76 +203,96 @@ class TestImagingPaste(PillowTestCase):
|
||||||
self.assertEqual(sum(head[:255]), 0)
|
self.assertEqual(sum(head[:255]), 0)
|
||||||
|
|
||||||
def test_color_mask_1(self):
|
def test_color_mask_1(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = Image.new(mode, (200, 200), (50, 60, 70, 80)[:len(mode)])
|
im = Image.new(mode, (200, 200), (50, 60, 70, 80)[: len(mode)])
|
||||||
color = (10, 20, 30, 40)[:len(mode)]
|
color = (10, 20, 30, 40)[: len(mode)]
|
||||||
|
|
||||||
self.assert_9points_paste(im, color, self.mask_1, [
|
self.assert_9points_paste(
|
||||||
(50, 60, 70, 80),
|
im,
|
||||||
(50, 60, 70, 80),
|
color,
|
||||||
(10, 20, 30, 40),
|
self.mask_1,
|
||||||
(50, 60, 70, 80),
|
[
|
||||||
(50, 60, 70, 80),
|
(50, 60, 70, 80),
|
||||||
(10, 20, 30, 40),
|
(50, 60, 70, 80),
|
||||||
(10, 20, 30, 40),
|
(10, 20, 30, 40),
|
||||||
(10, 20, 30, 40),
|
(50, 60, 70, 80),
|
||||||
(50, 60, 70, 80),
|
(50, 60, 70, 80),
|
||||||
])
|
(10, 20, 30, 40),
|
||||||
|
(10, 20, 30, 40),
|
||||||
|
(10, 20, 30, 40),
|
||||||
|
(50, 60, 70, 80),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_color_mask_L(self):
|
def test_color_mask_L(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = getattr(self, 'gradient_' + mode).copy()
|
im = getattr(self, "gradient_" + mode).copy()
|
||||||
color = 'white'
|
color = "white"
|
||||||
|
|
||||||
self.assert_9points_paste(im, color, self.mask_L, [
|
self.assert_9points_paste(
|
||||||
(127, 191, 254, 191),
|
im,
|
||||||
(111, 207, 206, 110),
|
color,
|
||||||
(127, 254, 127, 0),
|
self.mask_L,
|
||||||
(207, 207, 239, 239),
|
[
|
||||||
(191, 191, 190, 191),
|
(127, 191, 254, 191),
|
||||||
(207, 206, 111, 112),
|
(111, 207, 206, 110),
|
||||||
(254, 254, 254, 255),
|
(127, 254, 127, 0),
|
||||||
(239, 206, 206, 238),
|
(207, 207, 239, 239),
|
||||||
(254, 191, 127, 191),
|
(191, 191, 190, 191),
|
||||||
])
|
(207, 206, 111, 112),
|
||||||
|
(254, 254, 254, 255),
|
||||||
|
(239, 206, 206, 238),
|
||||||
|
(254, 191, 127, 191),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_color_mask_RGBA(self):
|
def test_color_mask_RGBA(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = getattr(self, 'gradient_' + mode).copy()
|
im = getattr(self, "gradient_" + mode).copy()
|
||||||
color = 'white'
|
color = "white"
|
||||||
|
|
||||||
self.assert_9points_paste(im, color, self.gradient_RGBA, [
|
self.assert_9points_paste(
|
||||||
(127, 191, 254, 191),
|
im,
|
||||||
(111, 207, 206, 110),
|
color,
|
||||||
(127, 254, 127, 0),
|
self.gradient_RGBA,
|
||||||
(207, 207, 239, 239),
|
[
|
||||||
(191, 191, 190, 191),
|
(127, 191, 254, 191),
|
||||||
(207, 206, 111, 112),
|
(111, 207, 206, 110),
|
||||||
(254, 254, 254, 255),
|
(127, 254, 127, 0),
|
||||||
(239, 206, 206, 238),
|
(207, 207, 239, 239),
|
||||||
(254, 191, 127, 191),
|
(191, 191, 190, 191),
|
||||||
])
|
(207, 206, 111, 112),
|
||||||
|
(254, 254, 254, 255),
|
||||||
|
(239, 206, 206, 238),
|
||||||
|
(254, 191, 127, 191),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_color_mask_RGBa(self):
|
def test_color_mask_RGBa(self):
|
||||||
for mode in ('RGBA', 'RGB', 'L'):
|
for mode in ("RGBA", "RGB", "L"):
|
||||||
im = getattr(self, 'gradient_' + mode).copy()
|
im = getattr(self, "gradient_" + mode).copy()
|
||||||
color = 'white'
|
color = "white"
|
||||||
|
|
||||||
self.assert_9points_paste(im, color, self.gradient_RGBa, [
|
self.assert_9points_paste(
|
||||||
(255, 63, 126, 63),
|
im,
|
||||||
(47, 143, 142, 46),
|
color,
|
||||||
(126, 253, 126, 255),
|
self.gradient_RGBa,
|
||||||
(15, 15, 47, 47),
|
[
|
||||||
(63, 63, 62, 63),
|
(255, 63, 126, 63),
|
||||||
(142, 141, 46, 47),
|
(47, 143, 142, 46),
|
||||||
(255, 255, 255, 0),
|
(126, 253, 126, 255),
|
||||||
(48, 15, 15, 47),
|
(15, 15, 47, 47),
|
||||||
(126, 63, 255, 63)
|
(63, 63, 62, 63),
|
||||||
])
|
(142, 141, 46, 47),
|
||||||
|
(255, 255, 255, 0),
|
||||||
|
(48, 15, 15, 47),
|
||||||
|
(126, 63, 255, 63),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_different_sizes(self):
|
def test_different_sizes(self):
|
||||||
im = Image.new('RGB', (100, 100))
|
im = Image.new("RGB", (100, 100))
|
||||||
im2 = Image.new('RGB', (50, 50))
|
im2 = Image.new("RGB", (50, 50))
|
||||||
|
|
||||||
im.copy().paste(im2)
|
im.copy().paste(im2)
|
||||||
im.copy().paste(im2, (0, 0))
|
im.copy().paste(im2, (0, 0))
|
||||||
|
|
|
@ -2,39 +2,38 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImagePoint(PillowTestCase):
|
class TestImagePoint(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
||||||
self.assertRaises(ValueError, im.point, list(range(256)))
|
self.assertRaises(ValueError, im.point, list(range(256)))
|
||||||
im.point(list(range(256))*3)
|
im.point(list(range(256)) * 3)
|
||||||
im.point(lambda x: x)
|
im.point(lambda x: x)
|
||||||
|
|
||||||
im = im.convert("I")
|
im = im.convert("I")
|
||||||
self.assertRaises(ValueError, im.point, list(range(256)))
|
self.assertRaises(ValueError, im.point, list(range(256)))
|
||||||
im.point(lambda x: x*1)
|
im.point(lambda x: x * 1)
|
||||||
im.point(lambda x: x+1)
|
im.point(lambda x: x + 1)
|
||||||
im.point(lambda x: x*1+1)
|
im.point(lambda x: x * 1 + 1)
|
||||||
self.assertRaises(TypeError, im.point, lambda x: x-1)
|
self.assertRaises(TypeError, im.point, lambda x: x - 1)
|
||||||
self.assertRaises(TypeError, im.point, lambda x: x/1)
|
self.assertRaises(TypeError, im.point, lambda x: x / 1)
|
||||||
|
|
||||||
def test_16bit_lut(self):
|
def test_16bit_lut(self):
|
||||||
""" Tests for 16 bit -> 8 bit lut for converting I->L images
|
""" Tests for 16 bit -> 8 bit lut for converting I->L images
|
||||||
see https://github.com/python-pillow/Pillow/issues/440
|
see https://github.com/python-pillow/Pillow/issues/440
|
||||||
"""
|
"""
|
||||||
im = hopper("I")
|
im = hopper("I")
|
||||||
im.point(list(range(256))*256, 'L')
|
im.point(list(range(256)) * 256, "L")
|
||||||
|
|
||||||
def test_f_lut(self):
|
def test_f_lut(self):
|
||||||
""" Tests for floating point lut of 8bit gray image """
|
""" Tests for floating point lut of 8bit gray image """
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
lut = [0.5 * float(x) for x in range(256)]
|
lut = [0.5 * float(x) for x in range(256)]
|
||||||
|
|
||||||
out = im.point(lut, 'F')
|
out = im.point(lut, "F")
|
||||||
|
|
||||||
int_lut = [x//2 for x in range(256)]
|
int_lut = [x // 2 for x in range(256)]
|
||||||
self.assert_image_equal(out.convert('L'), im.point(int_lut, 'L'))
|
self.assert_image_equal(out.convert("L"), im.point(int_lut, "L"))
|
||||||
|
|
||||||
def test_f_mode(self):
|
def test_f_mode(self):
|
||||||
im = hopper('F')
|
im = hopper("F")
|
||||||
self.assertRaises(ValueError, im.point, None)
|
self.assertRaises(ValueError, im.point, None)
|
||||||
|
|
|
@ -4,7 +4,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImagePutAlpha(PillowTestCase):
|
class TestImagePutAlpha(PillowTestCase):
|
||||||
|
|
||||||
def test_interface(self):
|
def test_interface(self):
|
||||||
|
|
||||||
im = Image.new("RGBA", (1, 1), (1, 2, 3, 0))
|
im = Image.new("RGBA", (1, 1), (1, 2, 3, 0))
|
||||||
|
@ -25,21 +24,21 @@ class TestImagePutAlpha(PillowTestCase):
|
||||||
self.assertEqual(im.getpixel((0, 0)), 1)
|
self.assertEqual(im.getpixel((0, 0)), 1)
|
||||||
|
|
||||||
im.putalpha(2)
|
im.putalpha(2)
|
||||||
self.assertEqual(im.mode, 'LA')
|
self.assertEqual(im.mode, "LA")
|
||||||
self.assertEqual(im.getpixel((0, 0)), (1, 2))
|
self.assertEqual(im.getpixel((0, 0)), (1, 2))
|
||||||
|
|
||||||
im = Image.new("P", (1, 1), 1)
|
im = Image.new("P", (1, 1), 1)
|
||||||
self.assertEqual(im.getpixel((0, 0)), 1)
|
self.assertEqual(im.getpixel((0, 0)), 1)
|
||||||
|
|
||||||
im.putalpha(2)
|
im.putalpha(2)
|
||||||
self.assertEqual(im.mode, 'PA')
|
self.assertEqual(im.mode, "PA")
|
||||||
self.assertEqual(im.getpixel((0, 0)), (1, 2))
|
self.assertEqual(im.getpixel((0, 0)), (1, 2))
|
||||||
|
|
||||||
im = Image.new("RGB", (1, 1), (1, 2, 3))
|
im = Image.new("RGB", (1, 1), (1, 2, 3))
|
||||||
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3))
|
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3))
|
||||||
|
|
||||||
im.putalpha(4)
|
im.putalpha(4)
|
||||||
self.assertEqual(im.mode, 'RGBA')
|
self.assertEqual(im.mode, "RGBA")
|
||||||
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
|
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
|
||||||
|
|
||||||
def test_readonly(self):
|
def test_readonly(self):
|
||||||
|
@ -49,5 +48,5 @@ class TestImagePutAlpha(PillowTestCase):
|
||||||
|
|
||||||
im.putalpha(4)
|
im.putalpha(4)
|
||||||
self.assertFalse(im.readonly)
|
self.assertFalse(im.readonly)
|
||||||
self.assertEqual(im.mode, 'RGBA')
|
self.assertEqual(im.mode, "RGBA")
|
||||||
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
|
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
|
||||||
|
|
|
@ -7,7 +7,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImagePutData(PillowTestCase):
|
class TestImagePutData(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
im1 = hopper()
|
im1 = hopper()
|
||||||
|
@ -33,32 +32,33 @@ class TestImagePutData(PillowTestCase):
|
||||||
im = Image.new("RGBA", (1, 1))
|
im = Image.new("RGBA", (1, 1))
|
||||||
im.putdata([value])
|
im.putdata([value])
|
||||||
return im.getpixel((0, 0))
|
return im.getpixel((0, 0))
|
||||||
|
|
||||||
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
|
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
|
||||||
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
|
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
|
||||||
self.assertEqual(put(-1), (255, 255, 255, 255))
|
self.assertEqual(put(-1), (255, 255, 255, 255))
|
||||||
self.assertEqual(put(-1), (255, 255, 255, 255))
|
self.assertEqual(put(-1), (255, 255, 255, 255))
|
||||||
if sys.maxsize > 2**32:
|
if sys.maxsize > 2 ** 32:
|
||||||
self.assertEqual(put(sys.maxsize), (255, 255, 255, 255))
|
self.assertEqual(put(sys.maxsize), (255, 255, 255, 255))
|
||||||
else:
|
else:
|
||||||
self.assertEqual(put(sys.maxsize), (255, 255, 255, 127))
|
self.assertEqual(put(sys.maxsize), (255, 255, 255, 127))
|
||||||
|
|
||||||
def test_pypy_performance(self):
|
def test_pypy_performance(self):
|
||||||
im = Image.new('L', (256, 256))
|
im = Image.new("L", (256, 256))
|
||||||
im.putdata(list(range(256))*256)
|
im.putdata(list(range(256)) * 256)
|
||||||
|
|
||||||
def test_mode_i(self):
|
def test_mode_i(self):
|
||||||
src = hopper('L')
|
src = hopper("L")
|
||||||
data = list(src.getdata())
|
data = list(src.getdata())
|
||||||
im = Image.new('I', src.size, 0)
|
im = Image.new("I", src.size, 0)
|
||||||
im.putdata(data, 2, 256)
|
im.putdata(data, 2, 256)
|
||||||
|
|
||||||
target = [2 * elt + 256 for elt in data]
|
target = [2 * elt + 256 for elt in data]
|
||||||
self.assertEqual(list(im.getdata()), target)
|
self.assertEqual(list(im.getdata()), target)
|
||||||
|
|
||||||
def test_mode_F(self):
|
def test_mode_F(self):
|
||||||
src = hopper('L')
|
src = hopper("L")
|
||||||
data = list(src.getdata())
|
data = list(src.getdata())
|
||||||
im = Image.new('F', src.size, 0)
|
im = Image.new("F", src.size, 0)
|
||||||
im.putdata(data, 2.0, 256.0)
|
im.putdata(data, 2.0, 256.0)
|
||||||
|
|
||||||
target = [2.0 * float(elt) + 256.0 for elt in data]
|
target = [2.0 * float(elt) + 256.0 for elt in data]
|
||||||
|
@ -68,8 +68,8 @@ class TestImagePutData(PillowTestCase):
|
||||||
# shouldn't segfault
|
# shouldn't segfault
|
||||||
# see https://github.com/python-pillow/Pillow/issues/1008
|
# see https://github.com/python-pillow/Pillow/issues/1008
|
||||||
|
|
||||||
arr = array('B', [0])*15000
|
arr = array("B", [0]) * 15000
|
||||||
im = Image.new('L', (150, 100))
|
im = Image.new("L", (150, 100))
|
||||||
im.putdata(arr)
|
im.putdata(arr)
|
||||||
|
|
||||||
self.assertEqual(len(im.getdata()), len(arr))
|
self.assertEqual(len(im.getdata()), len(arr))
|
||||||
|
@ -78,8 +78,8 @@ class TestImagePutData(PillowTestCase):
|
||||||
# shouldn't segfault
|
# shouldn't segfault
|
||||||
# see https://github.com/python-pillow/Pillow/issues/1008
|
# see https://github.com/python-pillow/Pillow/issues/1008
|
||||||
|
|
||||||
im = Image.new('F', (150, 100))
|
im = Image.new("F", (150, 100))
|
||||||
arr = array('f', [0.0])*15000
|
arr = array("f", [0.0]) * 15000
|
||||||
im.putdata(arr)
|
im.putdata(arr)
|
||||||
|
|
||||||
self.assertEqual(len(im.getdata()), len(arr))
|
self.assertEqual(len(im.getdata()), len(arr))
|
||||||
|
|
|
@ -4,20 +4,21 @@ from PIL import ImagePalette
|
||||||
|
|
||||||
|
|
||||||
class TestImagePutPalette(PillowTestCase):
|
class TestImagePutPalette(PillowTestCase):
|
||||||
|
|
||||||
def test_putpalette(self):
|
def test_putpalette(self):
|
||||||
def palette(mode):
|
def palette(mode):
|
||||||
im = hopper(mode).copy()
|
im = hopper(mode).copy()
|
||||||
im.putpalette(list(range(256))*3)
|
im.putpalette(list(range(256)) * 3)
|
||||||
p = im.getpalette()
|
p = im.getpalette()
|
||||||
if p:
|
if p:
|
||||||
return im.mode, p[:10]
|
return im.mode, p[:10]
|
||||||
return im.mode
|
return im.mode
|
||||||
|
|
||||||
self.assertRaises(ValueError, palette, "1")
|
self.assertRaises(ValueError, palette, "1")
|
||||||
for mode in ["L", "LA", "P", "PA"]:
|
for mode in ["L", "LA", "P", "PA"]:
|
||||||
self.assertEqual(palette(mode),
|
self.assertEqual(
|
||||||
("PA" if "A" in mode else "P",
|
palette(mode),
|
||||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
|
("PA" if "A" in mode else "P", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
|
||||||
|
)
|
||||||
self.assertRaises(ValueError, palette, "I")
|
self.assertRaises(ValueError, palette, "I")
|
||||||
self.assertRaises(ValueError, palette, "F")
|
self.assertRaises(ValueError, palette, "F")
|
||||||
self.assertRaises(ValueError, palette, "RGB")
|
self.assertRaises(ValueError, palette, "RGB")
|
||||||
|
|
|
@ -4,60 +4,59 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageQuantize(PillowTestCase):
|
class TestImageQuantize(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
image = hopper()
|
image = hopper()
|
||||||
converted = image.quantize()
|
converted = image.quantize()
|
||||||
self.assert_image(converted, 'P', converted.size)
|
self.assert_image(converted, "P", converted.size)
|
||||||
self.assert_image_similar(converted.convert('RGB'), image, 10)
|
self.assert_image_similar(converted.convert("RGB"), image, 10)
|
||||||
|
|
||||||
image = hopper()
|
image = hopper()
|
||||||
converted = image.quantize(palette=hopper('P'))
|
converted = image.quantize(palette=hopper("P"))
|
||||||
self.assert_image(converted, 'P', converted.size)
|
self.assert_image(converted, "P", converted.size)
|
||||||
self.assert_image_similar(converted.convert('RGB'), image, 60)
|
self.assert_image_similar(converted.convert("RGB"), image, 60)
|
||||||
|
|
||||||
def test_libimagequant_quantize(self):
|
def test_libimagequant_quantize(self):
|
||||||
image = hopper()
|
image = hopper()
|
||||||
try:
|
try:
|
||||||
converted = image.quantize(100, Image.LIBIMAGEQUANT)
|
converted = image.quantize(100, Image.LIBIMAGEQUANT)
|
||||||
except ValueError as ex:
|
except ValueError as ex:
|
||||||
if 'dependency' in str(ex).lower():
|
if "dependency" in str(ex).lower():
|
||||||
self.skipTest('libimagequant support not available')
|
self.skipTest("libimagequant support not available")
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
self.assert_image(converted, 'P', converted.size)
|
self.assert_image(converted, "P", converted.size)
|
||||||
self.assert_image_similar(converted.convert('RGB'), image, 15)
|
self.assert_image_similar(converted.convert("RGB"), image, 15)
|
||||||
self.assertEqual(len(converted.getcolors()), 100)
|
self.assertEqual(len(converted.getcolors()), 100)
|
||||||
|
|
||||||
def test_octree_quantize(self):
|
def test_octree_quantize(self):
|
||||||
image = hopper()
|
image = hopper()
|
||||||
converted = image.quantize(100, Image.FASTOCTREE)
|
converted = image.quantize(100, Image.FASTOCTREE)
|
||||||
self.assert_image(converted, 'P', converted.size)
|
self.assert_image(converted, "P", converted.size)
|
||||||
self.assert_image_similar(converted.convert('RGB'), image, 20)
|
self.assert_image_similar(converted.convert("RGB"), image, 20)
|
||||||
self.assertEqual(len(converted.getcolors()), 100)
|
self.assertEqual(len(converted.getcolors()), 100)
|
||||||
|
|
||||||
def test_rgba_quantize(self):
|
def test_rgba_quantize(self):
|
||||||
image = hopper('RGBA')
|
image = hopper("RGBA")
|
||||||
self.assertRaises(ValueError, image.quantize, method=0)
|
self.assertRaises(ValueError, image.quantize, method=0)
|
||||||
|
|
||||||
self.assertEqual(image.quantize().convert().mode, "RGBA")
|
self.assertEqual(image.quantize().convert().mode, "RGBA")
|
||||||
|
|
||||||
def test_quantize(self):
|
def test_quantize(self):
|
||||||
image = Image.open('Tests/images/caption_6_33_22.png').convert('RGB')
|
image = Image.open("Tests/images/caption_6_33_22.png").convert("RGB")
|
||||||
converted = image.quantize()
|
converted = image.quantize()
|
||||||
self.assert_image(converted, 'P', converted.size)
|
self.assert_image(converted, "P", converted.size)
|
||||||
self.assert_image_similar(converted.convert('RGB'), image, 1)
|
self.assert_image_similar(converted.convert("RGB"), image, 1)
|
||||||
|
|
||||||
def test_quantize_no_dither(self):
|
def test_quantize_no_dither(self):
|
||||||
image = hopper()
|
image = hopper()
|
||||||
palette = Image.open('Tests/images/caption_6_33_22.png').convert('P')
|
palette = Image.open("Tests/images/caption_6_33_22.png").convert("P")
|
||||||
|
|
||||||
converted = image.quantize(dither=0, palette=palette)
|
converted = image.quantize(dither=0, palette=palette)
|
||||||
self.assert_image(converted, 'P', converted.size)
|
self.assert_image(converted, "P", converted.size)
|
||||||
|
|
||||||
def test_quantize_dither_diff(self):
|
def test_quantize_dither_diff(self):
|
||||||
image = hopper()
|
image = hopper()
|
||||||
palette = Image.open('Tests/images/caption_6_33_22.png').convert('P')
|
palette = Image.open("Tests/images/caption_6_33_22.png").convert("P")
|
||||||
|
|
||||||
dither = image.quantize(dither=1, palette=palette)
|
dither = image.quantize(dither=1, palette=palette)
|
||||||
nodither = image.quantize(dither=0, palette=palette)
|
nodither = image.quantize(dither=0, palette=palette)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from PIL import Image, ImageDraw
|
||||||
class TestImagingResampleVulnerability(PillowTestCase):
|
class TestImagingResampleVulnerability(PillowTestCase):
|
||||||
# see https://github.com/python-pillow/Pillow/issues/1710
|
# see https://github.com/python-pillow/Pillow/issues/1710
|
||||||
def test_overflow(self):
|
def test_overflow(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
xsize = 0x100000008 // 4
|
xsize = 0x100000008 // 4
|
||||||
ysize = 1000 # unimportant
|
ysize = 1000 # unimportant
|
||||||
with self.assertRaises(MemoryError):
|
with self.assertRaises(MemoryError):
|
||||||
|
@ -29,11 +29,11 @@ class TestImagingResampleVulnerability(PillowTestCase):
|
||||||
im.resize((100, -100))
|
im.resize((100, -100))
|
||||||
|
|
||||||
def test_modify_after_resizing(self):
|
def test_modify_after_resizing(self):
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
# get copy with same size
|
# get copy with same size
|
||||||
copy = im.resize(im.size)
|
copy = im.resize(im.size)
|
||||||
# some in-place operation
|
# some in-place operation
|
||||||
copy.paste('black', (0, 0, im.width // 2, im.height // 2))
|
copy.paste("black", (0, 0, im.width // 2, im.height // 2))
|
||||||
# image should be different
|
# image should be different
|
||||||
self.assertNotEqual(im.tobytes(), copy.tobytes())
|
self.assertNotEqual(im.tobytes(), copy.tobytes())
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ class TestImagingCoreResampleAccuracy(PillowTestCase):
|
||||||
1f 1f e0 e0
|
1f 1f e0 e0
|
||||||
1f 1f e0 e0
|
1f 1f e0 e0
|
||||||
"""
|
"""
|
||||||
case = Image.new('L', size, 255 - color)
|
case = Image.new("L", size, 255 - color)
|
||||||
rectangle = ImageDraw.Draw(case).rectangle
|
rectangle = ImageDraw.Draw(case).rectangle
|
||||||
rectangle((0, 0, size[0] // 2 - 1, size[1] // 2 - 1), color)
|
rectangle((0, 0, size[0] // 2 - 1, size[1] // 2 - 1), color)
|
||||||
rectangle((size[0] // 2, size[1] // 2, size[0], size[1]), color)
|
rectangle((size[0] // 2, size[1] // 2, size[0], size[1]), color)
|
||||||
|
@ -58,13 +58,13 @@ class TestImagingCoreResampleAccuracy(PillowTestCase):
|
||||||
"""Restores a sample image from given data string which contains
|
"""Restores a sample image from given data string which contains
|
||||||
hex-encoded pixels from the top left fourth of a sample.
|
hex-encoded pixels from the top left fourth of a sample.
|
||||||
"""
|
"""
|
||||||
data = data.replace(' ', '')
|
data = data.replace(" ", "")
|
||||||
sample = Image.new('L', size)
|
sample = Image.new("L", size)
|
||||||
s_px = sample.load()
|
s_px = sample.load()
|
||||||
w, h = size[0] // 2, size[1] // 2
|
w, h = size[0] // 2, size[1] // 2
|
||||||
for y in range(h):
|
for y in range(h):
|
||||||
for x in range(w):
|
for x in range(w):
|
||||||
val = int(data[(y * w + x) * 2:(y * w + x + 1) * 2], 16)
|
val = int(data[(y * w + x) * 2 : (y * w + x + 1) * 2], 16)
|
||||||
s_px[x, y] = val
|
s_px[x, y] = val
|
||||||
s_px[size[0] - x - 1, size[1] - y - 1] = val
|
s_px[size[0] - x - 1, size[1] - y - 1] = val
|
||||||
s_px[x, size[1] - y - 1] = 255 - val
|
s_px[x, size[1] - y - 1] = 255 - val
|
||||||
|
@ -77,118 +77,134 @@ class TestImagingCoreResampleAccuracy(PillowTestCase):
|
||||||
for y in range(case.size[1]):
|
for y in range(case.size[1]):
|
||||||
for x in range(case.size[0]):
|
for x in range(case.size[0]):
|
||||||
if c_px[x, y] != s_px[x, y]:
|
if c_px[x, y] != s_px[x, y]:
|
||||||
message = '\nHave: \n{}\n\nExpected: \n{}'.format(
|
message = "\nHave: \n{}\n\nExpected: \n{}".format(
|
||||||
self.serialize_image(case),
|
self.serialize_image(case), self.serialize_image(sample)
|
||||||
self.serialize_image(sample),
|
|
||||||
)
|
)
|
||||||
self.assertEqual(s_px[x, y], c_px[x, y], message)
|
self.assertEqual(s_px[x, y], c_px[x, y], message)
|
||||||
|
|
||||||
def serialize_image(self, image):
|
def serialize_image(self, image):
|
||||||
s_px = image.load()
|
s_px = image.load()
|
||||||
return '\n'.join(
|
return "\n".join(
|
||||||
' '.join(
|
" ".join("{:02x}".format(s_px[x, y]) for x in range(image.size[0]))
|
||||||
'{:02x}'.format(s_px[x, y])
|
|
||||||
for x in range(image.size[0])
|
|
||||||
)
|
|
||||||
for y in range(image.size[1])
|
for y in range(image.size[1])
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_reduce_box(self):
|
def test_reduce_box(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (8, 8), 0xe1)
|
case = self.make_case(mode, (8, 8), 0xE1)
|
||||||
case = case.resize((4, 4), Image.BOX)
|
case = case.resize((4, 4), Image.BOX)
|
||||||
data = ('e1 e1'
|
# fmt: off
|
||||||
'e1 e1')
|
data = ("e1 e1"
|
||||||
|
"e1 e1")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (4, 4)))
|
self.check_case(channel, self.make_sample(data, (4, 4)))
|
||||||
|
|
||||||
def test_reduce_bilinear(self):
|
def test_reduce_bilinear(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (8, 8), 0xe1)
|
case = self.make_case(mode, (8, 8), 0xE1)
|
||||||
case = case.resize((4, 4), Image.BILINEAR)
|
case = case.resize((4, 4), Image.BILINEAR)
|
||||||
data = ('e1 c9'
|
# fmt: off
|
||||||
'c9 b7')
|
data = ("e1 c9"
|
||||||
|
"c9 b7")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (4, 4)))
|
self.check_case(channel, self.make_sample(data, (4, 4)))
|
||||||
|
|
||||||
def test_reduce_hamming(self):
|
def test_reduce_hamming(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (8, 8), 0xe1)
|
case = self.make_case(mode, (8, 8), 0xE1)
|
||||||
case = case.resize((4, 4), Image.HAMMING)
|
case = case.resize((4, 4), Image.HAMMING)
|
||||||
data = ('e1 da'
|
# fmt: off
|
||||||
'da d3')
|
data = ("e1 da"
|
||||||
|
"da d3")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (4, 4)))
|
self.check_case(channel, self.make_sample(data, (4, 4)))
|
||||||
|
|
||||||
def test_reduce_bicubic(self):
|
def test_reduce_bicubic(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (12, 12), 0xe1)
|
case = self.make_case(mode, (12, 12), 0xE1)
|
||||||
case = case.resize((6, 6), Image.BICUBIC)
|
case = case.resize((6, 6), Image.BICUBIC)
|
||||||
data = ('e1 e3 d4'
|
# fmt: off
|
||||||
'e3 e5 d6'
|
data = ("e1 e3 d4"
|
||||||
'd4 d6 c9')
|
"e3 e5 d6"
|
||||||
|
"d4 d6 c9")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (6, 6)))
|
self.check_case(channel, self.make_sample(data, (6, 6)))
|
||||||
|
|
||||||
def test_reduce_lanczos(self):
|
def test_reduce_lanczos(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (16, 16), 0xe1)
|
case = self.make_case(mode, (16, 16), 0xE1)
|
||||||
case = case.resize((8, 8), Image.LANCZOS)
|
case = case.resize((8, 8), Image.LANCZOS)
|
||||||
data = ('e1 e0 e4 d7'
|
# fmt: off
|
||||||
'e0 df e3 d6'
|
data = ("e1 e0 e4 d7"
|
||||||
'e4 e3 e7 da'
|
"e0 df e3 d6"
|
||||||
'd7 d6 d9 ce')
|
"e4 e3 e7 da"
|
||||||
|
"d7 d6 d9 ce")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (8, 8)))
|
self.check_case(channel, self.make_sample(data, (8, 8)))
|
||||||
|
|
||||||
def test_enlarge_box(self):
|
def test_enlarge_box(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (2, 2), 0xe1)
|
case = self.make_case(mode, (2, 2), 0xE1)
|
||||||
case = case.resize((4, 4), Image.BOX)
|
case = case.resize((4, 4), Image.BOX)
|
||||||
data = ('e1 e1'
|
# fmt: off
|
||||||
'e1 e1')
|
data = ("e1 e1"
|
||||||
|
"e1 e1")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (4, 4)))
|
self.check_case(channel, self.make_sample(data, (4, 4)))
|
||||||
|
|
||||||
def test_enlarge_bilinear(self):
|
def test_enlarge_bilinear(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (2, 2), 0xe1)
|
case = self.make_case(mode, (2, 2), 0xE1)
|
||||||
case = case.resize((4, 4), Image.BILINEAR)
|
case = case.resize((4, 4), Image.BILINEAR)
|
||||||
data = ('e1 b0'
|
# fmt: off
|
||||||
'b0 98')
|
data = ("e1 b0"
|
||||||
|
"b0 98")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (4, 4)))
|
self.check_case(channel, self.make_sample(data, (4, 4)))
|
||||||
|
|
||||||
def test_enlarge_hamming(self):
|
def test_enlarge_hamming(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (2, 2), 0xe1)
|
case = self.make_case(mode, (2, 2), 0xE1)
|
||||||
case = case.resize((4, 4), Image.HAMMING)
|
case = case.resize((4, 4), Image.HAMMING)
|
||||||
data = ('e1 d2'
|
# fmt: off
|
||||||
'd2 c5')
|
data = ("e1 d2"
|
||||||
|
"d2 c5")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (4, 4)))
|
self.check_case(channel, self.make_sample(data, (4, 4)))
|
||||||
|
|
||||||
def test_enlarge_bicubic(self):
|
def test_enlarge_bicubic(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (4, 4), 0xe1)
|
case = self.make_case(mode, (4, 4), 0xE1)
|
||||||
case = case.resize((8, 8), Image.BICUBIC)
|
case = case.resize((8, 8), Image.BICUBIC)
|
||||||
data = ('e1 e5 ee b9'
|
# fmt: off
|
||||||
'e5 e9 f3 bc'
|
data = ("e1 e5 ee b9"
|
||||||
'ee f3 fd c1'
|
"e5 e9 f3 bc"
|
||||||
'b9 bc c1 a2')
|
"ee f3 fd c1"
|
||||||
|
"b9 bc c1 a2")
|
||||||
|
# fmt: on
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (8, 8)))
|
self.check_case(channel, self.make_sample(data, (8, 8)))
|
||||||
|
|
||||||
def test_enlarge_lanczos(self):
|
def test_enlarge_lanczos(self):
|
||||||
for mode in ['RGBX', 'RGB', 'La', 'L']:
|
for mode in ["RGBX", "RGB", "La", "L"]:
|
||||||
case = self.make_case(mode, (6, 6), 0xe1)
|
case = self.make_case(mode, (6, 6), 0xE1)
|
||||||
case = case.resize((12, 12), Image.LANCZOS)
|
case = case.resize((12, 12), Image.LANCZOS)
|
||||||
data = ('e1 e0 db ed f5 b8'
|
data = (
|
||||||
'e0 df da ec f3 b7'
|
"e1 e0 db ed f5 b8"
|
||||||
'db db d6 e7 ee b5'
|
"e0 df da ec f3 b7"
|
||||||
'ed ec e6 fb ff bf'
|
"db db d6 e7 ee b5"
|
||||||
'f5 f4 ee ff ff c4'
|
"ed ec e6 fb ff bf"
|
||||||
'b8 b7 b4 bf c4 a0')
|
"f5 f4 ee ff ff c4"
|
||||||
|
"b8 b7 b4 bf c4 a0"
|
||||||
|
)
|
||||||
for channel in case.split():
|
for channel in case.split():
|
||||||
self.check_case(channel, self.make_sample(data, (12, 12)))
|
self.check_case(channel, self.make_sample(data, (12, 12)))
|
||||||
|
|
||||||
|
@ -204,29 +220,28 @@ class CoreResampleConsistencyTest(PillowTestCase):
|
||||||
for x in range(channel.size[0]):
|
for x in range(channel.size[0]):
|
||||||
for y in range(channel.size[1]):
|
for y in range(channel.size[1]):
|
||||||
if px[x, y] != color:
|
if px[x, y] != color:
|
||||||
message = "{} != {} for pixel {}".format(
|
message = "{} != {} for pixel {}".format(px[x, y], color, (x, y))
|
||||||
px[x, y], color, (x, y))
|
|
||||||
self.assertEqual(px[x, y], color, message)
|
self.assertEqual(px[x, y], color, message)
|
||||||
|
|
||||||
def test_8u(self):
|
def test_8u(self):
|
||||||
im, color = self.make_case('RGB', (0, 64, 255))
|
im, color = self.make_case("RGB", (0, 64, 255))
|
||||||
r, g, b = im.split()
|
r, g, b = im.split()
|
||||||
self.run_case((r, color[0]))
|
self.run_case((r, color[0]))
|
||||||
self.run_case((g, color[1]))
|
self.run_case((g, color[1]))
|
||||||
self.run_case((b, color[2]))
|
self.run_case((b, color[2]))
|
||||||
self.run_case(self.make_case('L', 12))
|
self.run_case(self.make_case("L", 12))
|
||||||
|
|
||||||
def test_32i(self):
|
def test_32i(self):
|
||||||
self.run_case(self.make_case('I', 12))
|
self.run_case(self.make_case("I", 12))
|
||||||
self.run_case(self.make_case('I', 0x7fffffff))
|
self.run_case(self.make_case("I", 0x7FFFFFFF))
|
||||||
self.run_case(self.make_case('I', -12))
|
self.run_case(self.make_case("I", -12))
|
||||||
self.run_case(self.make_case('I', -1 << 31))
|
self.run_case(self.make_case("I", -1 << 31))
|
||||||
|
|
||||||
def test_32f(self):
|
def test_32f(self):
|
||||||
self.run_case(self.make_case('F', 1))
|
self.run_case(self.make_case("F", 1))
|
||||||
self.run_case(self.make_case('F', 3.40282306074e+38))
|
self.run_case(self.make_case("F", 3.40282306074e38))
|
||||||
self.run_case(self.make_case('F', 1.175494e-38))
|
self.run_case(self.make_case("F", 1.175494e-38))
|
||||||
self.run_case(self.make_case('F', 1.192093e-07))
|
self.run_case(self.make_case("F", 1.192093e-07))
|
||||||
|
|
||||||
|
|
||||||
class CoreResampleAlphaCorrectTest(PillowTestCase):
|
class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||||
|
@ -244,13 +259,16 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||||
px = i.load()
|
px = i.load()
|
||||||
for y in range(i.size[1]):
|
for y in range(i.size[1]):
|
||||||
used_colors = {px[x, y][0] for x in range(i.size[0])}
|
used_colors = {px[x, y][0] for x in range(i.size[0])}
|
||||||
self.assertEqual(256, len(used_colors),
|
self.assertEqual(
|
||||||
'All colors should present in resized image. '
|
256,
|
||||||
'Only {} on {} line.'.format(len(used_colors), y))
|
len(used_colors),
|
||||||
|
"All colors should present in resized image. "
|
||||||
|
"Only {} on {} line.".format(len(used_colors), y),
|
||||||
|
)
|
||||||
|
|
||||||
@unittest.skip("current implementation isn't precise enough")
|
@unittest.skip("current implementation isn't precise enough")
|
||||||
def test_levels_rgba(self):
|
def test_levels_rgba(self):
|
||||||
case = self.make_levels_case('RGBA')
|
case = self.make_levels_case("RGBA")
|
||||||
self.run_levels_case(case.resize((512, 32), Image.BOX))
|
self.run_levels_case(case.resize((512, 32), Image.BOX))
|
||||||
self.run_levels_case(case.resize((512, 32), Image.BILINEAR))
|
self.run_levels_case(case.resize((512, 32), Image.BILINEAR))
|
||||||
self.run_levels_case(case.resize((512, 32), Image.HAMMING))
|
self.run_levels_case(case.resize((512, 32), Image.HAMMING))
|
||||||
|
@ -259,7 +277,7 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||||
|
|
||||||
@unittest.skip("current implementation isn't precise enough")
|
@unittest.skip("current implementation isn't precise enough")
|
||||||
def test_levels_la(self):
|
def test_levels_la(self):
|
||||||
case = self.make_levels_case('LA')
|
case = self.make_levels_case("LA")
|
||||||
self.run_levels_case(case.resize((512, 32), Image.BOX))
|
self.run_levels_case(case.resize((512, 32), Image.BOX))
|
||||||
self.run_levels_case(case.resize((512, 32), Image.BILINEAR))
|
self.run_levels_case(case.resize((512, 32), Image.BILINEAR))
|
||||||
self.run_levels_case(case.resize((512, 32), Image.HAMMING))
|
self.run_levels_case(case.resize((512, 32), Image.HAMMING))
|
||||||
|
@ -281,24 +299,21 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||||
for y in range(i.size[1]):
|
for y in range(i.size[1]):
|
||||||
for x in range(i.size[0]):
|
for x in range(i.size[0]):
|
||||||
if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel:
|
if px[x, y][-1] != 0 and px[x, y][:-1] != clean_pixel:
|
||||||
message = 'pixel at ({}, {}) is differ:\n{}\n{}'\
|
message = "pixel at ({}, {}) is differ:\n{}\n{}".format(
|
||||||
.format(x, y, px[x, y], clean_pixel)
|
x, y, px[x, y], clean_pixel
|
||||||
|
)
|
||||||
self.assertEqual(px[x, y][:3], clean_pixel, message)
|
self.assertEqual(px[x, y][:3], clean_pixel, message)
|
||||||
|
|
||||||
def test_dirty_pixels_rgba(self):
|
def test_dirty_pixels_rgba(self):
|
||||||
case = self.make_dirty_case('RGBA', (255, 255, 0, 128), (0, 0, 255, 0))
|
case = self.make_dirty_case("RGBA", (255, 255, 0, 128), (0, 0, 255, 0))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.BOX), (255, 255, 0))
|
self.run_dirty_case(case.resize((20, 20), Image.BOX), (255, 255, 0))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.BILINEAR),
|
self.run_dirty_case(case.resize((20, 20), Image.BILINEAR), (255, 255, 0))
|
||||||
(255, 255, 0))
|
self.run_dirty_case(case.resize((20, 20), Image.HAMMING), (255, 255, 0))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.HAMMING),
|
self.run_dirty_case(case.resize((20, 20), Image.BICUBIC), (255, 255, 0))
|
||||||
(255, 255, 0))
|
self.run_dirty_case(case.resize((20, 20), Image.LANCZOS), (255, 255, 0))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.BICUBIC),
|
|
||||||
(255, 255, 0))
|
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.LANCZOS),
|
|
||||||
(255, 255, 0))
|
|
||||||
|
|
||||||
def test_dirty_pixels_la(self):
|
def test_dirty_pixels_la(self):
|
||||||
case = self.make_dirty_case('LA', (255, 128), (0, 0))
|
case = self.make_dirty_case("LA", (255, 128), (0, 0))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.BOX), (255,))
|
self.run_dirty_case(case.resize((20, 20), Image.BOX), (255,))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.BILINEAR), (255,))
|
self.run_dirty_case(case.resize((20, 20), Image.BILINEAR), (255,))
|
||||||
self.run_dirty_case(case.resize((20, 20), Image.HAMMING), (255,))
|
self.run_dirty_case(case.resize((20, 20), Image.HAMMING), (255,))
|
||||||
|
@ -309,27 +324,27 @@ class CoreResampleAlphaCorrectTest(PillowTestCase):
|
||||||
class CoreResamplePassesTest(PillowTestCase):
|
class CoreResamplePassesTest(PillowTestCase):
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def count(self, diff):
|
def count(self, diff):
|
||||||
count = Image.core.get_stats()['new_count']
|
count = Image.core.get_stats()["new_count"]
|
||||||
yield
|
yield
|
||||||
self.assertEqual(Image.core.get_stats()['new_count'] - count, diff)
|
self.assertEqual(Image.core.get_stats()["new_count"] - count, diff)
|
||||||
|
|
||||||
def test_horizontal(self):
|
def test_horizontal(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
with self.count(1):
|
with self.count(1):
|
||||||
im.resize((im.size[0] - 10, im.size[1]), Image.BILINEAR)
|
im.resize((im.size[0] - 10, im.size[1]), Image.BILINEAR)
|
||||||
|
|
||||||
def test_vertical(self):
|
def test_vertical(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
with self.count(1):
|
with self.count(1):
|
||||||
im.resize((im.size[0], im.size[1] - 10), Image.BILINEAR)
|
im.resize((im.size[0], im.size[1] - 10), Image.BILINEAR)
|
||||||
|
|
||||||
def test_both(self):
|
def test_both(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
with self.count(2):
|
with self.count(2):
|
||||||
im.resize((im.size[0] - 10, im.size[1] - 10), Image.BILINEAR)
|
im.resize((im.size[0] - 10, im.size[1] - 10), Image.BILINEAR)
|
||||||
|
|
||||||
def test_box_horizontal(self):
|
def test_box_horizontal(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
box = (20, 0, im.size[0] - 20, im.size[1])
|
box = (20, 0, im.size[0] - 20, im.size[1])
|
||||||
with self.count(1):
|
with self.count(1):
|
||||||
# the same size, but different box
|
# the same size, but different box
|
||||||
|
@ -339,7 +354,7 @@ class CoreResamplePassesTest(PillowTestCase):
|
||||||
self.assert_image_similar(with_box, cropped, 0.1)
|
self.assert_image_similar(with_box, cropped, 0.1)
|
||||||
|
|
||||||
def test_box_vertical(self):
|
def test_box_vertical(self):
|
||||||
im = hopper('L')
|
im = hopper("L")
|
||||||
box = (0, 20, im.size[0], im.size[1] - 20)
|
box = (0, 20, im.size[0], im.size[1] - 20)
|
||||||
with self.count(1):
|
with self.count(1):
|
||||||
# the same size, but different box
|
# the same size, but different box
|
||||||
|
@ -354,7 +369,7 @@ class CoreResampleCoefficientsTest(PillowTestCase):
|
||||||
test_color = 254
|
test_color = 254
|
||||||
|
|
||||||
for size in range(400000, 400010, 2):
|
for size in range(400000, 400010, 2):
|
||||||
i = Image.new('L', (size, 1), 0)
|
i = Image.new("L", (size, 1), 0)
|
||||||
draw = ImageDraw.Draw(i)
|
draw = ImageDraw.Draw(i)
|
||||||
draw.rectangle((0, 0, i.size[0] // 2 - 1, 0), test_color)
|
draw.rectangle((0, 0, i.size[0] // 2 - 1, 0), test_color)
|
||||||
|
|
||||||
|
@ -365,7 +380,7 @@ class CoreResampleCoefficientsTest(PillowTestCase):
|
||||||
def test_nonzero_coefficients(self):
|
def test_nonzero_coefficients(self):
|
||||||
# regression test for the wrong coefficients calculation
|
# regression test for the wrong coefficients calculation
|
||||||
# due to bug https://github.com/python-pillow/Pillow/issues/2161
|
# due to bug https://github.com/python-pillow/Pillow/issues/2161
|
||||||
im = Image.new('RGBA', (1280, 1280), (0x20, 0x40, 0x60, 0xff))
|
im = Image.new("RGBA", (1280, 1280), (0x20, 0x40, 0x60, 0xFF))
|
||||||
histogram = im.resize((256, 256), Image.BICUBIC).histogram()
|
histogram = im.resize((256, 256), Image.BICUBIC).histogram()
|
||||||
|
|
||||||
# first channel
|
# first channel
|
||||||
|
@ -375,21 +390,26 @@ class CoreResampleCoefficientsTest(PillowTestCase):
|
||||||
# third channel
|
# third channel
|
||||||
self.assertEqual(histogram[0x100 * 2 + 0x60], 0x10000)
|
self.assertEqual(histogram[0x100 * 2 + 0x60], 0x10000)
|
||||||
# fourth channel
|
# fourth channel
|
||||||
self.assertEqual(histogram[0x100 * 3 + 0xff], 0x10000)
|
self.assertEqual(histogram[0x100 * 3 + 0xFF], 0x10000)
|
||||||
|
|
||||||
|
|
||||||
class CoreResampleBoxTest(PillowTestCase):
|
class CoreResampleBoxTest(PillowTestCase):
|
||||||
def test_wrong_arguments(self):
|
def test_wrong_arguments(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
for resample in (Image.NEAREST, Image.BOX, Image.BILINEAR,
|
for resample in (
|
||||||
Image.HAMMING, Image.BICUBIC, Image.LANCZOS):
|
Image.NEAREST,
|
||||||
|
Image.BOX,
|
||||||
|
Image.BILINEAR,
|
||||||
|
Image.HAMMING,
|
||||||
|
Image.BICUBIC,
|
||||||
|
Image.LANCZOS,
|
||||||
|
):
|
||||||
im.resize((32, 32), resample, (0, 0, im.width, im.height))
|
im.resize((32, 32), resample, (0, 0, im.width, im.height))
|
||||||
im.resize((32, 32), resample, (20, 20, im.width, im.height))
|
im.resize((32, 32), resample, (20, 20, im.width, im.height))
|
||||||
im.resize((32, 32), resample, (20, 20, 20, 100))
|
im.resize((32, 32), resample, (20, 20, 20, 100))
|
||||||
im.resize((32, 32), resample, (20, 20, 100, 20))
|
im.resize((32, 32), resample, (20, 20, 100, 20))
|
||||||
|
|
||||||
with self.assertRaisesRegex(TypeError,
|
with self.assertRaisesRegex(TypeError, "must be sequence of length 4"):
|
||||||
"must be sequence of length 4"):
|
|
||||||
im.resize((32, 32), resample, (im.width, im.height))
|
im.resize((32, 32), resample, (im.width, im.height))
|
||||||
|
|
||||||
with self.assertRaisesRegex(ValueError, "can't be negative"):
|
with self.assertRaisesRegex(ValueError, "can't be negative"):
|
||||||
|
@ -420,8 +440,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
|
|
||||||
for y0, y1 in split_range(dst_size[1], ytiles):
|
for y0, y1 in split_range(dst_size[1], ytiles):
|
||||||
for x0, x1 in split_range(dst_size[0], xtiles):
|
for x0, x1 in split_range(dst_size[0], xtiles):
|
||||||
box = (x0 * scale[0], y0 * scale[1],
|
box = (x0 * scale[0], y0 * scale[1], x1 * scale[0], y1 * scale[1])
|
||||||
x1 * scale[0], y1 * scale[1])
|
|
||||||
tile = im.resize((x1 - x0, y1 - y0), Image.BICUBIC, box)
|
tile = im.resize((x1 - x0, y1 - y0), Image.BICUBIC, box)
|
||||||
tiled.paste(tile, (x0, y0))
|
tiled.paste(tile, (x0, y0))
|
||||||
return tiled
|
return tiled
|
||||||
|
@ -447,8 +466,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
# Image.BOX emulates supersampling (480 / 8 = 60, 360 / 8 = 45)
|
# Image.BOX emulates supersampling (480 / 8 = 60, 360 / 8 = 45)
|
||||||
supersampled = im.resize((60, 45), Image.BOX)
|
supersampled = im.resize((60, 45), Image.BOX)
|
||||||
|
|
||||||
with_box = supersampled.resize(dst_size, Image.BICUBIC,
|
with_box = supersampled.resize(dst_size, Image.BICUBIC, (0, 0, 59.125, 44.125))
|
||||||
(0, 0, 59.125, 44.125))
|
|
||||||
without_box = supersampled.resize(dst_size, Image.BICUBIC)
|
without_box = supersampled.resize(dst_size, Image.BICUBIC)
|
||||||
|
|
||||||
# error with box should be much smaller than without
|
# error with box should be much smaller than without
|
||||||
|
@ -458,7 +476,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
|
|
||||||
def test_formats(self):
|
def test_formats(self):
|
||||||
for resample in [Image.NEAREST, Image.BILINEAR]:
|
for resample in [Image.NEAREST, Image.BILINEAR]:
|
||||||
for mode in ['RGB', 'L', 'RGBA', 'LA', 'I', '']:
|
for mode in ["RGB", "L", "RGBA", "LA", "I", ""]:
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
box = (20, 20, im.size[0] - 20, im.size[1] - 20)
|
box = (20, 20, im.size[0] - 20, im.size[1] - 20)
|
||||||
with_box = im.resize((32, 32), resample, box)
|
with_box = im.resize((32, 32), resample, box)
|
||||||
|
@ -480,7 +498,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
self.assertEqual(res.size, size)
|
self.assertEqual(res.size, size)
|
||||||
self.assert_image_equal(res, im.crop(box))
|
self.assert_image_equal(res, im.crop(box))
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
print('>>>', size, box)
|
print(">>>", size, box)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def test_no_passthrough(self):
|
def test_no_passthrough(self):
|
||||||
|
@ -500,7 +518,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
# check that the difference at least that much
|
# check that the difference at least that much
|
||||||
self.assert_image_similar(res, im.crop(box), 20)
|
self.assert_image_similar(res, im.crop(box), 20)
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
print('>>>', size, box)
|
print(">>>", size, box)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def test_skip_horizontal(self):
|
def test_skip_horizontal(self):
|
||||||
|
@ -518,10 +536,9 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
res = im.resize(size, flt, box)
|
res = im.resize(size, flt, box)
|
||||||
self.assertEqual(res.size, size)
|
self.assertEqual(res.size, size)
|
||||||
# Borders should be slightly different
|
# Borders should be slightly different
|
||||||
self.assert_image_similar(
|
self.assert_image_similar(res, im.crop(box).resize(size, flt), 0.4)
|
||||||
res, im.crop(box).resize(size, flt), 0.4)
|
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
print('>>>', size, box, flt)
|
print(">>>", size, box, flt)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def test_skip_vertical(self):
|
def test_skip_vertical(self):
|
||||||
|
@ -539,8 +556,7 @@ class CoreResampleBoxTest(PillowTestCase):
|
||||||
res = im.resize(size, flt, box)
|
res = im.resize(size, flt, box)
|
||||||
self.assertEqual(res.size, size)
|
self.assertEqual(res.size, size)
|
||||||
# Borders should be slightly different
|
# Borders should be slightly different
|
||||||
self.assert_image_similar(
|
self.assert_image_similar(res, im.crop(box).resize(size, flt), 0.4)
|
||||||
res, im.crop(box).resize(size, flt), 0.4)
|
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
print('>>>', size, box, flt)
|
print(">>>", size, box, flt)
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -9,15 +9,24 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImagingCoreResize(PillowTestCase):
|
class TestImagingCoreResize(PillowTestCase):
|
||||||
|
|
||||||
def resize(self, im, size, f):
|
def resize(self, im, size, f):
|
||||||
# Image class independent version of resize.
|
# Image class independent version of resize.
|
||||||
im.load()
|
im.load()
|
||||||
return im._new(im.im.resize(size, f))
|
return im._new(im.im.resize(size, f))
|
||||||
|
|
||||||
def test_nearest_mode(self):
|
def test_nearest_mode(self):
|
||||||
for mode in ["1", "P", "L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr",
|
for mode in [
|
||||||
"I;16"]: # exotic mode
|
"1",
|
||||||
|
"P",
|
||||||
|
"L",
|
||||||
|
"I",
|
||||||
|
"F",
|
||||||
|
"RGB",
|
||||||
|
"RGBA",
|
||||||
|
"CMYK",
|
||||||
|
"YCbCr",
|
||||||
|
"I;16",
|
||||||
|
]: # exotic mode
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
r = self.resize(im, (15, 12), Image.NEAREST)
|
r = self.resize(im, (15, 12), Image.NEAREST)
|
||||||
self.assertEqual(r.mode, mode)
|
self.assertEqual(r.mode, mode)
|
||||||
|
@ -25,12 +34,15 @@ class TestImagingCoreResize(PillowTestCase):
|
||||||
self.assertEqual(r.im.bands, im.im.bands)
|
self.assertEqual(r.im.bands, im.im.bands)
|
||||||
|
|
||||||
def test_convolution_modes(self):
|
def test_convolution_modes(self):
|
||||||
self.assertRaises(ValueError, self.resize, hopper("1"),
|
self.assertRaises(
|
||||||
(15, 12), Image.BILINEAR)
|
ValueError, self.resize, hopper("1"), (15, 12), Image.BILINEAR
|
||||||
self.assertRaises(ValueError, self.resize, hopper("P"),
|
)
|
||||||
(15, 12), Image.BILINEAR)
|
self.assertRaises(
|
||||||
self.assertRaises(ValueError, self.resize, hopper("I;16"),
|
ValueError, self.resize, hopper("P"), (15, 12), Image.BILINEAR
|
||||||
(15, 12), Image.BILINEAR)
|
)
|
||||||
|
self.assertRaises(
|
||||||
|
ValueError, self.resize, hopper("I;16"), (15, 12), Image.BILINEAR
|
||||||
|
)
|
||||||
for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]:
|
for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]:
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
r = self.resize(im, (15, 12), Image.BILINEAR)
|
r = self.resize(im, (15, 12), Image.BILINEAR)
|
||||||
|
@ -39,15 +51,27 @@ class TestImagingCoreResize(PillowTestCase):
|
||||||
self.assertEqual(r.im.bands, im.im.bands)
|
self.assertEqual(r.im.bands, im.im.bands)
|
||||||
|
|
||||||
def test_reduce_filters(self):
|
def test_reduce_filters(self):
|
||||||
for f in [Image.NEAREST, Image.BOX, Image.BILINEAR,
|
for f in [
|
||||||
Image.HAMMING, Image.BICUBIC, Image.LANCZOS]:
|
Image.NEAREST,
|
||||||
|
Image.BOX,
|
||||||
|
Image.BILINEAR,
|
||||||
|
Image.HAMMING,
|
||||||
|
Image.BICUBIC,
|
||||||
|
Image.LANCZOS,
|
||||||
|
]:
|
||||||
r = self.resize(hopper("RGB"), (15, 12), f)
|
r = self.resize(hopper("RGB"), (15, 12), f)
|
||||||
self.assertEqual(r.mode, "RGB")
|
self.assertEqual(r.mode, "RGB")
|
||||||
self.assertEqual(r.size, (15, 12))
|
self.assertEqual(r.size, (15, 12))
|
||||||
|
|
||||||
def test_enlarge_filters(self):
|
def test_enlarge_filters(self):
|
||||||
for f in [Image.NEAREST, Image.BOX, Image.BILINEAR,
|
for f in [
|
||||||
Image.HAMMING, Image.BICUBIC, Image.LANCZOS]:
|
Image.NEAREST,
|
||||||
|
Image.BOX,
|
||||||
|
Image.BILINEAR,
|
||||||
|
Image.HAMMING,
|
||||||
|
Image.BICUBIC,
|
||||||
|
Image.LANCZOS,
|
||||||
|
]:
|
||||||
r = self.resize(hopper("RGB"), (212, 195), f)
|
r = self.resize(hopper("RGB"), (212, 195), f)
|
||||||
self.assertEqual(r.mode, "RGB")
|
self.assertEqual(r.mode, "RGB")
|
||||||
self.assertEqual(r.size, (212, 195))
|
self.assertEqual(r.size, (212, 195))
|
||||||
|
@ -60,24 +84,29 @@ class TestImagingCoreResize(PillowTestCase):
|
||||||
# an endianness issues.
|
# an endianness issues.
|
||||||
|
|
||||||
samples = {
|
samples = {
|
||||||
'blank': Image.new('L', (2, 2), 0),
|
"blank": Image.new("L", (2, 2), 0),
|
||||||
'filled': Image.new('L', (2, 2), 255),
|
"filled": Image.new("L", (2, 2), 255),
|
||||||
'dirty': Image.new('L', (2, 2), 0),
|
"dirty": Image.new("L", (2, 2), 0),
|
||||||
}
|
}
|
||||||
samples['dirty'].putpixel((1, 1), 128)
|
samples["dirty"].putpixel((1, 1), 128)
|
||||||
|
|
||||||
for f in [Image.NEAREST, Image.BOX, Image.BILINEAR,
|
for f in [
|
||||||
Image.HAMMING, Image.BICUBIC, Image.LANCZOS]:
|
Image.NEAREST,
|
||||||
|
Image.BOX,
|
||||||
|
Image.BILINEAR,
|
||||||
|
Image.HAMMING,
|
||||||
|
Image.BICUBIC,
|
||||||
|
Image.LANCZOS,
|
||||||
|
]:
|
||||||
# samples resized with current filter
|
# samples resized with current filter
|
||||||
references = {
|
references = {
|
||||||
name: self.resize(ch, (4, 4), f)
|
name: self.resize(ch, (4, 4), f) for name, ch in samples.items()
|
||||||
for name, ch in samples.items()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for mode, channels_set in [
|
for mode, channels_set in [
|
||||||
('RGB', ('blank', 'filled', 'dirty')),
|
("RGB", ("blank", "filled", "dirty")),
|
||||||
('RGBA', ('blank', 'blank', 'filled', 'dirty')),
|
("RGBA", ("blank", "blank", "filled", "dirty")),
|
||||||
('LA', ('filled', 'dirty')),
|
("LA", ("filled", "dirty")),
|
||||||
]:
|
]:
|
||||||
for channels in set(permutations(channels_set)):
|
for channels in set(permutations(channels_set)):
|
||||||
# compile image from different channels permutations
|
# compile image from different channels permutations
|
||||||
|
@ -90,9 +119,15 @@ class TestImagingCoreResize(PillowTestCase):
|
||||||
self.assert_image_equal(ch, references[channels[i]])
|
self.assert_image_equal(ch, references[channels[i]])
|
||||||
|
|
||||||
def test_enlarge_zero(self):
|
def test_enlarge_zero(self):
|
||||||
for f in [Image.NEAREST, Image.BOX, Image.BILINEAR,
|
for f in [
|
||||||
Image.HAMMING, Image.BICUBIC, Image.LANCZOS]:
|
Image.NEAREST,
|
||||||
r = self.resize(Image.new('RGB', (0, 0), "white"), (212, 195), f)
|
Image.BOX,
|
||||||
|
Image.BILINEAR,
|
||||||
|
Image.HAMMING,
|
||||||
|
Image.BICUBIC,
|
||||||
|
Image.LANCZOS,
|
||||||
|
]:
|
||||||
|
r = self.resize(Image.new("RGB", (0, 0), "white"), (212, 195), f)
|
||||||
self.assertEqual(r.mode, "RGB")
|
self.assertEqual(r.mode, "RGB")
|
||||||
self.assertEqual(r.size, (212, 195))
|
self.assertEqual(r.size, (212, 195))
|
||||||
self.assertEqual(r.getdata()[0], (0, 0, 0))
|
self.assertEqual(r.getdata()[0], (0, 0, 0))
|
||||||
|
@ -102,12 +137,12 @@ class TestImagingCoreResize(PillowTestCase):
|
||||||
|
|
||||||
|
|
||||||
class TestImageResize(PillowTestCase):
|
class TestImageResize(PillowTestCase):
|
||||||
|
|
||||||
def test_resize(self):
|
def test_resize(self):
|
||||||
def resize(mode, size):
|
def resize(mode, size):
|
||||||
out = hopper(mode).resize(size)
|
out = hopper(mode).resize(size)
|
||||||
self.assertEqual(out.mode, mode)
|
self.assertEqual(out.mode, mode)
|
||||||
self.assertEqual(out.size, size)
|
self.assertEqual(out.size, size)
|
||||||
|
|
||||||
for mode in "1", "P", "L", "RGB", "I", "F":
|
for mode in "1", "P", "L", "RGB", "I", "F":
|
||||||
resize(mode, (112, 103))
|
resize(mode, (112, 103))
|
||||||
resize(mode, (188, 214))
|
resize(mode, (188, 214))
|
||||||
|
|
|
@ -3,7 +3,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageRotate(PillowTestCase):
|
class TestImageRotate(PillowTestCase):
|
||||||
|
|
||||||
def rotate(self, im, mode, angle, center=None, translate=None):
|
def rotate(self, im, mode, angle, center=None, translate=None):
|
||||||
out = im.rotate(angle, center=center, translate=translate)
|
out = im.rotate(angle, center=center, translate=translate)
|
||||||
self.assertEqual(out.mode, mode)
|
self.assertEqual(out.mode, mode)
|
||||||
|
@ -24,12 +23,12 @@ class TestImageRotate(PillowTestCase):
|
||||||
|
|
||||||
def test_angle(self):
|
def test_angle(self):
|
||||||
for angle in (0, 90, 180, 270):
|
for angle in (0, 90, 180, 270):
|
||||||
im = Image.open('Tests/images/test-card.png')
|
im = Image.open("Tests/images/test-card.png")
|
||||||
self.rotate(im, im.mode, angle)
|
self.rotate(im, im.mode, angle)
|
||||||
|
|
||||||
def test_zero(self):
|
def test_zero(self):
|
||||||
for angle in (0, 45, 90, 180, 270):
|
for angle in (0, 45, 90, 180, 270):
|
||||||
im = Image.new('RGB', (0, 0))
|
im = Image.new("RGB", (0, 0))
|
||||||
self.rotate(im, im.mode, angle)
|
self.rotate(im, im.mode, angle)
|
||||||
|
|
||||||
def test_resample(self):
|
def test_resample(self):
|
||||||
|
@ -38,18 +37,20 @@ class TestImageRotate(PillowTestCase):
|
||||||
# >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True)
|
# >>> im = im.rotate(45, resample=Image.BICUBIC, expand=True)
|
||||||
# >>> im.save('Tests/images/hopper_45.png')
|
# >>> im.save('Tests/images/hopper_45.png')
|
||||||
|
|
||||||
target = Image.open('Tests/images/hopper_45.png')
|
target = Image.open("Tests/images/hopper_45.png")
|
||||||
for (resample, epsilon) in ((Image.NEAREST, 10),
|
for (resample, epsilon) in (
|
||||||
(Image.BILINEAR, 5),
|
(Image.NEAREST, 10),
|
||||||
(Image.BICUBIC, 0)):
|
(Image.BILINEAR, 5),
|
||||||
|
(Image.BICUBIC, 0),
|
||||||
|
):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
im = im.rotate(45, resample=resample, expand=True)
|
im = im.rotate(45, resample=resample, expand=True)
|
||||||
self.assert_image_similar(im, target, epsilon)
|
self.assert_image_similar(im, target, epsilon)
|
||||||
|
|
||||||
def test_center_0(self):
|
def test_center_0(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
target = Image.open('Tests/images/hopper_45.png')
|
target = Image.open("Tests/images/hopper_45.png")
|
||||||
target_origin = target.size[1]/2
|
target_origin = target.size[1] / 2
|
||||||
target = target.crop((0, target_origin, 128, target_origin + 128))
|
target = target.crop((0, target_origin, 128, target_origin + 128))
|
||||||
|
|
||||||
im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC)
|
im = im.rotate(45, center=(0, 0), resample=Image.BICUBIC)
|
||||||
|
@ -58,7 +59,7 @@ class TestImageRotate(PillowTestCase):
|
||||||
|
|
||||||
def test_center_14(self):
|
def test_center_14(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
target = Image.open('Tests/images/hopper_45.png')
|
target = Image.open("Tests/images/hopper_45.png")
|
||||||
target_origin = target.size[1] / 2 - 14
|
target_origin = target.size[1] / 2 - 14
|
||||||
target = target.crop((6, target_origin, 128 + 6, target_origin + 128))
|
target = target.crop((6, target_origin, 128 + 6, target_origin + 128))
|
||||||
|
|
||||||
|
@ -68,10 +69,11 @@ class TestImageRotate(PillowTestCase):
|
||||||
|
|
||||||
def test_translate(self):
|
def test_translate(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
target = Image.open('Tests/images/hopper_45.png')
|
target = Image.open("Tests/images/hopper_45.png")
|
||||||
target_origin = (target.size[1] / 2 - 64) - 5
|
target_origin = (target.size[1] / 2 - 64) - 5
|
||||||
target = target.crop((target_origin, target_origin,
|
target = target.crop(
|
||||||
target_origin + 128, target_origin + 128))
|
(target_origin, target_origin, target_origin + 128, target_origin + 128)
|
||||||
|
)
|
||||||
|
|
||||||
im = im.rotate(45, translate=(5, 5), resample=Image.BICUBIC)
|
im = im.rotate(45, translate=(5, 5), resample=Image.BICUBIC)
|
||||||
|
|
||||||
|
@ -82,44 +84,43 @@ class TestImageRotate(PillowTestCase):
|
||||||
# resulting image should be black
|
# resulting image should be black
|
||||||
for angle in (90, 180, 270):
|
for angle in (90, 180, 270):
|
||||||
im = hopper().rotate(angle, center=(-1, -1))
|
im = hopper().rotate(angle, center=(-1, -1))
|
||||||
self.assert_image_equal(im, Image.new('RGB', im.size, 'black'))
|
self.assert_image_equal(im, Image.new("RGB", im.size, "black"))
|
||||||
|
|
||||||
def test_fastpath_translate(self):
|
def test_fastpath_translate(self):
|
||||||
# if we post-translate by -128
|
# if we post-translate by -128
|
||||||
# resulting image should be black
|
# resulting image should be black
|
||||||
for angle in (0, 90, 180, 270):
|
for angle in (0, 90, 180, 270):
|
||||||
im = hopper().rotate(angle, translate=(-128, -128))
|
im = hopper().rotate(angle, translate=(-128, -128))
|
||||||
self.assert_image_equal(im, Image.new('RGB', im.size, 'black'))
|
self.assert_image_equal(im, Image.new("RGB", im.size, "black"))
|
||||||
|
|
||||||
def test_center(self):
|
def test_center(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
self.rotate(im, im.mode, 45, center=(0, 0))
|
self.rotate(im, im.mode, 45, center=(0, 0))
|
||||||
self.rotate(im, im.mode, 45, translate=(im.size[0]/2, 0))
|
self.rotate(im, im.mode, 45, translate=(im.size[0] / 2, 0))
|
||||||
self.rotate(im, im.mode, 45, center=(0, 0),
|
self.rotate(im, im.mode, 45, center=(0, 0), translate=(im.size[0] / 2, 0))
|
||||||
translate=(im.size[0]/2, 0))
|
|
||||||
|
|
||||||
def test_rotate_no_fill(self):
|
def test_rotate_no_fill(self):
|
||||||
im = Image.new('RGB', (100, 100), 'green')
|
im = Image.new("RGB", (100, 100), "green")
|
||||||
target = Image.open('Tests/images/rotate_45_no_fill.png')
|
target = Image.open("Tests/images/rotate_45_no_fill.png")
|
||||||
im = im.rotate(45)
|
im = im.rotate(45)
|
||||||
self.assert_image_equal(im, target)
|
self.assert_image_equal(im, target)
|
||||||
|
|
||||||
def test_rotate_with_fill(self):
|
def test_rotate_with_fill(self):
|
||||||
im = Image.new('RGB', (100, 100), 'green')
|
im = Image.new("RGB", (100, 100), "green")
|
||||||
target = Image.open('Tests/images/rotate_45_with_fill.png')
|
target = Image.open("Tests/images/rotate_45_with_fill.png")
|
||||||
im = im.rotate(45, fillcolor='white')
|
im = im.rotate(45, fillcolor="white")
|
||||||
self.assert_image_equal(im, target)
|
self.assert_image_equal(im, target)
|
||||||
|
|
||||||
def test_alpha_rotate_no_fill(self):
|
def test_alpha_rotate_no_fill(self):
|
||||||
# Alpha images are handled differently internally
|
# Alpha images are handled differently internally
|
||||||
im = Image.new('RGBA', (10, 10), 'green')
|
im = Image.new("RGBA", (10, 10), "green")
|
||||||
im = im.rotate(45, expand=1)
|
im = im.rotate(45, expand=1)
|
||||||
corner = im.getpixel((0, 0))
|
corner = im.getpixel((0, 0))
|
||||||
self.assertEqual(corner, (0, 0, 0, 0))
|
self.assertEqual(corner, (0, 0, 0, 0))
|
||||||
|
|
||||||
def test_alpha_rotate_with_fill(self):
|
def test_alpha_rotate_with_fill(self):
|
||||||
# Alpha images are handled differently internally
|
# Alpha images are handled differently internally
|
||||||
im = Image.new('RGBA', (10, 10), 'green')
|
im = Image.new("RGBA", (10, 10), "green")
|
||||||
im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255))
|
im = im.rotate(45, expand=1, fillcolor=(255, 0, 0, 255))
|
||||||
corner = im.getpixel((0, 0))
|
corner = im.getpixel((0, 0))
|
||||||
self.assertEqual(corner, (255, 0, 0, 255))
|
self.assertEqual(corner, (255, 0, 0, 255))
|
||||||
|
|
|
@ -4,33 +4,35 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageSplit(PillowTestCase):
|
class TestImageSplit(PillowTestCase):
|
||||||
|
|
||||||
def test_split(self):
|
def test_split(self):
|
||||||
def split(mode):
|
def split(mode):
|
||||||
layers = hopper(mode).split()
|
layers = hopper(mode).split()
|
||||||
return [(i.mode, i.size[0], i.size[1]) for i in layers]
|
return [(i.mode, i.size[0], i.size[1]) for i in layers]
|
||||||
self.assertEqual(split("1"), [('1', 128, 128)])
|
|
||||||
self.assertEqual(split("L"), [('L', 128, 128)])
|
self.assertEqual(split("1"), [("1", 128, 128)])
|
||||||
self.assertEqual(split("I"), [('I', 128, 128)])
|
self.assertEqual(split("L"), [("L", 128, 128)])
|
||||||
self.assertEqual(split("F"), [('F', 128, 128)])
|
self.assertEqual(split("I"), [("I", 128, 128)])
|
||||||
self.assertEqual(split("P"), [('P', 128, 128)])
|
self.assertEqual(split("F"), [("F", 128, 128)])
|
||||||
|
self.assertEqual(split("P"), [("P", 128, 128)])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
split("RGB"), [('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
|
split("RGB"), [("L", 128, 128), ("L", 128, 128), ("L", 128, 128)]
|
||||||
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
split("RGBA"),
|
split("RGBA"),
|
||||||
[('L', 128, 128), ('L', 128, 128),
|
[("L", 128, 128), ("L", 128, 128), ("L", 128, 128), ("L", 128, 128)],
|
||||||
('L', 128, 128), ('L', 128, 128)])
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
split("CMYK"),
|
split("CMYK"),
|
||||||
[('L', 128, 128), ('L', 128, 128),
|
[("L", 128, 128), ("L", 128, 128), ("L", 128, 128), ("L", 128, 128)],
|
||||||
('L', 128, 128), ('L', 128, 128)])
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
split("YCbCr"),
|
split("YCbCr"), [("L", 128, 128), ("L", 128, 128), ("L", 128, 128)]
|
||||||
[('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
|
)
|
||||||
|
|
||||||
def test_split_merge(self):
|
def test_split_merge(self):
|
||||||
def split_merge(mode):
|
def split_merge(mode):
|
||||||
return Image.merge(mode, hopper(mode).split())
|
return Image.merge(mode, hopper(mode).split())
|
||||||
|
|
||||||
self.assert_image_equal(hopper("1"), split_merge("1"))
|
self.assert_image_equal(hopper("1"), split_merge("1"))
|
||||||
self.assert_image_equal(hopper("L"), split_merge("L"))
|
self.assert_image_equal(hopper("L"), split_merge("L"))
|
||||||
self.assert_image_equal(hopper("I"), split_merge("I"))
|
self.assert_image_equal(hopper("I"), split_merge("I"))
|
||||||
|
@ -44,7 +46,7 @@ class TestImageSplit(PillowTestCase):
|
||||||
def test_split_open(self):
|
def test_split_open(self):
|
||||||
codecs = dir(Image.core)
|
codecs = dir(Image.core)
|
||||||
|
|
||||||
if 'zip_encoder' in codecs:
|
if "zip_encoder" in codecs:
|
||||||
test_file = self.tempfile("temp.png")
|
test_file = self.tempfile("temp.png")
|
||||||
else:
|
else:
|
||||||
test_file = self.tempfile("temp.pcx")
|
test_file = self.tempfile("temp.pcx")
|
||||||
|
@ -53,9 +55,10 @@ class TestImageSplit(PillowTestCase):
|
||||||
hopper(mode).save(test_file)
|
hopper(mode).save(test_file)
|
||||||
im = Image.open(test_file)
|
im = Image.open(test_file)
|
||||||
return len(im.split())
|
return len(im.split())
|
||||||
|
|
||||||
self.assertEqual(split_open("1"), 1)
|
self.assertEqual(split_open("1"), 1)
|
||||||
self.assertEqual(split_open("L"), 1)
|
self.assertEqual(split_open("L"), 1)
|
||||||
self.assertEqual(split_open("P"), 1)
|
self.assertEqual(split_open("P"), 1)
|
||||||
self.assertEqual(split_open("RGB"), 3)
|
self.assertEqual(split_open("RGB"), 3)
|
||||||
if 'zip_encoder' in codecs:
|
if "zip_encoder" in codecs:
|
||||||
self.assertEqual(split_open("RGBA"), 4)
|
self.assertEqual(split_open("RGBA"), 4)
|
||||||
|
|
|
@ -3,7 +3,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageThumbnail(PillowTestCase):
|
class TestImageThumbnail(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
|
@ -2,7 +2,6 @@ from .helper import PillowTestCase, hopper, fromstring
|
||||||
|
|
||||||
|
|
||||||
class TestImageToBitmap(PillowTestCase):
|
class TestImageToBitmap(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
self.assertRaises(ValueError, lambda: hopper().tobitmap())
|
self.assertRaises(ValueError, lambda: hopper().tobitmap())
|
||||||
|
|
|
@ -2,7 +2,6 @@ from .helper import PillowTestCase, hopper
|
||||||
|
|
||||||
|
|
||||||
class TestImageToBytes(PillowTestCase):
|
class TestImageToBytes(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
data = hopper().tobytes()
|
data = hopper().tobytes()
|
||||||
self.assertIsInstance(data, bytes)
|
self.assertIsInstance(data, bytes)
|
||||||
|
|
|
@ -6,7 +6,6 @@ from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
class TestImageTransform(PillowTestCase):
|
class TestImageTransform(PillowTestCase):
|
||||||
|
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
from PIL import ImageTransform
|
from PIL import ImageTransform
|
||||||
|
|
||||||
|
@ -24,54 +23,61 @@ class TestImageTransform(PillowTestCase):
|
||||||
im.transform((100, 100), transform)
|
im.transform((100, 100), transform)
|
||||||
|
|
||||||
def test_extent(self):
|
def test_extent(self):
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
(w, h) = im.size
|
(w, h) = im.size
|
||||||
|
# fmt: off
|
||||||
transformed = im.transform(im.size, Image.EXTENT,
|
transformed = im.transform(im.size, Image.EXTENT,
|
||||||
(0, 0,
|
(0, 0,
|
||||||
w//2, h//2), # ul -> lr
|
w//2, h//2), # ul -> lr
|
||||||
Image.BILINEAR)
|
Image.BILINEAR)
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
scaled = im.resize((w*2, h*2), Image.BILINEAR).crop((0, 0, w, h))
|
scaled = im.resize((w * 2, h * 2), Image.BILINEAR).crop((0, 0, w, h))
|
||||||
|
|
||||||
# undone -- precision?
|
# undone -- precision?
|
||||||
self.assert_image_similar(transformed, scaled, 23)
|
self.assert_image_similar(transformed, scaled, 23)
|
||||||
|
|
||||||
def test_quad(self):
|
def test_quad(self):
|
||||||
# one simple quad transform, equivalent to scale & crop upper left quad
|
# one simple quad transform, equivalent to scale & crop upper left quad
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
(w, h) = im.size
|
(w, h) = im.size
|
||||||
|
# fmt: off
|
||||||
transformed = im.transform(im.size, Image.QUAD,
|
transformed = im.transform(im.size, Image.QUAD,
|
||||||
(0, 0, 0, h//2,
|
(0, 0, 0, h//2,
|
||||||
# ul -> ccw around quad:
|
# ul -> ccw around quad:
|
||||||
w//2, h//2, w//2, 0),
|
w//2, h//2, w//2, 0),
|
||||||
Image.BILINEAR)
|
Image.BILINEAR)
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
scaled = im.transform((w, h), Image.AFFINE,
|
scaled = im.transform(
|
||||||
(.5, 0, 0, 0, .5, 0),
|
(w, h), Image.AFFINE, (0.5, 0, 0, 0, 0.5, 0), Image.BILINEAR
|
||||||
Image.BILINEAR)
|
)
|
||||||
|
|
||||||
self.assert_image_equal(transformed, scaled)
|
self.assert_image_equal(transformed, scaled)
|
||||||
|
|
||||||
def test_fill(self):
|
def test_fill(self):
|
||||||
for mode, pixel in [
|
for mode, pixel in [
|
||||||
['RGB', (255, 0, 0)],
|
["RGB", (255, 0, 0)],
|
||||||
['RGBA', (255, 0, 0, 255)],
|
["RGBA", (255, 0, 0, 255)],
|
||||||
['LA', (76, 0)]
|
["LA", (76, 0)],
|
||||||
]:
|
]:
|
||||||
im = hopper(mode)
|
im = hopper(mode)
|
||||||
(w, h) = im.size
|
(w, h) = im.size
|
||||||
transformed = im.transform(im.size, Image.EXTENT,
|
transformed = im.transform(
|
||||||
(0, 0,
|
im.size,
|
||||||
w*2, h*2),
|
Image.EXTENT,
|
||||||
Image.BILINEAR,
|
(0, 0, w * 2, h * 2),
|
||||||
fillcolor='red')
|
Image.BILINEAR,
|
||||||
|
fillcolor="red",
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(transformed.getpixel((w-1, h-1)), pixel)
|
self.assertEqual(transformed.getpixel((w - 1, h - 1)), pixel)
|
||||||
|
|
||||||
def test_mesh(self):
|
def test_mesh(self):
|
||||||
# this should be a checkerboard of halfsized hoppers in ul, lr
|
# this should be a checkerboard of halfsized hoppers in ul, lr
|
||||||
im = hopper('RGBA')
|
im = hopper("RGBA")
|
||||||
(w, h) = im.size
|
(w, h) = im.size
|
||||||
|
# fmt: off
|
||||||
transformed = im.transform(im.size, Image.MESH,
|
transformed = im.transform(im.size, Image.MESH,
|
||||||
[((0, 0, w//2, h//2), # box
|
[((0, 0, w//2, h//2), # box
|
||||||
(0, 0, 0, h,
|
(0, 0, 0, h,
|
||||||
|
@ -80,54 +86,50 @@ class TestImageTransform(PillowTestCase):
|
||||||
(0, 0, 0, h,
|
(0, 0, 0, h,
|
||||||
w, h, w, 0))], # ul -> ccw around quad
|
w, h, w, 0))], # ul -> ccw around quad
|
||||||
Image.BILINEAR)
|
Image.BILINEAR)
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
scaled = im.transform((w//2, h//2), Image.AFFINE,
|
scaled = im.transform(
|
||||||
(2, 0, 0, 0, 2, 0),
|
(w // 2, h // 2), Image.AFFINE, (2, 0, 0, 0, 2, 0), Image.BILINEAR
|
||||||
Image.BILINEAR)
|
)
|
||||||
|
|
||||||
checker = Image.new('RGBA', im.size)
|
checker = Image.new("RGBA", im.size)
|
||||||
checker.paste(scaled, (0, 0))
|
checker.paste(scaled, (0, 0))
|
||||||
checker.paste(scaled, (w//2, h//2))
|
checker.paste(scaled, (w // 2, h // 2))
|
||||||
|
|
||||||
self.assert_image_equal(transformed, checker)
|
self.assert_image_equal(transformed, checker)
|
||||||
|
|
||||||
# now, check to see that the extra area is (0, 0, 0, 0)
|
# now, check to see that the extra area is (0, 0, 0, 0)
|
||||||
blank = Image.new('RGBA', (w//2, h//2), (0, 0, 0, 0))
|
blank = Image.new("RGBA", (w // 2, h // 2), (0, 0, 0, 0))
|
||||||
|
|
||||||
self.assert_image_equal(blank, transformed.crop((w//2, 0, w, h//2)))
|
self.assert_image_equal(blank, transformed.crop((w // 2, 0, w, h // 2)))
|
||||||
self.assert_image_equal(blank, transformed.crop((0, h//2, w//2, h)))
|
self.assert_image_equal(blank, transformed.crop((0, h // 2, w // 2, h)))
|
||||||
|
|
||||||
def _test_alpha_premult(self, op):
|
def _test_alpha_premult(self, op):
|
||||||
# create image with half white, half black,
|
# create image with half white, half black,
|
||||||
# with the black half transparent.
|
# with the black half transparent.
|
||||||
# do op,
|
# do op,
|
||||||
# there should be no darkness in the white section.
|
# there should be no darkness in the white section.
|
||||||
im = Image.new('RGBA', (10, 10), (0, 0, 0, 0))
|
im = Image.new("RGBA", (10, 10), (0, 0, 0, 0))
|
||||||
im2 = Image.new('RGBA', (5, 10), (255, 255, 255, 255))
|
im2 = Image.new("RGBA", (5, 10), (255, 255, 255, 255))
|
||||||
im.paste(im2, (0, 0))
|
im.paste(im2, (0, 0))
|
||||||
|
|
||||||
im = op(im, (40, 10))
|
im = op(im, (40, 10))
|
||||||
im_background = Image.new('RGB', (40, 10), (255, 255, 255))
|
im_background = Image.new("RGB", (40, 10), (255, 255, 255))
|
||||||
im_background.paste(im, (0, 0), im)
|
im_background.paste(im, (0, 0), im)
|
||||||
|
|
||||||
hist = im_background.histogram()
|
hist = im_background.histogram()
|
||||||
self.assertEqual(40*10, hist[-1])
|
self.assertEqual(40 * 10, hist[-1])
|
||||||
|
|
||||||
def test_alpha_premult_resize(self):
|
def test_alpha_premult_resize(self):
|
||||||
|
|
||||||
def op(im, sz):
|
def op(im, sz):
|
||||||
return im.resize(sz, Image.BILINEAR)
|
return im.resize(sz, Image.BILINEAR)
|
||||||
|
|
||||||
self._test_alpha_premult(op)
|
self._test_alpha_premult(op)
|
||||||
|
|
||||||
def test_alpha_premult_transform(self):
|
def test_alpha_premult_transform(self):
|
||||||
|
|
||||||
def op(im, sz):
|
def op(im, sz):
|
||||||
(w, h) = im.size
|
(w, h) = im.size
|
||||||
return im.transform(sz, Image.EXTENT,
|
return im.transform(sz, Image.EXTENT, (0, 0, w, h), Image.BILINEAR)
|
||||||
(0, 0,
|
|
||||||
w, h),
|
|
||||||
Image.BILINEAR)
|
|
||||||
|
|
||||||
self._test_alpha_premult(op)
|
self._test_alpha_premult(op)
|
||||||
|
|
||||||
|
@ -146,10 +148,7 @@ class TestImageTransform(PillowTestCase):
|
||||||
# Running by default, but I'd totally understand not doing it in
|
# Running by default, but I'd totally understand not doing it in
|
||||||
# the future
|
# the future
|
||||||
|
|
||||||
pattern = [
|
pattern = [Image.new("RGBA", (1024, 1024), (a, a, a, a)) for a in range(1, 65)]
|
||||||
Image.new('RGBA', (1024, 1024), (a, a, a, a))
|
|
||||||
for a in range(1, 65)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Yeah. Watch some JIT optimize this out.
|
# Yeah. Watch some JIT optimize this out.
|
||||||
pattern = None # noqa: F841
|
pattern = None # noqa: F841
|
||||||
|
@ -164,27 +163,37 @@ class TestImageTransform(PillowTestCase):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
(w, h) = im.size
|
(w, h) = im.size
|
||||||
for resample in (Image.BOX, "unknown"):
|
for resample in (Image.BOX, "unknown"):
|
||||||
self.assertRaises(ValueError, im.transform, (100, 100), Image.EXTENT,
|
self.assertRaises(
|
||||||
(0, 0,
|
ValueError,
|
||||||
w, h),
|
im.transform,
|
||||||
resample)
|
(100, 100),
|
||||||
|
Image.EXTENT,
|
||||||
|
(0, 0, w, h),
|
||||||
|
resample,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestImageTransformAffine(PillowTestCase):
|
class TestImageTransformAffine(PillowTestCase):
|
||||||
transform = Image.AFFINE
|
transform = Image.AFFINE
|
||||||
|
|
||||||
def _test_image(self):
|
def _test_image(self):
|
||||||
im = hopper('RGB')
|
im = hopper("RGB")
|
||||||
return im.crop((10, 20, im.width - 10, im.height - 20))
|
return im.crop((10, 20, im.width - 10, im.height - 20))
|
||||||
|
|
||||||
def _test_rotate(self, deg, transpose):
|
def _test_rotate(self, deg, transpose):
|
||||||
im = self._test_image()
|
im = self._test_image()
|
||||||
|
|
||||||
angle = - math.radians(deg)
|
angle = -math.radians(deg)
|
||||||
matrix = [
|
matrix = [
|
||||||
round(math.cos(angle), 15), round(math.sin(angle), 15), 0.0,
|
round(math.cos(angle), 15),
|
||||||
round(-math.sin(angle), 15), round(math.cos(angle), 15), 0.0,
|
round(math.sin(angle), 15),
|
||||||
0, 0]
|
0.0,
|
||||||
|
round(-math.sin(angle), 15),
|
||||||
|
round(math.cos(angle), 15),
|
||||||
|
0.0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
matrix[2] = (1 - matrix[0] - matrix[1]) * im.width / 2
|
matrix[2] = (1 - matrix[0] - matrix[1]) * im.width / 2
|
||||||
matrix[5] = (1 - matrix[3] - matrix[4]) * im.height / 2
|
matrix[5] = (1 - matrix[3] - matrix[4]) * im.height / 2
|
||||||
|
|
||||||
|
@ -194,8 +203,9 @@ class TestImageTransformAffine(PillowTestCase):
|
||||||
transposed = im
|
transposed = im
|
||||||
|
|
||||||
for resample in [Image.NEAREST, Image.BILINEAR, Image.BICUBIC]:
|
for resample in [Image.NEAREST, Image.BILINEAR, Image.BICUBIC]:
|
||||||
transformed = im.transform(transposed.size, self.transform,
|
transformed = im.transform(
|
||||||
matrix, resample)
|
transposed.size, self.transform, matrix, resample
|
||||||
|
)
|
||||||
self.assert_image_equal(transposed, transformed)
|
self.assert_image_equal(transposed, transformed)
|
||||||
|
|
||||||
def test_rotate_0_deg(self):
|
def test_rotate_0_deg(self):
|
||||||
|
@ -214,21 +224,18 @@ class TestImageTransformAffine(PillowTestCase):
|
||||||
im = self._test_image()
|
im = self._test_image()
|
||||||
|
|
||||||
size_up = int(round(im.width * scale)), int(round(im.height * scale))
|
size_up = int(round(im.width * scale)), int(round(im.height * scale))
|
||||||
matrix_up = [
|
matrix_up = [1 / scale, 0, 0, 0, 1 / scale, 0, 0, 0]
|
||||||
1 / scale, 0, 0,
|
matrix_down = [scale, 0, 0, 0, scale, 0, 0, 0]
|
||||||
0, 1 / scale, 0,
|
|
||||||
0, 0]
|
|
||||||
matrix_down = [
|
|
||||||
scale, 0, 0,
|
|
||||||
0, scale, 0,
|
|
||||||
0, 0]
|
|
||||||
|
|
||||||
for resample, epsilon in [(Image.NEAREST, 0),
|
for resample, epsilon in [
|
||||||
(Image.BILINEAR, 2), (Image.BICUBIC, 1)]:
|
(Image.NEAREST, 0),
|
||||||
transformed = im.transform(
|
(Image.BILINEAR, 2),
|
||||||
size_up, self.transform, matrix_up, resample)
|
(Image.BICUBIC, 1),
|
||||||
|
]:
|
||||||
|
transformed = im.transform(size_up, self.transform, matrix_up, resample)
|
||||||
transformed = transformed.transform(
|
transformed = transformed.transform(
|
||||||
im.size, self.transform, matrix_down, resample)
|
im.size, self.transform, matrix_down, resample
|
||||||
|
)
|
||||||
self.assert_image_similar(transformed, im, epsilon * epsilonscale)
|
self.assert_image_similar(transformed, im, epsilon * epsilonscale)
|
||||||
|
|
||||||
def test_resize_1_1x(self):
|
def test_resize_1_1x(self):
|
||||||
|
@ -250,28 +257,25 @@ class TestImageTransformAffine(PillowTestCase):
|
||||||
im = self._test_image()
|
im = self._test_image()
|
||||||
|
|
||||||
size_up = int(round(im.width + x)), int(round(im.height + y))
|
size_up = int(round(im.width + x)), int(round(im.height + y))
|
||||||
matrix_up = [
|
matrix_up = [1, 0, -x, 0, 1, -y, 0, 0]
|
||||||
1, 0, -x,
|
matrix_down = [1, 0, x, 0, 1, y, 0, 0]
|
||||||
0, 1, -y,
|
|
||||||
0, 0]
|
|
||||||
matrix_down = [
|
|
||||||
1, 0, x,
|
|
||||||
0, 1, y,
|
|
||||||
0, 0]
|
|
||||||
|
|
||||||
for resample, epsilon in [(Image.NEAREST, 0),
|
for resample, epsilon in [
|
||||||
(Image.BILINEAR, 1.5), (Image.BICUBIC, 1)]:
|
(Image.NEAREST, 0),
|
||||||
transformed = im.transform(
|
(Image.BILINEAR, 1.5),
|
||||||
size_up, self.transform, matrix_up, resample)
|
(Image.BICUBIC, 1),
|
||||||
|
]:
|
||||||
|
transformed = im.transform(size_up, self.transform, matrix_up, resample)
|
||||||
transformed = transformed.transform(
|
transformed = transformed.transform(
|
||||||
im.size, self.transform, matrix_down, resample)
|
im.size, self.transform, matrix_down, resample
|
||||||
|
)
|
||||||
self.assert_image_similar(transformed, im, epsilon * epsilonscale)
|
self.assert_image_similar(transformed, im, epsilon * epsilonscale)
|
||||||
|
|
||||||
def test_translate_0_1(self):
|
def test_translate_0_1(self):
|
||||||
self._test_translate(.1, 0, 3.7)
|
self._test_translate(0.1, 0, 3.7)
|
||||||
|
|
||||||
def test_translate_0_6(self):
|
def test_translate_0_6(self):
|
||||||
self._test_translate(.6, 0, 9.1)
|
self._test_translate(0.6, 0, 9.1)
|
||||||
|
|
||||||
def test_translate_50(self):
|
def test_translate_50(self):
|
||||||
self._test_translate(50, 50, 0)
|
self._test_translate(50, 50, 0)
|
||||||
|
|
|
@ -1,15 +1,23 @@
|
||||||
from . import helper
|
from . import helper
|
||||||
from .helper import PillowTestCase
|
from .helper import PillowTestCase
|
||||||
|
|
||||||
from PIL.Image import (FLIP_LEFT_RIGHT, FLIP_TOP_BOTTOM, ROTATE_90, ROTATE_180,
|
from PIL.Image import (
|
||||||
ROTATE_270, TRANSPOSE, TRANSVERSE)
|
FLIP_LEFT_RIGHT,
|
||||||
|
FLIP_TOP_BOTTOM,
|
||||||
|
ROTATE_90,
|
||||||
|
ROTATE_180,
|
||||||
|
ROTATE_270,
|
||||||
|
TRANSPOSE,
|
||||||
|
TRANSVERSE,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestImageTranspose(PillowTestCase):
|
class TestImageTranspose(PillowTestCase):
|
||||||
|
|
||||||
hopper = {mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy() for mode in [
|
hopper = {
|
||||||
'L', 'RGB', 'I;16', 'I;16L', 'I;16B'
|
mode: helper.hopper(mode).crop((0, 0, 121, 127)).copy()
|
||||||
]}
|
for mode in ["L", "RGB", "I;16", "I;16L", "I;16B"]
|
||||||
|
}
|
||||||
|
|
||||||
def test_flip_left_right(self):
|
def test_flip_left_right(self):
|
||||||
def transpose(mode):
|
def transpose(mode):
|
||||||
|
@ -19,10 +27,10 @@ class TestImageTranspose(PillowTestCase):
|
||||||
self.assertEqual(out.size, im.size)
|
self.assertEqual(out.size, im.size)
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x-2, 1)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((x-2, y-2)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, y - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, y-2)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, y - 2)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -35,10 +43,10 @@ class TestImageTranspose(PillowTestCase):
|
||||||
self.assertEqual(out.size, im.size)
|
self.assertEqual(out.size, im.size)
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y-2)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, y - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((x-2, y-2)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((x - 2, y - 2)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((x-2, 1)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((x - 2, 1)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -51,10 +59,10 @@ class TestImageTranspose(PillowTestCase):
|
||||||
self.assertEqual(out.size, im.size[::-1])
|
self.assertEqual(out.size, im.size[::-1])
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, x-2)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, x - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, 1)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((y-2, x-2)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, x - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((y-2, 1)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, 1)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -67,10 +75,10 @@ class TestImageTranspose(PillowTestCase):
|
||||||
self.assertEqual(out.size, im.size)
|
self.assertEqual(out.size, im.size)
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x-2, y-2)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((x - 2, y - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, y-2)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, y - 2)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((x-2, 1)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((x - 2, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -83,10 +91,10 @@ class TestImageTranspose(PillowTestCase):
|
||||||
self.assertEqual(out.size, im.size[::-1])
|
self.assertEqual(out.size, im.size[::-1])
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((y-2, 1)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((y-2, x-2)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, x - 2)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, x-2)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, x - 2)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -100,9 +108,9 @@ class TestImageTranspose(PillowTestCase):
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((1, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((1, x-2)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((1, x - 2)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((y-2, 1)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((y - 2, 1)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((y-2, x-2)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((y - 2, x - 2)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -115,10 +123,10 @@ class TestImageTranspose(PillowTestCase):
|
||||||
self.assertEqual(out.size, im.size[::-1])
|
self.assertEqual(out.size, im.size[::-1])
|
||||||
|
|
||||||
x, y = im.size
|
x, y = im.size
|
||||||
self.assertEqual(im.getpixel((1, 1)), out.getpixel((y-2, x-2)))
|
self.assertEqual(im.getpixel((1, 1)), out.getpixel((y - 2, x - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, 1)), out.getpixel((y-2, 1)))
|
self.assertEqual(im.getpixel((x - 2, 1)), out.getpixel((y - 2, 1)))
|
||||||
self.assertEqual(im.getpixel((1, y-2)), out.getpixel((1, x-2)))
|
self.assertEqual(im.getpixel((1, y - 2)), out.getpixel((1, x - 2)))
|
||||||
self.assertEqual(im.getpixel((x-2, y-2)), out.getpixel((1, 1)))
|
self.assertEqual(im.getpixel((x - 2, y - 2)), out.getpixel((1, 1)))
|
||||||
|
|
||||||
for mode in self.hopper:
|
for mode in self.hopper:
|
||||||
transpose(mode)
|
transpose(mode)
|
||||||
|
@ -130,19 +138,22 @@ class TestImageTranspose(PillowTestCase):
|
||||||
def transpose(first, second):
|
def transpose(first, second):
|
||||||
return im.transpose(first).transpose(second)
|
return im.transpose(first).transpose(second)
|
||||||
|
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT))
|
||||||
im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT))
|
self.assert_image_equal(im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM))
|
||||||
self.assert_image_equal(
|
|
||||||
im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM))
|
|
||||||
self.assert_image_equal(im, transpose(ROTATE_90, ROTATE_270))
|
self.assert_image_equal(im, transpose(ROTATE_90, ROTATE_270))
|
||||||
self.assert_image_equal(im, transpose(ROTATE_180, ROTATE_180))
|
self.assert_image_equal(im, transpose(ROTATE_180, ROTATE_180))
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
im.transpose(TRANSPOSE), transpose(ROTATE_90, FLIP_TOP_BOTTOM))
|
im.transpose(TRANSPOSE), transpose(ROTATE_90, FLIP_TOP_BOTTOM)
|
||||||
|
)
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
im.transpose(TRANSPOSE), transpose(ROTATE_270, FLIP_LEFT_RIGHT))
|
im.transpose(TRANSPOSE), transpose(ROTATE_270, FLIP_LEFT_RIGHT)
|
||||||
|
)
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
im.transpose(TRANSVERSE), transpose(ROTATE_90, FLIP_LEFT_RIGHT))
|
im.transpose(TRANSVERSE), transpose(ROTATE_90, FLIP_LEFT_RIGHT)
|
||||||
|
)
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM))
|
im.transpose(TRANSVERSE), transpose(ROTATE_270, FLIP_TOP_BOTTOM)
|
||||||
|
)
|
||||||
self.assert_image_equal(
|
self.assert_image_equal(
|
||||||
im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE))
|
im.transpose(TRANSVERSE), transpose(ROTATE_180, TRANSPOSE)
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user