mirror of
https://github.com/Tptr-lateworker/RealESR_Tools.git
synced 2025-01-07 03:17:34 +08:00
285 lines
9.5 KiB
C++
285 lines
9.5 KiB
C++
#include <iostream>
|
|
#include <regex>
|
|
#include <fstream>
|
|
#include <stdlib.h>
|
|
#include "include/configor/json.hpp"
|
|
#include "include/path.h"
|
|
#include "include/system.h"
|
|
|
|
using namespace std;
|
|
using namespace path;
|
|
using namespace configor;
|
|
string selfPath, selfName;
|
|
|
|
inline bool loadConfig(string path, json::value &data) {
|
|
data.clear();
|
|
ifstream file(path.c_str());
|
|
if (!file.is_open()) return true;
|
|
try {
|
|
file >> json::wrap(data);
|
|
} catch (exception &ERROR) { return true; }
|
|
file.close();
|
|
return false;
|
|
}
|
|
|
|
struct RegexRule {
|
|
struct _rule {
|
|
string _name, _path, _name_mode, _path_mode;
|
|
_rule() { _name = _path = _name_mode = _path_mode = ""; }
|
|
CONFIGOR_BIND(
|
|
json::value, _rule,
|
|
OPTIONAL(_name, "name"),
|
|
OPTIONAL(_path, "path"),
|
|
OPTIONAL(_name_mode, "name_mode"),
|
|
OPTIONAL(_path_mode, "path_mode")
|
|
);
|
|
};
|
|
vector<_rule> rule;
|
|
inline void init(const json::value &data) {
|
|
for (json::value x : data) rule.push_back(x);
|
|
}
|
|
inline bool check(const string &name, const string &path) const {
|
|
for (RegexRule::_rule x : rule) {
|
|
bool res1, res2;
|
|
res1 = res2 = true;
|
|
if (x._name != "") {
|
|
regex match(x._name);
|
|
if (x._name_mode == "search") res1 = regex_search(name, match);
|
|
else res1 = regex_match(name, match);
|
|
}
|
|
if (x._path != "") {
|
|
regex match(x._path);
|
|
if (x._path_mode == "search") res2 = regex_search(name, match);
|
|
else res2 = regex_match(name, match);
|
|
}
|
|
if (res1 && res2) return false;
|
|
}
|
|
return true;
|
|
}
|
|
void operator= (const json::value &data) { init(data); }
|
|
RegexRule() { rule.clear(); }
|
|
};
|
|
#define Addon_config to_string(config.config_data)
|
|
#define Addon_first config.addons.first
|
|
#define Addon_second config.addons.second
|
|
#define Addon_third config.addons.third
|
|
struct Addon {
|
|
vector<string> first, second, third;
|
|
inline void init(const json::value &data) {
|
|
if (data.count("first") > 0) for (json::value x : data["first"]) first.push_back(x);
|
|
if (data.count("second") > 0) for (json::value x : data["second"]) second.push_back(x);
|
|
if (data.count("third") > 0) for (json::value x : data["third"]) third.push_back(x);
|
|
}
|
|
void operator= (const json::value &data) { init(data); }
|
|
Addon() { first.clear(), second.clear(), third.clear(); }
|
|
};
|
|
struct Config {
|
|
json::value config_data;
|
|
string config_path;
|
|
string input_path, output_path, error_path, selector;
|
|
string model, scale, denoise, syncgap;
|
|
size_t pos_slash, is_file;
|
|
bool tree_restore, subdir_find, emptydir_find;
|
|
bool file_error, dir_error;
|
|
RegexRule match;
|
|
Addon addons;
|
|
|
|
CONFIGOR_BIND(
|
|
json::value, Config,
|
|
REQUIRED(input_path, "input_path"),
|
|
REQUIRED(output_path, "output_path"),
|
|
OPTIONAL(error_path, "error_path"),
|
|
OPTIONAL(selector, "selector"),
|
|
REQUIRED(model, "model"),
|
|
REQUIRED(scale, "scale"),
|
|
OPTIONAL(denoise, "denoise"),
|
|
OPTIONAL(syncgap, "syncgap"),
|
|
REQUIRED(tree_restore, "tree_restore"),
|
|
REQUIRED(subdir_find, "subdir_find"),
|
|
OPTIONAL(emptydir_find, "emptydir_find"),
|
|
OPTIONAL(file_error, "file_error"),
|
|
OPTIONAL(dir_error, "dir_error")
|
|
);
|
|
inline void init() {
|
|
pathDelete(input_path);
|
|
pathDelete(output_path);
|
|
pathDelete(error_path);
|
|
pathDelete(selector);
|
|
pos_slash = input_path.find_last_of('\\');
|
|
if (pos_slash == string::npos) pos_slash = 0;
|
|
is_file = getFileAttribute(input_path).is_file();
|
|
}
|
|
inline bool init(const string &configPath) {
|
|
json::value configData;
|
|
bool is_failed = loadConfig(configPath, configData);
|
|
if (is_failed) return true;
|
|
*this = configData;
|
|
|
|
config_data = configData;
|
|
config_path = configPath;
|
|
init();
|
|
if (configData.count("match") > 0) match.init(configData["match"]);
|
|
if (configData.count("addons") > 0) addons.init(configData["addons"]);
|
|
return false;
|
|
}
|
|
inline Config getSubConfig(const TraverseData *data) const {
|
|
Config _file = *this;
|
|
if (_file.is_file) {
|
|
_file.input_path = output_path + "\\" + input_path.substr(pos_slash);
|
|
} else {
|
|
if (tree_restore) _file.input_path = output_path + "\\" + data->fullpath().substr(input_path.length());
|
|
else _file.input_path = output_path + "\\" + data->name;
|
|
}
|
|
_file.output_path = _file.input_path;
|
|
_file.init();
|
|
return _file;
|
|
}
|
|
inline bool checkRegex(const string &name, const string &path) const { return match.check(name, path); }
|
|
Config() {
|
|
config_data = json::value();
|
|
config_path = "";
|
|
input_path = output_path = model = scale = "";
|
|
error_path = "";
|
|
selector = "*";
|
|
denoise = syncgap = "0";
|
|
pos_slash = is_file = 0;
|
|
tree_restore = subdir_find = emptydir_find = false;
|
|
file_error = true, dir_error = false;
|
|
match = RegexRule();
|
|
addons = Addon();
|
|
}
|
|
};
|
|
|
|
#define Waifu2x_Anime "models-upconv_7_anime_style_art_rgb"
|
|
#define Waifu2x_Photo "models-upconv_7_photo"
|
|
inline int getgroup_model(const string &model) {
|
|
if (model == "realesrgan" || model == "realesrnet" || model == "realesrgan-anime" || model == "DF2K" || model == "DF2K-JPEG") return 1;
|
|
if (model == "waifu2x-anime" || model == "waifu2x-photo") return 2;
|
|
if (model == "realcugan") return 3;
|
|
return 0;
|
|
}
|
|
inline void core(const Config &file) {
|
|
string command;
|
|
if (getgroup_model(file.model) == 1) {
|
|
command = (string)"models\\realesrgan.exe"
|
|
+ " -i " + pathQuote(file.input_path)
|
|
+ " -o " + pathQuote(file.output_path)
|
|
+ " -n " + pathQuote(file.model + "-x" + file.scale)
|
|
+ " -s " + file.scale;
|
|
}
|
|
if (getgroup_model(file.model) == 2) {
|
|
command = (string)"models\\waifu2x.exe"
|
|
+ " -i " + pathQuote(file.input_path)
|
|
+ " -o " + pathQuote(file.output_path)
|
|
+ " -m " + pathQuote(file.model == "waifu2x-anime" ? Waifu2x_Anime : Waifu2x_Photo)
|
|
+ " -s " + file.scale
|
|
+ " -n " + file.denoise;
|
|
}
|
|
if (getgroup_model(file.model) == 3) {
|
|
command = (string)"models\\realcugan.exe"
|
|
+ " -i " + pathQuote(file.input_path)
|
|
+ " -o " + pathQuote(file.output_path)
|
|
+ " -s " + file.scale
|
|
+ " -n " + file.denoise
|
|
+ " -c " + file.syncgap;
|
|
}
|
|
chdir(selfPath.c_str()); // 不知道是哪里出问题了, 这里必须手动切换目录.
|
|
executefile(command);
|
|
}
|
|
|
|
string to_string(const json::value &x) {
|
|
string res = json::dump(x);
|
|
for (size_t i = 0; i < res.size(); ++i)
|
|
if (res[i] == '\"')
|
|
res.insert(i++, "\\");
|
|
pathDelete(res);
|
|
return res;
|
|
}
|
|
string Addon_getRelativePath(const Config &config, string x) {
|
|
x = x.substr(config.output_path.size()); pathDelete(x);
|
|
return x;
|
|
}
|
|
json::value to_json(const Config &config, const vector<string> &data) {
|
|
json::value jsondata;
|
|
for (string x : data)
|
|
jsondata.push_back(Addon_getRelativePath(config, x));
|
|
return jsondata;
|
|
}
|
|
|
|
inline void process_error(const Config &config, const Config &data) {
|
|
string errorPath = config.error_path;
|
|
errorPath = errorPath + "\\" + data.input_path.substr(0, data.pos_slash).substr(config.output_path.size());
|
|
pathDelete(errorPath);
|
|
makedir(errorPath);
|
|
movefile(data.input_path, errorPath);
|
|
}
|
|
void executeAddon(const Config &config, const vector<string> &execute, const string ¶meter1, const string ¶meter2) {
|
|
for (string x : execute) {
|
|
copyfile("addons\\" + x, config.output_path + "\\" + x);
|
|
chdir(config.output_path.c_str());
|
|
executefile(x + " " + pathQuote(parameter1) + " " + pathQuote(parameter2));
|
|
deletefile(x);
|
|
chdir(selfPath.c_str());
|
|
}
|
|
}
|
|
|
|
void process(const Config &config) {
|
|
makedir(config.output_path);
|
|
executeAddon(config, Addon_first, Addon_config, "");
|
|
|
|
vector<string> data_addons;
|
|
if (config.is_file) {
|
|
Config _file = config.getSubConfig(nullptr);
|
|
if (config.file_error && pathExist(_file.input_path)) {
|
|
process_error(config, _file);
|
|
}
|
|
copyfile(config.input_path, _file.input_path);
|
|
data_addons.push_back(_file.input_path);
|
|
core(_file);
|
|
executeAddon(config, Addon_second, Addon_config, Addon_getRelativePath(config, _file.input_path));
|
|
} else {
|
|
vector<TraverseData> data;
|
|
traverse(config.input_path, data, config.selector, {true, true, config.subdir_find, config.emptydir_find});
|
|
for (TraverseData x : data) {
|
|
if (!x.attrib.is_folder() && config.checkRegex(x.name, x.path)) {
|
|
Config _file = config.getSubConfig(&x);
|
|
if (config.file_error && pathExist(_file.input_path)) {
|
|
process_error(config, _file);
|
|
}
|
|
data_addons.push_back(_file.input_path);
|
|
copyfile(x.fullpath(), _file.input_path);
|
|
core(_file);
|
|
executeAddon(config, Addon_second, Addon_config, Addon_getRelativePath(config, _file.input_path));
|
|
}
|
|
if (config.tree_restore && x.attrib.is_folder() && config.checkRegex(x.name, x.path)) {
|
|
Config _dir = config.getSubConfig(&x);
|
|
if (config.dir_error && pathExist(_dir.input_path)) {
|
|
process_error(config, _dir);
|
|
}
|
|
data_addons.push_back(_dir.input_path);
|
|
makedir(_dir.input_path);
|
|
executeAddon(config, Addon_second, Addon_config, Addon_getRelativePath(config, _dir.input_path));
|
|
}
|
|
}
|
|
}
|
|
|
|
executeAddon(config, Addon_third, Addon_config, to_string(to_json(config, data_addons)));
|
|
}
|
|
|
|
int main(int n, char **configPath) {
|
|
pathSplit(_pgmptr, selfPath, selfName);
|
|
pathDelete(selfPath), pathDelete(selfName);
|
|
for (int i = 1; i < n; ++i) {
|
|
Config config;
|
|
bool is_failed = config.init(configPath[i]);
|
|
if (is_failed) {
|
|
puts("ConfigFile Error");
|
|
system("pause");
|
|
// Create config file as default && reload
|
|
continue;
|
|
}
|
|
process(config);
|
|
}
|
|
return 0;
|
|
}
|