kopia lustrzana https://github.com/inkstitch/inkstitch
Update pyembroidery (#1683)
Embroidery formats (read) .hus: Husqvarna Embroidery Format .zhs: Zeng Hsing Embroidery Format Color formats (read & write) .col : Color format. .edr : Color format. .inf : Color format. Stitch formats (read & write) .pmv : Brother Stitch Format. Image (write) .png : Portable Network Graphic (line art) G-Code The export file format is not .txt anymore but .gcode Bug fixespull/1718/head
rodzic
3985b5ac71
commit
ab8c87928b
|
@ -8,6 +8,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import inkex
|
import inkex
|
||||||
|
import pyembroidery
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..threads import ThreadCatalog
|
from ..threads import ThreadCatalog
|
||||||
|
@ -22,6 +23,8 @@ class ApplyThreadlist(InkstitchExtension):
|
||||||
'''
|
'''
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
InkstitchExtension.__init__(self, *args, **kwargs)
|
InkstitchExtension.__init__(self, *args, **kwargs)
|
||||||
|
self.arg_parser.add_argument("-o", "--options", type=str, default=None, dest="page_1")
|
||||||
|
self.arg_parser.add_argument("-i", "--info", type=str, default=None, dest="page_2")
|
||||||
self.arg_parser.add_argument("-f", "--filepath", type=str, default="", dest="filepath")
|
self.arg_parser.add_argument("-f", "--filepath", type=str, default="", dest="filepath")
|
||||||
self.arg_parser.add_argument("-m", "--method", type=int, default=1, dest="method")
|
self.arg_parser.add_argument("-m", "--method", type=int, default=1, dest="method")
|
||||||
self.arg_parser.add_argument("-t", "--palette", type=str, default=None, dest="palette")
|
self.arg_parser.add_argument("-t", "--palette", type=str, default=None, dest="palette")
|
||||||
|
@ -34,26 +37,18 @@ class ApplyThreadlist(InkstitchExtension):
|
||||||
return
|
return
|
||||||
|
|
||||||
path = self.options.filepath
|
path = self.options.filepath
|
||||||
if not os.path.exists(path):
|
self.verify_path(path)
|
||||||
inkex.errormsg(_("File not found."))
|
|
||||||
sys.exit(1)
|
|
||||||
if os.path.isdir(path):
|
|
||||||
inkex.errormsg(_("The filepath specified is not a file but a dictionary.\nPlease choose a threadlist file to import."))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
method = self.options.method
|
method = self.options.method
|
||||||
if method == 1:
|
|
||||||
|
if path.endswith(('col', 'inf', 'edr')):
|
||||||
|
colors = self.parse_color_format(path)
|
||||||
|
elif method == 1:
|
||||||
colors = self.parse_inkstitch_threadlist(path)
|
colors = self.parse_inkstitch_threadlist(path)
|
||||||
else:
|
else:
|
||||||
colors = self.parse_threadlist_by_catalog_number(path)
|
colors = self.parse_threadlist_by_catalog_number(path)
|
||||||
|
|
||||||
if all(c is None for c in colors):
|
self.verify_colors(colors, method)
|
||||||
inkex.errormsg(_("Couldn't find any matching colors in the file."))
|
|
||||||
if method == 1:
|
|
||||||
inkex.errormsg(_('Please try to import as "other threadlist" and specify a color palette below.'))
|
|
||||||
else:
|
|
||||||
inkex.errormsg(_("Please chose an other color palette for your design."))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Iterate through the color blocks to apply colors
|
# Iterate through the color blocks to apply colors
|
||||||
element_color = ""
|
element_color = ""
|
||||||
|
@ -70,6 +65,23 @@ class ApplyThreadlist(InkstitchExtension):
|
||||||
style = element.node.get('style').replace("%s" % element_color, "%s" % colors[i])
|
style = element.node.get('style').replace("%s" % element_color, "%s" % colors[i])
|
||||||
element.node.set('style', style)
|
element.node.set('style', style)
|
||||||
|
|
||||||
|
def verify_path(self, path):
|
||||||
|
if not os.path.exists(path):
|
||||||
|
inkex.errormsg(_("File not found."))
|
||||||
|
sys.exit(1)
|
||||||
|
if os.path.isdir(path):
|
||||||
|
inkex.errormsg(_("The filepath specified is not a file but a dictionary.\nPlease choose a threadlist file to import."))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def verify_colors(self, colors, method):
|
||||||
|
if all(c is None for c in colors):
|
||||||
|
inkex.errormsg(_("Couldn't find any matching colors in the file."))
|
||||||
|
if method == 1:
|
||||||
|
inkex.errormsg(_('Please try to import as "other threadlist" and specify a color palette below.'))
|
||||||
|
else:
|
||||||
|
inkex.errormsg(_("Please chose an other color palette for your design."))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def parse_inkstitch_threadlist(self, path):
|
def parse_inkstitch_threadlist(self, path):
|
||||||
colors = []
|
colors = []
|
||||||
with open(path) as threadlist:
|
with open(path) as threadlist:
|
||||||
|
@ -83,6 +95,13 @@ class ApplyThreadlist(InkstitchExtension):
|
||||||
colors.append(None)
|
colors.append(None)
|
||||||
return colors
|
return colors
|
||||||
|
|
||||||
|
def parse_color_format(self, path):
|
||||||
|
colors = []
|
||||||
|
threads = pyembroidery.read(path).threadlist
|
||||||
|
for color in threads:
|
||||||
|
colors.append(color.hex_color())
|
||||||
|
return colors
|
||||||
|
|
||||||
def parse_threadlist_by_catalog_number(self, path):
|
def parse_threadlist_by_catalog_number(self, path):
|
||||||
palette_name = self.options.palette
|
palette_name = self.options.palette
|
||||||
palette = ThreadCatalog().get_palette_by_name(palette_name)
|
palette = ThreadCatalog().get_palette_by_name(palette_name)
|
||||||
|
|
|
@ -5,11 +5,19 @@
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
|
from inkex import errormsg
|
||||||
|
|
||||||
|
from ..i18n import _
|
||||||
from ..stitch_plan import generate_stitch_plan
|
from ..stitch_plan import generate_stitch_plan
|
||||||
|
|
||||||
|
|
||||||
class Input(object):
|
class Input(object):
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
embroidery_file = args[0]
|
embroidery_file = args[0]
|
||||||
|
if args[0].endswith(('edr', 'col', 'inf')):
|
||||||
|
msg = _("Ink/Stitch cannot import color formats directly. But you can open the embroidery file and apply the color with "
|
||||||
|
"Extensions > Ink/Stitch > Thread Color Management > Apply Threadlist")
|
||||||
|
errormsg(msg)
|
||||||
|
exit(0)
|
||||||
stitch_plan = generate_stitch_plan(embroidery_file)
|
stitch_plan = generate_stitch_plan(embroidery_file)
|
||||||
print(etree.tostring(stitch_plan).decode('utf-8'))
|
print(etree.tostring(stitch_plan).decode('utf-8'))
|
||||||
|
|
|
@ -9,10 +9,10 @@ import tempfile
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
from inkex import Boolean
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
import pyembroidery
|
import pyembroidery
|
||||||
|
from inkex import Boolean
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..output import write_embroidery_file
|
from ..output import write_embroidery_file
|
||||||
|
@ -28,7 +28,7 @@ class Zip(InkstitchExtension):
|
||||||
# it's kind of obnoxious that I have to do this...
|
# it's kind of obnoxious that I have to do this...
|
||||||
self.formats = []
|
self.formats = []
|
||||||
for format in pyembroidery.supported_formats():
|
for format in pyembroidery.supported_formats():
|
||||||
if 'writer' in format and format['category'] == 'embroidery':
|
if 'writer' in format and format['category'] in ['embroidery', 'color', 'image', 'stitch']:
|
||||||
extension = format['extension']
|
extension = format['extension']
|
||||||
self.arg_parser.add_argument('--format-%s' % extension, type=Boolean, dest=extension)
|
self.arg_parser.add_argument('--format-%s' % extension, type=Boolean, dest=extension)
|
||||||
self.formats.append(extension)
|
self.formats.append(extension)
|
||||||
|
|
|
@ -30,7 +30,7 @@ def object_commands():
|
||||||
|
|
||||||
def pyembroidery_debug_formats():
|
def pyembroidery_debug_formats():
|
||||||
for format in pyembroidery.supported_formats():
|
for format in pyembroidery.supported_formats():
|
||||||
if 'writer' in format and format['category'] != 'embroidery':
|
if 'writer' in format and format['category'] not in ['embroidery', 'image', 'color', 'stitch']:
|
||||||
yield format['extension'], format['description']
|
yield format['extension'], format['description']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ from .utils import build_environment, write_inx_file
|
||||||
|
|
||||||
def pyembroidery_input_formats():
|
def pyembroidery_input_formats():
|
||||||
for format in pyembroidery.supported_formats():
|
for format in pyembroidery.supported_formats():
|
||||||
if 'reader' in format and format['category'] == 'embroidery':
|
if 'reader' in format and format['category'] in ['embroidery', 'color', 'stitch']:
|
||||||
yield format['extension'], format['description']
|
yield format['extension'], format['description']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,13 @@ def pyembroidery_output_formats():
|
||||||
for format in pyembroidery.supported_formats():
|
for format in pyembroidery.supported_formats():
|
||||||
if 'writer' in format:
|
if 'writer' in format:
|
||||||
description = format['description']
|
description = format['description']
|
||||||
if format['category'] != "embroidery":
|
if format['category'] == "color":
|
||||||
|
description = "%s [COLOR]" % description
|
||||||
|
elif format['category'] == "image":
|
||||||
|
description = "%s [IMAGE]" % description
|
||||||
|
elif format['category'] == "stitch":
|
||||||
|
description = "%s [STITCH]" % description
|
||||||
|
elif format['category'] != "embroidery":
|
||||||
description = "%s [DEBUG]" % description
|
description = "%s [DEBUG]" % description
|
||||||
yield format['extension'], description, format['mimetype'], format['category']
|
yield format['extension'], description, format['mimetype'], format['category']
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import inkex
|
|
||||||
|
|
||||||
|
import inkex
|
||||||
import pyembroidery
|
import pyembroidery
|
||||||
|
|
||||||
from .commands import global_command
|
from .commands import global_command
|
||||||
|
@ -33,8 +33,8 @@ def _string_to_floats(string):
|
||||||
return [float(num) for num in floats]
|
return [float(num) for num in floats]
|
||||||
|
|
||||||
|
|
||||||
def get_origin(svg, xxx_todo_changeme):
|
def get_origin(svg, bounding_box):
|
||||||
(minx, miny, maxx, maxy) = xxx_todo_changeme
|
(minx, miny, maxx, maxy) = bounding_box
|
||||||
origin_command = global_command(svg, "origin")
|
origin_command = global_command(svg, "origin")
|
||||||
|
|
||||||
if origin_command:
|
if origin_command:
|
||||||
|
@ -52,7 +52,12 @@ def jump_to_stop_point(pattern, svg):
|
||||||
|
|
||||||
|
|
||||||
def write_embroidery_file(file_path, stitch_plan, svg, settings={}):
|
def write_embroidery_file(file_path, stitch_plan, svg, settings={}):
|
||||||
|
# convert from pixels to millimeters
|
||||||
|
# also multiply by 10 to get tenths of a millimeter as required by pyembroidery
|
||||||
|
scale = 10 / PIXELS_PER_MM
|
||||||
|
|
||||||
origin = get_origin(svg, stitch_plan.bounding_box)
|
origin = get_origin(svg, stitch_plan.bounding_box)
|
||||||
|
origin = origin * scale
|
||||||
|
|
||||||
pattern = pyembroidery.EmbPattern()
|
pattern = pyembroidery.EmbPattern()
|
||||||
stitch = Stitch(0, 0)
|
stitch = Stitch(0, 0)
|
||||||
|
@ -68,10 +73,6 @@ def write_embroidery_file(file_path, stitch_plan, svg, settings={}):
|
||||||
|
|
||||||
pattern.add_stitch_absolute(pyembroidery.END, stitch.x, stitch.y)
|
pattern.add_stitch_absolute(pyembroidery.END, stitch.x, stitch.y)
|
||||||
|
|
||||||
# convert from pixels to millimeters
|
|
||||||
# also multiply by 10 to get tenths of a millimeter as required by pyembroidery
|
|
||||||
scale = 10 / PIXELS_PER_MM
|
|
||||||
|
|
||||||
settings.update({
|
settings.update({
|
||||||
# correct for the origin
|
# correct for the origin
|
||||||
"translate": -origin,
|
"translate": -origin,
|
||||||
|
@ -92,6 +93,9 @@ def write_embroidery_file(file_path, stitch_plan, svg, settings={}):
|
||||||
settings['max_stitch'] = float('inf')
|
settings['max_stitch'] = float('inf')
|
||||||
settings['max_jump'] = float('inf')
|
settings['max_jump'] = float('inf')
|
||||||
settings['explicit_trim'] = False
|
settings['explicit_trim'] = False
|
||||||
|
elif file_path.endswith('.png'):
|
||||||
|
settings['linewidth'] = 1
|
||||||
|
settings['background'] = 'white'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pyembroidery.write(pattern, file_path, settings)
|
pyembroidery.write(pattern, file_path, settings)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2ab0085cc997762ece7b9f96aef86457a205ca82
|
Subproject commit 4817386d269a2724bf0c9a87d91a5103c6dffc78
|
|
@ -3,7 +3,9 @@
|
||||||
<name>Apply Threadlist</name>
|
<name>Apply Threadlist</name>
|
||||||
<id>org.inkstitch.apply_threadlist</id>
|
<id>org.inkstitch.apply_threadlist</id>
|
||||||
<param name="extension" type="string" gui-hidden="true">apply_threadlist</param>
|
<param name="extension" type="string" gui-hidden="true">apply_threadlist</param>
|
||||||
<param name="filepath" type="path" gui-text="Choose file" mode="file" filetypes="txt"/>
|
<param name="options" type="notebook">
|
||||||
|
<page name="options" gui-text="Options">
|
||||||
|
<param name="filepath" type="path" gui-text="Choose file" mode="file" filetypes="txt,edr,col,inf"/>
|
||||||
<param name="method" type="optiongroup" gui-text="Choose method">
|
<param name="method" type="optiongroup" gui-text="Choose method">
|
||||||
<option value="1">Apply Ink/Stitch threadlist</option>
|
<option value="1">Apply Ink/Stitch threadlist</option>
|
||||||
<option value="2">Apply other threadlist*</option>
|
<option value="2">Apply other threadlist*</option>
|
||||||
|
@ -13,6 +15,22 @@
|
||||||
<item value="{{ item }}">{{ item }}</item>
|
<item value="{{ item }}">{{ item }}</item>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</param>
|
</param>
|
||||||
|
</page>
|
||||||
|
<page name="info" gui-text="Help">
|
||||||
|
<label appearance="header">This extension applies colors from a color file to the objects in this document.</label>
|
||||||
|
<label>COL, INF, EDR</label>
|
||||||
|
<label indent="2">Select the file and apply. The chosen method is not important for these file types.</label>
|
||||||
|
<spacer />
|
||||||
|
<label>TXT</label>
|
||||||
|
<label indent="2">Import an Ink/Stitch threadlist file (created through the zip export option).</label>
|
||||||
|
<spacer />
|
||||||
|
<label indent="2">Import any other Threadlist file in txt format. Ink/Stitch will try to match the colors to the selected thread palette.
|
||||||
|
The objects in this document will be colored accordingly if color matching has been successful.</label>
|
||||||
|
<spacer />
|
||||||
|
<label>Get more information on our website</label>
|
||||||
|
<label appearance="url">https://inkstitch.org/docs/thread-color/#apply-threadlist</label>
|
||||||
|
</page>
|
||||||
|
</param>
|
||||||
<effect>
|
<effect>
|
||||||
<object-type>all</object-type>
|
<object-type>all</object-type>
|
||||||
<effects-menu>
|
<effects-menu>
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
<dataloss>true</dataloss>
|
<dataloss>true</dataloss>
|
||||||
</output>
|
</output>
|
||||||
{%- for format, description, mimetype, category in formats %}
|
{%- for format, description, mimetype, category in formats %}
|
||||||
{%- if category == "embroidery" %}
|
{%- if category != "vector" and category != "debug" %}
|
||||||
<param name="format-{{ format }}" type="boolean" _gui-text=".{{ format | upper }}: {{ description }}">false</param>
|
<param name="format-{{ format }}" type="boolean" _gui-text=".{{ format | upper }}: {{ description }}">false</param>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
<param name="format-threadlist" type="boolean" gui-text=".TXT: Threadlist [COLOR]">false</param>
|
||||||
<param name="format-svg" type="boolean" gui-text=".SVG: Scalable Vector Graphic">false</param>
|
<param name="format-svg" type="boolean" gui-text=".SVG: Scalable Vector Graphic">false</param>
|
||||||
<param name="format-threadlist" type="boolean" gui-text=".TXT: Threadlist">false</param>
|
|
||||||
<param name="extension" type="string" gui-hidden="true">zip</param>
|
<param name="extension" type="string" gui-hidden="true">zip</param>
|
||||||
<script>
|
<script>
|
||||||
{{ command_tag | safe }}
|
{{ command_tag | safe }}
|
||||||
|
|
Ładowanie…
Reference in New Issue