diff --git a/src/pystitch/EmbThread.py b/src/pystitch/EmbThread.py index 0db0ac1..229b06c 100644 --- a/src/pystitch/EmbThread.py +++ b/src/pystitch/EmbThread.py @@ -54,7 +54,7 @@ def find_nearest_color_index(find_color, values): closest_index = None current_closest_value = float("inf") for current_index, t in enumerate(values): - if t is None: + if t is None or getattr(t, "reserved", False): continue dist = color_distance_red_mean( red, green, blue, t.get_red(), t.get_green(), t.get_blue() diff --git a/src/pystitch/EmbThreadPec.py b/src/pystitch/EmbThreadPec.py index ff93a48..37c3f8c 100644 --- a/src/pystitch/EmbThreadPec.py +++ b/src/pystitch/EmbThreadPec.py @@ -65,17 +65,19 @@ def get_thread_set(): EmbThreadPec(9, 91, 166, "Electric Blue", "59"), EmbThreadPec(240, 249, 112, "Lemon Yellow", "60"), EmbThreadPec(227, 243, 91, "Fresh Green", "61"), - EmbThreadPec(255, 153, 0, "Orange", "62"), - EmbThreadPec(255, 240, 141, "Cream Yellow", "63"), - EmbThreadPec(255, 200, 200, "Applique", "64"), + # Machine functions, not real thread colors + EmbThreadPec(255, 200, 100, "Applique Material", "62", reserved=True), + EmbThreadPec(255, 200, 200, "Applique Position", "63", reserved=True), + EmbThreadPec(255, 200, 200, "Applique", "64", reserved=True), ] class EmbThreadPec(EmbThread): - def __init__(self, red, green, blue, description, catalog_number): + def __init__(self, red, green, blue, description, catalog_number, reserved=False): EmbThread.__init__(self) self.set_color(red, green, blue) self.description = description self.catalog_number = catalog_number self.brand = "Brother" self.chart = "Brother" + self.reserved = reserved diff --git a/test/test_palette.py b/test/test_palette.py index b99bd5a..c390c6c 100644 --- a/test/test_palette.py +++ b/test/test_palette.py @@ -43,7 +43,10 @@ def test_unique_palette_max(self): """If the entries equal the list they should all map.""" pattern = EmbPattern() threadset = get_thread_set() - for i in range(0, len(threadset)-2): + matchable_count = sum( + 1 for t in threadset if t is not None and not getattr(t, "reserved", False) + ) + for i in range(0, matchable_count): thread = EmbThread() thread.set_color(i, i, i) pattern += thread @@ -90,6 +93,31 @@ def test_nonrepeat_palette_same(self): self.assertEqual(palette[0], palette[3], "Red and Red") self.assertEqual(palette[1], palette[2], "Blue and Blue") + def test_reserved_indices_excluded_from_matching(self): + threadset = get_thread_set() + for i in (62, 63, 64): + self.assertTrue(threadset[i].reserved) + + # Two colliding "Deep Gold" threads used to fall through to the + # reserved index 62 slot (inkstitch#1105). + pattern = EmbPattern() + gold1 = EmbThread() + gold1.set_color(0xE8, 0xA9, 0x00) + gold2 = EmbThread() + gold2.set_color(0xE8, 0xA9, 0x00) + pattern.threadlist = [gold1, gold2] + palette = build_unique_palette(get_thread_set(), pattern.threadlist) + self.assertNotIn(62, palette) + self.assertNotIn(63, palette) + self.assertNotIn(64, palette) + + # An RGB value that lands on reserved must resolve to a real color + # instead. + exact = EmbThread() + exact.set_color(255, 200, 200) + index = exact.find_nearest_color_index(get_thread_set()) + self.assertNotIn(index, (62, 63, 64)) + def test_palette(self): """Similar colors map to the same index""" pattern = EmbPattern()