summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Neva <github.com@lexneva.name>2018-04-21 15:49:58 -0400
committerLex Neva <github.com@lexneva.name>2018-04-29 21:28:48 -0400
commit378f079e6d15757ed6cb0b2e04f50642b5adaaac (patch)
treebbe8294531943f8b4ab6eb7ab1b3b5bd112015f2
parentb3e9d12db4cfbbf8f1760d80fcd760d48a83e583 (diff)
add ThreadCatalog and palette matching
-rw-r--r--embroider_print.py2
-rw-r--r--inkstitch/threads/__init__.py1
-rw-r--r--inkstitch/threads/catalog.py72
3 files changed, 75 insertions, 0 deletions
diff --git a/embroider_print.py b/embroider_print.py
index cbdaeb09..7ab24876 100644
--- a/embroider_print.py
+++ b/embroider_print.py
@@ -21,6 +21,7 @@ from inkstitch.extensions import InkstitchExtension
from inkstitch.stitch_plan import patches_to_stitch_plan
from inkstitch.svg import render_stitch_plan
from inkstitch.utils import save_stderr, restore_stderr
+from inkstitch.threads import ThreadCatalog
from jinja2 import Environment, FileSystemLoader, select_autoescape
from datetime import date
@@ -290,6 +291,7 @@ class Print(InkstitchExtension):
patches = self.elements_to_patches(self.elements)
stitch_plan = patches_to_stitch_plan(patches)
+ ThreadCatalog().match_and_apply_palette(stitch_plan)
render_stitch_plan(self.document.getroot(), stitch_plan)
self.strip_namespaces()
diff --git a/inkstitch/threads/__init__.py b/inkstitch/threads/__init__.py
index fec82ced..03cd777b 100644
--- a/inkstitch/threads/__init__.py
+++ b/inkstitch/threads/__init__.py
@@ -1,2 +1,3 @@
from color import ThreadColor
from palette import ThreadPalette
+from catalog import ThreadCatalog
diff --git a/inkstitch/threads/catalog.py b/inkstitch/threads/catalog.py
new file mode 100644
index 00000000..0f959a52
--- /dev/null
+++ b/inkstitch/threads/catalog.py
@@ -0,0 +1,72 @@
+import os
+from os.path import dirname, realpath
+import sys
+from glob import glob
+from collections import Sequence
+from .palette import ThreadPalette
+
+class _ThreadCatalog(Sequence):
+ """Holds a set of ThreadPalettes."""
+
+ def __init__(self):
+ self.palettes = []
+ self.load_palettes(self.get_palettes_path())
+
+ def get_palettes_path(self):
+ if getattr(sys, 'frozen', None) is not None:
+ path = sys._MEIPASS
+ else:
+ path = dirname(dirname(dirname(realpath(__file__))))
+
+ return os.path.join(path, 'palettes')
+
+ def load_palettes(self, path):
+ for palette_file in glob(os.path.join(path, '*.gpl')):
+ self.palettes.append(ThreadPalette(palette_file))
+
+ def __getitem__(self, item):
+ return self.palettes[item]
+
+ def __len__(self):
+ return len(self.palettes)
+
+ def match_and_apply_palette(self, stitch_plan):
+ """Figure out which color palette was used and set thread names.
+
+ Scans the catalog of color palettes and chooses one that seems most
+ likely to be the one that the user used. A palette will only be
+ chosen if more tha 80% of the thread colors in the stitch plan are
+ exact matches for threads in the palette. All other threads will be
+ matched to the closest thread in the palette.
+ """
+
+ threads = [color_block.color for color_block in stitch_plan]
+
+ for palette in self:
+ num_matched = sum(1 for thread in threads if thread in palette)
+ if num_matched > (0.8 * len(threads)):
+ # Pick this one.
+ break
+ else:
+ # This block will only get run if we ran off the end of the loop
+ # without breaking. No palette had enough colors that exactly
+ # matched, so just do nothing.
+ return
+
+ for thread in threads:
+ nearest = palette.find_nearest(thread)
+
+ thread.name = nearest.name
+ thread.number = nearest.number
+ thread.manufacturer = nearest.manufacturer
+
+_catalog = None
+
+def ThreadCatalog():
+ """Singleton _ThreadCatalog factory"""
+
+ global _catalog
+ if _catalog is None:
+ _catalog = _ThreadCatalog()
+
+ return _catalog