import sys from pathlib import Path import tempfile import unittest import numpy as np from PIL import Image, ImageDraw sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from finish_masks import IllustrationCoverage, compile_finish, export_finish, extract_raw_ridges, prepare_illustration class RidgeBehavior(unittest.TestCase): def test_uniform_dark_glass_is_not_a_divider(self): self.assertFalse(extract_raw_ridges(Image.new('RGB', (128, 128), (28, 28, 28))).any()) def test_dark_colored_seams_and_no_opposite_edge_wrap(self): im = Image.new('RGB', (160, 160), (145, 145, 145)); d = ImageDraw.Draw(im) d.rectangle((75, 0, 81, 159), fill=(35, 48, 82)) confidence = extract_raw_ridges(im) self.assertGreater(int(confidence[80, 78]), 50) im = Image.new('RGB', (160, 160), (145, 145, 145));ImageDraw.Draw(im).rectangle((0, 0, 6, 159), fill=(10, 10, 10)) self.assertFalse(extract_raw_ridges(im)[:, 140:].any()) def test_both_sides_required_for_shadow_step(self): im = Image.new('RGB', (160, 160), (145, 145, 145));ImageDraw.Draw(im).rectangle((45, 0, 114, 159), fill=(10, 10, 10)) confidence = extract_raw_ridges(im) self.assertEqual(int(confidence[80, 45]), 0) self.assertEqual(int(confidence[80, 80]), 0) def test_master_fit_is_explicit(self): with self.assertRaises(ValueError): prepare_illustration(Image.new('RGB', (1000, 1400))) class PrintingComposition(unittest.TestCase): @classmethod def setUpClass(cls): cls.panes = np.full((2800, 2000), .8, dtype=np.float32) cls.ridges = np.zeros((2800, 2000), dtype=np.uint8);cls.ridges[:, 1000] = 255 cls.illustration = IllustrationCoverage(cls.panes, cls.ridges) cls.frame = Image.new('RGBA', (2000, 2800));ImageDraw.Draw(cls.frame).rectangle((0, 0, 1999, 2799), outline=(0, 0, 0, 255), width=24) cls.backing = Image.new('RGBA', (2000, 2800));d = ImageDraw.Draw(cls.backing) d.rectangle((300, 60, 1700, 360), fill=(0, 0, 0, 255));d.rectangle((300, 2180, 1700, 2730), fill=(0, 0, 0, 255)) cls.normal_overlay = Image.alpha_composite(cls.frame, cls.backing) cls.text = Image.new('RGBA', (2000, 2800));ImageDraw.Draw(cls.text).rectangle((850, 180, 900, 220), fill=(0, 0, 0, 255)) def masks(self): return {'normal': compile_finish(self.illustration, 'normal', self.normal_overlay, self.text), 'textless': compile_finish(self.illustration, 'textless', self.frame), 'borderless': compile_finish(self.illustration, 'borderless', self.backing, self.text), 'boundless': compile_finish(self.illustration, 'boundless')} def test_removed_layers_restore_only_their_protection(self): masks = {k: np.asarray(v) for k, v in self.masks().items()} self.assertEqual(int(masks['normal'][200, 870]), 0) self.assertEqual(int(masks['borderless'][200, 870]), 0) self.assertEqual(int(masks['textless'][200, 870]), 204) self.assertEqual(int(masks['boundless'][200, 870]), 204) self.assertEqual(int(masks['normal'][0, 0]), 0) self.assertEqual(int(masks['textless'][0, 0]), 0) self.assertEqual(int(masks['borderless'][0, 0]), 204) self.assertEqual(int(masks['boundless'][0, 0]), 204) for mask in masks.values(): self.assertFalse(mask[:, 1000].any()) def test_actual_alpha_union_and_detached_glyphs(self): overlay = Image.new('RGBA', (2000, 2800));text = Image.new('RGBA', (2000, 2800)) overlay.putpixel((123, 456), (0, 0, 0, 128));text.putpixel((123, 456), (0, 0, 0, 128)) text.putpixel((456, 789), (0, 0, 0, 255)) mask = np.asarray(compile_finish(self.illustration, 'borderless', overlay, text)) self.assertEqual(int(mask[456, 123]), 51) self.assertEqual(int(mask[789, 456]), 0) self.assertEqual(int(mask[790, 456]), 204) def test_invalid_component_contracts_fail(self): for printing, overlay, text in [('normal', self.frame, None), ('textless', self.frame, self.text), ('boundless', self.frame, None), ('borderless', None, self.text), ('normal', Image.new('RGB', (2000, 2800)), self.text), ('normal', Image.new('RGBA', (1000, 1400)), self.text), ('normal', Image.new('RGBA', (2000, 2800)), self.text)]: with self.subTest(printing=printing), self.assertRaises(ValueError): compile_finish(self.illustration, printing, overlay, text) def test_all_printing_exports_are_registered_opaque_scalars(self): with tempfile.TemporaryDirectory() as temporary: for printing, master in self.masks().items(): files = export_finish(master, Path(temporary), 'probe', printing) self.assertEqual([f['size'] for f in files], [[2000, 2800], [1000, 1400], [500, 700]]) for record in files: rgba = np.asarray(Image.open(record['path'])) self.assertTrue(np.all(rgba[:, :, 3] == 255)) self.assertTrue(np.array_equal(rgba[:, :, 0], rgba[:, :, 1])) self.assertTrue(np.array_equal(rgba[:, :, 0], rgba[:, :, 2])) if printing in ('normal', 'textless'): self.assertEqual(int(rgba[0, 0, 0]), 0) if __name__ == '__main__': unittest.main()