tightened up colorize(); split tests; moved tuple comparison fcn to helper.py

This commit is contained in:
tsennott 2018-07-08 20:09:39 -07:00
parent 4a6ec5ca72
commit 1eed17c70e
3 changed files with 83 additions and 82 deletions

View File

@ -307,6 +307,15 @@ def hopper(mode=None, cache={}):
return im.copy() return im.copy()
def tuple_approx_equal(actual, target, threshold):
"""Tests if tuple actual has values within threshold from tuple target"""
value = True
for i, target in enumerate(target):
value *= (target - threshold <= actual[i] <= target + threshold)
return value
def command_succeeds(cmd): def command_succeeds(cmd):
""" """
Runs the command, which must be a list of strings. Returns True if the Runs the command, which must be a list of strings. Returns True if the

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, hopper from helper import unittest, PillowTestCase, hopper, tuple_approx_equal
from PIL import ImageOps from PIL import ImageOps
from PIL import Image from PIL import Image
@ -95,87 +95,94 @@ class TestImageOps(PillowTestCase):
newimg = ImageOps.scale(i, 0.5) newimg = ImageOps.scale(i, 0.5)
self.assertEqual(newimg.size, (25, 25)) self.assertEqual(newimg.size, (25, 25))
def test_colorize(self): def test_colorize_2color(self):
# Test the colorizing function # Test the colorizing function with 2-color functionality
# Open test image (256px by 10px, black to white) # Open test image (256px by 10px, black to white)
im = Image.open("Tests/images/bw_gradient.png") im = Image.open("Tests/images/bw_gradient.png")
im = im.convert("L") im = im.convert("L")
# Create image with original 2-color functionality # Create image with original 2-color functionality
im_2c = ImageOps.colorize(im, 'red', 'green') im_test = ImageOps.colorize(im, 'red', 'green')
# Create image with original 2-color functionality with offsets
im_2c_offset = ImageOps.colorize(im,
black='red',
white='green',
blackpoint=50,
whitepoint=200)
# Create image with new three color functionality with offsets
im_3c_offset = ImageOps.colorize(im,
black='red',
white='green',
mid='blue',
blackpoint=50,
whitepoint=200,
midpoint=100)
# Define function for approximate equality of tuples
def tuple_approx_equal(actual, target, thresh):
value = True
for i, target in enumerate(target):
value *= (target - thresh <= actual[i] <= target + thresh)
return value
# Test output image (2-color) # Test output image (2-color)
left = (0, 1) left = (0, 1)
middle = (127, 1) middle = (127, 1)
right = (255, 1) right = (255, 1)
self.assertTrue(tuple_approx_equal(im_2c.getpixel(left), self.assertTrue(tuple_approx_equal(im_test.getpixel(left),
(255, 0, 0), thresh=1), (255, 0, 0), threshold=1),
'2-color image black incorrect') '2-color image black incorrect')
self.assertTrue(tuple_approx_equal(im_2c.getpixel(middle), self.assertTrue(tuple_approx_equal(im_test.getpixel(middle),
(127, 63, 0), thresh=1), (127, 63, 0), threshold=1),
'2-color image mid incorrect') '2-color image mid incorrect')
self.assertTrue(tuple_approx_equal(im_2c.getpixel(right), self.assertTrue(tuple_approx_equal(im_test.getpixel(right),
(0, 127, 0), thresh=1), (0, 127, 0), threshold=1),
'2-color image white incorrect') '2-color image white 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 # Test output image (2-color) with offsets
left = (25, 1) left = (25, 1)
middle = (125, 1) middle = (75, 1)
right = (225, 1) right = (125, 1)
self.assertTrue(tuple_approx_equal(im_2c_offset.getpixel(left), self.assertTrue(tuple_approx_equal(im_test.getpixel(left),
(255, 0, 0), thresh=1), (255, 0, 0), threshold=1),
'2-color image (with offset) black incorrect') '2-color image (with offset) black incorrect')
self.assertTrue(tuple_approx_equal(im_2c_offset.getpixel(middle), self.assertTrue(tuple_approx_equal(im_test.getpixel(middle),
(127, 63, 0), thresh=1), (127, 63, 0), threshold=1),
'2-color image (with offset) mid incorrect') '2-color image (with offset) mid incorrect')
self.assertTrue(tuple_approx_equal(im_2c_offset.getpixel(right), self.assertTrue(tuple_approx_equal(im_test.getpixel(right),
(0, 127, 0), thresh=1), (0, 127, 0), threshold=1),
'2-color image (with offset) white incorrect') '2-color image (with offset) white 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 # Test output image (3-color) with offsets
left = (25, 1) left = (25, 1)
left_middle = (75, 1) left_middle = (75, 1)
middle = (100, 1) middle = (100, 1)
right_middle = (150, 1) right_middle = (150, 1)
right = (225, 1) right = (225, 1)
self.assertTrue(tuple_approx_equal(im_3c_offset.getpixel(left), self.assertTrue(tuple_approx_equal(im_test.getpixel(left),
(255, 0, 0), thresh=1), (255, 0, 0), threshold=1),
'3-color image (with offset) black incorrect') '3-color image (with offset) black incorrect')
self.assertTrue(tuple_approx_equal(im_3c_offset.getpixel(left_middle), self.assertTrue(tuple_approx_equal(im_test.getpixel(left_middle),
(127, 0, 127), thresh=1), (127, 0, 127), threshold=1),
'3-color image (with offset) low-mid incorrect') '3-color image (with offset) low-mid incorrect')
self.assertTrue(tuple_approx_equal(im_3c_offset.getpixel(middle), self.assertTrue(tuple_approx_equal(im_test.getpixel(middle),
(0, 0, 255), thresh=1), (0, 0, 255), threshold=1),
'3-color image (with offset) mid incorrect') '3-color image (with offset) mid incorrect')
self.assertTrue(tuple_approx_equal(im_3c_offset.getpixel(right_middle), self.assertTrue(tuple_approx_equal(im_test.getpixel(right_middle),
(0, 63, 127), thresh=1), (0, 63, 127), threshold=1),
'3-color image (with offset) high-mid incorrect') '3-color image (with offset) high-mid incorrect')
self.assertTrue(tuple_approx_equal(im_3c_offset.getpixel(right), self.assertTrue(tuple_approx_equal(im_test.getpixel(right),
(0, 127, 0), thresh=1), (0, 127, 0), threshold=1),
'3-color image (with offset) white incorrect') '3-color image (with offset) white incorrect')

View File

@ -162,13 +162,10 @@ def colorize(image, black, white, mid=None, blackpoint=0,
# Initial asserts # Initial asserts
assert image.mode == "L" assert image.mode == "L"
assert 0 <= whitepoint <= 255 if mid is None:
assert 0 <= blackpoint <= 255 assert 0 <= blackpoint <= whitepoint <= 255
assert 0 <= midpoint <= 255 else:
assert blackpoint <= whitepoint assert 0 <= blackpoint <= midpoint <= whitepoint <= 255
if mid is not None:
assert blackpoint <= midpoint
assert whitepoint >= midpoint
# Define colors from arguments # Define colors from arguments
black = _color(black, "RGB") black = _color(black, "RGB")
@ -181,42 +178,28 @@ def colorize(image, black, white, mid=None, blackpoint=0,
green = [] green = []
blue = [] blue = []
# Create the low-end values
for i in range(0, blackpoint):
red.append(black[0])
green.append(black[1])
blue.append(black[2])
# Create the mapping (2-color) # Create the mapping (2-color)
if mid is None: if mid is None:
# Define ranges
range_low = range(0, blackpoint)
range_map = range(0, whitepoint - blackpoint) range_map = range(0, whitepoint - blackpoint)
range_high = range(0, 256 - whitepoint)
# Map
for i in range_low:
red.append(black[0])
green.append(black[1])
blue.append(black[2])
for i in range_map: for i in range_map:
red.append(black[0] + i * (white[0] - black[0]) // len(range_map)) red.append(black[0] + i * (white[0] - black[0]) // len(range_map))
green.append(black[1] + i * (white[1] - black[1]) // len(range_map)) green.append(black[1] + i * (white[1] - black[1]) // len(range_map))
blue.append(black[2] + i * (white[2] - black[2]) // len(range_map)) blue.append(black[2] + i * (white[2] - black[2]) // len(range_map))
for i in range_high:
red.append(white[0])
green.append(white[1])
blue.append(white[2])
# Create the mapping (3-color) # Create the mapping (3-color)
else: else:
# Define ranges
range_low = range(0, blackpoint)
range_map1 = range(0, midpoint - blackpoint) range_map1 = range(0, midpoint - blackpoint)
range_map2 = range(0, whitepoint - midpoint) range_map2 = range(0, whitepoint - midpoint)
range_high = range(0, 256 - whitepoint)
# Map
for i in range_low:
red.append(black[0])
green.append(black[1])
blue.append(black[2])
for i in range_map1: for i in range_map1:
red.append(black[0] + i * (mid[0] - black[0]) // len(range_map1)) red.append(black[0] + i * (mid[0] - black[0]) // len(range_map1))
green.append(black[1] + i * (mid[1] - black[1]) // len(range_map1)) green.append(black[1] + i * (mid[1] - black[1]) // len(range_map1))
@ -225,10 +208,12 @@ def colorize(image, black, white, mid=None, blackpoint=0,
red.append(mid[0] + i * (white[0] - mid[0]) // len(range_map2)) red.append(mid[0] + i * (white[0] - mid[0]) // len(range_map2))
green.append(mid[1] + i * (white[1] - mid[1]) // len(range_map2)) green.append(mid[1] + i * (white[1] - mid[1]) // len(range_map2))
blue.append(mid[2] + i * (white[2] - mid[2]) // len(range_map2)) blue.append(mid[2] + i * (white[2] - mid[2]) // len(range_map2))
for i in range_high:
red.append(white[0]) # Create the high-end values
green.append(white[1]) for i in range(0, 256 - whitepoint):
blue.append(white[2]) red.append(white[0])
green.append(white[1])
blue.append(white[2])
# Return converted image # Return converted image
image = image.convert("RGB") image = image.convert("RGB")