Skip to content
Appliqué Maker

What 225 real embroidery files taught us about PES, DST and VP3

Parsing 225 real-world PES, DST, JEF, VP3, XXX and PCS files: the PEC block every PES shares, DST trims as three jumps, VP3 without jumps, XXX's 12.4 mm trap, and more.

5 min read · Published September 29, 2026

Before shipping a writer for seven embroidery formats we wanted to read files that machines had actually accepted. So we collected 225 of them: files from Brother, Janome, Viking, Pfaff and Tajima users, purchased marketplace designs, and output from a dozen digitizing programs. Every one was parsed, its stitches, jumps, trims and colour changes counted, and compared to what its own header claimed. Here is what the pile taught us, format by format. The file formats guide has the reference version.

PES: ten versions, one stitch block

PES has been through versions 1 to 10, and the differences are almost all in the front of the file: design metadata, the object records that Brother's own software uses for editing, the thread list (from version 5 the thread entries can carry a name, code and brand instead of only an index into Brother's 64-colour palette). The stitches themselves live in a PEC block at the end, and that PEC block is the same structure in every version we saw, from a version 1 file made in 1998 to a version 10 file made in 2025.

That has a practical consequence: a reader that parses the PEC block and ignores everything before it opens every PES we have, and a machine only ever reads the PEC block. Version differences matter for editing software, not for stitching. It is also why our PES writer emits a minimal front section and a correct PEC block, and why a PES from us is byte-identical to the same stitch list written by pyembroidery.

PEC: a jump needs a needle-down before the next stitch

PEC encodes a jump as a flagged long move, and the encoding needs a stitch record at the landing point before the next stitch delta. pyembroidery, the reference library, writes a zero-length stitch there; files from Brother's own software have the same shape.

Our writer does the same when converting into PEC. The visible side effect is that a converted file's stitch count rises by one per jump landing; the lock stitches sit where a digitiser would put them anyway. The PES opening guide covers what else can go wrong with a PES in the wild.

DST: no colours, and a trim is three jumps

Tajima DST stores stitches as 3-byte records with a maximum move of 121 units, so 12.1 mm at 0.1 mm resolution; longer moves are split. It has no colour information at all, only a colour-change flag that stops the machine. The header can carry a colour count but not colours.

And a trim is not a command. Commercial machines are configured to trim after a run of consecutive jumps, and the convention most software follows is three jumps in a row. Our DST writer emits three jumps for every trim, and our reader turns three consecutive jumps back into a trim, which is what the converter relies on when it turns a DST into a format with explicit trims.

VP3: thread names, no jump command

Viking and Pfaff's VP3 stores colours as full thread definitions (name, RGB, manufacturer), which makes it the most informative format for thread matching. It has no jump command. A jump is simply a long move with the needle up, encoded as a stitch delta that exceeds the normal range; the machine decides what to do with it. Converting into VP3 therefore turns every jump into a long move; trims are written explicitly, so a design that trimmed before still trims.

The other thing VP3 taught us is that one writer in the wild, PEmbroider (the Processing library), writes block lengths that do not agree with the bytes that follow. Two of the fifteen VP3 files in the collection came from it. A reader that trusts the length field walks into the wrong bytes and produces a design several metres wide; ours now checks for the next block marker and re-synchronises when the length does not land on one, and reads all fifteen.

JEF: colours as chart indices, hoops as flags

Janome's JEF stores each colour as an index into Janome's thread chart, so a JEF looks different in every viewer that does not have that chart, and stores which hoop the design was made for as a flag in the header. Machines refuse a design whose flag names a hoop they do not have. The JEF guide is the full story; the short version is that our writer sets the hoop flag from the design's extents using the same thresholds as pyembroidery, so the machine accepts it on the smallest matching hoop.

XXX: the 12.4 mm trap

Singer and Compucon's XXX encodes a stitch as two signed bytes, and uses a specific escape sequence for jumps. A stitch of exactly 12.4 mm in one axis (124 units) collides with that escape: written in the long form, it is read back as a jump. We found it while round-tripping the collection through every writer: a handful of test designs with long stitches lost exactly one stitch each on the way through XXX. The fix is to cap plain stitch records at 12.3 mm and split anything longer, which our writer now does.

PCS: coordinates scaled by five thirds

Pfaff's old PCS format stores coordinates in units that are not tenths of a millimetre; a reader that assumes 0.1 mm gets a design at 60 percent of its size. The correction is a scale of 5/3, which pyembroidery carries as a constant and so do we; the seven PCS files in the collection open at the sizes their PES siblings report.

What we did with all this

Every quirk above is in our reader and writer, and every writer was checked against pyembroidery byte for byte on the same stitch list, so a machine that accepts one will accept the other. The free embroidery file viewer is the same reader; if it opens your file and shows the right number of colour blocks, the stitch file we generate for that machine will load. If you have a file that does not open, send it; it will be number 226. And if you are not sure which of these your machine reads, the which format guide is the place to start.