kopia lustrzana https://github.com/EmbroidePy/pyembroidery
Porównaj commity
71 Commity
Autor | SHA1 | Data |
---|---|---|
tatarize | 1f8d3e9a53 | |
Tatarize | c36428075c | |
tatarize | 6fd941f4b2 | |
luz paz | a5982a43a1 | |
tatarize | 3d0db61e7a | |
Tatarize | 93601f80a0 | |
Aurish Hammad Hafeez | 830144a6c9 | |
tatarize | 06225f67dd | |
Tatarize | adaff94bfa | |
tatarize | e8bede8595 | |
Tatarize | d47bcffe14 | |
Tatarize | 0603a9dfc1 | |
tatarize | a7aea4ec4e | |
Tatarize | 05cce93713 | |
Tatarize | c695770956 | |
Tatarize | 24836e05ec | |
Tatarize | 766737422d | |
Tatarize | 34a317ddcc | |
Tatarize | bb763735ce | |
Tatarize | 60de6fc829 | |
Tatarize | a3c1d54092 | |
Tatarize | 0057a10b5b | |
Tatarize | 0acd1e5fa9 | |
Tatarize | 285abccd1d | |
Tatarize | 8f9a27b354 | |
Tatarize | 114230900c | |
tatarize | b11b77a8cb | |
Tatarize | cc556e66ea | |
Tatarize | 057ec2af30 | |
Tatarize | 7ff2b30480 | |
Tatarize | a31c4d3b9b | |
tatarize | 9bc10c7d87 | |
B01ana | ce657b04b6 | |
tatarize | e13ec9e6df | |
Tatarize | 6b66a19a2f | |
tatarize | 86f10396d7 | |
Tatarize | afc12fd44d | |
Tatarize | 377ade47e8 | |
Tatarize | ee4250a2b0 | |
Tatarize | e81d925047 | |
Tatarize | 7a53628bfa | |
Tatarize | 06724d38bb | |
Tatarize | 4dc7c71ac2 | |
Tatarize | f7fdefe4a1 | |
Tatarize | 2bcbfffe1b | |
tatarize | 9091ef4bcc | |
tatarize | 3ce5ff40f5 | |
tatarize | 8ce7dbdea8 | |
tatarize | 7cf247e8a6 | |
tatarize | 43447a749e | |
tatarize | 3d032cc43b | |
tatarize | ec5bf0c46f | |
tatarize | 81a780f2ee | |
tatarize | d3f1d2bdf2 | |
Tatarize | 24a11c648d | |
tatarize | ec1c1544a6 | |
tatarize | 0da26fcbdc | |
Tatarize | a1c34b1203 | |
tatarize | 9cda28598f | |
Tatarize | 36c25da083 | |
Tatarize | 6208a25eb3 | |
tatarize | e23708fec3 | |
tatarize | ef3b78b27a | |
SReich-EMI | f1a6903484 | |
SReich-EMI | 94771e3dd8 | |
Tatarize | b887fd4610 | |
Tatarize | 048fd6710e | |
Tatarize | 0e8519ed48 | |
tatarize | 10e8d68df7 | |
Tatarize | 61122b9c74 | |
Tatarize | 816afa9ed8 |
|
@ -0,0 +1 @@
|
|||
github: [tatarize]
|
|
@ -0,0 +1,73 @@
|
|||
name: Unittest
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, dev]
|
||||
paths:
|
||||
- '**.py'
|
||||
- '.github/workflows/unittests.yml'
|
||||
pull_request:
|
||||
branches: [master]
|
||||
paths:
|
||||
- '**.py'
|
||||
- '.github/workflows/unittests.yml'
|
||||
|
||||
concurrency:
|
||||
group: unittests-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
unittests:
|
||||
|
||||
name: ${{ matrix.os }}+py${{ matrix.python-version }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-2019, macos-11]
|
||||
python-version: [3.11]
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout ${{ github.ref }}
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Identify precise Python version
|
||||
id: full-python-version
|
||||
shell: bash
|
||||
run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))")
|
||||
|
||||
- name: Cache Python env for ${{ matrix.os }}-py${{ steps.full-python-version.outputs.version }}
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.pythonLocation }}
|
||||
key: new-${{ matrix.os }}-py${{ steps.full-python-version.outputs.version }}-${{ hashFiles('requirements.txt') }}
|
||||
|
||||
- name: List environment
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJSON(github) }}
|
||||
JOB_CONTEXT: ${{ toJSON(job) }}
|
||||
STEPS_CONTEXT: ${{ toJSON(steps) }}
|
||||
RUNNER_CONTEXT: ${{ toJSON(runner) }}
|
||||
STRATEGY_CONTEXT: ${{ toJSON(strategy) }}
|
||||
MATRIX_CONTEXT: ${{ toJSON(matrix) }}
|
||||
run: |
|
||||
pip list
|
||||
env
|
||||
|
||||
- name: Run Unittests
|
||||
run: |
|
||||
python -m unittest discover test -v
|
||||
if ${{ matrix.experimental }} == true; then
|
||||
exit 0
|
||||
fi
|
|
@ -1,6 +1,6 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.6"
|
||||
- "3.9"
|
||||
script:
|
||||
- python -m unittest discover test
|
||||
- python -m unittest discover test
|
18
README.md
18
README.md
|
@ -29,7 +29,7 @@ Pyembroidery fully meets and exceeds all of these requirements.
|
|||
* It supports all the core commands where that format can use said command as well as FAST and SLOW for .u01.
|
||||
* SEQUINS work in all supported formats (.dst) that are known to support sequins. Further it supports SEQUIN to JUMP operations on the other formats.
|
||||
|
||||
Though previously mandated support for Python 2.7, this support was dropped at the end of life for that version. It is highly recommended that you upgrade. A `python27` branch is availible but that branch was merely forked from when the version was supported.
|
||||
Though previously mandated support for Python 2.7, this support was dropped at the end of life for that version. It is highly recommended that you upgrade. A `python27` branch is available but that branch was merely forked from when the version was supported.
|
||||
|
||||
|
||||
## Philosophy
|
||||
|
@ -52,7 +52,7 @@ Other reasonable elements:
|
|||
## Overview
|
||||
Readers are sent a fileobject/stream, an EmbPattern and sometimes a settings dict. The reader parses the file, adding in metadata, threads, and stitches with as much valid information as the file contains.
|
||||
|
||||
EmbPattern objects contain all relevant data. You can iterate stitch blocks .get_as_stitchblocks() or access the raw-stitches, threads, or metadata.
|
||||
EmbPattern objects contain all relevant data. You can iterate stitch blocks .get_as_stitchblock() or access the raw-stitches, threads, or metadata.
|
||||
|
||||
Writers are called to save a pattern to disk. The writers save raw-stitch data to disk. This data may, however, not be formatted in a way the writer can utilize effectively. For this reason, writers (except lossless csv) utilize the encoder to ensure whatever the data is in the pattern will be presented to the writer in a manner coherent to the writer.
|
||||
|
||||
|
@ -155,6 +155,7 @@ Pyembroidery will read:
|
|||
* .tbf
|
||||
* .u01
|
||||
* .xxx
|
||||
* .zhs
|
||||
* .zxy
|
||||
* .gcode
|
||||
|
||||
|
@ -201,7 +202,7 @@ Prints out a workable CSV file with the given data. Starting in 1.3 the csv patt
|
|||
|
||||
|
||||
#### Reading/Writing to JSON:
|
||||
Saves the pattern as a JSON object. This is intended to be useful as an interchange format since JSON is the most common data interchange format availible currently.
|
||||
Saves the pattern as a JSON object. This is intended to be useful as an interchange format since JSON is the most common data interchange format available currently.
|
||||
|
||||
|
||||
#### Writing to PNG:
|
||||
|
@ -339,7 +340,7 @@ There are many fully qualified methods of manipulating patterns. For example if
|
|||
pattern1 += pattern2
|
||||
```
|
||||
|
||||
You can also do pattern3 = pattern1 + pattern2 but that requires making an new pattern. With the `__iadd__()` dunder you can also perform actions like adding a colorchange.
|
||||
You can also do pattern3 = pattern1 + pattern2 but that requires making a new pattern. With the `__iadd__()` dunder you can also perform actions like adding a colorchange.
|
||||
|
||||
`pattern1 += "red"` will add a color change (if correct to do so), and a red thread to the threadlist.
|
||||
|
||||
|
@ -347,6 +348,10 @@ Other elements like `pattern += ((0,0), (20,20), (0,0))` will also work to appen
|
|||
|
||||
You can get a particular stitch of the pattern using `pattern[0]`. You can set string metadata elements `pattern['name'] = "My Design"`
|
||||
|
||||
### Thread Manipulation
|
||||
|
||||
If you wish to merely edit the thread colors these are located in the `.threadlist` attribute and you can call set a new `.color` or `.set_hex_color("#RRGGBB")`. You may also modify the various thread related metadata. This will be used for those embroidery types which preserve this thread information.
|
||||
|
||||
## Conversion
|
||||
|
||||
As pyembroidery is a fully fleshed out reader/writer within the mandate, it also does conversion.
|
||||
|
@ -528,7 +533,7 @@ The encoder will by default ignore any COLOR_BREAK that occurs before any stitch
|
|||
|
||||
You can expressly add any of the core commands to the patterns. These are generalized and try to play nice with other commands. When the patterns are written to disk, they call pattern.get_normalized_pattern() and save the normalized pattern. Saving to any format does not modify the pattern, ever. It writes the modified pattern out. It adds the max_jump and max_stitch to the encoding when it normalizes this to save. So each format can compile to a different set of stitches due to the max_jump etc. This is expressly an attempt to maintain as much data integrity as possible.
|
||||
|
||||
After a load, the pattern will be filled with raw basic stitch data, it's perfectly reasonable call .get_stable_pattern() on this which will make it into a series of stitches, color_breaks, sequence_breaks or get_pattern_interpolate_trim() which will allow you to introduce trim commands after a series of JUMP commands as specified and merge the untrimmed jumps. Or to iterate through the data with .get_as_stitchblocks() which is a generator that will produce stitch blocks from the raw loaded data. The stabilized pattern simply makes a new pattern, iterates through the current pattern by the stitchblocks and feeds that into add_stitch_block(). This results in a pattern without any jumps, trims, etc.
|
||||
After a load, the pattern will be filled with raw basic stitch data, it's perfectly reasonable call .get_stable_pattern() on this which will make it into a series of stitches, color_breaks, sequence_breaks or get_pattern_interpolate_trim() which will allow you to introduce trim commands after a series of JUMP commands as specified and merge the untrimmed jumps. Or to iterate through the data with .get_as_stitchblock() which is a generator that will produce stitch blocks from the raw loaded data. The stabilized pattern simply makes a new pattern, iterates through the current pattern by the stitchblocks and feeds that into add_stitch_block(). This results in a pattern without any jumps, trims, etc.
|
||||
|
||||
STITCH_BREAK
|
||||
|
||||
|
@ -561,7 +566,7 @@ While there's only NONE, and THREE_SMALL for contingencies currently, both the t
|
|||
|
||||
* The core units are 1/10th mm. This is what 1 refers to within most formats, and internally within pyembroidery itself. You are entirely permitted to use floating point numbers. When writing to a format, fractional values will be lost, but this shall happen in such a way to avoid the propagation of error. Relative stitches from position ( 0.0, 0.31 ) of (+5.4, +5.4), (+5.4, +5,4), (+5.4, +5,4) should encode as changes of 5,6 6,5 5,6. Taking the relative distance in the format as the integer change from the last integer position to the new one, maintaining a position as close to the absolute position as possible. All fractional values are considered significant.
|
||||
|
||||
In some read formats the formats themselves have a slightly different unit systems such as .PCD or .MIT these alternative units will be presented seemlessly as 1/10th mm units.
|
||||
In some read formats the formats themselves have a slightly different unit systems such as .PCD or .MIT these alternative units will be presented seamlessly as 1/10th mm units.
|
||||
|
||||
### Core Command Ordering
|
||||
|
||||
|
@ -599,4 +604,3 @@ Thanks to,
|
|||
---
|
||||
|
||||
This software is in no way derived from or based on Jackson Yee's abandoned 2006 "pyembroidery" project. The name was simply taken from libEmbroidery and written in python and thus a portmanteau of those. I was unaware of the project until after the all the principal work on this project was complete. I apologize for any confusion this may cause.
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ def process_header_info(out, prefix, value):
|
|||
out.metadata("copyright", value)
|
||||
elif prefix == "TC":
|
||||
values = [x.strip() for x in value.split(",")]
|
||||
out.add_thread({"hex": values[0], "description": value[1], "catalog": value[2]})
|
||||
out.add_thread({"hex": values[0], "description": values[1], "catalog": values[2]})
|
||||
else:
|
||||
out.metadata(prefix, value)
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -31,7 +31,7 @@ def get_thread_set():
|
|||
EmbThreadPec(246, 74, 138, "Deep Rose", "25"),
|
||||
EmbThreadPec(178, 118, 36, "Light Brown", "26"),
|
||||
EmbThreadPec(252, 187, 197, "Salmon Pink", "27"),
|
||||
EmbThreadPec(254, 55, 15, "Vermillion", "28"),
|
||||
EmbThreadPec(254, 55, 15, "Vermilion", "28"),
|
||||
EmbThreadPec(240, 240, 240, "White", "29"),
|
||||
EmbThreadPec(106, 28, 138, "Violet", "30"),
|
||||
EmbThreadPec(168, 221, 196, "Seacrest", "31"),
|
||||
|
@ -54,7 +54,7 @@ def get_thread_set():
|
|||
EmbThreadPec(247, 56, 102, "Carmine", "48"),
|
||||
EmbThreadPec(181, 75, 100, "Amber Red", "49"),
|
||||
EmbThreadPec(19, 43, 26, "Olive Green", "50"),
|
||||
EmbThreadPec(199, 1, 86, "Dark Fuschia", "51"),
|
||||
EmbThreadPec(199, 1, 86, "Dark Fuchsia", "51"),
|
||||
EmbThreadPec(254, 158, 50, "Tangerine", "52"),
|
||||
EmbThreadPec(168, 222, 235, "Light Blue", "53"),
|
||||
EmbThreadPec(0, 103, 62, "Emerald Green", "54"),
|
||||
|
|
|
@ -0,0 +1,574 @@
|
|||
import pyembroidery
|
||||
from pyembroidery import (
|
||||
CONTINGENCY_SEQUIN_UTILIZE,
|
||||
decode_embroidery_command,
|
||||
STITCH,
|
||||
COLOR_CHANGE,
|
||||
NEEDLE_SET,
|
||||
TRIM,
|
||||
JUMP,
|
||||
SEQUIN_MODE,
|
||||
SEQUIN_EJECT,
|
||||
STOP,
|
||||
SLOW,
|
||||
FAST,
|
||||
END,
|
||||
get_common_name_dictionary,
|
||||
COMMAND_MASK,
|
||||
)
|
||||
from pyembroidery.WriteHelper import write_string_utf8
|
||||
|
||||
WRITES_SPEEDS = True
|
||||
SEQUIN_CONTINGENCY = CONTINGENCY_SEQUIN_UTILIZE
|
||||
|
||||
|
||||
def write(pattern, f, settings=None):
|
||||
writer = GenericWriter(pattern, f, settings)
|
||||
writer.write()
|
||||
|
||||
|
||||
class GenericWriter:
|
||||
"""
|
||||
Generic Writer will write generic data fit to a formatted set of strings.
|
||||
|
||||
Blocks are established by the first segment.
|
||||
Colors are established by the first segment or the first segment after a color change or by a needle_set.
|
||||
Documents are established by the first segment, or the first segment after an end.
|
||||
|
||||
Segment is the default for any-command. Specific commands override segment.
|
||||
|
||||
stitch is the default stitch.
|
||||
stitch_first overrides stitch for the first stitch in a block.
|
||||
stitch_last overrides stitch for the last stitch in a block.
|
||||
|
||||
trims and jumps occurring before a color change belong to the previous color.
|
||||
trims and jumps occurring after a color change belong to the next color.
|
||||
|
||||
Missing segments are treated as if they never existed. Value properties will differ if segments are excluded.
|
||||
"""
|
||||
|
||||
def __init__(self, pattern, f, settings):
|
||||
self.pattern = pattern
|
||||
self.f = f
|
||||
self.settings = settings
|
||||
self.metadata_entry = settings.get("metadata_entry", None)
|
||||
self.thread_entry = settings.get("thread_entry", None)
|
||||
self.pattern_start = settings.get("pattern_start", None)
|
||||
self.pattern_end = settings.get("pattern_end", None)
|
||||
self.document_start = settings.get("document_start", None)
|
||||
self.document_end = settings.get("document_end", None)
|
||||
self.color_start = settings.get("color_start", None)
|
||||
self.color_end = settings.get("color_end", None)
|
||||
self.color_join = settings.get("color_join", None)
|
||||
self.block_start = settings.get("block_start", None)
|
||||
self.block_end = settings.get("block_end", None)
|
||||
self.block_join = settings.get("block_join", None)
|
||||
self.segment_start = settings.get("segment_start", None)
|
||||
self.segment = settings.get("segment", None)
|
||||
self.segment_end = settings.get("segment_end", None)
|
||||
self.segment_join = settings.get("segment_join", None)
|
||||
self.stitch_first = settings.get("stitch_first", None)
|
||||
self.stitch_last = settings.get("stitch_last", None)
|
||||
self.stitch = settings.get("stitch", None)
|
||||
self.stop = settings.get("stop", None)
|
||||
self.jump = settings.get("jump", None)
|
||||
self.trim = settings.get("trim", None)
|
||||
self.needle_set = settings.get("needle_set", None)
|
||||
self.color_change = settings.get("color_change", None)
|
||||
self.sequin = settings.get("sequin", None)
|
||||
self.sequin_mode = settings.get("sequin_mode", None)
|
||||
self.slow = settings.get("slow", None)
|
||||
self.fast = settings.get("fast", None)
|
||||
self.end = settings.get("end", None)
|
||||
|
||||
self.format_dictionary = {}
|
||||
self.pattern_established = False
|
||||
self.document_established = False
|
||||
self.color_established = False
|
||||
self.block_established = False
|
||||
self.document_index = -1
|
||||
self.thread = None
|
||||
self.thread_index = -1
|
||||
self.stitch_index = -1
|
||||
self.color_index = -1
|
||||
self.block_index = -1
|
||||
self.dx = 0
|
||||
self.dy = 0
|
||||
self.xx = 0
|
||||
self.yy = 0
|
||||
self.last_x = 0
|
||||
self.last_y = 0
|
||||
self.z = 0.0
|
||||
self.z_increment = settings.get("stitch_z_travel", 10.0)
|
||||
self.command_index = 0
|
||||
|
||||
self.current_stitch = None
|
||||
self.x = None
|
||||
self.y = None
|
||||
self.command = None
|
||||
self.cmd = None
|
||||
self.thread = None
|
||||
self.needle = None
|
||||
self.order = None
|
||||
self.cmd_str = None
|
||||
|
||||
self.block_closing = False
|
||||
self.color_closing = False
|
||||
self.document_closing = False
|
||||
|
||||
self.block_opening = False
|
||||
self.color_opening = False
|
||||
self.document_opening = False
|
||||
|
||||
def write_opens(self):
|
||||
if self.document_opening:
|
||||
self.document_opening = False
|
||||
if self.document_start is not None:
|
||||
write_string_utf8(self.f, self.document_start.format_map(self.format_dictionary))
|
||||
if self.color_opening:
|
||||
self.color_opening = False
|
||||
if self.color_join is not None and self.color_index != 0:
|
||||
write_string_utf8(self.f, self.color_join.format_map(self.format_dictionary))
|
||||
if self.color_start is not None:
|
||||
write_string_utf8(self.f, self.color_start.format_map(self.format_dictionary))
|
||||
if self.block_opening:
|
||||
self.block_opening = False
|
||||
if self.block_join is not None and self.block_index != 0:
|
||||
write_string_utf8(self.f, self.block_join.format_map(self.format_dictionary))
|
||||
if self.block_start is not None:
|
||||
write_string_utf8(self.f, self.block_start.format_map(self.format_dictionary))
|
||||
|
||||
def write_closes(self):
|
||||
if self.block_closing:
|
||||
self.block_closing = False
|
||||
if self.block_end is not None:
|
||||
write_string_utf8(self.f, self.block_end.format_map(self.format_dictionary))
|
||||
if self.color_closing:
|
||||
self.color_closing = False
|
||||
if self.color_end is not None:
|
||||
write_string_utf8(self.f, self.color_end.format_map(self.format_dictionary))
|
||||
if self.document_closing:
|
||||
self.document_closing = False
|
||||
if self.document_end is not None:
|
||||
write_string_utf8(self.f, self.document_end.format_map(self.format_dictionary))
|
||||
|
||||
def get_write_segment(self, cmd):
|
||||
# SEQUIN_MODE
|
||||
if cmd == SEQUIN_MODE and self.sequin_mode is not None:
|
||||
return self.sequin_mode
|
||||
|
||||
# SEQUIN
|
||||
if cmd == SEQUIN_EJECT and self.sequin is not None:
|
||||
return self.sequin
|
||||
|
||||
# STITCH
|
||||
if cmd == STITCH and self.stitch is not None:
|
||||
return self.stitch
|
||||
|
||||
# TRIM
|
||||
if cmd == TRIM and self.trim is not None:
|
||||
return self.trim
|
||||
|
||||
# JUMP
|
||||
if cmd == JUMP and self.jump is not None:
|
||||
return self.jump
|
||||
|
||||
# COLOR CHANGE
|
||||
if cmd == COLOR_CHANGE and self.color_change is not None:
|
||||
return self.color_change
|
||||
|
||||
# NEEDLE SET
|
||||
if cmd == NEEDLE_SET and self.needle_set is not None:
|
||||
return self.needle_set
|
||||
|
||||
# STOP COMMAND
|
||||
if cmd == STOP and self.stop is not None:
|
||||
return self.stop
|
||||
|
||||
# SLOW COMMAND
|
||||
if cmd == SLOW and self.slow is not None:
|
||||
return self.slow
|
||||
|
||||
# FAST COMMAND
|
||||
if cmd == FAST and self.fast is not None:
|
||||
return self.fast
|
||||
|
||||
# END COMMAND
|
||||
if cmd == END and self.end is not None:
|
||||
return self.end
|
||||
|
||||
# GENERIC SEGMENT
|
||||
return self.segment
|
||||
|
||||
def set_document_statistics(self):
|
||||
pattern = self.pattern
|
||||
self.format_dictionary.update(pattern.extras)
|
||||
|
||||
bounds = pattern.bounds() # convert to mm.
|
||||
width = bounds[2] - bounds[0]
|
||||
height = bounds[3] - bounds[1]
|
||||
|
||||
stitch_counts = {}
|
||||
for s in pattern.stitches:
|
||||
command = s[2] & COMMAND_MASK
|
||||
if command in stitch_counts:
|
||||
stitch_counts[command] += 1
|
||||
else:
|
||||
stitch_counts[command] = 1
|
||||
|
||||
names = get_common_name_dictionary()
|
||||
for name in names:
|
||||
value = names[name].lower()
|
||||
self.format_dictionary[value + "_count"] = stitch_counts.get(name,0)
|
||||
self.format_dictionary.update(
|
||||
{
|
||||
"stitch_total": pattern.count_stitches(),
|
||||
"thread_total": pattern.count_threads(),
|
||||
"extents_left": bounds[0],
|
||||
"extends_top": bounds[1],
|
||||
"extends_right": bounds[2],
|
||||
"extends_bottom": bounds[3],
|
||||
"extends_width": width,
|
||||
"extends_height": height,
|
||||
"extents_left_mm": bounds[0] / 10.0,
|
||||
"extends_top_mm": bounds[1] / 10.0,
|
||||
"extends_right_mm": bounds[2] / 10.0,
|
||||
"extends_bottom_mm": bounds[3] / 10.0,
|
||||
"extends_width_mm": width / 10.0,
|
||||
"extends_height_mm": height / 10.0,
|
||||
}
|
||||
)
|
||||
|
||||
def update_positions(self, x, y, cmd):
|
||||
self.dx = x - self.last_x
|
||||
self.dy = y - self.last_y
|
||||
idx = int(round(x - self.xx))
|
||||
idy = int(round(y - self.yy))
|
||||
self.xx += idx
|
||||
self.yy += idy
|
||||
self.format_dictionary.update(
|
||||
{
|
||||
"x": x,
|
||||
"y": y,
|
||||
"z": self.z,
|
||||
"_x": -x,
|
||||
"_y": -y,
|
||||
"dx": self.dx,
|
||||
"dy": self.dy,
|
||||
"idx": idx,
|
||||
"idy": idy,
|
||||
"_idx": -idx,
|
||||
"_idy": -idy,
|
||||
"ix": self.xx,
|
||||
"iy": self.yy,
|
||||
"_ix": -self.xx,
|
||||
"_iy": -self.yy,
|
||||
"last_x": self.last_x,
|
||||
"last_y": self.last_y,
|
||||
"_last_x": -self.last_x,
|
||||
"_last_y": -self.last_y,
|
||||
}
|
||||
)
|
||||
if cmd == STITCH:
|
||||
self.z += self.z_increment
|
||||
self.last_x = x
|
||||
self.last_y = y
|
||||
|
||||
def update_command(self):
|
||||
try:
|
||||
self.current_stitch = self.pattern.stitches[self.command_index]
|
||||
|
||||
self.x, self.y, self.command = self.current_stitch
|
||||
self.cmd, self.thread, self.needle, self.order = decode_embroidery_command(
|
||||
self.command
|
||||
)
|
||||
self.cmd_str = pyembroidery.get_common_name_dictionary()[self.cmd]
|
||||
except IndexError:
|
||||
self.current_stitch = None
|
||||
self.x = None
|
||||
self.y = None
|
||||
self.command = None
|
||||
self.cmd = None
|
||||
self.thread = None
|
||||
self.needle = None
|
||||
self.order = None
|
||||
self.cmd_str = None
|
||||
self.format_dictionary.update(
|
||||
{
|
||||
"index": self.command_index,
|
||||
"command": self.command,
|
||||
"cmd_str": self.cmd_str,
|
||||
"cmd": self.cmd,
|
||||
"cmd_thread": self.thread,
|
||||
"cmd_needle": self.needle,
|
||||
"cmd_order": self.order,
|
||||
}
|
||||
)
|
||||
|
||||
def open_pattern(self):
|
||||
if not self.pattern_established:
|
||||
self.pattern_established = True
|
||||
if self.pattern_start is not None:
|
||||
write_string_utf8(
|
||||
self.f, self.pattern_start.format_map(self.format_dictionary)
|
||||
)
|
||||
|
||||
def open_document(self):
|
||||
# DOCUMENT START
|
||||
if not self.document_established:
|
||||
self.document_established = True
|
||||
self.document_index += 1
|
||||
self.document_opening = True
|
||||
self.color_index = 0
|
||||
|
||||
self.format_dictionary.update(
|
||||
{
|
||||
"document_index": self.document_index,
|
||||
"document_index1": self.document_index + 1,
|
||||
"color_index": self.color_index,
|
||||
"color_index1": self.color_index + 1,
|
||||
"block_index": self.block_index,
|
||||
"block_index1": self.block_index + 1,
|
||||
}
|
||||
)
|
||||
|
||||
def open_color(self):
|
||||
# COLOR START
|
||||
if not self.color_established:
|
||||
self.color_established = True
|
||||
self.thread_index += 1
|
||||
self.color_opening = True
|
||||
|
||||
self.thread = self.pattern.get_thread_or_filler(self.thread_index)
|
||||
self.block_index = 0
|
||||
self.color_index += 1
|
||||
self.format_dictionary.update(
|
||||
{
|
||||
"document_index": self.document_index,
|
||||
"document_index1": self.document_index + 1,
|
||||
"color_index": self.color_index,
|
||||
"color_index1": self.color_index + 1,
|
||||
"block_index": self.block_index,
|
||||
"block_index1": self.block_index + 1,
|
||||
}
|
||||
)
|
||||
|
||||
def open_block(self):
|
||||
# BLOCK START
|
||||
if not self.block_established:
|
||||
self.block_established = True
|
||||
self.block_index += 1
|
||||
self.block_opening = True
|
||||
self.format_dictionary.update(
|
||||
{
|
||||
"document_index": self.document_index,
|
||||
"document_index1": self.document_index + 1,
|
||||
"color_index": self.color_index,
|
||||
"color_index1": self.color_index + 1,
|
||||
"block_index": self.block_index,
|
||||
"block_index1": self.block_index + 1,
|
||||
}
|
||||
)
|
||||
|
||||
def write_segment(self, segment):
|
||||
# SEGMENT
|
||||
if self.segment_start is not None:
|
||||
write_string_utf8(self.f, self.segment_start.format_map(self.format_dictionary))
|
||||
|
||||
write_string_utf8(self.f, segment.format_map(self.format_dictionary))
|
||||
|
||||
# SEGMENT JOIN
|
||||
if self.segment_join is not None:
|
||||
write_string_utf8(self.f, self.segment_join.format_map(self.format_dictionary))
|
||||
|
||||
# SEGMENT_END
|
||||
if self.segment_end is not None:
|
||||
write_string_utf8(self.f, self.segment_end.format_map(self.format_dictionary))
|
||||
|
||||
def close_pattern(self):
|
||||
if self.pattern_established:
|
||||
self.pattern_established = False
|
||||
if self.pattern_end is not None:
|
||||
write_string_utf8(
|
||||
self.f, self.pattern_end.format_map(self.format_dictionary)
|
||||
)
|
||||
|
||||
def close_document(self):
|
||||
# DOCUMENT END
|
||||
if self.document_established:
|
||||
self.document_established = False
|
||||
self.document_closing = True
|
||||
|
||||
def close_color(self):
|
||||
# COLOR END
|
||||
if self.color_established:
|
||||
self.color_established = False
|
||||
self.color_closing = True
|
||||
|
||||
def close_block(self):
|
||||
# BLOCK END
|
||||
if self.block_established:
|
||||
self.block_established = False
|
||||
self.block_closing = True
|
||||
|
||||
def write(self):
|
||||
# DOCUMENT STATISTICS
|
||||
self.set_document_statistics()
|
||||
|
||||
self.open_pattern()
|
||||
if self.metadata_entry is not None:
|
||||
for i, key in enumerate(self.pattern.extras):
|
||||
value = self.pattern.extras[key]
|
||||
self.format_dictionary.update({
|
||||
"metadata_index": i,
|
||||
"metadata_key": str(key),
|
||||
"metadata_value": str(value),
|
||||
})
|
||||
write_string_utf8(
|
||||
self.f, self.metadata_entry.format_map(self.format_dictionary)
|
||||
)
|
||||
|
||||
if self.thread_entry is not None:
|
||||
for i, thread in enumerate(self.pattern.threadlist):
|
||||
self.format_dictionary.update({
|
||||
"thread_index": i,
|
||||
"thread_color": thread.hex_color(),
|
||||
"thread_description": thread.description,
|
||||
"thread_brand": thread.brand,
|
||||
"thread_catalog_number": thread.catalog_number,
|
||||
"thread_chart": thread.chart,
|
||||
"thread_details": thread.details,
|
||||
"thread_weight": thread.weight,
|
||||
"thread_red": thread.get_red(),
|
||||
"thread_green": thread.get_green(),
|
||||
"thread_blue": thread.get_blue(),
|
||||
})
|
||||
write_string_utf8(
|
||||
self.f, self.thread_entry.format_map(self.format_dictionary)
|
||||
)
|
||||
for self.command_index in range(0, len(self.pattern.stitches)):
|
||||
self.update_command()
|
||||
write_segment = self.get_write_segment(self.cmd)
|
||||
|
||||
# MAIN CODE, there is something to write.
|
||||
if write_segment is not None:
|
||||
if isinstance(write_segment, dict):
|
||||
key, default = write_segment[None]
|
||||
key = key.format_map(self.format_dictionary)
|
||||
write_segment = write_segment.get(key, default)
|
||||
self.update_positions(self.x, self.y, self.cmd)
|
||||
if self.cmd == SEQUIN_MODE:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# SEQUIN
|
||||
if self.cmd == SEQUIN_EJECT:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# STITCH
|
||||
if self.cmd == STITCH:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# TRIM
|
||||
if self.cmd == TRIM:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
|
||||
# JUMP
|
||||
if self.cmd == JUMP:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# COLOR CHANGE
|
||||
if self.cmd == COLOR_CHANGE:
|
||||
self.open_document()
|
||||
|
||||
# NEEDLE SET
|
||||
if self.cmd == NEEDLE_SET:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
|
||||
# STOP COMMAND
|
||||
if self.cmd == STOP:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# SLOW COMMAND
|
||||
if self.cmd == SLOW:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# FAST COMMAND
|
||||
if self.cmd == FAST:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
# END COMMAND
|
||||
if self.cmd == END:
|
||||
self.open_document()
|
||||
self.open_color()
|
||||
self.open_block()
|
||||
|
||||
self.write_opens()
|
||||
self.write_segment(write_segment)
|
||||
|
||||
if self.cmd == SEQUIN_MODE:
|
||||
pass
|
||||
|
||||
# SEQUIN
|
||||
if self.cmd == SEQUIN_EJECT:
|
||||
pass
|
||||
|
||||
# STITCH
|
||||
if self.cmd == STITCH:
|
||||
pass
|
||||
|
||||
# TRIM
|
||||
if self.cmd == TRIM:
|
||||
self.close_block()
|
||||
|
||||
# JUMP
|
||||
if self.cmd == JUMP:
|
||||
pass
|
||||
|
||||
# COLOR CHANGE
|
||||
if self.cmd == COLOR_CHANGE:
|
||||
self.close_block()
|
||||
self.close_color()
|
||||
|
||||
# NEEDLE SET
|
||||
if self.cmd == NEEDLE_SET:
|
||||
pass
|
||||
|
||||
# STOP COMMAND
|
||||
if self.cmd == STOP:
|
||||
pass
|
||||
|
||||
# SLOW COMMAND
|
||||
if self.cmd == SLOW:
|
||||
pass
|
||||
|
||||
# FAST COMMAND
|
||||
if self.cmd == FAST:
|
||||
pass
|
||||
|
||||
# END COMMAND
|
||||
if self.cmd == END:
|
||||
self.close_block()
|
||||
self.close_color()
|
||||
self.close_document()
|
||||
self.write_closes()
|
||||
|
||||
self.close_block()
|
||||
self.close_color()
|
||||
self.close_document()
|
||||
self.close_pattern()
|
|
@ -3,6 +3,7 @@ from .ReadHelper import read_int_32le, signed8
|
|||
|
||||
|
||||
def read_jef_stitches(f, out, settings=None):
|
||||
color_index = 1
|
||||
while True:
|
||||
b = bytearray(f.read(2))
|
||||
if len(b) != 2:
|
||||
|
@ -22,7 +23,13 @@ def read_jef_stitches(f, out, settings=None):
|
|||
out.move(x, y)
|
||||
continue
|
||||
if ctrl == 0x01:
|
||||
out.color_change(0, 0)
|
||||
# PATCH: None means stop since it was color #0
|
||||
if out.threadlist[color_index] is None:
|
||||
out.stop(0, 0)
|
||||
del out.threadlist[color_index]
|
||||
else:
|
||||
out.color_change(0, 0)
|
||||
color_index += 1
|
||||
continue
|
||||
if ctrl == 0x10:
|
||||
break
|
||||
|
@ -54,7 +61,11 @@ def read(f, out, settings=None):
|
|||
|
||||
for i in range(0, count_colors):
|
||||
index = abs(read_int_32le(f))
|
||||
out.add_thread(jef_threads[index % len(jef_threads)])
|
||||
if index == 0:
|
||||
# Patch: If we have color 0. Go ahead and set that to None.
|
||||
out.threadlist.append(None)
|
||||
else:
|
||||
out.add_thread(jef_threads[index % len(jef_threads)])
|
||||
|
||||
f.seek(stitch_offset, 0)
|
||||
read_jef_stitches(f, out, settings)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import datetime
|
||||
|
||||
from .EmbConstant import *
|
||||
from .EmbThread import build_nonrepeat_palette
|
||||
from .EmbThreadJef import get_thread_set
|
||||
from .WriteHelper import write_int_8, write_int_32le, write_string_utf8
|
||||
|
||||
|
@ -30,7 +29,46 @@ def write(pattern, f, settings=None):
|
|||
date_string = settings.get("date", date_string)
|
||||
|
||||
pattern.fix_color_count()
|
||||
color_count = pattern.count_threads()
|
||||
# REMOVE BUG: color_count = pattern.count_threads(). #
|
||||
|
||||
# PATCH
|
||||
jef_threads = get_thread_set()
|
||||
last_index = None
|
||||
last_thread = None
|
||||
palette = []
|
||||
color_toggled = False
|
||||
color_count = 0 # Color and Stop count.
|
||||
index_in_threadlist = 0
|
||||
for stitch in pattern.stitches:
|
||||
# Iterate all stitches.
|
||||
flags = stitch[2] & COMMAND_MASK
|
||||
if flags == COLOR_CHANGE or index_in_threadlist == 0:
|
||||
# If color change *or* initial color unset.
|
||||
thread = pattern.threadlist[index_in_threadlist]
|
||||
index_in_threadlist += 1
|
||||
color_count += 1
|
||||
index_of_jefthread = thread.find_nearest_color_index(jef_threads)
|
||||
if last_index == index_of_jefthread and last_thread != thread:
|
||||
# Last thread and current thread pigeonhole to same jefcolor.
|
||||
# We set that thread to None. And get the second closest color.
|
||||
repeated_thread = jef_threads[index_of_jefthread]
|
||||
repeated_index = index_of_jefthread
|
||||
jef_threads[index_of_jefthread] = None
|
||||
index_of_jefthread = thread.find_nearest_color_index(jef_threads)
|
||||
jef_threads[repeated_index] = repeated_thread
|
||||
palette.append(index_of_jefthread)
|
||||
last_index = index_of_jefthread
|
||||
last_thread = thread
|
||||
color_toggled = False
|
||||
if flags == STOP:
|
||||
color_count += 1
|
||||
color_toggled = not color_toggled
|
||||
if color_toggled:
|
||||
palette.append(0)
|
||||
else:
|
||||
palette.append(last_index)
|
||||
# END PATCH
|
||||
|
||||
offsets = 0x74 + (color_count * 8)
|
||||
write_int_32le(f, offsets)
|
||||
write_int_32le(f, 0x14)
|
||||
|
@ -48,7 +86,7 @@ def write(pattern, f, settings=None):
|
|||
elif data == TRIM:
|
||||
if trims:
|
||||
point_count += 2 * command_count_max
|
||||
elif data == COLOR_CHANGE:
|
||||
elif data == COLOR_CHANGE or data == STOP: # PATCH: INCLUDE STOP.
|
||||
point_count += 2
|
||||
elif data == END:
|
||||
break
|
||||
|
@ -86,9 +124,12 @@ def write(pattern, f, settings=None):
|
|||
y_hoop_edge = 1000 - half_height
|
||||
write_hoop_edge_distance(f, x_hoop_edge, y_hoop_edge)
|
||||
|
||||
jef_threads = get_thread_set()
|
||||
# REMOVE (We covered this in PATCH).
|
||||
#jef_threads = get_thread_set()
|
||||
#
|
||||
#palette = build_nonrepeat_palette(jef_threads, pattern.threadlist)
|
||||
# END REMOVE
|
||||
|
||||
palette = build_nonrepeat_palette(jef_threads, pattern.threadlist)
|
||||
for t in palette:
|
||||
write_int_32le(f, t)
|
||||
|
||||
|
@ -109,7 +150,7 @@ def write(pattern, f, settings=None):
|
|||
write_int_8(f, dx)
|
||||
write_int_8(f, -dy)
|
||||
continue
|
||||
elif data == COLOR_CHANGE:
|
||||
elif data == COLOR_CHANGE or data == STOP: # PATCH INCLUDE STOP.
|
||||
f.write(b"\x80\x01")
|
||||
write_int_8(f, dx)
|
||||
write_int_8(f, -dy)
|
||||
|
|
|
@ -31,8 +31,8 @@ def read_pec(f, out, pes_chart=None):
|
|||
stitch_block_end = read_int_24le(f) - 5 + f.tell()
|
||||
# The end of this value is already 5 into the stitchblock.
|
||||
|
||||
# 3 bytes, '\x31\xff\xf0', 6 2-byte shorts. 15 total.
|
||||
f.seek(0x0F, 1)
|
||||
# 3 bytes, '\x31\xff\xf0', 4 2-byte shorts. 11 total.
|
||||
f.seek(0x0B, 1)
|
||||
read_pec_stitches(f, out)
|
||||
f.seek(stitch_block_end, 0)
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ from .EmbThreadPec import get_thread_set
|
|||
from .PecGraphics import draw_scaled, get_blank
|
||||
from .WriteHelper import (
|
||||
write_int_8,
|
||||
write_int_16be,
|
||||
write_int_16le,
|
||||
write_int_24le,
|
||||
write_string_utf8,
|
||||
|
@ -23,6 +22,8 @@ FLAG_LONG = 0b10000000
|
|||
PEC_ICON_WIDTH = 48
|
||||
PEC_ICON_HEIGHT = 38
|
||||
|
||||
GROUP_LONG = False
|
||||
|
||||
|
||||
def write(pattern, f, settings=None):
|
||||
pattern.fix_color_count()
|
||||
|
@ -60,6 +61,11 @@ def write_pec_header(pattern, f, threadlist):
|
|||
f.write(b"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20")
|
||||
add_value = current_thread_count - 1
|
||||
color_index_list.insert(0, add_value)
|
||||
assert (
|
||||
color_index_list[0] < 255
|
||||
), "too many color changes, ({0}) out of bounds (0, 255)".format(
|
||||
len(color_index_list)
|
||||
)
|
||||
f.write(bytes(bytearray(color_index_list)))
|
||||
else:
|
||||
f.write(b"\x20\x20\x20\x20\x64\x20\x00\x20\x00\x20\x20\x20\xFF")
|
||||
|
@ -81,10 +87,6 @@ def write_pec_block(pattern, f, extends):
|
|||
write_int_16le(f, int(round(height)))
|
||||
write_int_16le(f, 0x1E0)
|
||||
write_int_16le(f, 0x1B0)
|
||||
|
||||
write_int_16be(f, 0x9000 | -int(round(extends[0])))
|
||||
write_int_16be(f, 0x9000 | -int(round(extends[1])))
|
||||
|
||||
pec_encode(pattern, f)
|
||||
|
||||
stitch_block_length = f.tell() - stitch_block_start_position
|
||||
|
@ -109,23 +111,39 @@ def write_pec_graphics(pattern, f, extends):
|
|||
f.write(bytes(bytearray(blank)))
|
||||
|
||||
|
||||
def encode_long_form(value):
|
||||
value &= 0b0000111111111111
|
||||
value |= 0b1000000000000000
|
||||
return value
|
||||
def write_value(f, value, long=False, flag=0):
|
||||
data = []
|
||||
if not long and -64 < value < 63:
|
||||
data.append(value & MASK_07_BIT)
|
||||
else:
|
||||
value &= 0b0000111111111111
|
||||
value |= 0b1000000000000000
|
||||
value |= flag << 8
|
||||
data.append((value >> 8) & 0xFF)
|
||||
data.append(value & 0xFF)
|
||||
f.write(bytes(bytearray(data)))
|
||||
|
||||
|
||||
def flag_jump(long_form):
|
||||
return long_form | (JUMP_CODE << 8)
|
||||
def write_trimjump(f, dx, dy):
|
||||
write_value(f, dx, long=True, flag=TRIM_CODE)
|
||||
write_value(f, dy, long=True, flag=TRIM_CODE)
|
||||
|
||||
|
||||
def flag_trim(long_form):
|
||||
return long_form | (TRIM_CODE << 8)
|
||||
def write_jump(f, dx, dy):
|
||||
write_value(f, dx, long=True, flag=JUMP_CODE)
|
||||
write_value(f, dy, long=True, flag=JUMP_CODE)
|
||||
|
||||
|
||||
def write_stitch(f, dx, dy):
|
||||
long = GROUP_LONG and -64 < dx < 63 and -64 < dy < 63
|
||||
write_value(f, dx, long)
|
||||
write_value(f, dy, long)
|
||||
|
||||
|
||||
def pec_encode(pattern, f):
|
||||
color_two = True
|
||||
jumping = False
|
||||
jumping = True
|
||||
init = True
|
||||
stitches = pattern.stitches
|
||||
xx = 0
|
||||
yy = 0
|
||||
|
@ -140,33 +158,18 @@ def pec_encode(pattern, f):
|
|||
if data == STITCH:
|
||||
if jumping:
|
||||
if dx != 0 and dy != 0:
|
||||
f.write(b"\x00\x00")
|
||||
write_stitch(f, 0, 0)
|
||||
jumping = False
|
||||
if -64 < dx < 63 and -64 < dy < 63:
|
||||
f.write(bytes(bytearray([dx & MASK_07_BIT, dy & MASK_07_BIT])))
|
||||
else:
|
||||
dx = encode_long_form(dx)
|
||||
dy = encode_long_form(dy)
|
||||
data = [(dx >> 8) & 0xFF, dx & 0xFF, (dy >> 8) & 0xFF, dy & 0xFF]
|
||||
f.write(bytes(bytearray(data)))
|
||||
continue
|
||||
write_stitch(f, dx, dy)
|
||||
elif data == JUMP:
|
||||
jumping = True
|
||||
dx = encode_long_form(dx)
|
||||
dx = flag_trim(dx)
|
||||
dy = encode_long_form(dy)
|
||||
dy = flag_trim(dy)
|
||||
f.write(
|
||||
bytes(
|
||||
bytearray(
|
||||
[(dx >> 8) & 0xFF, dx & 0xFF, (dy >> 8) & 0xFF, dy & 0xFF]
|
||||
)
|
||||
)
|
||||
)
|
||||
continue
|
||||
if init:
|
||||
write_jump(f, dx, dy)
|
||||
else:
|
||||
write_trimjump(f, dx, dy)
|
||||
elif data == COLOR_CHANGE:
|
||||
if jumping:
|
||||
f.write(b"\x00\x00")
|
||||
write_stitch(f, 0, 0)
|
||||
jumping = False
|
||||
f.write(b"\xfe\xb0")
|
||||
if color_two:
|
||||
|
@ -174,11 +177,11 @@ def pec_encode(pattern, f):
|
|||
else:
|
||||
f.write(b"\x01")
|
||||
color_two = not color_two
|
||||
continue
|
||||
elif data == STOP:
|
||||
continue # These will already be processed into duplicate colors.
|
||||
pass # These will already be processed into duplicate colors.
|
||||
elif data == TRIM:
|
||||
continue
|
||||
pass
|
||||
elif data == END:
|
||||
f.write(b"\xff")
|
||||
break
|
||||
init = False
|
||||
|
|
|
@ -1,172 +0,0 @@
|
|||
import pyembroidery.EmbPattern as EmbPattern
|
||||
import math
|
||||
|
||||
|
||||
def distance_squared(x0, y0, x1, y1):
|
||||
dx = x1 - x0
|
||||
dy = y1 - y0
|
||||
dx *= dx
|
||||
dy *= dy
|
||||
return dx + dy
|
||||
|
||||
|
||||
def distance(x0, y0, x1, y1):
|
||||
return math.sqrt(distance_squared(x0, y0, x1, y1))
|
||||
|
||||
|
||||
def towards(a, b, amount):
|
||||
return (amount * (b - a)) + a
|
||||
|
||||
|
||||
def angleR(x0, y0, x1, y1):
|
||||
return math.atan2(y1 - y0, x1 - x0)
|
||||
|
||||
|
||||
def oriented(x0, y0, x1, y1, r):
|
||||
radians = angleR(x0, y0, x1, y1)
|
||||
return (x0 + (r * math.cos(radians)), y0 + (r * math.sin(radians)))
|
||||
|
||||
|
||||
class WriteEncoder():
|
||||
def __init__(self):
|
||||
self.max_jump = float('inf') # type: float
|
||||
self.max_stitch = float('inf') # type: float
|
||||
self.tie_on = False # type: bool
|
||||
self.tie_off = False # type: bool
|
||||
self.needle_x = 0 # type: float
|
||||
self.needle_y = 0 # type: float
|
||||
self.translate_x = 0 # type: float
|
||||
self.translate_y = 0 # type: float
|
||||
|
||||
def set_translation(self, x, y):
|
||||
self.translate_x = x
|
||||
self.translate_y = y
|
||||
|
||||
def jumpTo(self, transcode, x, y):
|
||||
self.step_to(transcode, x, y, self.max_jump, EmbPattern.JUMP)
|
||||
transcode.append([x, y, EmbPattern.JUMP])
|
||||
|
||||
def stitchTo(self, transcode, x, y):
|
||||
self.step_to(transcode, x, y, self.max_stitch, EmbPattern.STITCH)
|
||||
transcode.append([x, y, EmbPattern.STITCH])
|
||||
|
||||
def step_to(self, transcode, x, y, length, data):
|
||||
distance_x = x - self.needle_x
|
||||
distance_y = y - self.needle_y
|
||||
if abs(distance_x) > length or abs(distance_y) > length:
|
||||
stepsX = math.ceil(abs(distance_x / length))
|
||||
stepsY = math.ceil(abs(distance_y / length))
|
||||
if (stepsX > stepsY):
|
||||
steps = stepsX
|
||||
else:
|
||||
steps = stepsY
|
||||
stepSizeX = distance_x / steps
|
||||
stepSizeY = distance_y / steps
|
||||
|
||||
q = 0
|
||||
qe = steps
|
||||
qx = self.needle_x
|
||||
qy = self.needle_y
|
||||
while q < qe:
|
||||
transcode.append([round(qx), round(qy), data])
|
||||
q += 1
|
||||
qx += stepSizeX
|
||||
qy += stepSizeY
|
||||
|
||||
def lock_stitch(self, transcode, lock_x, lock_y, anchor_x, anchor_y):
|
||||
dist = distance(lock_x, lock_y, anchor_x, anchor_y)
|
||||
if dist > self.max_stitch:
|
||||
p = oriented(lock_x, lock_y, anchor_x, anchor_y, self.max_stitch)
|
||||
anchor_x = p[0]
|
||||
anchor_y = p[1]
|
||||
f = (towards(lock_x, anchor_x, .33), towards(lock_y, anchor_y, .33))
|
||||
s = (towards(lock_x, anchor_x, .66), towards(lock_y, anchor_y, .66))
|
||||
self.stitchTo(transcode, lock_x, lock_y)
|
||||
self.stitchTo(transcode, f[0], f[1])
|
||||
self.stitchTo(transcode, s[0], s[1])
|
||||
self.stitchTo(transcode, f[0], f[1])
|
||||
|
||||
def process(self, p):
|
||||
self.needle_x = 0
|
||||
self.needle_y = 0
|
||||
copy = EmbPattern.EmbPattern()
|
||||
EmbPattern.set(p, copy)
|
||||
layer = copy.stitches
|
||||
for stitch in layer:
|
||||
stitch[0] = round(stitch[0] - self.translate_x)
|
||||
stitch[1] = round(stitch[1] - self.translate_y)
|
||||
p.stitches = []
|
||||
p.threadlist = []
|
||||
self.write_code(copy, p)
|
||||
self.write_thread(copy, p)
|
||||
return p
|
||||
|
||||
def write_thread(self, pattern_from, pattern_to):
|
||||
threads_to = pattern_to.threadlist
|
||||
threads_to.extend(pattern_from.threadlist)
|
||||
|
||||
def write_code(self, pattern_source, pattern_dest):
|
||||
source = pattern_source.stitches
|
||||
dest = pattern_dest.stitches
|
||||
flags = EmbPattern.NO_COMMAND
|
||||
trimmed = True
|
||||
for i, stitch in enumerate(source):
|
||||
x = stitch[0]
|
||||
y = stitch[1]
|
||||
flags = stitch[2]
|
||||
if flags == EmbPattern.STITCH:
|
||||
if trimmed:
|
||||
self.jumpTo(dest, x, y)
|
||||
self.needle_x = x
|
||||
self.needle_y = y
|
||||
if self.tie_on:
|
||||
b = source[i + 1]
|
||||
bx = b[0]
|
||||
by = b[1]
|
||||
self.lock_stitch(dest, x, y, bx, by)
|
||||
dest.append([x, y, EmbPattern.STITCH])
|
||||
trimmed = False;
|
||||
else:
|
||||
self.stitchTo(dest, x, y)
|
||||
elif flags == EmbPattern.FRAME_EJECT:
|
||||
if not trimmed:
|
||||
dest.append([self.needle_x, self.needle_y, EmbPattern.TRIM])
|
||||
trimmed = True
|
||||
self.jumpTo(dest, x, y)
|
||||
dest.append([x, y, EmbPattern.STOP])
|
||||
elif flags == EmbPattern.BREAK:
|
||||
if not trimmed:
|
||||
dest.append([self.needle_x, self.needle_y, EmbPattern.TRIM])
|
||||
trimmed = True
|
||||
continue # do not update the needle.
|
||||
elif flags == EmbPattern.BREAK_COLOR:
|
||||
if not trimmed:
|
||||
dest.append([self.needle_x, self.needle_y, EmbPattern.TRIM])
|
||||
trimmed = True
|
||||
dest.append([x, y, EmbPattern.COLOR_CHANGE])
|
||||
continue # do not update the needle.
|
||||
elif flags == EmbPattern.STITCH_FINAL:
|
||||
if self.tie_off:
|
||||
b = source[i - 1]
|
||||
bx = b[0]
|
||||
by = b[1]
|
||||
self.lock_stitch(dest, x, y, bx, by)
|
||||
self.stitchTo(dest, x, y)
|
||||
dest.append([x, y, EmbPattern.TRIM])
|
||||
trimmed = True
|
||||
elif flags == EmbPattern.STITCH_FINAL_COLOR:
|
||||
if self.tie_off:
|
||||
b = source[i - 1]
|
||||
bx = b[0]
|
||||
by = b[1]
|
||||
self.lock_stitch(dest, x, y, bx, by)
|
||||
self.stitchTo(dest, x, y)
|
||||
dest.append([x, y, EmbPattern.TRIM])
|
||||
dest.append([x, y, EmbPattern.COLOR_CHANGE])
|
||||
trimmed = True
|
||||
else:
|
||||
dest.append(stitch)
|
||||
self.needle_x = x
|
||||
self.needle_y = y
|
||||
if flags != EmbPattern.END:
|
||||
dest.append([self.needle_x, self.needle_y, EmbPattern.END])
|
|
@ -1,8 +1,11 @@
|
|||
from .ReadHelper import read_int_32le, signed8
|
||||
from .ReadHelper import read_int_32le, read_int_16le, read_int_8, read_int_24be, signed8
|
||||
|
||||
|
||||
def read_zhs_stitches(f, out):
|
||||
count = 0
|
||||
|
||||
xx = 0
|
||||
yy = 0
|
||||
while True:
|
||||
count += 1
|
||||
b = bytearray(f.read(3))
|
||||
|
@ -10,25 +13,96 @@ def read_zhs_stitches(f, out):
|
|||
break
|
||||
ctrl = b[0]
|
||||
if ctrl == 0x10:
|
||||
# Checksum
|
||||
continue
|
||||
# x
|
||||
x = 0
|
||||
x += b[1] & 0b00000001
|
||||
x += b[2] & 0b00000010
|
||||
x += b[1] & 0b00000100
|
||||
x += b[2] & 0b00001000
|
||||
x += b[1] & 0b00010000
|
||||
x += b[2] & 0b00100000
|
||||
x += b[1] & 0b01000000
|
||||
x += b[2] & 0b10000000
|
||||
x = signed8(x)
|
||||
if x >= 63:
|
||||
x += 1
|
||||
if x <= -63:
|
||||
x -= 1
|
||||
|
||||
# y
|
||||
y = 0
|
||||
y += b[2] & 0b00000001
|
||||
y += b[1] & 0b00000010
|
||||
y += b[2] & 0b00000100
|
||||
y += b[1] & 0b00001000
|
||||
y += b[2] & 0b00010000
|
||||
y += b[1] & 0b00100000
|
||||
y += b[2] & 0b01000000
|
||||
y += b[1] & 0b10000000
|
||||
|
||||
y = signed8(y)
|
||||
if y >= 63:
|
||||
y += 1
|
||||
if y <= -63:
|
||||
y -= 1
|
||||
|
||||
xx += x
|
||||
yy += y
|
||||
if ctrl == 0x41:
|
||||
# Still unmapped.
|
||||
pass
|
||||
x = signed8(b[1])
|
||||
y = signed8(b[2])
|
||||
if ctrl == 0x02:
|
||||
out.stitch(x, y)
|
||||
elif ctrl == 0x02:
|
||||
out.stitch(xx, -yy)
|
||||
xx = 0
|
||||
yy = 0
|
||||
continue
|
||||
if ctrl == 0x01:
|
||||
out.move(x, y)
|
||||
elif ctrl == 0x01:
|
||||
out.move(xx, -yy)
|
||||
xx = 0
|
||||
yy = 0
|
||||
continue
|
||||
if ctrl == 0x04:
|
||||
elif ctrl == 0x04:
|
||||
xx = 0
|
||||
yy = 0
|
||||
out.color_change()
|
||||
continue
|
||||
if ctrl == 0x80:
|
||||
elif ctrl == 0x80:
|
||||
break
|
||||
out.end()
|
||||
|
||||
|
||||
def read_zhs_header(f, out):
|
||||
color_count = read_int_8(f)
|
||||
for i in range(color_count):
|
||||
out.add_thread(read_int_24be(f))
|
||||
length = read_int_16le(f)
|
||||
b = bytearray(f.read(length))
|
||||
thread_data = b.decode('utf8')
|
||||
threads = thread_data.split("&$")
|
||||
try:
|
||||
for i, data in enumerate(threads[1:]):
|
||||
thread = out.threadlist[i]
|
||||
parts = data.split("&#")
|
||||
try:
|
||||
if len(parts[0]):
|
||||
thread.chart = parts[0]
|
||||
if len(parts[1]):
|
||||
thread.description = parts[1]
|
||||
if len(parts[2]) > 3:
|
||||
thread.catalog_number = parts[2][:-2]
|
||||
except IndexError:
|
||||
pass
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
|
||||
def read(f, out, settings=None):
|
||||
f.seek(0x0F, 0)
|
||||
stitch_start_position = read_int_32le(f)
|
||||
header_start_position = read_int_32le(f)
|
||||
f.seek(header_start_position, 0)
|
||||
read_zhs_header(f, out)
|
||||
f.seek(stitch_start_position, 0)
|
||||
read_zhs_stitches(f, out)
|
||||
|
|
|
@ -6,6 +6,8 @@ from .EmbFunctions import *
|
|||
from .EmbMatrix import EmbMatrix
|
||||
from .EmbPattern import EmbPattern
|
||||
from .EmbThread import EmbThread
|
||||
from .EmbCompress import compress, expand
|
||||
import pyembroidery.GenericWriter as GenericWriter
|
||||
|
||||
# items available in a sub-heirarchy (e.g. pyembroidery.PecGraphics.get_graphic_as_string)
|
||||
from .PecGraphics import get_graphic_as_string
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
10
setup.py
10
setup.py
|
@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|||
|
||||
setuptools.setup(
|
||||
name="pyembroidery",
|
||||
version="1.4.28",
|
||||
version="1.4.36",
|
||||
author="Tatarize",
|
||||
author_email="tatarize@gmail.com",
|
||||
description="Embroidery IO library",
|
||||
|
@ -13,13 +13,17 @@ setuptools.setup(
|
|||
long_description_content_type="text/markdown",
|
||||
url="https://github.com/EmbroidePy/pyembroidery",
|
||||
packages=setuptools.find_packages(),
|
||||
classifiers=(
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
"Programming Language :: Python :: 3.6",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
'Topic :: Software Development :: Libraries :: Python Modules'
|
||||
),
|
||||
],
|
||||
)
|
|
@ -59,6 +59,7 @@ class Turtle:
|
|||
}
|
||||
evaluate_lsystem(initial, rules, 3) # 6
|
||||
|
||||
|
||||
def get_big_pattern():
|
||||
pattern = EmbPattern()
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
|
||||
|
@ -131,6 +132,85 @@ def get_shift_pattern():
|
|||
return pattern
|
||||
|
||||
|
||||
def get_shift_stop_pattern():
|
||||
pattern = EmbPattern()
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_command(STOP)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_command(STOP)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "ivory")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "ivory")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_command(STOP)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "ivory")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_command(STOP)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "violet")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_command(STOP)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "white")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "salmon")
|
||||
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
|
||||
pattern.add_command(MATRIX_ROTATE, 22.5)
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "lime")
|
||||
return pattern
|
||||
|
||||
|
||||
def get_simple_stop():
|
||||
pattern = EmbPattern()
|
||||
pattern += (0,0)
|
||||
pattern += (0, 100)
|
||||
pattern += (100, 100)
|
||||
pattern += (100, 0)
|
||||
pattern += (0, 0)
|
||||
pattern.stop()
|
||||
pattern += (0, 0)
|
||||
pattern += (0, 100)
|
||||
pattern += (100, 100)
|
||||
pattern += (100, 0)
|
||||
pattern += (0, 0)
|
||||
return pattern
|
||||
|
||||
|
||||
def get_long_jump():
|
||||
pattern = EmbPattern()
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
|
||||
pattern.add_block([(3000, 3000), (3000, 3100), (3100, 3100), (3100, 3000), (3000, 3000)], "red")
|
||||
return pattern
|
||||
|
||||
|
||||
def get_simple_pattern():
|
||||
pattern = EmbPattern()
|
||||
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestDataCatalog(unittest.TestCase):
|
||||
|
||||
def test_catalog_files(self):
|
||||
for f in EmbPattern.supported_formats():
|
||||
self.assertIn("extensions", f)
|
||||
self.assertIn("extension", f)
|
||||
self.assertIn("description", f)
|
||||
self.assertIn("category", f)
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestColorFormats(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
from pyembroidery import *
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
@ -168,4 +168,34 @@ class TestConverts(unittest.TestCase):
|
|||
self.position_equals(t_pattern.stitches, 0, -1)
|
||||
print("jef->xxx: ", t_pattern.stitches)
|
||||
self.addCleanup(os.remove, file1)
|
||||
self.addCleanup(os.remove, file2)
|
||||
self.addCleanup(os.remove, file2)
|
||||
|
||||
def test_jef_stop_write_simple(self):
|
||||
file = "stop.jef"
|
||||
write_jef(get_simple_stop(), file)
|
||||
s_pattern = read_jef(file)
|
||||
self.assertEqual(s_pattern.count_stitch_commands(STOP), 1)
|
||||
self.assertEqual(s_pattern.count_color_changes(), 0)
|
||||
self.addCleanup(os.remove, file)
|
||||
|
||||
def test_jef_stop_write_large(self):
|
||||
file = "stop2.jef"
|
||||
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)
|
||||
|
||||
write_jef(pattern, file)
|
||||
f_pattern = read_jef(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)
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
from pyembroidery import *
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
@ -168,4 +168,9 @@ class TestConverts(unittest.TestCase):
|
|||
self.position_equals(t_pattern.stitches, 0, -1)
|
||||
print("pes->xxx: ", t_pattern.stitches)
|
||||
self.addCleanup(os.remove, file1)
|
||||
self.addCleanup(os.remove, file2)
|
||||
self.addCleanup(os.remove, file2)
|
||||
|
||||
def test_write_pes_long(self):
|
||||
file1 = "long.pes"
|
||||
write_pes(get_long_jump(), file1)
|
||||
self.addCleanup(os.remove, file1)
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
from pyembroidery import *
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestDataPreservation(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestEmbpattern(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestEmbpattern(unittest.TestCase):
|
||||
|
@ -110,4 +110,4 @@ class TestEmbpattern(unittest.TestCase):
|
|||
from pyembroidery.EmbEncoder import Transcoder
|
||||
encoder = Transcoder()
|
||||
encoder.transcode(pattern, pattern)
|
||||
self.assertNotEquals(len(pattern.stitches), 0)
|
||||
self.assertNotEqual(len(pattern.stitches), 0)
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
|
||||
from test.pattern_for_tests import *
|
||||
from pyembroidery import GenericWriter
|
||||
|
||||
|
||||
class TestConverts(unittest.TestCase):
|
||||
def test_generic_write_stitch(self):
|
||||
file1 = "convert.dst"
|
||||
file2 = "convert.txt"
|
||||
self.addCleanup(os.remove, file1)
|
||||
self.addCleanup(os.remove, file2)
|
||||
pattern = get_fractal_pattern()
|
||||
pattern.write(file1)
|
||||
|
||||
pattern = EmbPattern(file1)
|
||||
|
||||
EmbPattern.write_embroidery(
|
||||
GenericWriter,
|
||||
pattern,
|
||||
file2,
|
||||
{
|
||||
"segment_start": "\t\t",
|
||||
"segment_end": "\n",
|
||||
"segment": "{cmd_str} {x},{y}",
|
||||
"stitch": "Stitch: {x},{y}",
|
||||
"jump": "Jump {x},{y}",
|
||||
"trim": "Trim: {x},{y}",
|
||||
"color_change": "Color-Change: {x},{y}",
|
||||
"block_start": "\t{{\n",
|
||||
"block_end": "\t}}\n",
|
||||
"color_start": "[\n",
|
||||
"color_end": "]\n",
|
||||
},
|
||||
)
|
||||
print("write generic: ", file1)
|
||||
|
||||
def test_generic_write_gcode(self):
|
||||
gcode_writer_dict = {
|
||||
"scale": (-0.1, -0.1),
|
||||
"pattern_start": "(STITCH_COUNT: {stitch_total})\n"
|
||||
"(THREAD_COUNT: {color_change_count})\n"
|
||||
"(EXTENTS_LEFT: {extents_left:.3f})\n"
|
||||
"(EXTENTS_TOP: {extends_top:.3f})\n"
|
||||
"(EXTENTS_RIGHT: {extends_right:.3f})\n"
|
||||
"(EXTENTS_BOTTOM: {extends_bottom:.3f})\n"
|
||||
"(EXTENTS_WIDTH: {extends_width:.3f})\n"
|
||||
"(EXTENTS_HEIGHT: {extends_height:.3f})\n"
|
||||
"(COMMAND_STITCH: {stitch_count})\n"
|
||||
"(COMMAND_COLOR_CHANGE: {color_change_count})\n"
|
||||
"(COMMAND_TRIM: {trim_count})\n"
|
||||
"(COMMAND_STOP: {stop_count})\n"
|
||||
"(COMMAND_END: {end_count})\n",
|
||||
"metadata_entry": "({metadata_key}: {metadata_value})\n",
|
||||
"thread_entry": "(Thread{thread_index}: {thread_color} {thread_description} {thread_brand} {thread_catalog_number})\n",
|
||||
"stitch": "G00 X{x:.3f} Y{y:.3f}\nG00 Z{z:.1f}\n",
|
||||
"color_change": "M00\n",
|
||||
"stop": "M00\n",
|
||||
"end": "M30\n",
|
||||
}
|
||||
file1 = "file-gcode.gcode"
|
||||
file2 = "file-generic.gcode"
|
||||
pattern = get_fractal_pattern()
|
||||
pattern.fix_color_count()
|
||||
EmbPattern.write_embroidery(
|
||||
GenericWriter,
|
||||
pattern,
|
||||
file2,
|
||||
gcode_writer_dict,
|
||||
)
|
||||
pattern.write(file1)
|
||||
f1 = open(file1, "rb").read()
|
||||
f2 = open(file2, "rb").read()
|
||||
self.assertEqual(f1, f2)
|
||||
self.addCleanup(os.remove, file1)
|
||||
self.addCleanup(os.remove, file2)
|
|
@ -3,7 +3,7 @@ from __future__ import print_function
|
|||
import unittest
|
||||
|
||||
from pyembroidery import *
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestInterpolate(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestJson(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestOverloads(unittest.TestCase):
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# from __future__ import print_function
|
||||
#
|
||||
# import random
|
||||
# import unittest
|
||||
#
|
||||
# from EmbCompress import expand, compress
|
||||
#
|
||||
#
|
||||
# class TestReadHus(unittest.TestCase):
|
||||
#
|
||||
# def test_fake_compression(self):
|
||||
# for i in range(10):
|
||||
# s = random.randint(10, 100000)
|
||||
# test_bytes = bytearray(random.getrandbits(8) for _ in range(s))
|
||||
# compressed_bytes = compress(test_bytes)
|
||||
# uncompressed = bytearray(expand(compressed_bytes, len(test_bytes)))
|
||||
# self.assertEqual(test_bytes, uncompressed)
|
|
@ -3,7 +3,7 @@ from __future__ import print_function
|
|||
import unittest
|
||||
|
||||
from pyembroidery import *
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
|
||||
|
||||
class TestTrims(unittest.TestCase):
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import print_function
|
|||
|
||||
import unittest
|
||||
|
||||
from pattern_for_tests import *
|
||||
from test.pattern_for_tests import *
|
||||
from pyembroidery import *
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue