Giter Club home page Giter Club logo

pyembroidery's Introduction

EmbroidePy

wxPython embroidery viewer based on pyembroidery. Loads up and natively accesses the embroidery.

embroiderypy

Installing

pip install embroidepy

Then to run:

embroidepy

pyembroidery's People

Contributors

ali-sajjad-rizavi avatar aurishhammadhafeez avatar b01ana avatar luzpaz avatar sreich-emi avatar tatarize avatar yuyueshihaoren avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyembroidery's Issues

Hus Writer

I write the HUS reader after reimplementing what is basically ARJ compression. There are likely a few cheats to perform the compression operations the easiest of which is likely to write that the first 256 elements are 8 bits long and the last 256 characters are never used. Then every 8 bits will equal a character equal to the byte. We can then just dump the uncompressed data and it will be sent through the decompressor unscathed. The alternative is actually searching the 1k window and building the actual frequency trees etc. Having studied the code to build mine up from nothing. This should have no issues since the decompression routine is unable to care and only checks for tree validity.

Thread __str__ TypeError: not enough arguments for format string

for s in pattern.get_as_stitchblock(): thread = s[1]; print(thread)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/andreymal/.local/lib/python3.7/site-packages/pyembroidery/EmbThread.py", line 150, in __str__
    return "EmbThread %s %s" % self.description, self.hex_color()
TypeError: not enough arguments for format string

Import and Export Json.

There's a python builtin json so the implementation is basically done. There's certainly going to be some applications that could use such things.

DST extends data is not accurate.

The extends data properly should be the amount in mm rather than 1/10 mm. So the values should be divided by 10 for +X, -X, +Y, -Y and the AX and AY values are entirely able to be calculated as the distance in 1/10th mm the start location is from the end location.

Question about COLOR_BREAK and COLOR_CHANGE

Hello!

I'm tring to add stitch blocks with different thread colors to an EmbPattern and later retrieve them again as color blocks, e.g. like this:

>>> from pyembroidery import EmbPattern
>>> pattern = EmbPattern()
>>> stitches_1 = [[0,1],[2,3]]
>>> stitches_2 = [[4,5],[6,7]]

>>> pattern.add_block(stitches_1, 0xFF0000)
>>> pattern.add_block(stitches_2, 0x0000FF)

Now when I call pattern.get_as_colorblocks(), I would expect to get two separate color blocks. But I get only a single block:

>>> blocks = pattern.get_as_colorblocks()
>>> print(len(list(blocks)))
1

>>> blocks = pattern.get_as_colorblocks()
>>> block = next(blocks)
>>> print(block)
([[0, 1, 0], [2, 3, 0], [0, 0, 226], [4, 5, 0], [6, 7, 0], [0, 0, 226]], <pyembroidery.EmbThread.EmbThread object at 0x10b1a7ed0>)

The function add_block automatically appends the COLOR_BREAK [0, 0, 226] after the stitches of each block. But the function get_as_colorblocks only splits the blocks at COLOR_CHANGE or NEEDLE_SET. Is this the intended behavior?

I also tried adding a COLOR_BREAK manually between the blocks:

>>> pattern.add_block(stitches_1, 0xFF0000)
>>> pattern.color_change()
>>> pattern.add_block(stitches_2, 0x0000FF)

But this has the effect that the color of the second block is skipped and the second block gets a random third color. This is visible in the exported vp3 file and seems logical, because the COLOR_CHANGE is directly after the COLOR_BREAK and both commands go to the next thread color.

Do you have a suggestion how to add stitch blocks and later retrieve them from the EmbPattern?

What is the difference between COLOR_CHANGE and COLOR_BREAK? Could get_as_colorblocks maybe also split at COLOR_BREAK?

I'm using the pyembroidery version 1.4.12

DMCA and the CSD format, omission.

The CSD reader exists in libembroidery but was not ported over or utilized in this product because it contained an encryption scheme. By definition bypassing encryption violates DMCA.

In PyEmbroidery add the supported format:

    yield ({
        "description": "Singer / Poem",
        "extension": "csd",
        "mimetype": "application/x-csd",
        "category": "embroidery",
        "reader": CsdReader,
    })

And the reader:

from EmbThread import EmbThread
from .ReadHelper import read_int_8

CsdSubMaskSize = 479
CsdXorMaskSize = 501

_subMask = [0] * CsdSubMaskSize
_xorMask = [0] * CsdXorMaskSize

_decryptArray = [
    0x43, 0x6E, 0x72, 0x7A, 0x76, 0x6C, 0x61, 0x6F, 0x7C, 0x29, 0x5D, 0x62, 0x60, 0x6E, 0x61, 0x62, 0x20,
    0x41, 0x66, 0x6A, 0x3A, 0x35, 0x5A, 0x63, 0x7C, 0x37, 0x3A, 0x2A, 0x25, 0x24, 0x2A, 0x33, 0x00, 0x10,
    0x14, 0x03, 0x72, 0x4C, 0x48, 0x42, 0x08, 0x7A, 0x5E, 0x0B, 0x6F, 0x45, 0x47, 0x5F, 0x40, 0x54, 0x5C,
    0x57, 0x55, 0x59, 0x53, 0x3A, 0x32, 0x6F, 0x53, 0x54, 0x50, 0x5C, 0x4A, 0x56, 0x2F, 0x2F, 0x62, 0x2C,
    0x22, 0x65, 0x25, 0x28, 0x38, 0x30, 0x38, 0x22, 0x2B, 0x25, 0x3A, 0x6F, 0x27, 0x38, 0x3E, 0x3F, 0x74,
    0x37, 0x33, 0x77, 0x2E, 0x30, 0x3D, 0x34, 0x2E, 0x32, 0x2B, 0x2C, 0x0C, 0x18, 0x42, 0x13, 0x16, 0x0A,
    0x15, 0x02, 0x0B, 0x1C, 0x1E, 0x0E, 0x08, 0x60, 0x64, 0x0D, 0x09, 0x51, 0x25, 0x1A, 0x18, 0x16, 0x19,
    0x1A, 0x58, 0x10, 0x14, 0x5B, 0x08, 0x15, 0x1B, 0x5F, 0xD5, 0xD2, 0xAE, 0xA3, 0xC1, 0xF0, 0xF4, 0xE8,
    0xF8, 0xEC, 0xA6, 0xAB, 0xCD, 0xF8, 0xFD, 0xFB, 0xE2, 0xF0, 0xFE, 0xFA, 0xF5, 0xB5, 0xF7, 0xF9, 0xFC,
    0xB9, 0xF5, 0xEF, 0xF4, 0xF8, 0xEC, 0xBF, 0xC3, 0xCE, 0xD7, 0xCD, 0xD0, 0xD7, 0xCF, 0xC2, 0xDB, 0xA4,
    0xA0, 0xB0, 0xAF, 0xBE, 0x98, 0xE2, 0xC2, 0x91, 0xE5, 0xDC, 0xDA, 0xD2, 0x96, 0xC4, 0x98, 0xF8, 0xC9,
    0xD2, 0xDD, 0xD3, 0x9E, 0xDE, 0xAE, 0xA5, 0xE2, 0x8C, 0xB6, 0xAC, 0xA3, 0xA9, 0xBC, 0xA8, 0xA6, 0xEB,
    0x8B, 0xBF, 0xA1, 0xAC, 0xB5, 0xA3, 0xBB, 0xB6, 0xA7, 0xD8, 0xDC, 0x9A, 0xAA, 0xF9, 0x82, 0xFB, 0x9D,
    0xB9, 0xAB, 0xB3, 0x94, 0xC1, 0xA0, 0x8C, 0x8B, 0x8E, 0x95, 0x8F, 0x87, 0x99, 0xE7, 0xE1, 0xA3, 0x83,
    0x8B, 0xCF, 0xA3, 0x85, 0x9D, 0x83, 0xD4, 0xB7, 0x83, 0x84, 0x91, 0x97, 0x9F, 0x88, 0x8F, 0xDD, 0xAD,
    0x90]


def BuildDecryptionTable(seed):
    mul1 = 0x41C64E6D
    add1 = 0x3039
    for i in range(0, CsdSubMaskSize):
        seed *= mul1
        seed += add1
        seed &= 0xFFFFFFFF
        _subMask[i] = (seed >> 16) & 0xFF
    for i in range(0, CsdXorMaskSize):
        seed *= mul1
        seed += add1
        seed &= 0xFFFFFFFF
        _xorMask[i] = (seed >> 16) & 0xFF


def DecodeCsdByte(fileOffset, val, type):
    if type != 0:
        fileOffsetHigh = fileOffset & 0xFFFFFF00
        fileOffsetLow = fileOffset & 0xFF
        newOffset = fileOffsetLow
        fileOffsetLow = fileOffsetHigh
        final = fileOffsetLow % 0x300
        if final != 0x100 and final != 0x200:
            newOffset = _decryptArray[newOffset] | fileOffsetHigh
        elif final != 0x100 and final == 0x200:
            if newOffset == 0:
                fileOffsetHigh = fileOffsetHigh - 0x100
            newOffset = _decryptArray[newOffset] | fileOffsetHigh
        elif newOffset != 1 and newOffset != 0:
            newOffset = _decryptArray[newOffset] | fileOffsetHigh
        else:
            fileOffsetHigh = fileOffsetHigh - 0x100
            newOffset = _decryptArray[newOffset] | fileOffsetHigh
    else:
        newOffset = fileOffset
    return ((val ^ _xorMask[newOffset % CsdXorMaskSize]) - _subMask[newOffset % CsdSubMaskSize]) & 0xFF


# /*! Reads a file with the given \a fileName and loads the data into \a pattern.
#  *  Returns \c true if successful, otherwise returns \c false. */

def read_csd_stitches(f, out):
    type = 0
    identifier = [0] * 8
    colorChange = -1
    colorOrder = [0] * 14
    for i in range(0, 8):
        identifier[i] = read_int_8(f)

    if identifier[0] != 0x7C and identifier[2] != 0xC3:
        type = 1
    if type == 0:
        BuildDecryptionTable(0xC)
    else:
        BuildDecryptionTable(identifier[0])
    f.seek(8, 0)  # Seek Set
    for i in range(0, 16):
        thread = EmbThread()
        r = DecodeCsdByte(f.tell(), read_int_8(f), type)
        g = DecodeCsdByte(f.tell(), read_int_8(f), type)
        b = DecodeCsdByte(f.tell(), read_int_8(f), type)
        thread.set_color(r, g, b)
        thread.catalogNumber = ""
        thread.description = ""
        out.add_thread(thread)
    unknown1 = DecodeCsdByte(f.tell(), read_int_8(f), type)
    unknown2 = DecodeCsdByte(f.tell(), read_int_8(f), type)

    for i in range(0, 14):
        colorOrder[i] = DecodeCsdByte(f.tell(), read_int_8(f), type)

    while True:
        b0 = DecodeCsdByte(f.tell(), read_int_8(f), type)
        b1 = DecodeCsdByte(f.tell(), read_int_8(f), type)
        b2 = DecodeCsdByte(f.tell(), read_int_8(f), type)

        dx = int(b2)
        dy = int(b1)

        if b0 == 0xF8 or b0 == 0x87 or b0 == 0x91:
            break

        negativeX = ((b0 & 0x20) > 0)
        negativeY = ((b0 & 0x40) > 0)

        if negativeX:
            dx = -dx
        if not negativeY:
            dy = -dy

        b0 &= 0xFF ^ 0xE0

        if (b0 & 0x1F) == 0:
            out.stitch(dx, dy)
        elif (b0 & 0x0C) > 0:
            out.color_change()
            if colorChange >= 14:
                break  # Invalid color change.
            colorChange += 1
        elif (b0 & 0x1F) > 0:
            out.trim()
            out.move(dx, dy)
        else:
            out.stitch(dx, dy)


def read(f, out, settings=None):
    read_csd_stitches(f, out)

COLOR_BREAK at end of pattern still allocates a thread.

The writers count the color changes rather than the threads, but for a few formats it writes the threads to disk and this will have an extra thread that encodes for zero stitches. Post-stitch color breaks should be ignored not just by not calling CHANGE_COLOR but also by not allocating that thread.

Import Commands

hey @tartarize! In the Ink/Stitch project there was a question raised, that I would like to transfer to you, since it also might be interesting for other use cases of pyembroidery.

When we import stitch files as color blocks, we get all the commands as they are written in the embroidery file. Now, that we want to transfer them into the svg representation, we are very interested into a file specific "translation" of the commands (e.g. jump jump jump = trim). I found the 'get_pattern_interpolate_trim' function, which is already very helpful to translate most of the trim commands, but I was wondering, if pyembroidery could deliver a more file-specific result? It would also be nice to have recognition for other commands such as the stop command, etc.

Repr code and api rough edge smoothing.

  • EmbMatrix, EmbPattern, should have proper __repr__ code.
  • The EmbPattern() repr should use the stitch command constants rather than the number values.
  • EmbPattern *= EmbMatrix should transform the pattern by that matrix.
  • There may be some utility to be gained by porting in the Matrix code from svgelements to replace the EmbMatrix. It would make the matrix highly similar to Pillow's needed matrix code form and SVGs. And would get all the fancy code things I worked in there like using matrixible strings.
  • EmbPattern() should work, in part, as an interface bit of code for loading and saving filenames. (EmbPattern('my_embroidery.dst') * 'scale(2)').write('my_convertedembroidery.vp3')

With a proper *args, **kwargs erasure for EmbPattern the example write code:

from pyembroidery import *
pattern = EmbPattern()
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
write_dst(pattern, "file.dst")

Could easily become.

from pyembroidery import *
pattern = EmbPattern([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red").write('file.dst')

None of this would need breaking changes.

Some software cannot load DST->VP3. Sometimes.

While the VP3 software properly loads the files, some conversions from DST to VP3 do not properly align up. This needs to be investigated.

Wilcom does not properly load the file. Whereas Premier+ 2 does.

For a directly converted DST file.

Merge two patterns

I am having trouble merging two pes files.

The idea is to load them separtly, translate some of them, and then merge them together.
Is it possible to do that ?

Add in Color Formats.

Many formats lack colors and some have assistance files that only contain colors. While the forced checking and reading of these file formats might be beyond the scope of pyembroidery. I don't actually care where the filestream comes from a disk or the internet and it's not really the projects job to know this. It is the case that these helper formats exist and should be readable and often writeable.

I believe these to be EDR, INF, COL for the major ones. Since reading the format will leave the colors in these blank and it'll just invent colors when it needs them later (and only in a lossless manner), it should just allow reading a format that only adds colors and does nothing else. This should just work.

converted png does't get proper thread

hello, I have convert .dst file to png but that png files threads(Stitching Point) are not getting properly how can i get proper png file (with proper stitching point)

Trims do not work in pyembroidery when written from Ink/Stitch

I have a Husqvarna viking Topaz 50 machine, which does trims. When doing designs in inkstitch exported through pyembroidery, my trims does not work as I expect (they do not trim at all).

Free version of Premier (Husqvarna/Pfaff embroidery software), tells me there are no trims in the generated vp3 file. The free version of truesize e4, tells me there are only two trims in the vp3 file (a file with two colors).

Saving to formats like dst or pes, generates the trims as expected.

The issue is also described in Ink/Stitch ( #inkstitch/inkstitch#495). Enclosing a zip file containing a number of files to give details outline cat face p0.0-006.zip

The files are described below, and contain information on the difference when using Premier/trueview or going through pyembroidery.

  • The inkscape svg file which contains the design, as done with inkscape and Ink/Stitch (done more or less from scratch, however, the paths are imported from a drawing done in illustrator). That does not seem to have ill effects.
  • The vp3 file as created by Ink/Stitch (outline cat face p0.0-006.vp3). It does not manage to convince my embroidery machine to do any trimming, neither does it make Wilcom truesize believe it should.
  • A screen dump of Wilcom truesize interpretation of the vp3 file created by Ink/Stitch (Wilcom truesize interpretation of InkStitch vp3 file.PNG). It seem to accurately describe all trims not occuring (color changes are trimmed, but they are always trimmed independent on what commands the vp3 file contains, so likely not due to a trim command in Ink/Stitch vp3 file)
  • The dst file created by Ink/Stitch. It convinces Wilcom truesize that there are trim commands defined in the file, just as claimed by Ink/Stitch.
  • The vp3 file created by taking the Ink/Stitch dst file into Wilcom truesize, and export as a vp3 file (outline cat face p0.0-006 wilcom from dst.VP3). That vp3 file, according to Wilcom, does contain a number of the wanted trim commands (not all of the ones defined from the beginning in the dst file, but many). It convinces my embroidery machine to trim the thread in many of the wanted places. Side note: Taking the Ink/Stitch vp3 file and saving from Wilcom truesize as vp3 does not produce any visible trims. It does add one extra line, likely a start thread, so something is missing in the vp3 file as saved by Ink/Stitch.
  • A wilcom truesize screen dump of its interpretation of the vp3 file Wilcom truesize created using the Ink/Stich dst file (Wilcom truesize interpretation of InkStitch dst file saved as vp3 with lines.png). With lines showing the differences between Wilcom truesize view, and final results on the embroidery machine:
  • Wilcom was almost right. There is an extra start thread it expects, which does not show up (encircled in black in the screen dump). Wilcom expects same extra thread when just saving the InkStitch vp3 file using Wilcom truesize. Likely something I have extra in my svg file.
    Three threads which are not trimmed, although Wilcom expects them to be (shown as three black lines on the screen dump). One up in top left corner of the eye, and two connecting to and from the nose.

Jef trim on machines.

inkstitch/inkstitch#374 suggests there is a failure to trim for some Jef outputs. The comparison chart for the 400E and 500E says there are "Programmable Jump Thread Trimming". ( http://www.sewvacdirect.com/content/Comparison%20Chart%20400E%20vs%20500E.pdf )

Auto says anything longer than 3mm is trimmed. But, manual, suggests there is a read trim points from the program is an option.

  1. Cutting Command.
    When this option is turned on, the machine trim the threads at the trim code if the imported stitch data file contains a trim command (cutting command).

If these points exist, pyembroidery does not acknowledge them. It assumes all the jumps are going to be cutting for reading, and treats them as such. Has 0x80 0x02 as move/jump and 0x80 0x01 as color change. In effect it treats all jef commands in the Easy method. Cutting after all color changes.

The embroideryware EW3lines.jef. Tries to do 0x80 0x02 (0,0) 0x80 0x02 (x,y) at the start then between the different stitch block does. 0x80 0x01 (0,0) 0x80 0x02 (0,0) 0x80 0x02 (x,y). This formatting is not seen in Janome's software which does these elements as `0x80 0x01 0x80 0x02 (x y).

If that is an example of a trim command. Then a trim command is equal to a jump command of zero distance.

@jameskolme could you test this theory? Or have any way to produce a file with trims and another without from the same hopefully Janome source.

The relevant file is 3chevptrims. 3chevptrims has 0x80 0x02 without any distance as trims. The other files are 3chevj which is a janome produced file, 3chevw which is wilcom produced, and 3chevp which is pyembroidery produced (without attempting any trim coding).

jef trims.zip

If it works, the changes needed to fix are quite minimal:

  • Add an option to switch between these modes for reading and writing in jef.
  • When manual mode: Write a zero distance move as a trim for saving.
  • Read a zero distance move as a trim for loading.

Assuming my speculation there is correct, which would need to be proven.

Export PES has no trims.

inkstitch/inkstitch#689

@ursus-kirk -- To the best of my knowledge there are no trims within the PES format.

        elif data == TRIM:
            continue

If you have an example of the format performing such an operation independent of a long jump, I would like to see such a file.

Rendering

Can this module render supported embroidery files to JPG/PNG?

CSV is not valid.

The CSV is a holdover from Embroidermodder but the changes to columns and extra spaces are not actually valid CSV formatting.

Test files not included

Hello - This is a question more than an issue - I'm new to python and interested in learning embroidery formats. I thought a good way for me to better understand both would be to debug through the tests in this project, but it doesn't seem like the test files are included. Am I missing them, or can I download them from somewhere?

Thanks!
Jared

Transcode (object, object) malforms.

The use of transcode(my_emb, my_emb) seems pretty straightforward but causes an infinite loop as it fails. Needs to offload the data, clear it and copy it back into the class when "source is destination".

pyembroidery cannot read vp3 files with true trims in them

When reading a vp3 file which contains true trims (trims which are not only a colour change), pyembroidery reads it wrong. This is also mentioned in Ink/Stitch (inkstitch/inkstitch#516)

As can be seen in below picture, a lot is missing. Both stitches and colours. To the left is Premier, to the right is the interpretation by Ink/Stitch (pyembroidery):
Artboard 1

Enclosed are the files behind above views, containing the example, of a vp3 file which is fully readable in both Wilcom TrueSizer and Premier. But not in Ink/Stitch. It is collected as a zip (vp3 with trim.zip):

  • vp3 file with trims that work in vp3 (outline cat face p0.0-006 wilcom from dst.VP3)
  • screendump of how it looks in Premier, Husqvarna vp3 reading software (outline cat face with trims in vp3 read by Premier.PNG)
  • screendump of how it looks in Ink/Stitch, reading using pyembroidery (outline cat face with trims in vp3 read by InkStitch.PNG)

The example above is linked to the issue previously mentioned, #68 so the main stitch file is the same. One reason for this seem to be pyembroidery Vp3Reader. It assumes that all end points in a vp3-file is the end of the color_block, even if it is stated that there are more stitches in that colour block. A simple remedy is to remove that assumption (in vp3_read_colorblock remove the return following after the out command in "elif y == 0x03:". Doing that reads all the trimmed stitches into pyembroidery. Unfortunately, now the trims are missing (ignore the colour difference, my mistake):

output from inkstitch after removing return in vp3reader

Import complex numbers are coordinate data.

I had generally assumed in several places that coordinate data would be c[0], c[1] or c.x c.y but it turns out some projects like mathandy/svgpathtools use an interesting trick where they call x the real part and y is the imag part of a complex number. Using the native x, i coordinate field within complex numbers as x,y.

Edge Condition: rounding out of write permitted range.

Turns out there's a couple ways the encoder and writer can exceed the permitted range. It is entirely possible to have something like -0.5 -> 99.5 -> 199.5 while range limited to never exceed 100 units. Since this is correctly within that range it is permitted. However, because these round to -1, 100, 200 when rounded they can end out rounding outside the permitted range. To combat this, I added a ROUND parameter for writers that rounds the incoming values. So -1, 100, 200 are used early in the encoding and it correctly then subdivides that first stitch-gap.

It is however, still an open question if it can be coaxed into exceeding the range because the interpolated stitches are rounded. Can subdivided integer positions fall on the half-unit in such a way that rounding it off that half-unit position causes it to exceed the range?

edr palette format

I'm not sure. but the last color in the palette is used as the background color.
it’s mostly white and in the palette it’s ffffff00

Saving as DST and PES does not product the same results

When I save the same pattern in DST and PES, I don't see the same result.

Most of the times for dst files there is a wire who go from the center to the first stitch.
Here an example, the first image is a dst file and the second one is a pes file. They were saved from the same pattern.
CaptureDst
CapturePES

Also, sometimes, the pes file is not centered even I use "move_center_to_origin". Here an another example :
CapturePositionDST
CapturePositionPES

Is there something I should do differently depending on the format ?

EDIT : I am not sure if the issue is with pyembroiderdy or if Wilcom True Sizer is not displaying correctly the files ...

.dst (Embroidery) to .png conversion

I have converted .dst file to png format but it showing different colors always.
not showing original colors.

--------------code

import sys
import pyembroidery
import uuid

unique_filename = str(uuid.uuid4())

api_link = sys.argv[1]

filename = "../img/customized-images/"+unique_filename+".png"

pyembroidery.convert(api_link, filename, {"encode": False})

print(unique_filename+".png")

---------code end

HUS format writing

I've mapped out most of the formatting. I can actually read the format currently. However, that is done with copyrighted code, so that's a non-starter. Well, deobfuscated and ported code still properly derived from a copyrighted source, still a non-starter. I still need to study the code to figure out precisely what it's doing so I write the functionality without using any of Robert Jung's code, also time is no longer a thing that matters to compress a few k of bytes, so modern code might be faster. It also means I might cheat and not do a lot of compression searching, since the code is ultimately LZSS I could, in theory, just give everything in its direct character formulation. The bit he had a patent (now expired) on is actually kinda cryptic. And the format itself bears a lot of similarity to zip-DEFLATE. The ARJ compression is a lot like ZIP-deflate but also had an expired patent to do with hash tables for the huffman coding which is in the code here, which was licensed to Greenleaf (with slightly different values and a smaller sliding window) which belonged to a guy, who sold it to a guy, then died, who then died. I think the rights, if there are any belong to a personal trainer in Texas. Since the patent is expired and wouldn't cover the formatting anyway the way to write this is to solve how the formatting works and just code up that part. Especially as most of the underlying workings are pointless. It just needs to produce something compatible.

G-Code, Embroidermodder .TXT

@jameskolme If you actually need that sort of formatting it's not that hard to add. The old .txt was an export from Embroidermodder which I neglected to port. If you'd use G-code instead I'd have to know what commands you used for that. There's not a 1 to 1 for embroidery as such. But, the actual command structure is pretty easy to follow.

+Xxx writer.

Adding in an Xxx writer. Apparently they are the only accepted format for Singer Quantum xl-6000 and kind of need exporting for my app. Also, was already a thing in libembroidery even though clearly a couple of the numbers are off.

"Singer Quantum XL-6000, .XXX file on Singer Compatible design card, Cable to computer connection"

@supertobi inkstitch/pyembroidery#69 I added .xxx writer but I likely need a check as to whether the resulting files sew.

butterfly.zip

Though there's clearly some other elements that need to be conveyed.

Phc Load Issue.

@mgua I checked the load issue you posted in inkstitch/pyembroidery#68 and it does seem to be a real issue. Odds are good I move around the file in some invalid way that is exposed by the later version but held true for Phc version 1.

1.3.0 Breaking Corrections

Convert OPTION_ENABLE_TIE_ON OPTION_ENABLE_TIE_OFF to contingency based settings, allowing for other types of tie ons.

CONTINGENCY_TIEON_NONE
CONTINGENCY_TIEON_THREE_SMALL

CONTINGENCY_TIEOFF_NONE
CONTINGENCY_TIEOFF_THREE_SMALL


Rename:
CONTINGENCY_NONE = 0xF0
CONTINGENCY_JUMP_NEEDLE = 0xF1
CONTINGENCY_SEW_TO = 0xF2

To:
CONTINGENCY_LONGSTITCH_NONE = 0xF0
CONTINGENCY_LONGSTITCH_JUMP_NEEDLE = 0xF1
CONTINGENCY_LONGSTITCH_SEW_TO = 0xF2


Explicit Trim defaults to False.


COLOR_CHANGE gets needle selections.
COLOR_CHANGE = 5
NEEDLE_1 = 0x100
NEEDLE_2 = 0x200
NEEDLE_3 = 0x300
NEEDLE_4 = 0x400
...
NEEDLE_CHANGE_1 = COLOR_CHANGE | NEEDLE_1
NEEDLE_CHANGE_2 = COLOR_CHANGE | NEEDLE_2
NEEDLE_CHANGE_3 = COLOR_CHANGE | NEEDLE_3
NEEDLE_CHANGE_4 = COLOR_CHANGE | NEEDLE_4
...

These should apply both reading and writing. However, simply using & COMMAND_MASK will convert these more specific commands into simple COLOR_CHANGE commands.

PEC read does not properly order the elements.

The correct methodology for PEC reading that the current move is flagged with move or trim. Which is contrary to the required pyembroidery ordering.

These commands are so often causing edge conditions that they might properly need to be split up into their actual required commands. Or provide extra methods that mean stitch_then_move or move_then_stitch. TRIM is read to be move to location then trim, but the trim will have already happened in PEC at that point. That or specify a per command required ordering.

InkStitch Affair (Posterity Record)

I got banned from InkStitch.

Relevant CoC: https://www.contributor-covenant.org/version/1/4/code-of-conduct.html


Lex commented:

I do think there's a clear need for both a stitch count and the ability to move back and forth more precisely in the timeline. The way the simulator is implemented right now, going backward is... not so easy. I think we can do this perhaps by having it take snapshots every X stitches so that it can go back to a previous state, but it may be awhile before we get a chance to implement it.


I replied:

@lexelby

I don't believe that the code is correct if it cannot instantly display the rendering. I'm guessing you're rendering the stuff to a display image or something weird. That is, if you're thinking about snapshots or whatnot. It must be broken in a very slow way. -- I'll add my 'ever-so-helpful-2-cents'... you're doing it wrong. I implemented a timeline stitch simulator for android which is way less powerful than most desktop info and it works seemlessly forward and backwards. From the times I've looked at the stitch simulator, it's pretty clear that flickers a lot between frames and I gotta suggest that the slowness there is not a requirement.
As for the processing I coded up a jfiddle to do this to demonstrate the manner.

https://jsfiddle.net/Tatarize/0bdpuonL/

Drop on an exported CSV and it'll process the generated SVG to add and remove the stitches (note, no attempt is made to make this not suck, it literally regenerates the entire SVG each tick). For ww's sake the info button will give the exact stitch it is currently at, and I made it go forwards and backwards for show. The seek bar is also generally for show, but I couldn't really get it to hook up right.


Lex Replied:

you're doing it wrong

Not helpful and not tactful.

Obviously I'd like to be able to support going forward and backward. The fact that I haven't done it should suggest to you that it's not easy or I'd have done it already. In this case what you aren't taking into account is that the simulator is not a web browser and it can't just render SVG.

Please remember to keep your comments in this community tactful. We have a code of conduct and it's important that we all try to work together in a spirit of cooperation and not competition. For example, in this case, if you suspected I was doing it wrong, a more tactful way to express this would be to ask questions about how it works currently.


I replied:

In this case what you aren't taking into account is that the simulator is not a web browser and it can't just render SVG.

It could be. I mean the print preview is an a web browser rendering an SVG. I hacked up a simulator that will also give @wwderw the exact actual stitch number in a couple hours.

But, it's also clear that there's something wrong at the core with how you're doing this if you cannot do this instantly and in real time. There's no software package today that couldn't render that stuff in real time. The flicker, for example, is because the canvas is erasing the background and redrawing it. You catch that and stop it from wasting that time (self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase)) in that giant flicker and you're telling me that passing the paint routine a subset of points cannot be real time?

I swear I've messed with various canvases from rendering my own by implementing Bresenham's line drawing and Wu's algorithms directly on bitmaps and android and little javascript canvases both Canvas and SVG. They can all draw a large set of lines quite rapidly when you hand them the lines. There is nothing that should be faster about running it by inefficiently implementing svg changes (by deleting the entire svg and recreating it each tick) in javascript in a web browser that should be faster than a pretty raw rendered windows.

My comment there is honest, this cannot be correctly done. There's some rather easy and fundamental flaw that, when identified and rectified will make everything significantly better. If you can't do this thing, you must be doing it wrong. Find that bug and you suppose things like snapshots going backwards or something. wx cannot possibly be that slow, it has double buffering and GL.


Lex Replied:

I'm going to tell you again: the way you're going about talking about this is offensive and I need you to stop. This is not a competition and you don't need to prove that I'm doing it wrong. I need you to assume good intent and skill on my part and assume that if I haven't done it the way you're saying, there is probably a good reason for that. Approach the conversation on that footing. I've already given suggestions about how to get across what you're saying without being offensive.

If you say "you're doing it wrong" or similar again, I will temporarily suspended your commenting privileges. This is your last warning. Please understand that I appreciate the contributions that you've made to our project but I can't allow behavior like this to continue.


(3 hours later)
I replied:

You are not your code. I am not at all making any personal comments about you. I categorically do not mean "doing it wrong" to be a pejorative. I do stuff wrong all the time. I mean to say that what you are saying should not actually be the case. I would never speak ill of you or anybody here, I do not make personal comments about people. My comment should not be construed as doing that. It was not my intent to be offensive. It's not intended as a pejorative. I'm not trying to one-up you are make some kind of dig at you or your code. I'm telling you that, with considerable expertise in a lot of canvas technologies, it categorically must be the case that it can do that. There's no canvas technology today that could should be unable to do this.

Here I'll prove it.

[EDITED TO REMOVE CODE WITHOUT LICENSE]

Attached you'll find a standalone python script (requires pyembroidery, wx), a nice little PES file, and in a directory go ahead and run the script with that file. You'll get the same a wx window that will (with some flickering), run the simulation backwards and unstitch everything and do so in real time without any caching (adapted from https://wiki.wxpython.org/DoubleBufferedDrawing ). It must be doable if I can do it. So when you say it can't be done that way you *******************.


I replied, again:

Here, takes the example stitch as the default stitch. Gets rid of the flicker. Adds menu items to set Forwards and Backwards so you can switch them on the fly.

[EDITED TO REMOVE CODE WITHOUT LICENSE]


Lex replied,

@tatarize, I'm suspending your access to the Ink/Stitch organization for 1 week.

I warned you that saying "you're doing it wrong" or similar again would result in a suspension. Asterisks won't help you here; your intent was clear.

Our code of conduct contains the following items relevant to this discussion:

Being respectful of differing viewpoints and experiences
Gracefully accepting constructive criticism
Focusing on what is best for the community
Showing empathy towards other community members

I'll add some responses to what you've said, but none of the following should be construed as an opportunity to appeal the decision to suspend you:

It was not my intent to be offensive.

Intent is irrelevant. I expressed the fact that I found your comments offensive and at that point empathy would suggest that you should stop whether you agree it is offensive or not. There was plenty of opportunity at that point to discuss better ways to communicate to avoid offense.

Here I'll prove it.

Being right is no excuse for rude behavior. I'll also remind you that our similar conversation regarding the fill algorithm (with similar offensive behavior) resulted in your discovery that your assumptions were incorrect.

So when you say it can't be done

I never said that it could not be done in my comment.

One final note: again, I appreciate your contributions to this community. However, I want it to be known that being a valued contributor does not excuse one from abiding by the code of conduct.

Please take the next week to consider what's happened here, as I will. If you decide to resume interaction in this community, I truly hope that we can converse in a way that avoids offense on either side. Let's try to work together to make that happen.

As a reminder, as per the code of conduct, if anyone would like to discuss this situation, please feel free to reach out to me at ***********


I emailed:

The CoC is boilerplate anti-harassment. Not anti-'know a bunch of stuff and come off rather pompous'. Telling somebody they are wrong, when they are demonstratively wrong does come off as rather rude, but it's not personal harassment, doxing, or trolling. It's actually constructive.

The CoC doesn't actually say anything negative about making constructive criticisms. Rather it recommends accepting such criticisms gracefully. I've checked into wx enough to see how you were doing it wrong, more than just that you were. Being right does matter, so does providing helpful code that fixes the wrongness.

Your ability to be offended by criticism does not make criticism offensive. Things are not actually offensive just because you can be offended by them. None of it was intended at all as offensive. But, moreover, none of it was about you, it was about how you coded that section. Generally booting people for criticising your work doesn't seem like it's remarkably helpful. None of it was harassing, doxing, abuse, or anything else generally covered by any such Code of Conduct.

You might want to change the CoC from boilerplate anti-harassment to something more akin to don't criticise my work, even if you don't make ad hominem comments, and are right.

--

Though, do me a solid and send this (attached script) to wwderw, Or just throw toss it on pyembroidery as a pull request for him. It loads and saves, simulates forwards and backwards (realtime, no flicker), with pausing and restarting, has a seekbar that can do stitch by stitch incrementation. And has a stitch editor that uses the wx.grid to allow easy editing of all the stitch commands. He can right click, duplicate lines, delete lines, and change the stitch functions he needs to change And export it back again, without going through a csv file


Lex Emailed back:

I've extended your suspension to 30 days. It's irrelevant whether you think you violated the code of conduct. I told you something offended me and you continued


Lex Posted:

In the interest of full transparency:

I've extended the suspension to 30 days after receiving an email from tatarize containing another occurrence of "doing it wrong".

If anyone in the community objects to the way I've handled this situation, I'd really appreciate hearing your thoughts. You can reach out above or post here, whichever you prefer.


I emailed back:

The code of conduct is about calling people names based on their race or ethnicity, doxing them, or sexually harassing them. It is not a document about 'respec-ma-authorta' or being offended by constructive criticism. If you want to ban me because I pointed out that your code is flawed, you can do that. But, don't try to blame the code of conduct for that. It does not say whack people with a big stick when you think they are wrong, especially if they demonstrate they aren't wrong. And then insist they violated the rules that don't exist (given that the rules say you should accept criticism gracefully, and shouldn't insult people's gender or race). And extending such punishments further when they point out that they violated no rule.

Understand the things you find being irrelevant:

  1. Not intending any insult.
  2. Being correct about technical matters.
  3. Not violating the code of conduct.

I do not see how working together constructively would actually work, if you ban me from any contributions for making constructive criticism and then cite the code of conduct that says 'accept constructive criticism gracefully' and extend the ban further when I point this out. I am generally inclined towards gracefully accepting and giving mea culpas. If you'd like to abide by your own CoC, do what's best for the community and accept constructive criticism, I'd be perfectly willing to accept that. If not, go ahead and modify pyembroidery to comment out .phb and .phc and .mit those formats have bugs and without an ability to contribute they likely won't be addressable.


Lex Posted:

Just in case anyone was tempted to use them, I've removed the code links from tatarize's posts above. They have no open source licenses attached and are therefore copyrighted works that we have no permission to use.


I emailed back:

"I've removed the code links from tatarize's posts above." -- Oh, yes, because goodness forbid anybody check and see that I'm right and your code is generally in bad form. Hence the need for suggesting the weird tricks that were obviously going to be pointless if it was done correctly. Also, copyright covers actual text in that particular order. The general outline of how to to do something correctly isn't copyrighted. Especially considering it's how everybody should render that frame. By, you know correctly, rendering frames rather than constructing it piecemeal like your code does for inexplicable reasons.

If you're going to censor the evidence that I was right, and got booted for making true, non-personal statements, could you at least add in a comment to that effect. I mean without the code showing I'm right, just a paragraph about how you got totally butt-hurt about how I said the way you were doing it couldn't possibly be correct and hacked together a fix to every problem in the script in an hour. Though the version there didn't include the fixes for the scaling which are pretty trivial but let your window be anysize and just scales the design to match (another advantage of correctly rendering frames, you can scale the entire design correctly, rather than only future stitches).


At this point started changing the code and sending a new version to pypi. That seemingly looks like a new and updated version.

https://pypi.org/project/pyembroidery2/


I posted
(Full Disclosure, from a different account. This action is actually rather disreputable. I do feel some shame about that. But, I felt more umbridge.)

I'm guessing that ban will be permanent, given the pyembroidery theft

For the record, I would never in anyway mess with the project other than fix bugs. It was/is a labor of love.

Trying to steal it saddens me. I would only gracefully redirect the project to a different home, where I could again continue to contribute to my own project.

Making PyPi look like there's a newer version out there they should use instead seems generally unsavory. Rather than pyembroidery-inkstitch or a different name. You could simply integrate the pyembroidery code into inkstitch or freeze it at a particular version, without uploading somebody else's code to the index. Redirecting people to somewhere else, where issue cannot be resolved seems problematic.

https://pypi.org/project/pyembroidery2/

@kaalleen

What Lex was doing wrong was incrementally building an image by adding one line at a time. One might naively believe that is needed but it's not. GPUs are not CPUs you can send them everything you want them to do, all at once and they will implement that frame. One frame does not take longer than one frame, so long as you make the same number of GPU calls. And you can simply call DrawLines().

Properly done, you clear the image and send it all the lines simultaneously, having preprocessed the lines at the start. It goes much faster, you can get rid of the flicker, you can scale it on the fly (because each frame is independent) and scale it to the window, and you can run the simulator backwards and forwards. I also implemented a seekbar that works effectively. It's all MIT code, so you can just snip out the bits you need. I posted a properly working simulator with a bunch of GUI stuff (by the way use wxGlide to build a gui, rather than doing that by hand).

I'm more annoyed that censoring clearly MIT licensed code, might lead people to continue doing it the wrong way rather than fixing it. I know it needs to be censored because it shows I was right. But, please don't let the project suffer just to defend ego.

https://github.com/EmbroidePy/EmbroidePy will demonstrate the proper way to do those things.
(Under MIT License)

@wwderw I'll make sure to add a sequin injector to the GUI, in a bit. Properly stitch simulation does kind of require iterating through the stitches at the stitch level, so there's no better way to do it than a raw-editing sequin injector code there.

The community code of conduct that says don't insult people's race, ethnicity, or sexual orientation, and to accept criticism gracefully. Not do not criticise people's implementations of things. It says do not be a bigot, not 'respec-ma-authorita' and don't point out when I've goofed.

I would recommend, going forward, that Lex needs to take criticism with more grace (as the CoC suggests). That your ability to be offended at true statements of facts, backed up with demonstrative evidence, with no intended insult or any discussion about you personally is not extremely helpful with regard to community building. Nor is banning people who disagree with you, a reasonable methodology to foster allowing a free exchange of ideas.

For what it's worth man, I forgive you.

I understand that people do take offense at non-offensive things, and they do not want to be wrong about things. ( https://www.youtube.com/watch?v=QleRgTBMX88 ). And once somebody digs their heels in, it's decidedly harder stop. I mean stealing my code and pretending its a newer version for anybody on PyPi is, ironically, the logical conclusion to somebody being correct, and then choosing that hill to die on.

I generally just never make personal comments about people. And work to be productive and helpful, so that if people want to ban me for whatever reasons they won't seem very good reasons. Also, generally I don't much care for threats as such and tend to think any community that would ban people for saying somebody was wrong when, they were, isn't worth the required kowtowing. I always act as if the rules in place are those of a productive open community (which is what the CoC actually is), and then ignore any claims to the contrary. So clearly, if an open community would accept reasonable evidence and truthful constructive criticism, I assume all communities do. Getting banned therefore says more about the community than myself.

You could stop. Not steal my code. Not ban me for saying you were wrong, and pointing out how you were wrong. Actually build an open community that gracefully accepts constructive criticism. You could actually just be a bigger man. I forgive you either way.

With love,
Tatarize.


Lex Replied:

Of course the ban is permanent. Somewhere around your third or fourth increasingly harassing email, I gave up on trying to work this out in a reasonable fashion.

I'm not stealing your code. It's MIT licensed, and I left your copyright notice and your name on it. My goal was to allow Ink/Stitch to continue without my having to continue to interact with you. I get to choose when to draw the line and stop receiving abuse from you.

That said, since the current solution is upsetting to you I'll try to come up with something different.

As you can see, I've edited your comment to paraphrase it, as you've given up your right to an audience in this community. The full comment is available in edit history should anyone like to see it.

Goodbye, and I'm sorry you chose to end our collaboration in this way.


@tatarize was blocked due to repeated violations of several parts of the CoC. The triggering incident occurred in #267 (comment), although there had previously been a pattern of borderline-inappropriate comments in other issues.

His violations were in essence:

  • Repeating (multiple times) an action that a member had expressed was upsetting.
    • Using the phrase "you're doing it wrong" even after being warned.
    • This violates the clause on showing empathy to other members of the community.
    • This resulted in a 7-day suspension.
  • Sending harassing emails to [email protected].
    • This again included "doing it wrong".
  • I replied asking that he please consider pausing for awhile before hitting reply, and asking if we could work things out in a reasonable manner after a break.
    • This resulted in a 30-day suspension.
  • Replying with increasingly offensive and harassing emails.
    • This resulted in a permanent ban.
  • After the above actions, @tatarize posted a final issue using a separate account: #271.

Please don't lie. I give you full permission to publish all my email here in full. If there's harassment in them, that should be properly judged. If you're going to call them harassing and abuse at least demonstrate that claim. Go ahead and publish them (in full) and demonstrate that fact. There was no reply to the 3rd email, and the 4th was in response to your actions to defame me. I feel, perhaps unjustly, that the truth is a valid defense and censoring the fact that I was, in fact, correct seemed to be defamation. To me it looks like I said, a duck is a duck. You took offense and insisted I should empathise with that offense. And I responded with, "but it's a duck" and got banned.

Again, the code of conduct is against fat shaming and being transphobic, it gives empathy as an example of a good behavior. It also gives gracefully accepting criticism as a good behavior.

It did not even occur to me that you could be serious. I cannot even find it in my person to be offended by having somebody point out an error. And, even now, I cannot empathise with that reaction, it doesn't even make logical sense to me. Finding out that I'm wrong about something is the only way I grow as an person. I welcome it. And demonstratively have a track record of overtly admitting to it without hesitation. I do not view it as some kind of competition. I do not view it as showing somebody is wrong makes me somehow better. It is, rather, the only way to grow as a person. I can only accept truthful constructive criticism with grace. So it did not compute that you might not be able to. And, that is, admittedly, an error on my part.

--

My objection to pyemboridery2 is that it represents that as a newer more official project, on the python index. Clearly if somebody looks for a python project that'll seem newer and with some major 2.0.0 overhaul, when the code is identical and or worse. There are clearly ways to keep the code in a maintainable, updatable form, without misrepresenting to would-be users. It's basically done and feels like you're trying to steal the thunder. Especially considering there's no need for any update. It isn't as if you waited until you needed to update something.

PS. I did find your flippant statement "Unless you have a barudan machine then your guess is as good as mine. Let's wait for his answer. " on the pull request #234 insulting. In part because I know the formats inside and out, and I spent a long time telling you explicitly that embroidery machines don't work like that and that they can't work like that, and how they actually work, and correctly parsing @wwderw's statements, and have coded for embroidery machines for more than a decade, and you equated my considerable expertise with a guess. It seemed rather discourteous and dismissive after I spent a long time trying to be helpful, by explicitly correcting that mistake. As if bringing it to your attention repeatedly was caused by dumb luck or a coin flip. And perhaps finally getting through to you, lured me into the false sense of security, that you could accept criticism. That maybe I had earned some understanding that when I say something can't be true, and that if you think it is, you must be doing it wrong, that maybe you might take my expert opinion into consideration rather than plead offense and break out the ban hammer because I had the audacity to demonstrate that I know how GPU accelerated canvases work and that your suggested understanding of their limitations, could not be true. -- You will find the same thing to be true when you switch over to 2-opt as well and away from your kludgy and slow present methods, you really are doing that wrong. And I mean no offense by that.

For what it's worth, it was fun while it lasted. I wish you the best. And if you'd ever reflect on the affair in the future, and see that your actions may not have been entirely appropriate, or even if you didn't, I'd be more than happy to contribute again.

Write SVG version "colorchart".

It might be helpful write a version of SVG that only contains the color information. Basically a stitch chart in SVG. Since SVG has text and color box making capabilities it shouldn't be too hard. And somebody might just have a PES file and want a color_chart or something. And pyembroidery could do that rather easily.

Sequin Eject sequence can exceed max distance.

In a bunch of trimmed jumps if the node is moved significantly away from the others, it will not jump to within the range to plant the sequin causing range error.

TRIM, JUMP, JUMP, JUMP, (too far) SEQUIN_EJECT, JUMP causes an unfixed range error even processed with the encoder.

Pec/Pes STOP for read and write.

With regards to #62, PEC stops can be implemented just as color changes to the same color, because Brother machines stop even when the color change is to the same current color.

This interpolation should be done for the user directly. A preprocess should identify any STOP in a Pes or Pec, duplicate the relevant thread change the stop into a COLOR_CHANGE.

Likewise after the loading of a pec/pes a post-process should identify duplicate colors and replace the relevant COLOR_CHANGE with a STOP.

This methodology is used for PES/PEC but not for other formats like U01 or JEF which actively ignores the color change if it changes colors to the same color.

I have an little problem with the embroidery quality from InkStich ...

Maybe I am really wrong here. But first I like your work you guys done. Sorry my English is not fine and a bit rusted.
I made 744 in Issues but one of the guys wrote me in a pm I should try here my asking ;-)
So to history of the file X3mmY0,2mm45Grad.svg.txt to see in Inkscape download and delete the .txt at the end of the file.
I made a line from X0 Y0 to X+3 than Y+0,2 than X-3 Y+0,2 [mm] and so on = a nice I for embroidery I made the sew up from hand. Do that in InkStitch and all looks fine when exporting JEF or other ... I like re-importing the files in other layer xD.

But than when I change the angel of the I to 45° it start again ... Stitch coordinates don't come at the right position. They are far away.

Same happened if I import any other JEF (or other Format) in InkStitch and save it in same or other sewing format - the points starts moving around ... don't think that is what someone will have. Think @kaalleen can explain my Problem much better.

X3mmY0,2mm45Grad

Non-ASCII DST header is not working: 'utf-8' codec can't decode byte 0xe4 in position 3: invalid continuation byte

See this file: https://andreymal.org/files/emb/дизайн 1.DST

It was created using russian version of Tajima DG/ML by Pulse 14.

pyembroidery can't read this file:

>>> pyembroidery.read_dst('дизайн 1.DST')
  File "pyembroidery/DstReader.py", line 58, in dst_read_header
    header_string = header.decode('utf8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe4 in position 3: invalid continuation byte

The header has a non-ASCII string "дизайн 1" that is actually encoded using ANSI encoding (Windows-1251 for Russia):

>>> print(header.decode('windows-1251'))
'LA:дизайн 1        \rST:   3294\rCO:  0\r+X:  298\r

Could you provide a way to set a custom header encoding for the read_dst function?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.