#include "parseargs.hh" #include #include constexpr int DEFAULT_ITERATIONS = 2000; using path = std::filesystem::path; namespace po = boost::program_options; /** * \brief Ensures correct output path * * Checks if an output file exists, and if yes if it has an extension. In case * it doesn’t exist, `output_` is appended at the beginning of the input * filename. If the output path does not have an extension, the type `.png` is * appended at the end of the path. * * \param[in] t_vm Arguments passed to the program * \param[out] t_input Input path * \param[out] t_output Output path */ void processFilenames(po::variables_map const &t_vm, path const &t_input, path &t_output) { if (!t_vm.count("output")) { t_output.replace_filename("output_" + std::string{t_input.filename().string()}); } else if (!t_output.has_extension()) { t_output.replace_extension(".png"); } } /** * Parses the arguments given to the program, formats them and returns them as * a tuple. If `-h` or `--help` or a malformed argument is passed, then the * list of arguments and their comment will be displayed, and the program will * exit. * * \param[in] t_ac Number of arguments passed to the program * \param[in] t_av Arguments passed to the program * \return Tuple of path, path, int, int, int, int, int, bool and bool */ [[nodiscard]] auto parse_args(int t_ac, char **t_av) -> ParsedArgs { ParsedArgs ret{}; po::options_description desc("Allowed options"); desc.add_options()("help,h", "Display this help message")( "input,i", po::value(), "Input image")("output,o", po::value(), "Image output path (default: \"output_\" + input path)")( "iterations,n", po::value(), "Number of iterations (default: 2000)")( "method,m", po::value(), "Method number to be used (default: 1)")( "form,f", po::value(), "Select shape (1:square, 2:triangle)")( "cols,c", po::value(), "For method 5 only, number of columns the reference image should be " "divided into. If the value is equal to 0, then it will be assumed " "there will be as many rows as there are collumns. (default: 0)")( "rows,r", po::value(), "For method 5 only, number of rows the reference image should be " "divided into. (default: 1)")( "submethod,S", po::value(), "Sub-method that will be used to generate the individual tiles from " "method 5. (default: 1)")("size,s", "Enables controlled size of the random shapes")( "verbose,v", "Enables verbosity"); po::variables_map vm; po::store(po::parse_command_line(t_ac, t_av, desc), vm); po::notify(vm); if (vm.count("help") || !vm.count("input")) { std::cout << desc << "\n"; std::exit(!vm.count("help")); } auto const input_path = vm["input"].as(); auto output_path = vm.count("output") ? vm["output"].as() : input_path.filename(); processFilenames(vm, input_path, output_path); ret.input_path = input_path; ret.output_path = output_path; ret.iterations = vm.count("iterations") ? vm["iterations"].as() : DEFAULT_ITERATIONS; ret.method = vm.count("method") ? vm["method"].as() : 1; switch (vm.count("form") ? vm["form"].as() : 1) { case 2: ret.shape = Shape::ShapeType::Triangle; break; case 1: ret.shape = Shape::ShapeType::Square; break; default: ret.shape = Shape::ShapeType::Square; break; } ret.cols = vm.count("cols") ? vm["cols"].as() : 0; ret.rows = vm.count("rows") ? vm["rows"].as() : 1; ret.submethod = vm.count("submethod") ? vm["submethod"].as() : 1; ret.controlled_size = vm.count("size"); ret.verbose = vm.count("verbose"); return ret; }