Porównaj commity

...

71 Commity

Autor SHA1 Wiadomość Data
tatarize 1f8d3e9a53
Merge pull request #159 from EmbroidePy/unittests
Add in unittest/funding info
2023-07-03 04:20:50 -07:00
Tatarize c36428075c Add in unittest/funding info 2023-07-02 23:54:02 -07:00
tatarize 6fd941f4b2
Merge pull request #155 from luzpaz/typos
Fix typos
2022-10-01 21:23:26 -07:00
luz paz a5982a43a1 Fix typos
Found via `codespell-q 3`
2022-10-01 23:34:58 -04:00
tatarize 3d0db61e7a
Merge pull request #147 from aurishhammadhafeez/aurishhammadhafeez-patch-1
Update README.md
2022-06-10 22:05:49 -07:00
Tatarize 93601f80a0 fix thread parse mistake in DstReader 2022-06-10 22:02:10 -07:00
Aurish Hammad Hafeez 830144a6c9
Update README.md
get_as_stitchblocks() mentioned in the README.md is not a function
2022-04-30 05:53:10 +05:00
tatarize 06225f67dd
Merge pull request #146 from EmbroidePy/generic-writer
Import GenericWriter Correctly
2022-04-26 06:51:36 -07:00
Tatarize adaff94bfa Import GenericWriter, version bump 2022-04-26 06:50:18 -07:00
tatarize e8bede8595
Merge pull request #145 from EmbroidePy/generic-writer
Generic writer: Dynamic Segment
2022-04-24 02:29:40 -07:00
Tatarize d47bcffe14 Version bump 1.4.35 2022-04-24 02:26:36 -07:00
Tatarize 0603a9dfc1 GenericWriter: Create scheme for dynamic variable value creation 2022-04-24 02:24:31 -07:00
tatarize a7aea4ec4e
Merge pull request #143 from EmbroidePy/generic-writer
Generic Writer
2022-04-19 01:18:00 -07:00
Tatarize 05cce93713 remove 2.7 python filter_map() 2022-04-19 01:10:46 -07:00
Tatarize c695770956 Non-relative imports 2022-04-19 00:57:06 -07:00
Tatarize 24836e05ec Version Bump 2022-04-19 00:52:53 -07:00
Tatarize 766737422d correct tupleness 2022-04-19 00:51:06 -07:00
Tatarize 34a317ddcc update test code for gcode writing test 2022-04-19 00:49:36 -07:00
Tatarize bb763735ce Update tests to duplicate gcode writing 2022-04-19 00:45:40 -07:00
Tatarize 60de6fc829 Small changes to support gcode duplication 2022-04-19 00:45:02 -07:00
Tatarize a3c1d54092 Improve/add document statistics 2022-04-19 00:04:45 -07:00
Tatarize 0057a10b5b Add tests as package. Correct import 2022-04-19 00:03:45 -07:00
Tatarize 0acd1e5fa9 Add metadata and thread entry values 2022-04-19 00:02:53 -07:00
Tatarize 285abccd1d Correct opening/closing orders 2022-04-19 00:02:15 -07:00
Tatarize 8f9a27b354 Merge remote-tracking branch 'origin/master' into generic-writer 2022-04-18 22:52:39 -07:00
Tatarize 114230900c Use format_map rather than format() 2022-02-01 04:43:03 -08:00
tatarize b11b77a8cb
Merge pull request #138 from EmbroidePy/readme-colors
Include section on thread info manipulation
2022-01-04 08:17:14 -08:00
Tatarize cc556e66ea Include section on thread info manipulation 2022-01-04 08:15:47 -08:00
Tatarize 057ec2af30 Generic Writer (incomplete) 2021-12-31 22:51:43 -08:00
Tatarize 7ff2b30480 Test for keys in `supported_formats`. 2021-12-20 19:39:43 -08:00
Tatarize a31c4d3b9b Version Bump 1.4.33 2021-12-20 19:34:27 -08:00
tatarize 9bc10c7d87
Merge pull request #135 from B01ana/B01ana-patch-1
Add missing 'extensions' key for ZHS
2021-12-20 19:32:04 -08:00
B01ana ce657b04b6
Add missing 'extensions' key for ZHS
Add missing 'extensions' key for ZHS in supported_formats dictionary
2021-12-20 14:30:13 +02:00
tatarize e13ec9e6df
Merge pull request #134 from EmbroidePy/ZHS
Version Bump 1.4.32
2021-12-20 02:28:49 -08:00
Tatarize 6b66a19a2f Version Bump 1.4.32 2021-12-20 02:25:36 -08:00
tatarize 86f10396d7
Merge pull request #131 from EmbroidePy/ZHS
Zhs Reader
2021-12-20 02:19:44 -08:00
Tatarize afc12fd44d Restore bytearray() usage 2021-12-20 01:53:34 -08:00
Tatarize 377ade47e8 Add long write test 2021-12-20 00:53:09 -08:00
Tatarize ee4250a2b0 Simplify and correct PEC writer 2021-12-20 00:52:37 -08:00
Tatarize e81d925047 First set of bytes is just a long_form stitch 2021-12-19 23:31:47 -08:00
Tatarize 7a53628bfa Correct writer for Pec.
First set of bytes is just a jump
2021-12-19 22:41:20 -08:00
Tatarize 06724d38bb Merge branch 'master' into ZHS
# Conflicts:
#	pyembroidery/ZhsReader.py
2021-12-19 20:07:49 -08:00
Tatarize 4dc7c71ac2 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	pyembroidery/EmbPattern.py
#	pyembroidery/ZhsReader.py
2021-10-01 09:12:20 -07:00
Tatarize f7fdefe4a1 Include ZHS Reader 2021-09-30 03:01:16 -07:00
Tatarize 2bcbfffe1b Correct Pec Reader, offset is 4 bytes earlier, and that is a jump command that should be loaded. 2021-09-30 02:59:47 -07:00
tatarize 9091ef4bcc
Remove Debug Code 2021-07-25 23:38:31 -07:00
tatarize 3ce5ff40f5
Version Bump 2021-07-25 23:38:08 -07:00
tatarize 8ce7dbdea8
Merge pull request #127 from EmbroidePy/1.4.30
Zhs Corrections, Implementation
2021-07-25 23:31:57 -07:00
tatarize 7cf247e8a6
Update README.md 2021-07-25 23:26:50 -07:00
tatarize 43447a749e
Version Bump 2021-07-25 23:17:10 -07:00
tatarize 3d032cc43b
Edge Condition Signed Value
Corrects a mangling bug.
2021-07-25 23:09:46 -07:00
tatarize ec5bf0c46f
ZhsColors 2021-07-25 17:15:01 -07:00
tatarize 81a780f2ee
Zhs Reader Improvements 2021-07-25 09:06:01 -07:00
tatarize d3f1d2bdf2
Zhs Corrections, Implementation 2021-07-25 07:36:00 -07:00
Tatarize 24a11c648d Semi Functional Zhs reader. 2021-07-25 07:27:02 -07:00
tatarize ec1c1544a6
disable hus test 2021-03-04 19:08:53 -08:00
tatarize 0da26fcbdc
Merge pull request #116 from EmbroidePy/issue115
Jef ColorCount Bug
2021-03-04 18:45:11 -08:00
Tatarize a1c34b1203 Integrate Version 2021-03-04 18:42:35 -08:00
tatarize 9cda28598f
Merge pull request #120 from EmbroidePy/master
import changes
2021-03-04 18:35:24 -08:00
Tatarize 36c25da083 Correct final JefReader issues. 2021-03-04 18:31:19 -08:00
Tatarize 6208a25eb3 Partially Done 2021-03-04 18:06:08 -08:00
tatarize e23708fec3
Merge pull request #118 from SReich-EMI/patch-2
corrected insert_stitch_relative
2021-03-04 17:42:00 -08:00
tatarize ef3b78b27a
Merge pull request #117 from SReich-EMI/patch-1
check for number of color changes overflow
2021-03-04 17:31:22 -08:00
SReich-EMI f1a6903484
corrected insert_stitch_relative
there were the commands for the new stitches hard coded to TRIM, so that nothing else could be made irrespective of the input tot the function
2021-03-04 21:42:50 +01:00
SReich-EMI 94771e3dd8
check for number of color changes overflow
added assert error if the number of color changes is aboth 255 as this is not possible.
2021-03-04 21:39:46 +01:00
Tatarize b887fd4610 Version Bump 2021-03-03 06:14:55 -08:00
Tatarize 048fd6710e Correct JefWriter x2
Correct HusTest x2
2021-03-03 05:54:48 -08:00
Tatarize 0e8519ed48 Correct JefWriter
Correct HusTest
2021-03-03 05:48:22 -08:00
tatarize 10e8d68df7
Jef ColorCount Bug
inkscape/inkscape#905
EmbroidePy/pyembroidery#115
2021-03-03 05:40:15 -08:00
Tatarize 61122b9c74 Create test_read_hus.py 2021-03-02 17:20:18 -08:00
Tatarize 816afa9ed8 git-sync 2021-03-02 17:10:11 -08:00
41 zmienionych plików z 2836 dodań i 1987 usunięć

1
.github/FUNDING.yml vendored 100644
Wyświetl plik

@ -0,0 +1 @@
github: [tatarize]

73
.github/workflows/unittests.yml vendored 100644
Wyświetl plik

@ -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

Wyświetl plik

@ -1,6 +1,6 @@
language: python
python:
- "2.7"
- "3.6"
- "3.9"
script:
- python -m unittest discover test
- python -m unittest discover test

Wyświetl plik

@ -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.

Wyświetl plik

@ -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

Wyświetl plik

@ -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"),

Wyświetl plik

@ -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()

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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])

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -1 +0,0 @@

Wyświetl plik

@ -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'
),
],
)

0
test/__init__.py 100644
Wyświetl plik

Wyświetl plik

@ -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")

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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):

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):

Wyświetl plik

@ -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 *