diff options
Diffstat (limited to 'lib/threads/palette.py')
| -rw-r--r-- | lib/threads/palette.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/threads/palette.py b/lib/threads/palette.py new file mode 100644 index 00000000..e1f47c7f --- /dev/null +++ b/lib/threads/palette.py @@ -0,0 +1,72 @@ +from collections import Set +from .color import ThreadColor +from colormath.color_objects import sRGBColor, LabColor +from colormath.color_conversions import convert_color +from colormath.color_diff import delta_e_cie1994 + + +def compare_thread_colors(color1, color2): + # K_L=2 indicates textiles + return delta_e_cie1994(color1, color2, K_L=2) + + +class ThreadPalette(Set): + """Holds a set of ThreadColors all from the same manufacturer.""" + + def __init__(self, palette_file): + self.threads = dict() + self.parse_palette_file(palette_file) + + def parse_palette_file(self, palette_file): + """Read a GIMP palette file and load thread colors. + + Example file: + + GIMP Palette + Name: Ink/Stitch: Metro + Columns: 4 + # RGB Value Color Name Number + 240 186 212 Sugar Pink 1624 + 237 171 194 Carnatio 1636 + + """ + + with open(palette_file) as palette: + line = palette.readline().strip() + if line.lower() != "gimp palette": + raise ValueError("Invalid gimp palette header") + + self.name = palette.readline().strip() + if self.name.lower().startswith('name: ink/stitch: '): + self.name = self.name[18:] + + columns_line = palette.readline() + headers_line = palette.readline() + + for line in palette: + fields = line.split("\t", 3) + thread_color = [int(field) for field in fields[:3]] + thread_name, thread_number = fields[3].strip().rsplit(" ", 1) + thread_name = thread_name.strip() + + thread = ThreadColor(thread_color, thread_name, thread_number, manufacturer=self.name) + self.threads[thread] = convert_color(sRGBColor(*thread_color, is_upscaled=True), LabColor) + + def __contains__(self, thread): + return thread in self.threads + + def __iter__(self): + return iter(self.threads) + + def __len__(self): + return len(self.threads) + + def nearest_color(self, color): + """Find the thread in this palette that looks the most like the specified color.""" + + if isinstance(color, ThreadColor): + color = color.rgb + + color = convert_color(sRGBColor(*color, is_upscaled=True), LabColor) + + return min(self, key=lambda thread: compare_thread_colors(self.threads[thread], color)) |
