VIP — Husqvarna / PFAFF
pyembroidery non ha un reader VIP, ma VIP è
essenzialmente un body HUS con un header diverso: i
flussi comando/x/y usano la stessa compressione Greg-Hus
(EmbCompress) di HUS/VP3, senza XOR
sulla parte dati (verificato decomprimendo i blocchi e confrontando il
percorso punto-per-punto con i file di riferimento).
Header
| Offset | Tipo | Significato |
|---|---|---|
| 0x00 | uint32 | magic 0x0190FC5D |
| 0x04 | int32 | numberOfStitches (include l'END record finale) |
| 0x08 | int32 | numberOfColors |
| 0x0C | int16 | posX (max X) |
| 0x0E | int16 | posY (max Y) |
| 0x10 | int16 | negX (min X) |
| 0x12 | int16 | negY (min Y) |
| 0x14 | int32 | attributeOffset — início del blocco comandi (compresso) |
| 0x18 | int32 | xOffset — início del blocco delta-X (compresso) |
| 0x1C | int32 | yOffset — início del blocco delta-Y (compresso) |
| 0x20 | 8 byte | stringa / riservato (zero nei fixture) |
| 0x2A | int32 | colorLength = 0x2E + 8·numberOfColors (formula nei fixture) |
| 0x2E | 4·n byte | blocco colori cifrato (vedi sotto) |
Blocco colori
Ogni colore è 4 byte (r, g, b, 0), XOR-chained con un
keystream derivato da vipDecodingTable di libembroidery
(vendored in reference/vendor/, generato con
scripts/gen_vip_table.py).
decoded[i] = encoded[i] ^ TABLE[i] ^ encoded[i-1] (encoded[-1] = 0)
encoded[i] = decoded[i] ^ TABLE[i] ^ encoded[i-1]
Plaintext noto in tutti i fixture: 1a 15 eb 84 → #348D1A.
Le formule per layout multicolore (colorLength,
attributeOffset in funzione di n) sono verificate
solo per n = 1 estrapolate — è flaggato nel writer.
Flussi compressi
command_block = file[attributeOffset : xOffset]
x_block = file[xOffset : yOffset]
y_block = file[yOffset : EOF]
commands = EmbCompress.expand(command_block, numberOfStitches) // 1 byte/stitch
xs = EmbCompress.expand(x_block, numberOfStitches) // signed8 delta
ys = EmbCompress.expand(y_block, numberOfStitches) // signed8 delta Comandi (come HUS)
| byte | meaning |
|---|---|
0x80 | STITCH |
0x81 | JUMP |
0x84 | COLOR CHANGE |
0x88 | TRIM |
0x90 | END |
Per le 52 lettere monogramma del progetto, tutti i comandi sono
0x80 terminati da un singolo 0x90;
numberOfColors == 1 in tutti i file.
Scrittura (core TS)
packages/core/src/writers/vip.ts e
hus.ts condividono hus-vip-body.ts. I flussi
usano un blocco EmbCompress stored (tabella Huffman
letterale degenerata, ≤ 65535 record — con gate). Stato:
software-verified (round-trip + read-back via
pyembroidery scripts/verify_hus_vip.py); accettazione su
macchina reale / Artist Toolkit ancora pendente.
pyembroidery scrive il count del blocco EmbCompress little-endian mentre tutti i decoder lo leggono MSB-first — funziona per puro lucky size. Il nostro writer lo scrive in decoder order, verificato per ogni size.
Compressione: EmbCompress
Classica "Greg's HUS compression". La sorgente Python provata è
pyembroidery/EmbCompress.py (licenza MIT). Per
leggere VIP/HUS/VP3 serve solo expand(); per
scrivere serve anche compress(). Vedi la pagina
EmbCompress.