/* * Copyright (c) 2015 Tricoire Sebastien 3dsman@free.fr * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * */ #include "OE_io.h" #include "OE_document.h" #include "stitchs/OE_staticstitch.h" #include "stitchs/OE_linkstitch.h" #include "OE_utils.h" #include #include static bool loadFromPES(std::string path, OE_document* document); //static bool saveToPES(const OE_document* document, std::string path); extern const OE_io ioPes; const OE_io ioPes = {"pes", "Brother PES format", loadFromPES, 0}; static const int pecThreadCount = 65; struct PESCol { unsigned char rgb[3]; const char* name; const char* dummy; }; static const PESCol pecThreads[] = { {{ 0, 0, 0}, "Unknown", ""}, /* Index 0 */ {{ 14, 31, 124}, "Prussian Blue", ""}, /* Index 1 */ {{ 10, 85, 163}, "Blue", ""}, /* Index 2 */ {{ 0, 135, 119}, "Teal Green", ""}, /* Index 3 */ /* TODO: Verify RGB value is correct */ {{ 75, 107, 175}, "Cornflower Blue", ""}, /* Index 4 */ {{237, 23, 31}, "Red", ""}, /* Index 5 */ {{209, 92, 0}, "Reddish Brown", ""}, /* Index 6 */ {{145, 54, 151}, "Magenta", ""}, /* Index 7 */ {{228, 154, 203}, "Light Lilac", ""}, /* Index 8 */ {{145, 95, 172}, "Lilac", ""}, /* Index 9 */ {{158, 214, 125}, "Mint Green", ""}, /* Index 10 */ /* TODO: Verify RGB value is correct */ {{232, 169, 0}, "Deep Gold", ""}, /* Index 11 */ {{254, 186, 53}, "Orange", ""}, /* Index 12 */ {{255, 255, 0}, "Yellow", ""}, /* Index 13 */ {{112, 188, 31}, "Lime Green", ""}, /* Index 14 */ {{186, 152, 0}, "Brass", ""}, /* Index 15 */ {{168, 168, 168}, "Silver", ""}, /* Index 16 */ {{125, 111, 0}, "Russet Brown", ""}, /* Index 17 */ /* TODO: Verify RGB value is correct */ {{255, 255, 179}, "Cream Brown", ""}, /* Index 18 */ {{ 79, 85, 86}, "Pewter", ""}, /* Index 19 */ {{ 0, 0, 0}, "Black", ""}, /* Index 20 */ {{ 11, 61, 145}, "Ultramarine", ""}, /* Index 21 */ {{119, 1, 118}, "Royal Purple", ""}, /* Index 22 */ {{ 41, 49, 51}, "Dark Gray", ""}, /* Index 23 */ {{ 42, 19, 1}, "Dark Brown", ""}, /* Index 24 */ {{246, 74, 138}, "Deep Rose", ""}, /* Index 25 */ {{178, 118, 36}, "Light Brown", ""}, /* Index 26 */ {{252, 187, 197}, "Salmon Pink", ""}, /* Index 27 */ /* TODO: Verify RGB value is correct */ {{254, 55, 15}, "Vermillion", ""}, /* Index 28 */ {{240, 240, 240}, "White", ""}, /* Index 29 */ {{106, 28, 138}, "Violet", ""}, /* Index 30 */ {{168, 221, 196}, "Seacrest", ""}, /* Index 31 */ {{ 37, 132, 187}, "Sky Blue", ""}, /* Index 32 */ {{254, 179, 67}, "Pumpkin", ""}, /* Index 33 */ {{255, 243, 107}, "Cream Yellow", ""}, /* Index 34 */ {{208, 166, 96}, "Khaki", ""}, /* Index 35 */ {{209, 84, 0}, "Clay Brown", ""}, /* Index 36 */ {{102, 186, 73}, "Leaf Green", ""}, /* Index 37 */ {{ 19, 74, 70}, "Peacock Blue", ""}, /* Index 38 */ {{135, 135, 135}, "Gray", ""}, /* Index 39 */ {{216, 204, 198}, "Warm Gray", ""}, /* Index 40 */ /* TODO: Verify RGB value is correct */ {{ 67, 86, 7}, "Dark Olive", ""}, /* Index 41 */ {{253, 217, 222}, "Flesh Pink", ""}, /* Index 42 */ /* TODO: Verify RGB value is correct */ {{249, 147, 188}, "Pink", ""}, /* Index 43 */ {{ 0, 56, 34}, "Deep Green", ""}, /* Index 44 */ {{178, 175, 212}, "Lavender", ""}, /* Index 45 */ {{104, 106, 176}, "Wisteria Violet", ""}, /* Index 46 */ {{239, 227, 185}, "Beige", ""}, /* Index 47 */ {{247, 56, 102}, "Carmine", ""}, /* Index 48 */ {{181, 75, 100}, "Amber Red", ""}, /* Index 49 */ /* TODO: Verify RGB value is correct */ {{ 19, 43, 26}, "Olive Green", ""}, /* Index 50 */ {{199, 1, 86}, "Dark Fuschia", ""}, /* Index 51 */ /* TODO: Verify RGB value is correct */ {{254, 158, 50}, "Tangerine", ""}, /* Index 52 */ {{168, 222, 235}, "Light Blue", ""}, /* Index 53 */ {{ 0, 103, 62}, "Emerald Green", ""}, /* Index 54 */ /* TODO: Verify RGB value is correct */ {{ 78, 41, 144}, "Purple", ""}, /* Index 55 */ {{ 47, 126, 32}, "Moss Green", ""}, /* Index 56 */ {{255, 204, 204}, "Flesh Pink", ""}, /* Index 57 */ /* TODO: Verify RGB value is correct */ /* TODO: Flesh Pink is Index 42, is this Index incorrect? */ {{255, 217, 17}, "Harvest Gold", ""}, /* Index 58 */ {{ 9, 91, 166}, "Electric Blue", ""}, /* Index 59 */ {{240, 249, 112}, "Lemon Yellow", ""}, /* Index 60 */ {{227, 243, 91}, "Fresh Green", ""}, /* Index 61 */ {{255, 153, 0}, "Orange", ""}, /* Index 62 */ /* TODO: Verify RGB value is correct */ /* TODO: Orange is Index 12, is this Index incorrect? */ {{255, 240, 141}, "Cream Yellow", ""}, /* Index 63 */ /* TODO: Verify RGB value is correct */ /* TODO: Cream Yellow is Index 34, is this Index incorrect? */ {{255, 200, 200}, "Applique", ""} /* Index 64 */ }; static int getU8(std::ifstream& in) { unsigned char u = 0; if (in.good()) in.read((char*)&u, 1); return u; } static bool loadFromPES(std::string path, OE_document* document) { std::ifstream in(path); if (!in.is_open()) return false; in.seekg(8); int pecstart = getU8(in); pecstart |= getU8(in)<<8; pecstart |= getU8(in)<<16; pecstart |= getU8(in)<<24; std::cout << "PES: " << "pecstart=" << pecstart << std::endl; std::cout << "PES: " << "jumping to " << (pecstart+48) << std::endl; in.seekg(pecstart+48); int nThreads = getU8(in)+1; std::cout << "PES: " << nThreads << " threads" << std::endl; for (int thread=0; thread= pecThreadCount) { std::cout << "PES: " << "thread " << thread << " unmanaged color " << iCol << ". Fallbacking." << std::endl; iCol = 0; } const PESCol* col = &pecThreads[iCol]; std::cout << "PES: " << "thread " << thread << " col (" << (int)col->rgb[0] << ", " << (int)col->rgb[1] << ", " << (int)col->rgb[2] << ")" << std::endl; document->threads.push_back(new OE_thread(OE_color(col->rgb[0]/255.0, col->rgb[1]/255.0, col->rgb[2]/255.0), OE_thread::defaultWidth)); } OE_staticstitch* stitch = 0; std::cout << "PES: " << "jumping to " << (pecstart+532) << std::endl; in.seekg(pecstart+532); int iCol = 0; auto itThread = document->threads.begin(); int nstitchs = 0; // TODO remove int ntrims = 0; // TODO remove int njumps = 0; // TODO remove long long x=0; long long y=0; while(in.good()) { int val1 = getU8(in); int val2 = getU8(in); if (val1 == 0xFF && val2 == 0x00) { std::cout << "PES: " << "end of program" << std::endl; break; } else if (val1 == 0xFE && val2 == 0xB0) { std::cout << "PES: " << "stitch end, thread change" << std::endl; getU8(in); iCol++; itThread++; continue; } int stitchType = 0; /* High bit set means 12-bit offset, otherwise 7-bit signed delta */ if(val1 & 0x80) { if(val1 & 0x20) stitchType = 1; // trim + move to if(val1 & 0x10) stitchType = 2; // move to val1 = ((val1 & 0x0F) << 8) + val2; /* Signed 12-bit arithmetic */ if(val1 & 0x800) { val1 -= 0x1000; } val2 = getU8(in); } else if(val1 >= 0x40) { val1 -= 0x80; } if(val2 & 0x80) { if(val2 & 0x20) stitchType = 1; // trim + move to if(val2 & 0x10) stitchType = 2; // move to val2 = ((val2 & 0x0F) << 8) + getU8(in); /* Signed 12-bit arithmetic */ if(val2 & 0x800) { val2 -= 0x1000; } } else if(val2 >= 0x40) { val2 -= 0x80; } x += val1; y += val2; if ((stitchType == 0 && !stitch) || stitchType) { OE_staticstitch* newStitch = new OE_staticstitch(*itThread); if (stitch) document->addStitch(new OE_linkstitch(stitch, newStitch)); document->addStitch(newStitch); stitch = newStitch; } stitch->addPoint(x/10.0, y/10.0); if (stitchType == 1) ntrims++; if (stitchType == 1 || stitchType == 2) njumps++; nstitchs++; } std::cout << "PES: " << iCol << "threads parsed" << std::endl; std::cout << "PES: " << nstitchs << "points parsed" << std::endl; std::cout << "PES: " << ntrims << "trims parsed" << std::endl; std::cout << "PES: " << njumps << "jumps parsed" << std::endl; in.close(); return true; }