pyembroidery

repository·main·Indexed 43 days ago

https://github.com/embroidepy/pyembroidery

A Python library for reading, writing, and converting various embroidery file formats. It provides a robust API for managing stitches, threads, and metadata via the EmbPattern object, supporting low-level machine commands and middle-level pattern abstractions. Features include support for geometric transformations, thread/needle change encoding, and utility exports to CSV, JSON, PNG, and SVG.

Tokens
4.4K
Snippets
11
Records
19
Agent score
6%

What's inside pyembroidery

  1. Overview of the pyembroidery workflow

    main

    The library follows a specific data flow for reading, writing, and converting embroidery files. The core data structure is the EmbPattern object.

    Data Flow Models

    • Read: File $\rightarrow$ Reader $\rightarrow$ Pattern (An EmbPattern is created from a file object/stream).
    • Write: Pattern $\rightarrow$ Encoder $\rightarrow$ Pattern $\rightarrow$ Writer $\rightarrow$ File (The encoder ensures data is coherent for the specific writer/format).
    • Convert: File $\rightarrow$ Reader $\rightarrow$ Pattern $\rightarrow$ Encoder $\rightarrow$ Pattern $\rightarrow$ Writer $\rightarrow$ File (A full round-trip conversion).

    Key Components

    • Reader: Parses files and populates an EmbPattern with metadata, threads, and stitches.
    • EmbPattern: The central object containing all pattern data.
    • Encoder: Converts low-level and middle-level commands into a format suitable for the writer. It can be called directly on a pattern using .get_normalized_pattern() to return a new, encoded pattern without modifying the original.
  2. Handle thread and needle changes in pyembroidery

    main

    The library distinguishes between COLOR_CHANGE and NEEDLE_SET commands to accurately represent different machine behaviors (e.g., Barudan machines).

    Command Encoding

    Commands can encode specific needle or thread information using a bit-packed format: 0bnnnnnnnnttttttttcccccccc where:

    • n = needle encoding
    • t = thread encoding
    • c = command encoding

    Middle-level Commands

    • SET_CHANGE_SEQUENCE: Used to preset the thread change sequence. For example, encode_thread_change(SET_CHANGE_SEQUENCE, 17) makes the first color change switch to the thread at index 17 in the threadlist, after which subsequent changes follow the standard order (index 0, 1, 2, etc.).
    • COLOR_BREAK: Can be used to encode desired thread change orders.

    Implementation Note

    To parse these complex commands, use the helper functions in EmbFunctions.py: encode_thread_change and decode_embroidery_command. If information is unknown (e.g., a DST file that doesn't support color info), the value will be returned as unknown thread, unknown needle.

  3. Understand the pyembroidery coordinate system and units

    main

    Units

    • The core unit is 1/10th mm.
    • While you can use floating-point numbers, fractional values may be lost when writing to certain formats. pyembroidery attempts to maintain precision by encoding relative distances as integer changes from the last integer position.

    Coordinate System

    • Orientation: The +y direction is down and -y is up (when viewed horizontally). +x is right and -x is left. This matches modern graphics systems.
    • Origin: All patterns start at the origin (0,0).
    • Centering: Because absolute positioning is maintained, an off-center pattern will stay at its absolute position. Use pattern.move_center_to_origin() to center the pattern at (0,0), though this will lose the original absolute position data.
    • Interfacing: pyembroidery automatically flips the y-axis when reading from or writing to embroidery formats (except SVG) to ensure seamless interfacing.
  4. How to manipulate patterns and threads

    main

    Patterns support several Pythonic manipulation methods:

    • Appending Patterns: Use += to add one pattern to another (pattern1 += pattern2).
    • Adding Stitches: Append coordinate tuples directly (pattern += ((0,0), (20,20))).
    • Adding Color Changes: Use pattern += "color_name" to add a color change and update the threadlist.
    • Metadata: Access or set metadata via dictionary syntax (pattern['name'] = "My Design").
    • Thread Editing: Modify colors via the .threadlist attribute using .color or .set_hex_color("#RRGGBB").
    # Append patterns
    pattern1 += pattern2
    
    # Add a color change
    pattern1 += "red"
    
    # Append specific stitches
    pattern1 += ((0,0), (20,20), (0,0))
    
    # Set metadata
    pattern1['name'] = "My Design"
    
    # Edit thread color
    pattern1.threadlist[0].set_hex_color("#RRGGBB")
  5. Understand the EmbPattern data structure

    main

    An EmbPattern object is composed of three primary elements:

    1. stitches: A list of lists. Each inner list contains three elements: [x, y, command].
      • x and y are absolute locations.
      • command is an integer. For best practices, commands should be referenced by name from EmbConstant.py and masked using stitch[stitch_index][2] & COMMAND_MASK to isolate the lower 8 bits.
    2. threadlist: A list of EmbThread class objects. This acts as a reference table for thread information. If not explicitly specified, the threadlist is used in the order provided. Usually, one thread is provided for each color change.
    3. extras: A dict used to store metadata (e.g., file labels) or internal graphics (e.g., 1-bit images in PEC files) that are not part of the raw stitch data.
  6. Use versions for machine-specific file control

    main

    The get_supported_formats() method returns format information that includes a versions element. This contains a tuple of values that can be passed to the settings dictionary as {'version': <version_name>}.

    This allows for fine-grained control over specific file versions, such as the extended header in DST or specific versions like 6 or 6t in the PesWriter. This is the intended method for delivering machine-specific files or different command structures (like Gcode).

  7. How to stabilize or normalize a loaded pattern

    main

    When you load a pattern from a file, it is filled with raw basic stitch data. To make this data easier to work with or to prepare it for specific operations, you should use one of the following methods:

    • get_stable_pattern(): Creates a new pattern by iterating through the current pattern's stitchblocks and re-adding them. This results in a pattern without raw jumps or trims, making it a clean series of stitches and breaks.
    • get_pattern_interpolate_trim(): Introduces trim commands after a series of JUMP commands as specified and merges untrimmed jumps.
    • get_as_stitchblock(): A generator that produces stitch blocks from the raw loaded data.
    • get_pattern_merge_jumps(): Returns a pattern where all sequences of JUMP are replaced with a single STITCH_BREAK command, allowing the encoder to produce optimized jumps.

    Note: Calling get_normalized_pattern() is done automatically during the write process. Saving a pattern to disk does not modify the original pattern object; it writes a modified version to the file.

  8. Compose an embroidery pattern with EmbPattern

    main

    To create an embroidery pattern from scratch, instantiate an EmbPattern object. You can add stitches using absolute coordinates, relative coordinates, or by adding blocks of coordinates. Once the pattern is composed, use write_dst (or other format-specific write functions) to save it to a file.

    Common methods for adding data include:

    • add_block(coordinates, color): Adds a sequence of points as a single block.
    • add_stitch_relative(command, dx, dy): Adds a stitch relative to the current position.
    • add_stitch_absolute(command, x, y): Adds a stitch at an absolute coordinate.
    • add_command(command): Adds a positionless command (like TRIM or COLOR_CHANGE).

    Note: When using add_command, the command is treated as positionless. If you add a command that includes x and y operands, behavior is undefined. Internally, elements are stored as [x, y, command] to facilitate position usage, but the API expects command, x, y (or just command).

    from pyembroidery import *
    
    # Create a new pattern
    pattern = EmbPattern()
    
    # Add a square block of stitches in red
    pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
    
    # Save the pattern to a DST file
    write_dst(pattern, "file.dst")
  9. Use shorthand commands for pattern composition

    main

    For common embroidery operations, pyembroidery provides shorthand methods that wrap add_stitch_relative. These are often more readable than calling the low-level constants directly. You can omit dx and dy parameters if the position should not change (e.g., for thread trimming or color changes).

    Available shorthand methods:

    • pattern.stitch(dx, dy)
    • pattern.trim()
    • pattern.color_change()
    pattern.stitch(dx, dy)
    pattern.trim()
    pattern.color_change()
  10. Read embroidery patterns from disk

    main

    To load an embroidery pattern, use pyembroidery.read(filename). The library automatically detects the correct reader based on the file extension. For specific formats, you can use discrete reader functions like read_dst, read_pes, or read_exp.

    Note on IO Errors: Starting in version 1.5.0, pyembroidery raises explicit IOError if a writer is unsupported or a file does not exist, rather than failing silently.

    import pyembroidery
    
    # Load using extension detection
    pattern = pyembroidery.read("myembroidery.exp")
    
    # Load using specific reader
    pattern = pyembroidery.read_dst(file)
  11. Write embroidery patterns to disk

    main

    To save a pattern, use pyembroidery.write(pattern, filename). You can also use discrete writer functions (e.g., write_dst, write_svg, write_png) which do not rely on file extensions to determine the format.

    Supported utility formats include .csv (lossless), .json (interchange), .png (image), .txt (lossy text), and .svg (vector).

    # Standard write
    pyembroidery.write(pattern, "myembroidery.dst")
    
    # Discrete writers
    pyembroidery.write_svg(pattern, file)
    pyembroidery.write_png(pattern, file)
    pyembroidery.write_csv(pattern, file)