#include "cis_param.h" #include #include #include #include #include #include #include namespace correct { typedef struct _cond_data { bool clr; int dpi; int val; }CONDDATA; typedef struct _correct_data { std::string name; std::vector data; }CORDATA; const char* names[] = {SANE_OPT_NAME(CIS_SP) , SANE_OPT_NAME(CIS_EXPO_FB), SANE_OPT_NAME(CIS_EXPO_FG), SANE_OPT_NAME(CIS_EXPO_FR) , SANE_OPT_NAME(CIS_EXPO_BB), SANE_OPT_NAME(CIS_EXPO_BG), SANE_OPT_NAME(CIS_EXPO_BR) // , SANE_OPT_NAME(CIS_STRETCH_H), SANE_OPT_NAME(CIS_STRETCH_V) }, *names_plus[] = {SANE_OPT_NAME(CIS_GAIN_FRONT), SANE_OPT_NAME(CIS_GAIN_BACK) , SANE_OPT_NAME(CIS_OFFSET_FRONT), SANE_OPT_NAME(CIS_OFFSET_BACK) }; static bool add_data(std::vector& que, const char* name, CONDDATA& data) { bool found = false; for(auto& v: que) { if(v.name == name) { found = true; v.data.push_back(data); break; } } return found; } static void parse_mode(gb_json* root, std::vector& que, CONDDATA& data) { gb_json *child = nullptr, *leaf = nullptr; root->get_value("ExposureF", child); if(child) { // R - G - B if(child->children() >= 3) { leaf = child->first_child(); leaf->value(data.val); leaf->release(); add_data(que, SANE_OPT_NAME(CIS_EXPO_FR), data); leaf = child->next_child(); leaf->value(data.val); leaf->release(); add_data(que, SANE_OPT_NAME(CIS_EXPO_FG), data); leaf = child->next_child(); leaf->value(data.val); leaf->release(); add_data(que, SANE_OPT_NAME(CIS_EXPO_FB), data); } child->release(); } root->get_value("ExposureB", child); if(child) { // R - G - B if(child->children() >= 3) { leaf = child->first_child(); leaf->value(data.val); leaf->release(); add_data(que, SANE_OPT_NAME(CIS_EXPO_BR), data); leaf = child->next_child(); leaf->value(data.val); leaf->release(); add_data(que, SANE_OPT_NAME(CIS_EXPO_BG), data); leaf = child->next_child(); leaf->value(data.val); leaf->release(); add_data(que, SANE_OPT_NAME(CIS_EXPO_BB), data); } child->release(); } root->get_value("GainF", child); if(child) { int ind = 0; leaf = child->first_child(); while(leaf) { std::string n(SANE_OPT_NAME(CIS_GAIN_FRONT)); leaf->value(data.val); leaf->release(); n += "-" + std::to_string(++ind); if(!add_data(que, n.c_str(), data)) break; leaf = child->next_child(); } child->release(); } root->get_value("GainB", child); if(child) { int ind = 0; leaf = child->first_child(); while(leaf) { std::string n(SANE_OPT_NAME(CIS_GAIN_BACK)); leaf->value(data.val); leaf->release(); n += "-" + std::to_string(++ind); if(!add_data(que, n.c_str(), data)) break; leaf = child->next_child(); } child->release(); } root->get_value("OffsetF", child); if(child) { int ind = 0; leaf = child->first_child(); while(leaf) { std::string n(SANE_OPT_NAME(CIS_OFFSET_FRONT)); leaf->value(data.val); leaf->release(); n += "-" + std::to_string(++ind); if(!add_data(que, n.c_str(), data)) break; leaf = child->next_child(); } child->release(); } root->get_value("OffsetB", child); if(child) { int ind = 0; leaf = child->first_child(); while(leaf) { std::string n(SANE_OPT_NAME(CIS_OFFSET_BACK)); leaf->value(data.val); leaf->release(); n += "-" + std::to_string(++ind); if(!add_data(que, n.c_str(), data)) break; leaf = child->next_child(); } child->release(); } if(root->get_value("Sp", data.val)) add_data(que, SANE_OPT_NAME(CIS_SP), data); } static bool sort_cd(const CONDDATA& l, const CONDDATA& r) { if(l.dpi < r.dpi) return true; else if(l.dpi > r.dpi) return false; else return l.clr > r.clr; } std::vector load_old_correct_data(const char* file, std::vector* dpis = nullptr) { std::vector old; std::string cont(utils::load_mini_file(file, nullptr)); gb_json *root = new gb_json(); std::vector res; for(auto& v: names) { CORDATA cd; cd.name = v; old.push_back(cd); } for(auto& v: names_plus) { for(int i = 0; i < CIS_SECTOR_COUNT; ++i) { CORDATA cd; cd.name = v; cd.name += "-" + std::to_string(i + 1); old.push_back(cd); } } if(root->attach_text(&cont[0])) { gb_json* child = root->first_child(); while(child) { CONDDATA data; int val = 0; if(child->get_value("ColorMode", val)) { data.clr = val; if(child->get_value("DpiMode", val)) { if(val == 1) data.dpi = 200; else if(val == 2) data.dpi = 300; else if(val == 3) data.dpi = 600; else data.dpi = 0; if(data.dpi) { if(std::find(res.begin(), res.end(), data.dpi) == res.end()) res.push_back(data.dpi); parse_mode(child, old, data); } } } child->release(); child = root->next_child(); } } root->release(); for(int i = 0; i < old.size(); ++i) { if(old[i].data.size() == 0) { printf("No correct data for '%s'\n", old[i].name.c_str()); old.erase(old.begin() + i); i--; } else { std::sort(old[i].data.begin(), old[i].data.end(), sort_cd); } } if(dpis) { std::sort(res.begin(), res.end()); *dpis = std::move(res); } return std::move(old); } int save_correct_data(CORDATA& data, std::vector& fixed_dpi, int init_dpi, bool init_clr) { correct::CONDDATA def; int err = 0; std::string root(CIS_CORRECT_DATA_PATH), cont(""), clr(""), gray(""); gb_json *init = new gb_json(); uint8_t *utf8 = (uint8_t*)WORDS_COLOR_COLOR; err = utils::utf8_2_web(utf8, clr); if(err) clr = WORDS_COLOR_COLOR; utf8 = (uint8_t*)WORDS_COLOR_GRAY; err = utils::utf8_2_web(utf8, gray); if(err) gray = WORDS_COLOR_GRAY; for(auto& item: data.data) { if(item.clr == init_clr && item.dpi == init_dpi) def = item; else { std::string key(SANE_OPT_NAME(CIS_MODE)); key += "=="; if(item.clr) key += clr; else key += gray; key += "&&"; if(fixed_dpi.size()) { key += SANE_OPT_NAME(RESOLUTION); for(size_t i = 0; i < fixed_dpi.size(); ++i) { if(item.dpi <= fixed_dpi[i]) { if(i + 1 < fixed_dpi.size()) { if(i == 0) key += "<=" + std::to_string((fixed_dpi[i] + fixed_dpi[i + 1]) / 2); else // key += ">" + std::to_string((fixed_dpi[i] + fixed_dpi[i - 1]) / 2) // + "&&" + SANE_OPT_NAME(RESOLUTION) // + "<=" + std::to_string((fixed_dpi[i] + fixed_dpi[i + 1]) / 2); key += "==[" + std::to_string((fixed_dpi[i] + fixed_dpi[i - 1]) / 2) + "," + std::to_string((fixed_dpi[i] + fixed_dpi[i + 1]) / 2) + "]"; } else key += ">" + std::to_string(i > 0 ? (fixed_dpi[i] + fixed_dpi[i - 1]) / 2 : fixed_dpi[i]); break; } else if(i == fixed_dpi.size() - 1) key += ">=" + std::to_string(fixed_dpi[i]); } } else { key += SANE_OPT_NAME(CIS_DPI); key += "==" + std::to_string(item.dpi); } init->set_value(key.c_str(), item.val); } } init->set_value("default", def.val); cont = init->to_string(); init->release(); utils::save_2_file(&cont[0], cont.length(), (root + data.name + ".json").c_str()); return err; } }; namespace cis { std::vector get_fixed_resolution(void) { std::vector res; res.push_back(300); res.push_back(600); return std::move(res); } int get_sector_pixels(int sec_num, int dpi, bool side) { // both side and all sectors has the same pixel if(dpi == 600) return 1296; else return 648; } int get_line_stream_length(int dpi, bool color) { int l = get_sector_pixels(0, dpi, true) * CIS_SECTOR_COUNT; if(color) l *= 3; return l; } void update_correct_data(int init_dpi, bool init_clr, bool force) { std::string src("/usr/local/huago/cameraparam.json"), root(CIS_CORRECT_DATA_PATH); uint64_t src_m = 0, dst_m = 0; std::vector fixed_res; // (get_fixed_resolution()); std::vector old(correct::load_old_correct_data(src.c_str(), &fixed_res)); if(utils::get_file_time(src.c_str(), nullptr, &src_m, nullptr) && !force) return; std::sort(fixed_res.begin(), fixed_res.end()); for(auto& v: correct::names) { std::string fn(root + v + ".json"); if(!force && utils::get_file_time(fn.c_str(), nullptr, &dst_m, nullptr) == 0 && dst_m >= src_m) { printf("%s is up-to-date.\n", fn.c_str()); continue; } for(auto& n: old) { if(n.name == v) { correct::save_correct_data(n, fixed_res, init_dpi, init_clr); break; } } } for(auto& v: correct::names_plus) { for(int i = 0; i < CIS_SECTOR_COUNT; ++i) { std::string fn(std::string(v) + "-" + std::to_string(i + 1)); if(!force && utils::get_file_time((root + fn + ".json").c_str(), nullptr, &dst_m, nullptr) == 0 && dst_m >= src_m) { printf("%s is up-to-date.\n", fn.c_str()); continue; } for(auto& n: old) { if(n.name == fn) { correct::save_correct_data(n, fixed_res, init_dpi, init_clr); break; } } } } } void load_correct_data_to_json(gb_json* jsn) { std::string root(CIS_CORRECT_DATA_PATH); gb_json *child = nullptr; gb_json *last = new gb_json(); for(auto& v: correct::names) { jsn->get_value(v, child); if(child) { std::string data(utils::load_mini_file((root + v + ".json").c_str(), nullptr)); if(last->attach_text(&data[0])) { gb_json* def = nullptr; child->get_value("default", def); if(def) { utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' Before: %s\n", v, child->to_string().c_str()); def->attach_text(&data[0]); def->key() = "default"; def->release(); utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' After: %s\n", v, child->to_string().c_str()); } } child->release(); } } for(auto& v: correct::names_plus) { for(int i = 0; i < CIS_SECTOR_COUNT; ++i) { std::string fn(v); fn += "-" + std::to_string(i + 1); jsn->get_value(fn.c_str(), child); if(child) { std::string data(utils::load_mini_file((root + fn + ".json").c_str(), nullptr)); if(last->attach_text(&data[0])) { gb_json* def = nullptr; child->get_value("default", def); if(def) { utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' Before: %s\n", fn.c_str(), child->to_string().c_str()); def->attach_text(&data[0]); def->key() = "default"; def->release(); utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' After: %s\n", fn.c_str(), child->to_string().c_str()); } } child->release(); } } } last->release(); } }