EmbroidePy / pyembroidery

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

What is the difference between EmbroidePy / pyembroidery and inkstitch / pyembroidery #95

Open apfz opened 3 years ago

apfz commented 3 years ago

I am writing custom software for which I want to use pyembroidery.

Could you briefly explain the difference between the two libraries EmbroidePy / pyembroidery and inkstitch / pyembroidery? I am not immediately seeing which one I should use.

Thanks in advance!

tatarize commented 3 years ago

You should use this one, mostly because it is maintained. It's also available on pypi. And I'm happy to correct anything you find and make it easier to use. I actually have the expertise to correct any issues, and do usually right away.


I wrote all of pyembroidery, both forks. There was a falling out a few years ago after I made some constructive criticism about a misunderstanding he had about animation. Lex's feelings were hurt and he escalated the situation to permibanning me. He didn't want to deal with me so he has an older fork with a couple fewer formats and a couple extra bugs. (You can read the affair if you'd like, #1).

I tend to every so often check the issues on inkstich for anybody with a format issue and them correct them here. @kaalleen usually comes by a while later to fix what's needed, from that. It's a bit hamfisted and completely unneeded game of telephone. But, even in the best of times that version is quite behind the one here.

apfz commented 3 years ago

Thanks for the clarification!

I am trying to write a webapplication (reactjs with nodejs backend) that can convert svg into pes files. Could you perhaps guide me a little bit on how I could to this? I would really appreciate that.

And well done btw for making and sustaining this library

tatarize commented 3 years ago

How in depth? I mean if you wanted a pretty basic doing of that, I wrote a top notch svg reader and parser and pyembroidery so you could run this little code fragment and you'd find all those path commands converted.

import glob

from pyembroidery import *
from svgelements import *

for svg_file in glob.glob("*.svg"):
    svg = SVG(svg_file)
    pattern = EmbPattern()
    for element in svg.elements(transform="scale(%f)" % (254.0 / 96.0)):
        if isinstance(element, Shape):
            element = Path(element)
        if isinstance(element, Path):
            for subpath in element.as_subpaths():
                subpath = Path(subpath)
                distance = subpath.length(error=1e7, min_depth=4)
                segments = int(distance / 20.0)
                points = [subpath.point(i / float(segments)) for i in range(int(segments))]
                points = [(p.x, p.y) for p in points]
                pattern.add_block(points, subpath.stroke)
    PyEmbroidery.write(pattern, svg_file + ".pes")

That'd do that basic request. Quickly load a svg, grab the path commands and write the strokes as stitches. Done.

Somebody clearly is using pyembroidery for some online service stuff ( https://htmtopdf.herokuapp.com/embroidery/ ) which is actually quite nice and clearly works.

There's a lot more such things could do. PES actually have a component for the shapes themselves. At least some of the shapes are actually loaded up as PES objects, within the format. Rect, Circle, bunch of other objects. In theory some of those could be converted over and used directly in the PES. It was part a project a few years back with reverse engineering PES. ( https://edutechwiki.unige.ch/en/Embroidery_format_PES ). It ( https://github.com/frno7/libpes ) was never completed but Josh (of Embroidermodder) parsed out most of the stuff for the higher order format. And, no file ever found in the wild ever had any higher level PES objects.

If your intent is to do some fills and such, I do have plans to write some code to do that eventually but none of it exists just yet. Which means filled in svg objects wouldn't register as anything. So depending on the intended depth of your attempt there's a lot of stuff that could be done.

( Also, wrote this up on kinda a lark, a while back. https://jsfiddle.net/Tatarize/sL8z1vmh/ )

apfz commented 3 years ago

That's really interesting. I have to dive in to the provided code a bit to better understand it, im sure I can figure it out. The javascript part is also really good, I'll have a look at it too.

So basically I am trying to replicate inkstitch in a web app as a hobby project for my wife's embroidery business. We make our designs in illustrator and export an svg to inkstitch. Inkscape is too slow to work with, and therefor looking to code something up myself. So yes, im looking at how any shape (filled and outline) from SVG can be converted to PES.

Regarding the fill stitches, would you say that in ink stitch it should be coded somewhere how filled polygons and curved, filled shapes are converted as it seems to be working there?

tatarize commented 3 years ago

Yeah, the code behind the fill stitches in inkstitch is pretty easy to duplicate. Conceptually it's a pathing heuristics with some two-opt code, where you assemble the fills to be eulerian paths and reduce them rather quickly. It makes a lot easier methodology than the split and merge nodes and tatsumi fills in most embroidery software. I was planning on doing something somewhat directly on image objects. My first move in embroidery software was for my brother's company https://www.photoembroidery.com/ which converts photos into embroidery. There's a lot of people who use it to run logos and I was thinking I could write a dirtier and easier version to make logo fills. And make people less inclined to use the photoembroidery software for that stuff which it's not really made for (it does embroidery replicas of full color images).

Currently I'm working on laser cutting software (https://github.com/meerk40t/meerk40t) but I'm planning on moving some of the concepts there over to embroidery. And thus the eventual plan implement fills rather natively. I think a lot of the design choices Lex made for inkstitch were generally wrong. I see why they were made but, it would be a lot better off with a system more like what you're talking about. It's the reason why, when offering to help, I jumped at lowest level backend stuff that would be more broadly useful to everybody who wanted to get into Embroidery by solving a lot of the formatting issues.

tatarize commented 3 years ago

I had implemented my own Eulerian fill algorithm a year or two ago, for some proprietary software I write (Touch Embroidery for Android). So I ported it over to python since I'm planning at some point to make an open source embroidery program with that code.

https://github.com/meerk40t/meerk40t/commit/f927f6cf8188f8ff7e656e892e36347271b21155

>>> from CutPlanner import *
>>> fill = EulerianFill(2)
>>> fill.get_fill([Point(0,0), Point(50,50), Point(100, 0)])
[Point(2,2), Point(98,2), Point(96,4), Point(94,6), Point(6,6), Point(8,8), Point(92,8), Point(90,10), Point(10,10), Point(12,12), Point(88,12), Point(86,14), Point(14,14), Point(16,16), Point(84,16), Point(82,18), Point(18,18), Point(20,20), Point(80,20), Point(78,22), Point(22,22), Point(24,24), Point(76,24), Point(74,26), Point(26,26), Point(28,28), Point(72,28), Point(70,30), Point(30,30), Point(32,32), Point(68,32), Point(66,34), Point(34,34), Point(36,36), Point(64,36), Point(62,38), Point(38,38), Point(40,40), Point(60,40), Point(58,42), Point(42,42), Point(44,44), Point(56,44), Point(54,46), Point(46,46), Point(48,48), Point(52,48), Point(50,50), Point(50,50), Point(50,50), Point(52,48), Point(54,46), Point(56,44), Point(58,42), Point(60,40), Point(62,38), Point(64,36), Point(66,34), Point(68,32), Point(70,30), Point(72,28), Point(74,26), Point(76,24), Point(78,22), Point(80,20), Point(82,18), Point(84,16), Point(86,14), Point(88,12), Point(90,10), Point(92,8), Point(94,6), Point(96,4), Point(4,4), Point(2,2), Point(98,2), Point(2,2)]

It relies a bit on the svgelements Point code, and some functions in there. But, has the needed early work to implement the algorithm. It should work a few orders of magnitude faster than inkstitch, I write the code with some custom designed algorithms that will dwarf the other methods. I put it in the dev branch of MeerK40t it takes an angle and a distance between scanlines. Since I needed to view the results. Select an item in the 0.6.3 branch and type: "embroider 20deg 1mm" and it would replace that shape with an embroidery.

The need generally is to parse svg find anything with a fill and fill that shape. Which isn't too hard to do once the algorithm is down.

In don't actually know inkstitch does with satin stitches etc, or how they'd be defined in some dropped in svg. I generally am planning to write my own software, in part because the the idea of defining a bunch of stuff in svg and 'calling that embroidery' is wildly limiting. It rather needs a bunch of shapes and paths and you specify how to fill each of them on the fly and in what order, and that's kinda something you can piggyback in inkscape but it isn't that great. Also, there's need to look at the actual outputting embroidery itself and altering it, like adding sequins etc.

tatarize commented 3 years ago

@apfz If you still care, I wrote vpype-embroidery ( https://github.com/EmbroidePy/vpype-embroidery ) and vpype-vectrace ( https://github.com/tatarize/vpype-vectrace ). These things combined can totally do either of those. It's entirely possible to use efill within vpype-embroidery to fill svg shapes. It's a pretty streamlined system there. With vectrace you can trace some image files people might have laying around since it will do the basic vector path from raster creation stuff.

apfz commented 3 years ago

Very interesting! This is going to be really helpful. Thank you for tagging me here.