/* GfxEntryPanel::handleAction * Handles the action [id]. Returns true if the action was handled, * false otherwise *******************************************************************/ bool GfxEntryPanel::handleAction(string id) { // Don't handle actions if hidden if (!isActivePanel()) return false; // We're only interested in "pgfx_" actions if (!id.StartsWith("pgfx_")) return false; // Mirror if (id == "pgfx_mirror") { // Mirror X getImage()->mirror(false); // Update UI gfx_canvas->updateImageTexture(); gfx_canvas->Refresh(); // Update variables image_data_modified = true; setModified(); } // Flip else if (id == "pgfx_flip") { // Mirror Y getImage()->mirror(true); // Update UI gfx_canvas->updateImageTexture(); gfx_canvas->Refresh(); // Update variables image_data_modified = true; setModified(); } // Rotate else if (id == "pgfx_rotate") { // Prompt for rotation angle string angles[] = { "90", "180", "270" }; int choice = wxGetSingleChoiceIndex("Select rotation angle", "Rotate", 3, angles, 0); // Rotate image switch (choice) { case 0: getImage()->rotate(90); break; case 1: getImage()->rotate(180); break; case 2: getImage()->rotate(270); break; default: break; } // Update UI gfx_canvas->updateImageTexture(); gfx_canvas->Refresh(); // Update variables image_data_modified = true; setModified(); } // Translate else if (id == "pgfx_translate") { // Create translation editor dialog Palette8bit* pal = theMainWindow->getPaletteChooser()->getSelectedPalette(); TranslationEditorDialog ted(theMainWindow, pal, " Colour Remap", gfx_canvas->getImage()); // Create translation to edit ted.openTranslation(prev_translation); // Show the dialog if (ted.ShowModal() == wxID_OK) { // Apply translation to image getImage()->applyTranslation(&ted.getTranslation(), pal); // Update UI gfx_canvas->updateImageTexture(); gfx_canvas->Refresh(); // Update variables image_data_modified = true; gfx_canvas->updateImageTexture(); setModified(); prev_translation.copy(ted.getTranslation()); } } // Colourise else if (id == "pgfx_colourise") { Palette8bit* pal = theMainWindow->getPaletteChooser()->getSelectedPalette(); GfxColouriseDialog gcd(theMainWindow, entry, pal); gcd.setColour(last_colour); // Show colourise dialog if (gcd.ShowModal() == wxID_OK) { // Colourise image getImage()->colourise(gcd.getColour(), pal); // Update UI gfx_canvas->updateImageTexture(); gfx_canvas->Refresh(); // Update variables image_data_modified = true; Refresh(); setModified(); } rgba_t gcdcol = gcd.getColour(); last_colour = S_FMT("RGB(%d, %d, %d)", gcdcol.r, gcdcol.g, gcdcol.b); } // Tint else if (id == "pgfx_tint") { Palette8bit* pal = theMainWindow->getPaletteChooser()->getSelectedPalette(); GfxTintDialog gtd(theMainWindow, entry, pal); gtd.setValues(last_tint_colour, last_tint_amount); // Show tint dialog if (gtd.ShowModal() == wxID_OK) { // Tint image getImage()->tint(gtd.getColour(), gtd.getAmount(), pal); // Update UI gfx_canvas->updateImageTexture(); gfx_canvas->Refresh(); // Update variables image_data_modified = true; Refresh(); setModified(); } rgba_t gtdcol = gtd.getColour(); last_tint_colour = S_FMT("RGB(%d, %d, %d)", gtdcol.r, gtdcol.g, gtdcol.b); last_tint_amount = (int)(gtd.getAmount() * 100.0); } // Crop else if (id == "pgfx_crop") { Palette8bit* pal = theMainWindow->getPaletteChooser()->getSelectedPalette(); GfxCropDialog gcd(theMainWindow, entry, pal); // Show crop dialog if (gcd.ShowModal() == wxID_OK) { // stuff } } // alPh/tRNS else if (id == "pgfx_alph" || id == "pgfx_trns") { setModified(); Refresh(); } // Optimize PNG else if (id == "pgfx_pngopt") { // This is a special case. If we set the entry as modified, SLADE will prompt // to save it, rewriting the entry and cancelling the optimization done... if (EntryOperations::optimizePNG(entry)) setModified(false); else wxMessageBox("Warning: Couldn't optimize this image, check console log for info", "Warning", wxOK|wxCENTRE|wxICON_WARNING); Refresh(); } // Extract all else if (id == "pgfx_extract") { extractAll(); } // Convert else if (id == "pgfx_convert") { GfxConvDialog gcd(theMainWindow); gcd.CenterOnParent(); gcd.openEntry(entry); gcd.ShowModal(); if (gcd.itemModified(0)) { // Get image and conversion info SImage* image = gcd.getItemImage(0); SIFormat* format = gcd.getItemFormat(0); // Write converted image back to entry format->saveImage(*image, entry_data, gcd.getItemPalette(0)); // This makes the "save" button (and the setModified stuff) redundant and confusing! // The alternative is to save to entry effectively (uncomment the importMemChunk line) // but remove the setModified and image_data_modified lines, and add a call to refresh // to get the PNG tRNS status back in sync. //entry->importMemChunk(entry_data); image_data_modified = true; setModified(); // Fix tRNS status if we converted to paletted PNG int MENU_GFXEP_PNGOPT = theApp->getAction("pgfx_pngopt")->getWxId(); int MENU_GFXEP_ALPH = theApp->getAction("pgfx_alph")->getWxId(); int MENU_GFXEP_TRNS = theApp->getAction("pgfx_trns")->getWxId(); int MENU_ARCHGFX_EXPORTPNG = theApp->getAction("arch_gfx_exportpng")->getWxId(); if (format->getName() == "PNG") { ArchiveEntry temp; temp.importMemChunk(entry_data); temp.setType(EntryType::getType("png")); menu_custom->Enable(MENU_GFXEP_ALPH, true); menu_custom->Enable(MENU_GFXEP_TRNS, true); menu_custom->Check(MENU_GFXEP_TRNS, EntryOperations::gettRNSChunk(&temp)); menu_custom->Enable(MENU_ARCHGFX_EXPORTPNG, false); menu_custom->Enable(MENU_GFXEP_PNGOPT, true); toolbar->enableGroup("PNG", true); } else { menu_custom->Enable(MENU_GFXEP_ALPH, false); menu_custom->Enable(MENU_GFXEP_TRNS, false); menu_custom->Enable(MENU_ARCHGFX_EXPORTPNG, true); menu_custom->Enable(MENU_GFXEP_PNGOPT, false); toolbar->enableGroup("PNG", false); } // Refresh getImage()->open(entry_data, 0, format->getId()); gfx_canvas->Refresh(); } } // Unknown action else return false; // Action handled return true; }
int main(int argc, char *argv[]) { DIR *dir; ofstream fout; char slash = Unix ? '/' : '\\'; // It is '/' or '\' depending on OS char POS_PATH_BASE[MAX_PATH_LENGTH]; char NEG_PATH_BASE[MAX_PATH_LENGTH]; clock_t tic, toc; if (argc != 4) { error("Usage: train [POS_DIR] [NEG_DIR] [OUTPUT_FILE]."); } if (!(dir = opendir(argv[1]))) { error("train: [POS_DIR] open failed."); } /* Set POS_PATH_BASE to [POS_DIR] and append '/' or '\' */ strcpy(POS_PATH_BASE, argv[1]); sprintf(POS_PATH_BASE, "%s%c", POS_PATH_BASE, slash); closedir(dir); if (!(dir = opendir(argv[2]))) { error("train: [NEG_DIR] open failed."); } /* Set NEG_PATH_BASE to [NEG_DIR] and append '/' or '\' */ strcpy(NEG_PATH_BASE, argv[2]); sprintf(NEG_PATH_BASE, "%s%c", NEG_PATH_BASE, slash); closedir(dir); fout.open(argv[3]); if (!(fout)) { error("train: [OUTPUT_FILE] open failed."); } /** Command is correct **/ echoOS(); cout << "This program provides cascaded-AdaBoost training.\n" << "Please make sure that [POS_DIR] and [NEG_DIR] contain only training image data,\n" << " whose size is " << WINDOW_WIDTH << " x " << WINDOW_HEIGHT << ".\n" << "Press [Enter] to continue, or ctrl+C/D/Z to exit ..."; getchar(); tic = clock(); /* Use only one large matrix for storing all POS / NEG feature data */ CvMat *POS = NULL, *NEG = NULL; int N1, N2; /* number of positive / negative images */ int blockCount = 0; /* number of blocks in an image */ /* [1] Feature extraction */ /* First, check for validity of extraction parameters */ assert(!(360 % (BIN_NUM * 2))); // (360 / BIN_NUM / 2) should be an integer */ assert(360 / BIN_NUM == BIN_SIZE); assert(BIN_SIZE >> 1 == HALF_BIN_SIZE); cout << "\nStart of feature extraction ...\n"; /* Should pass (CvMat *&) to really create the matrices */ extractAll(POS_PATH_BASE, POS, N1, blockCount); cout << "Extraction of POS data completed.\n"; #if CHECKNaN cout << "Check POS matrix for NaN values:" << endl; if (checkNaN(POS, "POS")) { error("POS matrix contains NaN values!"); } else { cout << "OK!" << endl; } #endif extractAll(NEG_PATH_BASE, NEG, N2, blockCount); cout << "Extraction of NEG data completed.\n"; #if CHECKNaN cout << "Check NEG matrix for NaN values:" << endl; if (checkNaN(NEG, "NEG")) { error("NEG matrix contains NaN values!"); } else { cout << "OK!" << endl; } #endif assert(blockCount > 0); cout << endl << "# of blocks per image: " << blockCount << ".\n"; #if GETCHAR getchar(); #endif /* [2] Cascaded-AdaBoost training */ cout << "Start of cascaded-AdaBoost training ...\n"; srand(time(NULL)); float F_current = 1.0; // current overall false positive rate int i = 1; // AdaBoost stage counter int rejectCount = 0; // # of negative images rejected so far /* Allocate rejection table */ /** Note: All the xxxTable[]'s are of boolean flags **/ bool *rejectTable = new bool[ N2 ]; memset(rejectTable, 0, N2); bool stop = false; // Stopping flag vector<AdaStrong> H; // A cascade of AdaBoost strong classifiers /*** The training algorithm ***/ while (F_current > F_target && !stop) { /* upper bound for j */ int jEnd = (i == 1) ? (ni + 1) : ni; for (int j = 1; j <= jEnd; j++) { /* Learn an A[i,j] stage */ cout << "\nLearning stage A[" << i << "," << j << "]...\n"; if ((stop = learnA(N1, N2, blockCount, rejectCount, rejectTable, POS, NEG, H, F_current))) { break; } cout << "Stage A[" << i << "," << j << "] completed.\n"; #if GETCHAR getchar(); #endif } #if META if (stop) break; /* Learn a M[i] stage */ cout << "\nLearning stage M[" << i << "]...\n"; learnM(); cout << "Stage M[" << i << "," << j << "] completed.\n"; #if GETCHAR getchar(); #endif #endif i++; } // End of loop while (F_current > F_target && !stop) cout << "The entire training process completed.\nWriting model parameters to " << argv[3] << " ... "; /* Write model parameters to [OUTPUT_FILE]. See docs/train_format.txt for explanation. */ writeModel(H, fout); cout << "done!\n"; /* Show running time */ toc = clock(); runningTime(tic, toc); /* Don't forget to close the file stream */ fout.close(); return 0; }
int main(int iArgC, char *cArgV[]) { #ifdef __GLIBCXX__ // Set a better exception handler std::set_terminate(__gnu_cxx::__verbose_terminate_handler); #endif // Disable stdin/printf/etc. sync for a speed boost std::ios_base::sync_with_stdio(false); // Declare the supported options. po::options_description poActions("Actions"); poActions.add_options() ("list,l", "list files in the archive") ("extract-all,X", "extract all files in the archive") ("extract,x", po::value<std::string>(), "extract a specific file") ("add,a", po::value<std::string>(), "add a file at the end of the archive") ("insert,i", po::value<std::string>(), "add a file at a specific point in the archive") ("metadata,m", "list archive attributes/metadata") ("set-metadata,e", po::value<std::string>(), "change archive attributes/metadata") ("overwrite,o", po::value<std::string>(), "replace a file in the archive with new data") ("rename,r", po::value<std::string>(), "rename a file inside the archive") ("delete,d", po::value<std::string>(), "remove a file from the archive") ("uncompressed-size,z", po::value<int>(), "[with -u only] specify the uncompressed size to use with -i") ; po::options_description poOptions("Options"); poOptions.add_options() ("type,t", po::value<std::string>(), "specify the archive type (default is autodetect)") ("list-types", "list available formats that can be passed to --type") ("filetype,y", po::value<std::string>(), "specify the file type when inserting (default is generic file)") ("attribute,b", po::value<std::string>(), "specify the file attributes when inserting (optional)") ("unfiltered,u", "do not filter files (no encrypt/decrypt/compress/decompress)") ("script,s", "format output suitable for script parsing") ("force,f", "force open even if the archive is not in the given format") ("create,c", "create a new archive file instead of opening an existing one") ; po::options_description poHidden("Hidden parameters"); poHidden.add_options() ("archive", "archive file to manipulate") ("help", "produce help message") ; po::options_description poVisible(""); poVisible.add(poActions).add(poOptions); po::options_description poComplete("Parameters"); poComplete.add(poActions).add(poOptions).add(poHidden); po::variables_map mpArgs; std::string strFilename; std::string strType; bool bScript = false; // show output suitable for script parsing? bool bForceOpen = false; // open anyway even if archive not in given format? bool bCreate = false; // create a new archive? try { po::parsed_options pa = po::parse_command_line(iArgC, cArgV, poComplete); // Parse the global command line options for (std::vector<po::option>::iterator i = pa.options.begin(); i != pa.options.end(); i++) { if (i->string_key.empty()) { // If we've already got an archive filename, complain that a second one // was given (probably a typo.) if (!strFilename.empty()) { std::cerr << "Error: unexpected extra parameter (multiple archive " "filenames given?!)" << std::endl; return RET_BADARGS; } assert(i->value.size() > 0); // can't have no values with no name! strFilename = i->value[0]; } else if (i->string_key.compare("help") == 0) { std::cout << "Copyright (C) 2010-2016 Adam Nielsen <*****@*****.**>\n" "This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n" "and you are welcome to change and redistribute it under certain conditions;\n" "see <http://www.gnu.org/licenses/> for details.\n" "\n" "Utility to manipulate archive files used by games to store data files.\n" "Build date " __DATE__ " " __TIME__ << "\n" "\n" "Usage: gamearch <archive> <action> [action...]\n" << poVisible << "\n" << std::endl; return RET_OK; } else if ( (i->string_key.compare("list-types") == 0) ) { for (const auto& i : ga::ArchiveManager::formats()) { std::string code = i->code(); std::cout << code; int len = code.length(); if (len < 20) std::cout << std::string(20 - len, ' '); std::cout << ' ' << i->friendlyName() << '\n'; } return RET_OK; } else if ( (i->string_key.compare("t") == 0) || (i->string_key.compare("type") == 0) ) { if (i->value.size() == 0) { std::cerr << PROGNAME ": --type (-t) requires a parameter. Use " "--list-types to see valid values." << std::endl; return RET_BADARGS; } strType = i->value[0]; } else if ( (i->string_key.compare("s") == 0) || (i->string_key.compare("script") == 0) ) { bScript = true; } else if ( (i->string_key.compare("f") == 0) || (i->string_key.compare("force") == 0) ) { bForceOpen = true; } else if ( (i->string_key.compare("u") == 0) || (i->string_key.compare("unfiltered") == 0) ) { bUseFilters = false; } else if ( (i->string_key.compare("c") == 0) || (i->string_key.compare("create") == 0) ) { bCreate = true; } } if (strFilename.empty()) { std::cerr << "Error: no game archive filename given" << std::endl; return RET_BADARGS; } std::unique_ptr<stream::file> psArchive; if (bCreate && strType.empty()) { std::cerr << "Error: You must specify the --type of archive to create" << std::endl; return RET_BADARGS; } std::cout << (bCreate ? "Creating " : "Opening ") << strFilename << " as type " << (strType.empty() ? "<autodetect>" : strType) << std::endl; try { psArchive = std::make_unique<stream::file>(strFilename, bCreate); } catch (const stream::open_error& e) { std::cerr << "Error " << (bCreate ? "creating" : "opening") << " archive file " << strFilename << ": " << e.what() << std::endl; return RET_SHOWSTOPPER; } // Get the format handler for this file format ga::ArchiveManager::handler_t pArchType; if (strType.empty()) { // Need to autodetect the file format. for (const auto& i : ga::ArchiveManager::formats()) { ga::ArchiveType::Certainty cert = i->isInstance(*psArchive); switch (cert) { case ga::ArchiveType::Certainty::DefinitelyNo: // Don't print anything (TODO: Maybe unless verbose?) break; case ga::ArchiveType::Certainty::Unsure: std::cout << "File could be a " << i->friendlyName() << " [" << i->code() << "]" << std::endl; // If we haven't found a match already, use this one if (!pArchType) pArchType = i; break; case ga::ArchiveType::Certainty::PossiblyYes: std::cout << "File is likely to be a " << i->friendlyName() << " [" << i->code() << "]" << std::endl; // Take this one as it's better than an uncertain match pArchType = i; break; case ga::ArchiveType::Certainty::DefinitelyYes: std::cout << "File is definitely a " << i->friendlyName() << " [" << i->code() << "]" << std::endl; pArchType = i; // Don't bother checking any other formats if we got a 100% match goto finishTesting; } if (cert != ga::ArchiveType::Certainty::DefinitelyNo) { // We got a possible match, see if it requires any suppdata auto suppList = i->getRequiredSupps(*psArchive, strFilename); if (suppList.size() > 0) { // It has suppdata, see if it's present std::cout << " * This format requires supplemental files..." << std::endl; bool bSuppOK = true; for (const auto& s : suppList) { try { stream::file test_presence(s.second, false); } catch (const stream::open_error&) { bSuppOK = false; std::cout << " * Could not find/open " << s.second << ", archive is probably not " << i->code() << std::endl; break; } } if (bSuppOK) { // All supp files opened ok std::cout << " * All supp files present, archive is likely " << i->code() << std::endl; // Set this as the most likely format pArchType = i; } } } } finishTesting: if (!pArchType) { std::cerr << "Unable to automatically determine the file type. Use " "the --type option to manually specify the file format." << std::endl; return RET_BE_MORE_SPECIFIC; } } else { auto pTestType = ga::ArchiveManager::byCode(strType); if (!pTestType) { std::cerr << "Unknown file type given to -t/--type: " << strType << std::endl; return RET_BADARGS; } pArchType = pTestType; } assert(pArchType != NULL); if (!bCreate) { // Check to see if the file is actually in this format if (pArchType->isInstance(*psArchive) == ga::ArchiveType::Certainty::DefinitelyNo) { if (bForceOpen) { std::cerr << "Warning: " << strFilename << " is not a " << pArchType->friendlyName() << ", open forced." << std::endl; } else { std::cerr << "Invalid format: " << strFilename << " is not a " << pArchType->friendlyName() << "\n" << "Use the -f option to try anyway." << std::endl; return RET_BE_MORE_SPECIFIC; } } } // See if the format requires any supplemental files auto suppList = pArchType->getRequiredSupps(*psArchive, strFilename); camoto::SuppData suppData; for (const auto& s : suppList) { try { std::cout << "Opening supplemental file " << s.second << std::endl; auto suppStream = std::make_unique<stream::file>(s.second, false); suppData[s.first] = std::move(suppStream); } catch (const stream::open_error& e) { std::cerr << "Error opening supplemental file " << s.second << ": " << e.what() << std::endl; return RET_SHOWSTOPPER; } } // Open the archive file std::shared_ptr<ga::Archive> pArchive; try { if (bCreate) { pArchive = pArchType->create(std::move(psArchive), suppData); } else { pArchive = pArchType->open(std::move(psArchive), suppData); } assert(pArchive); } catch (const camoto::error& e) { std::cerr << "Error " << (bCreate ? "creating" : "opening") << " archive file: " << e.what() << std::endl; return RET_SHOWSTOPPER; } // File type of inserted files defaults to empty, which means 'generic file' std::string strLastFiletype; // Last attribute value set with -b auto iLastAttr = ga::Archive::File::Attribute::Default; // Last value set with -z stream::len lenReal = 0; // Run through the actions on the command line for (auto& i : pa.options) { if (i.string_key.compare("list") == 0) { listFiles(std::string(), std::string(), *pArchive, bScript); } else if (i.string_key.compare("extract-all") == 0) { extractAll(pArchive, bScript); } else if (i.string_key.compare("metadata") == 0) { listAttributes(pArchive.get(), bScript); } else if (i.string_key.compare("set-metadata") == 0) { std::string strIndex, strValue; if (!split(i.value[0], '=', &strIndex, &strValue)) { std::cerr << PROGNAME ": -e/--set-metadata requires an index and " "a value (e.g. --set-metadata 0=example)" << std::endl; return RET_BADARGS; } unsigned int index = strtoul(strIndex.c_str(), nullptr, 0); setAttribute(pArchive.get(), bScript, index, strValue); } else if (i.string_key.compare("extract") == 0) { std::string strArchFile, strLocalFile; bool bAltDest = split(i.value[0], '=', &strArchFile, &strLocalFile); if (!bAltDest) sanitisePath(strLocalFile); std::cout << " extracting: " << strArchFile; if (strArchFile.compare(strLocalFile)) std::cout << " (into " << strLocalFile << ")"; std::cout << std::flush; try { // Find the file auto destArch = pArchive; ga::Archive::FileHandle id; findFile(&destArch, &id, strArchFile); if (!id) { std::cout << " [failed; file not found]"; iRet = RET_NONCRITICAL_FAILURE; // one or more files failed } else { // Found it, open on disk auto pfsIn = destArch->open(id, bUseFilters); try { auto fsOut = std::make_shared<stream::output_file>(strLocalFile, true); try { stream::copy(*fsOut, *pfsIn); } catch (const stream::error& e) { std::cout << " [failed; read/write error: " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way } } catch (const stream::error&) { std::cout << " [failed; unable to create output file]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way } } } catch (const stream::error& e) { std::cout << " [failed; " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way } std::cout << std::endl; } else if (i.string_key.compare("delete") == 0) { std::string& strArchFile = i.value[0]; std::cout << " deleting: " << strArchFile << std::flush; try { auto destArch = pArchive; ga::Archive::FileHandle id; findFile(&destArch, &id, strArchFile); if (!id) { std::cout << " [failed; file not found]"; iRet = RET_NONCRITICAL_FAILURE; // one or more files failed } else { destArch->remove(id); } } catch (const stream::error& e) { std::cout << " [failed; " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way } std::cout << std::endl; } else if (i.string_key.compare("insert") == 0) { std::string strSource, strInsertBefore; if (!split(i.value[0], ':', &strSource, &strInsertBefore)) { std::cerr << PROGNAME ": -i/--insert requires a file to insert " "before (parameter should end with \":beforeme.xyz\")\n" "Or use --add instead." << std::endl; return RET_BADARGS; } std::string strArchFile, strLocalFile; bool bAltDest = split(strSource, '=', &strArchFile, &strLocalFile); std::cout << " inserting: " << strArchFile; if (!strLastFiletype.empty()) std::cout << " as type " << strLastFiletype; std::cout << " (before " << strInsertBefore; if (bAltDest) std::cout << ", from " << strLocalFile; std::cout << ")"; if (lenReal != 0) std::cout << ", with uncompressed size " << lenReal; std::cout << std::flush; // Try to find strInsertBefore auto destArch = pArchive; ga::Archive::FileHandle idBeforeThis; findFile(&destArch, &idBeforeThis, strInsertBefore); if (!idBeforeThis) { std::cout << " [failed; could not find " << strInsertBefore << "]"; iRet = RET_NONCRITICAL_FAILURE; // one or more files failed continue; } try { insertFile(destArch, strLocalFile, strArchFile, idBeforeThis, strLastFiletype, iLastAttr, lenReal); } catch (const stream::error& e) { std::cout << " [failed; " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way } std::cout << std::endl; // Remember --filetype/-y } else if (i.string_key.compare("filetype") == 0) { //} else if (i.string_key.compare("y") == 0) { strLastFiletype = i.value[0]; // Remember --attributes/-b } else if (i.string_key.compare("attribute") == 0) { //} else if (i.string_key.compare("b") == 0) { std::string nextAttr = i.value[0]; bool disable = (nextAttr[0] == '-'); if (disable) nextAttr = nextAttr.substr(1); ga::Archive::File::Attribute next; if (nextAttr.compare("empty") == 0) next = ga::Archive::File::Attribute::Vacant; else if (nextAttr.compare("hidden") == 0) next = ga::Archive::File::Attribute::Hidden; else if (nextAttr.compare("compressed") == 0) next = ga::Archive::File::Attribute::Compressed; else if (nextAttr.compare("encrypted") == 0) next = ga::Archive::File::Attribute::Encrypted; else { std::cerr << "Unknown attribute " << nextAttr << ", valid values are: empty hidden compressed encrypted" << std::endl; iRet = RET_UNCOMMON_FAILURE; next = ga::Archive::File::Attribute::Default; } if (next != ga::Archive::File::Attribute::Default) { auto allowed = pArchive->getSupportedAttributes(); if (allowed & next) { if (disable) iLastAttr &= ~next; else iLastAttr |= next; } else { std::cerr << "Warning: Attribute unsupported by archive format, " "ignoring: " << nextAttr << std::endl; } } // Remember --uncompressed-size/-z } else if (i.string_key.compare("uncompressed-size") == 0) { //} else if (i.string_key.compare("z") == 0) { if (bUseFilters) { std::cerr << PROGNAME ": -z/--uncompressed-size only needs to be " "specified when it can't be determined automatically (i.e. when " "-u/--unfiltered is in use.)" << std::endl; return RET_BADARGS; } lenReal = strtoul(i.value[0].c_str(), NULL, 0); // Ignore --type/-t } else if (i.string_key.compare("type") == 0) { } else if (i.string_key.compare("t") == 0) { // Ignore --script/-s } else if (i.string_key.compare("script") == 0) { } else if (i.string_key.compare("s") == 0) { // Ignore --force/-f } else if (i.string_key.compare("force") == 0) { } else if (i.string_key.compare("f") == 0) { } else if ((!i.string_key.empty()) && (i.value.size() > 0)) { // None of the above (single param) options matched, so it's probably // an option with up to two filenames (with an equal-sign as a // separator.) It could also be the --type option, which we'll ignore. std::string& strParam = i.value[0]; std::string strArchFile, strLocalFile; bool bAltDest = split(strParam, '=', &strArchFile, &strLocalFile); if (i.string_key.compare("add") == 0) { std::cout << " adding: " << strArchFile; if (!strLastFiletype.empty()) std::cout << " as type " << strLastFiletype; if (bAltDest) std::cout << " (from " << strLocalFile << ")"; if (lenReal != 0) std::cout << ", with uncompressed size set to " << lenReal; std::cout << std::endl; try { insertFile(pArchive, strLocalFile, strArchFile, nullptr, strLastFiletype, iLastAttr, lenReal); } catch (const stream::error& e) { std::cout << " [failed; " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a usual way } } else if (i.string_key.compare("rename") == 0) { if ((!bAltDest) || (boost::equals(strArchFile, strLocalFile))) { std::cout << "ignoring attempt to rename " << strArchFile << " into the same name" << std::endl; } else { std::cout << " renaming: " << strArchFile << " to " << strLocalFile << std::flush; try { auto destArch = pArchive; ga::Archive::FileHandle id; findFile(&destArch, &id, strArchFile); if (!id) { std::cout << " [failed; file not found inside archive]"; iRet = RET_NONCRITICAL_FAILURE; // one or more files failed } else { destArch->rename(id, strLocalFile); } } catch (const stream::error& e) { std::cout << " [failed; " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a common way } std::cout << std::endl; } } else if (i.string_key.compare("overwrite") == 0) { std::cout << "overwriting: " << strArchFile; if (bAltDest) std::cout << " (from " << strLocalFile << ")"; if (lenReal != 0) std::cout << ", with uncompressed size set to " << lenReal; std::cout << std::flush; try { // Find the file auto destArch = pArchive; ga::Archive::FileHandle id; findFile(&destArch, &id, strArchFile); if (!id) { std::cout << " [failed; file not found inside archive]"; iRet = RET_NONCRITICAL_FAILURE; // one or more files failed } else { // Found it, open replacement file auto sSrc = std::make_shared<stream::input_file>(strLocalFile); stream::len lenSource = sSrc->size(); // Note that we are opening the file into an output_sptr (instead // of an inout_sptr) as this is more efficient. By foregoing read // access to the file, it means a compressed file won't be // decompressed in case we want to read it. Which we don't, // because we're about to completely overwrite it. auto psDest = destArch->open(id, bUseFilters); // Set the size of the stream within the archive, so it exactly // holds the data we want to write. psDest->truncate(lenSource); if (!bUseFilters) { if (lenReal) { pArchive->resize(id, lenSource, lenReal); } else { // Leave the prefiltered/decompressed size unchanged pArchive->resize(id, lenSource, id->realSize); } } psDest->seekp(0, stream::start); stream::copy(*psDest, *sSrc); psDest->flush(); } } catch (const stream::open_error&) { std::cout << " [failed; unable to open replacement file]"; iRet = RET_NONCRITICAL_FAILURE; // one or more files failed } catch (const stream::error& e) { std::cout << " [failed; " << e.what() << "]"; iRet = RET_UNCOMMON_FAILURE; // some files failed, but not in a common way } std::cout << std::endl; } // else it's the archive filename, but we already have that } } // for (all command line elements) pArchive->flush(); } catch (const po::unknown_option& e) { std::cerr << PROGNAME ": " << e.what() << ". Use --help for help." << std::endl; return RET_BADARGS; } catch (const po::invalid_command_line_syntax& e) { std::cerr << PROGNAME ": " << e.what() << ". Use --help for help." << std::endl; return RET_BADARGS; } return iRet; }
/** * Calls itself recursively to extract any subfolders as well. */ void extractAll(std::shared_ptr<ga::Archive> archive, bool bScript) { unsigned int index = (unsigned int)-1; for (const auto& i : archive->files()) { index++; // Get the name of the file we're extracting from the archive-> std::string strLocalFile = i->strName; sanitisePath(strLocalFile); if (strLocalFile.empty()) { // This file has no filename (probably the archive format doesn't // support filenames) so we have to make one up. std::ostringstream ss; ss << "@" << index; strLocalFile = ss.str(); } if (i->fAttr & ga::Archive::File::Attribute::Folder) { // Tell the user what's going on if (bScript) { std::cout << "mkdir=" << strLocalFile; } else { std::cout << " mkdir: " << strLocalFile << '/' << std::flush; } fs::path old; try { // If the folder exists, add .1 .2 .3 etc. onto the end until an // unused name is found. This allows extracting folders with the // same name, without their files ending up lumped together in // the same real on-disk folder. if (fs::exists(strLocalFile)) { std::ostringstream ss; int j = 1; do { ss.str(std::string()); // empty the stringstream ss << strLocalFile << '.' << j; j++; } while (fs::exists(ss.str())); strLocalFile = ss.str(); if (!bScript) { std::cout << " (as " << strLocalFile << ")"; } } fs::create_directory(strLocalFile); if (bScript) std::cout << ";created=" << strLocalFile; old = fs::current_path(); fs::current_path(strLocalFile); if (bScript) std::cout << ";status=ok"; std::cout << std::endl; } catch (const fs::filesystem_error&) { if (bScript) { std::cout << ";status=fail"; } else { std::cout << " [failed; skipping folder]"; } ::iRet = RET_NONCRITICAL_FAILURE; // one or more files failed std::cout << std::endl; continue; } auto subArch = archive->openFolder(i); extractAll(std::move(subArch), bScript); fs::current_path(old); } else { // Tell the user what's going on if (bScript) { std::cout << "extracting=" << strLocalFile; } else { std::cout << " extracting: " << strLocalFile; } // Open on disk try { auto pfsIn = archive->open(i, bUseFilters); // If the file exists, add .1 .2 .3 etc. onto the end until an // unused name is found. This allows extracting files with the // same name, without them getting overwritten. if (fs::exists(strLocalFile)) { std::ostringstream ss; int j = 1; do { ss.str(std::string()); // empty the stringstream ss << strLocalFile << '.' << j; j++; } while (fs::exists(ss.str())); strLocalFile = ss.str(); if (!bScript) { std::cout << " (into " << strLocalFile << ")"; } } std::cout << std::flush; if (bScript) std::cout << ";wrote=" << strLocalFile; auto fsOut = std::make_unique<stream::output_file>(strLocalFile, true); // Copy the data from the in-archive stream to the on-disk stream stream::copy(*fsOut, *pfsIn); if (bScript) std::cout << ";status=ok"; } catch (...) { if (bScript) { std::cout << ";status=fail"; } else { std::cout << " [error]"; } ::iRet = RET_NONCRITICAL_FAILURE; // one or more files failed } std::cout << std::endl; } } return; }
// ---------------------------------------------------------------------------- // Handles the action [id]. // Returns true if the action was handled, false otherwise // ---------------------------------------------------------------------------- bool GfxEntryPanel::handleEntryPanelAction(std::string_view id) { // We're only interested in "pgfx_" actions if (!StrUtil::startsWith(id, "pgfx_")) return false; // For pgfx_brush actions, the string after pgfx is a brush name if (StrUtil::startsWith(id, "pgfx_brush")) { gfx_canvas_->setBrush(SBrush::get(std::string{ id })); button_brush_->setIcon(StrUtil::afterFirst(id, '_')); } // Editing - drag mode else if (id == "pgfx_drag") { editing_ = false; gfx_canvas_->setEditingMode(GfxCanvas::EditMode::None); } // Editing - draw mode else if (id == "pgfx_draw") { editing_ = true; gfx_canvas_->setEditingMode(GfxCanvas::EditMode::Paint); gfx_canvas_->setPaintColour(cb_colour_->colour()); } // Editing - erase mode else if (id == "pgfx_erase") { editing_ = true; gfx_canvas_->setEditingMode(GfxCanvas::EditMode::Erase); } // Editing - translate mode else if (id == "pgfx_magic") { editing_ = true; gfx_canvas_->setEditingMode(GfxCanvas::EditMode::Translate); } // Editing - set translation else if (id == "pgfx_settrans") { // Create translation editor dialog TranslationEditorDialog ted( theMainWindow, *theMainWindow->paletteChooser()->selectedPalette(), " Colour Remap", image()); // Create translation to edit ted.openTranslation(edit_translation_); // Show the dialog if (ted.ShowModal() == wxID_OK) { // Set the translation edit_translation_.copy(ted.getTranslation()); gfx_canvas_->setTranslation(&edit_translation_); } } // Editing - set brush else if (id == "pgfx_setbrush") { auto p = button_brush_->GetScreenPosition() -= GetScreenPosition(); p.y += button_brush_->GetMaxHeight(); PopupMenu(menu_brushes_, p); } // Mirror else if (id == "pgfx_mirror") { // Mirror X image()->mirror(false); // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; setModified(); } // Flip else if (id == "pgfx_flip") { // Mirror Y image()->mirror(true); // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; setModified(); } // Rotate else if (id == "pgfx_rotate") { // Prompt for rotation angle wxString angles[] = { "90", "180", "270" }; int choice = wxGetSingleChoiceIndex("Select rotation angle", "Rotate", 3, angles, 0); // Rotate image switch (choice) { case 0: image()->rotate(90); break; case 1: image()->rotate(180); break; case 2: image()->rotate(270); break; default: break; } // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; setModified(); } // Translate else if (id == "pgfx_remap") { // Create translation editor dialog auto pal = MainEditor::currentPalette(); TranslationEditorDialog ted(theMainWindow, *pal, " Colour Remap", &gfx_canvas_->image()); // Create translation to edit ted.openTranslation(prev_translation_); // Show the dialog if (ted.ShowModal() == wxID_OK) { // Apply translation to image image()->applyTranslation(&ted.getTranslation(), pal); // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; gfx_canvas_->updateImageTexture(); setModified(); prev_translation_.copy(ted.getTranslation()); } } // Colourise else if (id == "pgfx_colourise") { auto pal = MainEditor::currentPalette(); GfxColouriseDialog gcd(theMainWindow, entry_, *pal); gcd.setColour(last_colour); // Show colourise dialog if (gcd.ShowModal() == wxID_OK) { // Colourise image image()->colourise(gcd.colour(), pal); // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; Refresh(); setModified(); } last_colour = gcd.colour().toString(ColRGBA::StringFormat::RGB); } // Tint else if (id == "pgfx_tint") { auto pal = MainEditor::currentPalette(); GfxTintDialog gtd(theMainWindow, entry_, *pal); gtd.setValues(last_tint_colour, last_tint_amount); // Show tint dialog if (gtd.ShowModal() == wxID_OK) { // Tint image image()->tint(gtd.colour(), gtd.amount(), pal); // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; Refresh(); setModified(); } last_tint_colour = gtd.colour().toString(ColRGBA::StringFormat::RGB); last_tint_amount = (int)(gtd.amount() * 100.0); } // Crop else if (id == "pgfx_crop") { auto image = this->image(); auto pal = MainEditor::currentPalette(); GfxCropDialog gcd(theMainWindow, image, pal); // Show crop dialog if (gcd.ShowModal() == wxID_OK) { // Prompt to adjust offsets auto crop = gcd.cropRect(); if (crop.tl.x > 0 || crop.tl.y > 0) { if (wxMessageBox( "Do you want to adjust the offsets? This will keep the graphic in the same relative " "position it was before cropping.", "Adjust Offsets?", wxYES_NO) == wxYES) { image->setXOffset(image->offset().x - crop.tl.x); image->setYOffset(image->offset().y - crop.tl.y); } } // Crop image image->crop(crop.x1(), crop.y1(), crop.x2(), crop.y2()); // Update UI gfx_canvas_->updateImageTexture(); gfx_canvas_->Refresh(); // Update variables image_data_modified_ = true; Refresh(); setModified(); } } // alPh/tRNS else if (id == "pgfx_alph" || id == "pgfx_trns") { setModified(); Refresh(); } // Optimize PNG else if (id == "pgfx_pngopt") { // This is a special case. If we set the entry as modified, SLADE will prompt // to save it, rewriting the entry and cancelling the optimization done... if (EntryOperations::optimizePNG(entry_)) setModified(false); else wxMessageBox( "Warning: Couldn't optimize this image, check console log for info", "Warning", wxOK | wxCENTRE | wxICON_WARNING); Refresh(); } // Extract all else if (id == "pgfx_extract") { extractAll(); } // Convert else if (id == "pgfx_convert") { GfxConvDialog gcd(theMainWindow); gcd.CenterOnParent(); gcd.openEntry(entry_); gcd.ShowModal(); if (gcd.itemModified(0)) { // Get image and conversion info auto image = gcd.itemImage(0); auto format = gcd.itemFormat(0); // Write converted image back to entry format->saveImage(*image, entry_data_, gcd.itemPalette(0)); // This makes the "save" button (and the setModified stuff) redundant and confusing! // The alternative is to save to entry effectively (uncomment the importMemChunk line) // but remove the setModified and image_data_modified lines, and add a call to refresh // to get the PNG tRNS status back in sync. // entry->importMemChunk(entry_data); image_data_modified_ = true; setModified(); // Fix tRNS status if we converted to paletted PNG int MENU_GFXEP_PNGOPT = SAction::fromId("pgfx_pngopt")->wxId(); int MENU_GFXEP_ALPH = SAction::fromId("pgfx_alph")->wxId(); int MENU_GFXEP_TRNS = SAction::fromId("pgfx_trns")->wxId(); int MENU_ARCHGFX_EXPORTPNG = SAction::fromId("arch_gfx_exportpng")->wxId(); if (format->name() == "PNG") { ArchiveEntry temp; temp.importMemChunk(entry_data_); temp.setType(EntryType::fromId("png")); menu_custom_->Enable(MENU_GFXEP_ALPH, true); menu_custom_->Enable(MENU_GFXEP_TRNS, true); menu_custom_->Check(MENU_GFXEP_TRNS, EntryOperations::gettRNSChunk(&temp)); menu_custom_->Enable(MENU_ARCHGFX_EXPORTPNG, false); menu_custom_->Enable(MENU_GFXEP_PNGOPT, true); toolbar_->enableGroup("PNG", true); } else { menu_custom_->Enable(MENU_GFXEP_ALPH, false); menu_custom_->Enable(MENU_GFXEP_TRNS, false); menu_custom_->Enable(MENU_ARCHGFX_EXPORTPNG, true); menu_custom_->Enable(MENU_GFXEP_PNGOPT, false); toolbar_->enableGroup("PNG", false); } // Refresh this->image()->open(entry_data_, 0, format->id()); gfx_canvas_->Refresh(); } } // Unknown action else return false; // Action handled return true; }
void Zip::extract(QNetworkReply* reply) { #ifdef Q_OS_MAC // CFURLRef appURLRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); // char path[PATH_MAX]; // if (!CFURLGetFileSystemRepresentation(appURLRef, TRUE, (UInt8 *)path, PATH_MAX)) { // // error! // } // CFRelease(appURLRef); // QString filePath = QString(path); // QString rootDirectory = filePath.left(filePath.lastIndexOf("/")); QDir dir = QDir(QCoreApplication::applicationDirPath()); dir.cdUp(); dir.cdUp(); #else QString rootDirectory = QCoreApplication::applicationDirPath() + "/"; #endif // Write download into File QFileInfo fileInfo=reply->url().path(); qDebug() << reply->url().path(); QString fileName = rootDirectory + fileInfo.fileName(); qDebug()<<"Writing downloaded file into "<<fileName; QFile file(fileName); file.open(QIODevice::WriteOnly); file.write(reply->readAll()); file.close(); zip_file zipFile(fileName.toStdString()); try { std::vector <zip_info> updateFiles = zipFile.infolist(); // Rename all current files with available update. for (size_t i=0;i<updateFiles.size();i++) { QString sourceFilePath = rootDirectory + QString::fromStdString(updateFiles[i].filename); QDir appDir( QCoreApplication::applicationDirPath() ); QFileInfo file( sourceFilePath ); if(file.exists()) { //qDebug()<<tr("Moving file %1 to %2").arg(sourceFilePath).arg(sourceFilePath+".oldversion"); appDir.rename( sourceFilePath, sourceFilePath+".oldversion" ); } } // Install updated Files extractAll(&zipFile); } catch(std::exception const& e) { qDebug() << "Exception: " << e.what() << "\n"; } // Delete update archive while(QFile::remove(fileName) ) { }; /// Restart extracted Updater in install mode /// ./extractedpath/TARGET appPath extractedpath QApplication::exit(200); // Restart ap to clean up and start usual business ///d->manager()->helper()->restartApplication(); }