Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions pyembroidery/EmbPattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
import pyembroidery.PmvReader as PmvReader
import pyembroidery.PmvWriter as PmvWriter
import pyembroidery.PngWriter as PngWriter
import pyembroidery.PltReader as PltReader
import pyembroidery.PltWriter as PltWriter
import pyembroidery.QliReader as QliReader
import pyembroidery.QliWriter as QliWriter
import pyembroidery.SewReader as SewReader
import pyembroidery.ShvReader as ShvReader
import pyembroidery.SpxReader as SpxReader
Expand All @@ -70,6 +74,7 @@
import pyembroidery.ZhsReader as ZhsReader
import pyembroidery.ZxyReader as ZxyReader


from .EmbEncoder import Transcoder as Normalizer
from .EmbFunctions import *
from .EmbThread import EmbThread
Expand Down Expand Up @@ -1397,6 +1402,28 @@ def supported_formats():
},
}
)
yield (
{
"description": "Statler Stitcher",
"extension": "qli",
"extensions": ("qli",),
"mimetype": "text/plain",
"category": "quilting",
"reader": QliReader,
"writer": QliWriter,
}
)
yield (
{
"description": "HPGL2",
"extension": "plt",
"extensions": ("plt",),
"mimetype": "text/plain",
"category": "quilting",
"reader": PltReader,
"writer": PltWriter,
}
)
yield (
{
"description": "Husqvarna Embroidery Format",
Expand Down
36 changes: 36 additions & 0 deletions pyembroidery/PltReader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import re

from .EmbFunctions import *

PU_COMMAND = re.compile(r"PU\s*([0-9]+)\s*,\s*([0-9]+)")
PD_COMMAND = re.compile(r"PD\s*([0-9]+)\s*,\s*([0-9]+)")
SP_COMMAND = re.compile(r"SP\s*([0-9]+)\s*")


def read(f, out, settings=None):
data = f.read()
data = str(data, "utf8")
lines = data.split(";")
for line in lines:
line = line.strip()
match = PU_COMMAND.match(line)
if match:
x = int(match.group(1)) / 4.0
y = int(match.group(2)) / 4.0
out.move_abs(x, y)
out.stitch_abs(x, y)

match = PD_COMMAND.match(line)
if match:
x = int(match.group(1)) / 4.0
y = int(match.group(2)) / 4.0
out.stitch_abs(x, y)

match = SP_COMMAND.match(line)
if match:
pen = int(match.group(1))
out.needle_change(pen)

if line == "EN":
print("Done")
break
59 changes: 59 additions & 0 deletions pyembroidery/PltWriter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""
HPGL2 Plot vector graphics are used commonly in pen plotters and vinyl cutters and have been a pretty mature language
since the 1970s. Here we are using a subset of the main language and commands to work with somewhat common form of
quilting machine. While this will process a lot of the more complex methods simple quilting stitches are expected to
work and are the typical goal product.

The standard step size of 1 unit in HPGL is 1/40 mm. As opposed to 1/10 mm which is standard for embroidery. HPGL is
increasing Y is downwards, which is contrary to most embroidery.
"""

from .WriteHelper import write_string_utf8

from .EmbFunctions import *


def write(pattern, f, settings=None):
write_string_utf8(f, "IN;\n")
write_string_utf8(f, "IP;\n")

trimmed = True

stitches = pattern.stitches
xx = 0
yy = 0

pen_id = 1
write_string_utf8(f, "SP%d;\n" % pen_id)

for stitch in stitches:
# 4 to convert 1/10mm to 1/40mm.
x = stitch[0] * 4.0
y = stitch[1] * 4.0
data = stitch[2] & COMMAND_MASK
dx = int(round(x - xx))
dy = int(round(y - yy))
xx += dx
yy += dy
if data == STITCH:
if trimmed:
write_string_utf8(f, "PU %d, %d;\n" % (int(xx), int(yy)))
else:
write_string_utf8(f, "PD %d, %d;\n" % (int(xx), int(yy)))
trimmed = False
elif data == JUMP:
if trimmed:
write_string_utf8(f, "PU %d, %d;\n" % (int(xx), int(yy)))
else:
write_string_utf8(f, "PD %d, %d;\n" % (int(xx), int(yy)))
elif data == COLOR_CHANGE:
pen_id += 1
write_string_utf8(f, "SP%d;\n" % pen_id)
trimmed = True
elif data == STOP:
trimmed = True
elif data == TRIM:
trimmed = True
elif data == END:
write_string_utf8(f, "EN;\n")
break
5 changes: 5 additions & 0 deletions pyembroidery/QliReader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .EmbFunctions import *


def read(f, out, settings=None):
pass
7 changes: 7 additions & 0 deletions pyembroidery/QliWriter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import math

from .EmbFunctions import *


def write(pattern, f, settings=None):
pass
210 changes: 210 additions & 0 deletions test/test_convert_plt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
from __future__ import print_function

import unittest

from test.pattern_for_tests import *


class TestConverts(unittest.TestCase):

def position_equals(self, stitches, j, k):
self.assertEqual(stitches[j][:1], stitches[k][:1])

def test_convert_plt_to_u01(self):
file1 = "convert_u01.plt"
file2 = "converted_plt.u01"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 16)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->u01: ", t_pattern.stitches)
# self.addCleanup(os.remove, file1)
# self.addCleanup(os.remove, file2)

def test_convert_plt_to_csv(self):
file1 = "convert_csv.plt"
file2 = "converted_plt.csv"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->csv: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_exp(self):
file1 = "convert_exp.plt"
file2 = "converted_plt.exp"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->exp: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_pes(self):
file1 = "convert_pes.plt"
file2 = "converted_plt.pes"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->pes: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_jef(self):
file1 = "convert_jef.plt"
file2 = "converted_plt.jef"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->jef: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_pec(self):
file1 = "convert_pec.plt"
file2 = "converted_plt.pec"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->pec: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_vp3(self):
file1 = "convert_vp3.plt"
file2 = "converted_plt.vp3"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->vp3: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_dst(self):
file1 = "convert_dst.plt"
file2 = "converted_plt.dst"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->dst: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_gcode(self):
file1 = "convert_gcode.plt"
file2 = "converted_plt.gcode"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->gcode: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_xxx(self):
file1 = "convert_xxx.plt"
file2 = "converted_plt.xxx"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->xxx: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_convert_plt_to_tbf(self):
file1 = "convert_tbf.plt"
file2 = "converted_plt.tbf"
get_big_pattern().write(file1)
f_pattern = EmbPattern(file1)
f_pattern.write(file2)
t_pattern = EmbPattern(file2)

self.assertIsNotNone(t_pattern)
self.assertEqual(t_pattern.count_stitch_commands(NEEDLE_SET), 16)
self.assertEqual(t_pattern.count_stitch_commands(STITCH), 16 * 5)
self.position_equals(t_pattern.stitches, 0, -1)
print("plt->tbf: ", t_pattern.stitches)
self.addCleanup(os.remove, file1)
self.addCleanup(os.remove, file2)

def test_plt_stop_write_large(self):
file = "stop2.plt"
pattern = get_shift_stop_pattern()
n_pattern = pattern.get_normalized_pattern()
self.assertEqual(n_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(n_pattern.count_stitch_commands(STITCH), 16 * 5)
self.assertEqual(n_pattern.count_stitch_commands(STOP), 5)

pattern.write(file)
f_pattern = EmbPattern(file)

self.assertIsNotNone(f_pattern)

with open(file, "rb") as f:
f.seek(0x18)
colors = f.read(1)
self.assertEqual(ord(colors), f_pattern.count_color_changes() + f_pattern.count_stitch_commands(STOP) + 1)

self.assertEqual(f_pattern.count_stitch_commands(COLOR_CHANGE), 15)
self.assertEqual(f_pattern.count_stitch_commands(STITCH), 16 * 5)
self.assertEqual(f_pattern.count_stitch_commands(STOP), 5)
self.addCleanup(os.remove, file)