"""Tests for the pure parts of Tools/character_match.py.""" import os import sys import unittest from PIL import Image sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import character_match as cm # noqa: E402 class ColourTests(unittest.TestCase): def test_white_is_light_and_neutral(self): light, a, b = cm.rgb_to_lab((255, 255, 255)) self.assertAlmostEqual(light, 100.0, delta=0.2) self.assertAlmostEqual(a, 0.0, delta=0.2) self.assertAlmostEqual(b, 0.0, delta=0.2) def test_black_is_dark(self): self.assertAlmostEqual(cm.rgb_to_lab((0, 0, 0))[0], 0.0, delta=0.1) def test_identical_colours_have_no_distance(self): self.assertAlmostEqual(cm.delta_e76(cm.rgb_to_lab((120, 90, 70)), cm.rgb_to_lab((120, 90, 70))), 0.0, delta=1e-9) def test_red_green_are_far_apart(self): distance = cm.delta_e76(cm.rgb_to_lab((200, 40, 40)), cm.rgb_to_lab((40, 160, 40))) self.assertGreater(distance, 40.0) class MaskTests(unittest.TestCase): def _image(self, figure_colour, background_colour): image = Image.new("RGB", (60, 100), background_colour) pixels = image.load() for y in range(20, 90): for x in range(25, 35): pixels[x, y] = figure_colour return image def test_saturated_figure_on_grey_is_found(self): mask = cm._subject_mask(self._image((150, 90, 60), (190, 190, 190))) box = cm.bbox(mask) self.assertIsNotNone(box) self.assertLess(box[0], 30) self.assertGreater(box[2], 30) def test_grey_frame_yields_empty_mask(self): mask = cm._subject_mask(self._image((190, 190, 190), (190, 190, 190))) self.assertIsNone(cm.bbox(mask)) def test_stats_report_figure_proportions(self): mask = Image.new("L", (40, 80), 0) pixels = mask.load() for y in range(10, 70): for x in range(15, 25): pixels[x, y] = 255 stats = cm.mask_stats(mask) self.assertEqual(stats["area"], 600) self.assertAlmostEqual(stats["aspect"], 6.0, delta=0.01) self.assertAlmostEqual(stats["fill"], 1.0, delta=0.01) class PaletteTests(unittest.TestCase): def test_dominant_colour_is_reported(self): colours = [(200, 40, 40)] * 90 + [(20, 60, 200)] * 10 palette = cm.dominant(colours, count=2) self.assertEqual(len(palette), 2) red, _, _ = cm.rgb_to_lab(palette[0]) self.assertGreater(red, 30.0) def test_palette_distance_is_zero_for_the_same_palette(self): palette = cm.dominant([(200, 40, 40)] * 50) self.assertAlmostEqual(cm.palette_delta_e(palette, palette), 0.0, delta=1e-6) def test_empty_palette_is_not_a_number(self): self.assertNotEqual(cm.palette_delta_e([], [(1, 2, 3)]), cm.palette_delta_e([], [(1, 2, 3)])) if __name__ == "__main__": unittest.main()