Embroidery format PEC
PEC Format
The PEC format is read directly by embroidery machines. It is often included in PES files in order to do the machine part of the code. If the PEC file is standalone rather than embedded in the PES file it often begins with the magic string "#PEC0001" and then has the rest of the file. PES files always start with #PESxxxx then an exact reference to the position of the PEC file within that file.
PEC Header
First PEC Section
The first part of the PEC header is 512 bytes.
Type | Bytes | Value | Description |
---|---|---|---|
`char` | 19 | Label string prefixed with `"LA:"` and padded with space (`0x20`) | |
`char` | 1 | `'\r'` | carriage return character |
`u8` | 11 | `0x20` (typical) | Unknown |
`u8` | 1 | `0xFF` | ? | Unknown |
`u16` | 2 | `0x00FF` (typical) | Unknown |
`u8` | 1 | `6` (typical) | Thumbnail image width in bytes, with 8 bit pixels per byte, so `6` would mean 6×8 = 48 pixels per line |
`u8` | 1 | `38` (typical) | Thumbnail image height in pixels |
`u8` | 12 | `0x20` | `0x64` | `0xFF` | ? | Unknown, usually 20 20 20 20 64 20 00 20 00 20 20 20 |
`u8` | 1 | _N_ | Number of colors minus one, 0xFF means 0 colors. |
`u8` | 1 + _N_ | Palette index | |
`u8` | 462 - _N_ | `0x20` (typical) | Padding to second section. |
Second PEC Section
The second part of the PEC header.
Type | Bytes | Value | Description |
---|---|---|---|
`u16` | 2 | `0x0000` (typical) | Unknown |
`u16` | 2 | Offset to thumbnail image subsection relative to the PEC section offset plus 512 bytes | |
`u16` | 2 | `0x3100` (typical) | Unknown |
`u16` | 2 | `0xF0FF` (typical) | Unknown |
`s16` | 2 | Width | |
`s16` | 2 | Height | |
`u16` | 2 | `0x01E0` (typical) | Unknown |
`u16` | 2 | `0x01B0` (typical) | Unknown |
4 | Unknown | ||
pec-stitch-list-subsection | PEC stitch list subsection | ||
pec-thumbnail-image-subsection | PEC thumbnail image subsection |
PEC stitch list subsection
The PEC stitch list come in dx and dy relative coordinate pairs. Depending on the bit patterns used, 2, 3 or 4 bytes are used for the coordinate pairs as explained below. Note that if the first coordinates are (0, 0) the embroidery machine apparently ignores them. The first nonzero coordinate pair is relative to the minimum bound coordinates.
Type | Bytes | Value | Description |
---|---|---|---|
`u8` | 1 or 2 | Stitch dx coordinate | |
`u8` | 1 or 2 | Stitch dy coordinate |
Each stitch we read the dx or dy coordinate. The topmost bit in a coordinate is the flag for long form. If the bit is zero then the following 7 bits are 2s complement binary for the dx or dy value. If the long form is flagged then the next three bits there are control bits, and the remaining 12 (including all 8 of the next bit) are overtly 12 bit 2s complement binary.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|
0 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
In short form, the first most significant bit is 0 and the remaining b6-b0 are 2s complement of a 7 bit number with a max range of 127.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | c0 | c1 | c2 | b11 | b10 | b9 | b8 | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
In long form, the first most significant bit is 1. The following three bits are then control codes, and the remaining b11-b0 are 2s complement of a 12 bit number with a max range of 2047 in any extend.
Commands
Since sort form can only encode stitches, all commands will always set the long-form bit.
Jump
Jumps are long form stitches with the command bit for Jump set.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 1 | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
Trim
Trim commands are long form stitches with the command bit for Trim set.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 1 | 0 | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
Color Change
0xfe 0xb0 2, 1, 2, 1, 2, 1... alternating back and forth.
END
File end is simply writing 0xFF.
PEC thumbnail image subsection
There is always one main thumbnail image plus one for each color. The size of each thumbnail is the thumbnail width multiplied with the thumbnail height number of bytes (width and height are given in the PEC section). The pixels are oriented from the top left corner, with one pixel per bit starting with the most significant bit in the first byte.
The following 64 threads have been verified with a Brother Innovis 955 sewing and embroidery machine and its “EMBROIDERY” thread space.
PEC colors
Index | Code | Name | Type | RGB color |
---|---|---|---|---|
1 | 007 | Prussian Blue | A | `#1a0a94` |
2 | 000 | Blue | A | `#0f75ff` |
3 | 534 | Teal Green | A | `#00934c` |
4 | 070 | Corn Flower Blue | A | `#babdfe` |
5 | 800 | Red | A | `#ec0000` |
6 | 000 | Reddish Brown | A | `#e4995a` |
7 | 620 | Magenta | A | `#cc48ab` |
8 | 810 | Light Lilac | A | `#fdc4fa` |
9 | 000 | Lilac | A | `#dd84cd` |
10 | 502 | Mint Green | A | `#6bd38a` |
11 | 214 | Deep Gold | A | `#e4a945` |
12 | 208 | Orange | A | `#ffbd42` |
13 | 000 | Yellow | A | `#ffe600` |
14 | 513 | Lime Green | A | `#6cd900` |
15 | 328 | Brass | A | `#c1a941` |
16 | 005 | Silver | A | `#b5ad97` |
17 | 000 | Russet Brown | A | `#ba9c5f` |
18 | 000 | Cream Brown | A | `#faf59e` |
19 | 704 | Pewter | A | `#808080` |
20 | 900 | Black | A | `#000000` |
21 | 000 | Ultramarine | A | `#001cdf` |
22 | 000 | Royal Purple | A | `#df00b8` |
23 | 707 | Dark Gray | A | `#626262` |
24 | 058 | Dark Brown | A | `#69260d` |
25 | 086 | Deep Rose | A | `#ff0060` |
26 | 323 | Light Brown | A | `#bf8200` |
27 | 079 | Salmon Pink | A | `#f39178` |
28 | 000 | Vermilion | A | `#ff6805` |
29 | 001 | White | A | `#f0f0f0` |
30 | 000 | Violet | A | `#c832cd` |
31 | 000 | Seacrest | A | `#b0bf9b` |
32 | 019 | Sky Blue | A | `#65bfeb` |
33 | 000 | Pumpkin | A | `#ffba04` |
34 | 010 | Cream Yellow | A | `#fff06c` |
35 | 000 | Khaki | A | `#feca15` |
36 | 000 | Clay Brown | A | `#f38101` |
37 | 000 | Leaf Green | A | `#37a923` |
38 | 405 | Peacock Blue | A | `#23465f` |
39 | 000 | Gray | A | `#a6a695` |
40 | 000 | Warm Gray | A | `#cebfa6` |
41 | 000 | Dark Olive | A | `#96aa02` |
42 | 307 | Linen | A | `#ffe3c6` |
43 | 000 | Pink | A | `#ff99d7` |
44 | 000 | Deep Green | A | `#007004` |
45 | 000 | Lavender | A | `#edccfb` |
46 | 000 | Wisteria Violet | A | `#c089d8` |
47 | 843 | Beige | A | `#e7d9b4` |
48 | 000 | Carmine | A | `#e90e86` |
49 | 000 | Amber Red | A | `#cf6829` |
50 | 000 | Olive Green | A | `#408615` |
51 | 107 | Dark Fuchsia | A | `#db1797` |
52 | 209 | Tangerine | A | `#ffa704` |
53 | 017 | Light Blue | A | `#b9ffff` |
54 | 507 | Emerald Green | A | `#228927` |
55 | 614 | Purple | A | `#b612cd` |
56 | 515 | Moss Green | A | `#00aa00` |
57 | 124 | Flesh Pink | A | `#fea9dc` |
58 | 000 | Harvest Gold | A | `#fed510` |
59 | 000 | Electric Blue | A | `#0097df` |
60 | 205 | Lemon Yellow | A | `#ffff84` |
61 | 027 | Fresh Green | A | `#cfe774` |
62 | 000 | Applique Material | A | `#ffc864` |
63 | 000 | Applique Position | A | `#ffc8c8` |
64 | 000 | Applique | A | `#ffc8c8` |
Writing PEC
If the PEC block is part of a PES file, after PESv4, the advent of thread descriptions in the PES header means the color codes are overloaded rather than use the magic numbers lookup chart. Most all loaders will use a hybrid of the PES header for the colors, and the PEC block for the color values.
Write PEC Elements
If we are writing a basic output into PEC format, we should do the following:
- Write "LA:"
- Write 20 bytes, name, this is typically truncated at 8 characters, padded with space (0x20)
- Write 1 byte, 0x0D
- Write 12 bytes, 12 copies of 0x20
- Write 1 byte, 0xFF
- Write 1 byte, 0x00
- Write 1 byte, 0x06, Graphics size information.
- Write 1 byte, 0x26, Graphics size information.
- Write 12 bytes, 0x20, 12 spaces.
- Write 1 byte, #Color_Changes, (n) number of color changes.
- Write n bytes, #Index Color each change.
- Write (463-n) spaces, that is to say pad color changes to 463 in total.
(This is 512 bytes from the start of the PEC FILE)
- Write 2 bytes, 0x00 0x00, two bytes of zeros.
- Write 3 bytes, (NOTE: 3 bytes) position of graphics offset value. (20 + PEC_ENCODE)
- Write 1 byte: 0x31
- Write 1 byte: 0xFF
- Write 1 byte: 0xF0
- Write 2 bytes, Width.
- Write 2 bytes, Height.
- Write 2 bytes, 0x01E0
- Write 2 bytes, 0x01B0
- Write 2 bytes BIGENDIAN 0x9000 - minX
- Write 2 bytes BIGENDIAN 0x9000 - minY
- Write Pec Encoded stitches.
- Write Graphics Objects.
Write Pec Encoded Stitches.
Though it might be technically right and there are documents with mixed length stitches, if the X or Y is long form they both should be. Just as both X and Y get flagged for jumps and trims, when we jump and trim. It's unknown which of these are technically valid and on which machines. But, both doing this consistently seems to be maximally compatible.
Stitch
Write stitches below 127 in short form.
Short form stitches are 2 bytes. X, Y. These are 7 bit signed integers. 0b0???????, 0b0???????
Write stitches above 127 in long form. 0b1000????_????????, 0b1000????_???????? the topmost nibble is command data, and the bottom 12 bits are coordinate data.
Jumps are long form stitches with the command bit for Jump set. 0b1001????_????????, 0b1001????_????????
Trim commands are long form stitches with the command bit for Trim set. 0b1010????_????????, 0b1010????_????????
Color changes should write: Write 1 byte: 0xfe Write 1 byte: 0xb0 Write 1 byte: 2, 1, 2, 1, 2, 1... alternating back and forth. Starting with 2 and each additional color change use the next character in sequence.
For END write: Write 1 byte: 0xFF
Write Graphics
- 1 copy of blank.
- N copies of blank. (where N is the number of colors used).
Blank Graphics
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xF0, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x0F, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x20, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x20, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0xF0, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0x0F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
Consideration of the Wilcom Bug
A bug in Wilcom's reading of how to make this valid leads to two different interpretations.
Properly in PE-Design, if you reuse the same thread it doesn't add another thread entry to the thread table at the start. Rather it lists the unique threads. So if you used black, white, black, white, red, black, white. Brother would say you used 3 threads and define them in the header. In the PEC file it would list these 14 1D 14 1D 05 14 1D. Assigning the first thread value to 14, the second to 1D, and the third finally to 05.
Wilcom however, loads the thread table as three threads black, white, red, then completely ignores the order listed in the PEC table and uses them in a cycle coloring them black, red, white, black, red, white, black. This bug is easily duplicated.
When saving PE-Design will save the unique threads. When saving Wilcom will save all threads, in a list, repeating them as needed. And it will pigeon hole colors into being the nearest relevant color, when writing the PEC. However, Wilcom writes the PES file with the table colors referring to the header, so PE-Design loads these correctly. However they are previewed by PE-Design as wrong when you check the Open Dialog.
So when these colors get pigeon-holed into the same PECThread index value but refer to different colors, PE-Design will interpret them incorrectly, in the rare preview of the stitches. However, if we only provide the unique colors table as PES properly requires, Wilcom will read these in error if there a duplicate color, prior to exhausting all unique colors.
The embroidery machine will use those PEC colors for the preview screens, and accept that when a color change happens that it moves to the next needle. If #17 is the closest color to the first thread, so it calls that 17. And #17 is closest color to the second thread, it should not use #17 again. But, properly PE-Design takes #17 to always refer to the same thread no matter what. And Wilcom won't care, and just cycle to the next thread in it's chart.
The problem here is a bit of a catch-22. If you read/write the files properly, there will be a rather notable incompatibility with Wilcom. And it'll work fine with PE-Design. If you read/write the files in Wilcom's way, PE-Design will load the PES blocks fine and seem to work without issue outside of preview on load, and Wilcom will also work correctly for the most part, even though it's technically still wrong and will suffer in a few minor ways.
For max compatibility export the correct PES file with unique threads in the header, and detect the error when the number of threads is equal to the number of colors listed in the pec section. If the threads in the header is equal to the colors indexed in the PEC section, then use 1 to 1, if there are fewer colors in the header, properly index them as PE-Design expects.
Credits
This file and the accompanied PES file, give credit to:
- A lot of this information is consolidated from Frno7's Wiki which I did a lot of work on.
- As well as some rather important work by JoshVarga from Embroidermodder.
- treveradams
- This old site, http://www.achatina.de/sewing/main/TECHNICL.HTM
- Some early work done on the graphics decoding by Linus Torvalds (yes, that one).