EmbroidePy / pyembroidery

pyembroidery library for reading and writing a variety of embroidery formats.
MIT License
181 stars 33 forks source link

PES (or PEC) writer introduces additional stitches #112

Closed SReich-EMI closed 3 years ago

SReich-EMI commented 3 years ago

Dear all, I'm quite new to pyembroidery, so I hope it's not a stupid question. I produce pes-files with inkstitch and wanted to modify them with pyembroidery. In this process I recognised, that just by reading and saving a pes-file, the writer introduces additional stitches. Once it adds TRIMs bevore JUMPs and also new STITCHEs after the JUMPs. I have an example, where I see four more stitches each time I open and save the file:

`

pin = r'C:\temp'
input_files = os.path.join(pin, 'Test_InkStitch.pes')

for i in range(10):
    pattern = pyembroidery.read(input_files)
    print(np.array(pattern.stitches).shape)

    plt.figure()
    plt.plot(np.array(pattern.stitches)[:,2],'o')
    plt.xlim(0, 20)
    plt.show()

    plt.figure()
    plt.plot(np.array(pattern.stitches)[:,0],'o')
    plt.plot(np.array(pattern.stitches)[:,1],'o')
    plt.xlim(0, 20)
    plt.show()

    pyembroidery.write(pattern, os.path.join(pin, 'Test_InkStitch_{0}.pes'.format(str(i))))

    input_files = os.path.join(pin, 'Test_InkStitch_{0}.pes'.format(str(i)))

` Here is the test-file, however I think this should happen with all files. Test_InkStitch.zip

Until it runs through the stitches in PecWriter.pec_encode() the number of stitches is the same, so I think it happens when really writing the data.

Is this a bug, or is there any explanation, why this happens?

Kind regards Stefan

tatarize commented 3 years ago

Though I haven't checked the exact issue here, it's likely not a bug. Some encoding schemes actually require additional things to work. It often interpolates extra stitches in places during the normalization process.

You should be able to duplicate this more directly with get_normalized_pattern() which will transcode outside of the save routine.

All the different writing formats have different requirements and needs so some need trims, others jump with implied trims etc. These can be adjusted and tweaked as needed. But, mostly it will allow changes of the exact stitches in order to make sure it's in a format that can be read correctly for the given format. CSV defaults that stuff to off since it can write lossless data.

While a bit of an older version inkstitch uses pyembroidery to write this stuff out to begin with.

--

If it's repeatedly adding additional trims and stitches when it would have already trimmed it might be in error and could be fixed in the transcoder to better record the state.

tatarize commented 3 years ago

The 4 additional stitches are a tie off. Go ahead and turn the tieoffs off if your work already has tie-offs.

pyembroidery.write(pattern, file.dst, { "tie_on": CONTINGENCY_TIE_ON_NONE, "tie_off":CONTINGENCY_TIE_OFF_NONE}

I used to be worse at python. Modernly I'd put all that stuff properly in kwarg, and keep it backwards compatible.

tatarize commented 3 years ago

They should be off by default. I'd guess it's trims or something.

tatarize commented 3 years ago

stitch-editor

Looks like it's adding a stitch at the very start from when I checked it specifically in EmbrodePy. It's an extra stitch being interpreted there. And seems to be in error. In theory after a JUMP in pes, it needs to stitch at the final location, but it's not looking ahead and seeing it already has that there. So it's adding it each time since PES requires that stitch.

Sometimes formats stitch means "go x,y; stitch." and sometimes it means "stitch; go x,y" In the latter case a JUMP followed by a stitch would stitch first at the end point of the stitch command. So if the intent is to put a stitch at the first point it overtly adds one.

tatarize commented 3 years ago

Okay, it's an issue between read and write somehow. The encoding is doing its job correctly.

tatarize commented 3 years ago

https://github.com/EmbroidePy/pyembroidery/blob/d52b213b3dfebfef77b896fd3d68fb82e62108b8/pyembroidery/PecWriter.py#L137

The jumping is still set and it writes a stitch to get out of the jump mode there. It should have realized that dx and dy being zero in a stitch would clear the jumping anyway or force the jump clear on every stitch correctly.

tatarize commented 3 years ago
import os

import numpy as np
from matplotlib import pyplot as plt
from pyembroidery import EmbPattern

pin = "."

input_files = os.path.join(pin, 'Test_InkStitch.pes')

for i in range(10):
    pattern = EmbPattern(input_files)
    print(np.array(pattern.stitches).shape)

    plt.figure()
    plt.plot(np.array(pattern.stitches)[:, 2], 'o')
    plt.xlim(0, 20)
    plt.show()

    plt.figure()
    plt.plot(np.array(pattern.stitches)[:, 0], 'o')
    plt.plot(np.array(pattern.stitches)[:, 1], 'o')
    plt.xlim(0, 20)
    plt.show()

    input_files = os.path.join(pin, 'Test_InkStitch_{0}.pes'.format(str(i)))
    pattern.write(input_files, full_jump=False, tie_on=None)

Seems properly stable now. It won't multi-interpolate that stitch now.

tatarize commented 3 years ago

Doesn't really need the full_jump or tie_on, it's just a bug in the writer.

Published 1.4.27

SReich-EMI commented 3 years ago

Thanks a lot for the fast reply and fixing of hte bug. Is there any complete documentation of the PES-file available? Then I maybe could also help in fixing and improving. In Python I'm familiar only EmboidePy is new for me.

tatarize commented 3 years ago

@SReich-EMI This is pretty complete:

https://edutechwiki.unige.ch/en/Embroidery_format_PES

Took a bit to write it. But, it's solid. Some work by JoshVarga is well worth looking at too. Though a lot of the stuff is pointless since you're building the PES block for the Brother Editor not really for the machine which only checks the lookup, and finds the pec block and follows the commands in that.

tatarize commented 3 years ago

Also: https://jsfiddle.net/sL8z1vmh/ is worth looking at for some PES stuff since it made a point to parse everything in the PES file even the EmbRect objects. If you actually want to get into the nitty gritty of the format. Which I hope pyembroidery makes unneeded since it parses everything for you and should work.

More helpful than format work though if you see anything that's hard to use about my API it would be solid if you'd point that out and what you would have expected for an API.