Pillow/Tests/test_imageops.py
2019-04-01 20:03:02 +11:00

263 lines
9.9 KiB
Python

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