kopia lustrzana https://github.com/inkstitch/inkstitch
add inkstitch.threads.ThreadPalette class
rodzic
dc5c8c6314
commit
b3e9d12db4
|
@ -1 +1,2 @@
|
|||
from color import ThreadColor
|
||||
from palette import ThreadPalette
|
||||
|
|
|
@ -2,10 +2,11 @@ import simplestyle
|
|||
import re
|
||||
import colorsys
|
||||
|
||||
|
||||
class ThreadColor(object):
|
||||
hex_str_re = re.compile('#([0-9a-z]{3}|[0-9a-z]{6})', re.I)
|
||||
|
||||
def __init__(self, color, name=None, description=None):
|
||||
def __init__(self, color, name=None, number=None, manufacturer=None):
|
||||
if color is None:
|
||||
self.rgb = (0, 0, 0)
|
||||
elif isinstance(color, (list, tuple)):
|
||||
|
@ -16,7 +17,8 @@ class ThreadColor(object):
|
|||
raise ValueError("Invalid color: " + repr(color))
|
||||
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.number = number
|
||||
self.manufacturer = manufacturer
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, ThreadColor):
|
||||
|
@ -77,4 +79,4 @@ class ThreadColor(object):
|
|||
# convert back to values in the range of 0-255
|
||||
color = tuple(value * 255 for value in color)
|
||||
|
||||
return ThreadColor(color, name=self.name, description=self.description)
|
||||
return ThreadColor(color, name=self.name, number=self.number, manufacturer=self.manufacturer)
|
||||
|
|
|
@ -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))
|
Ładowanie…
Reference in New Issue