newtx/hardware/cis/cis_param.cpp

503 lines
15 KiB
C++
Raw Permalink Normal View History

#include "cis_param.h"
#include <vector>
#include <string>
#include <algorithm>
#include <base/utils.h>
#include <json/gb_json.h>
#include <sane/sane_name.h>
#include <base/words.h>
namespace correct
{
typedef struct _cond_data
{
bool clr;
int dpi;
int val;
}CONDDATA;
typedef struct _correct_data
{
std::string name;
std::vector<CONDDATA> 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<CORDATA>& 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<CORDATA>& 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<CORDATA> load_old_correct_data(const char* file, std::vector<int>* dpis = nullptr)
{
std::vector<CORDATA> old;
std::string cont(utils::load_mini_file(file, nullptr));
gb_json *root = new gb_json();
std::vector<int> 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<int>& 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<int> get_fixed_resolution(void)
{
std::vector<int> 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<int> fixed_res; // (get_fixed_resolution());
std::vector<correct::CORDATA> 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();
}
}