Embroidermodder / libembroidery

Library for reading/writing/manipulating machine and design embroidery files
https://www.libembroidery.org
zlib License
45 stars 13 forks source link

correct read pes tested #116

Open fabricocouto opened 2 years ago

fabricocouto commented 2 years ago

change

embFile_seek(file, pecstart + 532, SEEK_SET); readPecStitches(pattern, file);

to

embFile_seek(file, pecstart + 528, SEEK_SET); readPecStitchespes(pattern, file);

add void

static void readPecStitchespes(EmbPattern patterns, EmbFile file) { int stitchNumber = 0; int val1 = 0; int val3 = 0; int val2 = 0; int stitchType = 0; while(!embFile_eof(file)) {

        val1 =(unsigned char) binaryReadUInt8(file);
        val2 =(unsigned char) binaryReadUInt8(file);

        stitchType = NORMAL;
        if (val1 == 0xFF && val2 == 0x00) {
           embPattern_addStitchRel(patterns, 0.0, 0.0, END, 1);
            break;
        }
        if (val1 == 0xFE && val2 == 0xB0) {
             binaryReadUInt8(file);
              embPattern_addStitchRel(patterns, 0.0, 0.0, STOP, 1);
            stitchNumber += 1;
        } else {
            if (val1 & 0x80) {
                if (val1 & 0x20) {
                    stitchType =TRIM;
                }
                if (val1 & 0x10) {
                    stitchType = JUMP;
                }
                val1 = ((val1 & 0x0F) << 8) + val2;
                if (val1 & 0x800) {
                    val1 -= 0x1000;
                }
                val2 =  binaryReadUInt8(file);
            } else if (val1 >= 0x40) {
                val1 -= 0x80;
            }
            if (val2 & 0x80) {
                if (val2 & 0x20) {
                    stitchType = TRIM;
                }
                if (val2 & 0x10) {
                    stitchType = JUMP;
                }
                val2 = ((val2 & 0x0F) << 8) +  binaryReadUInt8(file);
                if (val2 & 0x800) {
                    val2 -= 0x1000;
                }
            } else if (val2 > 0x3F) {
                val2 -= 0x80;
            }
            embPattern_addStitchRel(patterns,  val1 / 10.0, val2 / 10.0, stitchType, 1);
          stitchNumber += 1;
        }
    }

}

tatarize commented 2 years ago

This issue needs additional input. The line in the PEC writer code and PEC reader code for this code segment is wrong.

https://github.com/Embroidermodder/libembroidery/blob/256bd911d64cacdb9757680e4d57f041a48c4151/format-pec.c#L442

binaryWriteUShortBE(file, (unsigned short)(0x9000 | -roundDouble(bounds.left)));
binaryWriteUShortBE(file, (unsigned short)(0x9000 | -roundDouble(bounds.top)));

What looks to be bounds.left and bounds.top is actually just a JUMP stitch. The stitch reading starts 4 stitches earlier, and this is inside the stitch block.

This became evident after, in personal correspondence with fabicocouto, he gave me a couple examples of files that did not fit this pattern and actually had a short movement stitch for the first value. Give 0x05 for the first value which is not a jump stitch value but what's worse is actually 1 byte rather than 2. So jumping into the file at PECStart 532 actually started at a y-value rather than x-value which caused the rest of the file read to be corrupted.

What's more it's entirely possible that bounds.left or bounds.top can actually be +2 which gives you -2 as the value this writes to the file 0x9000 | 0xFFFE which is actually exactly equal to 0xFFFE which is PEC code for END and instantly terminates the read in some Embroidery software like EO and Wilcom E4+, though not Wilcom E3, but ending the reading there is actually the correct interpretation of that code there. And it results from this bug.