2024-01-19 08:54:58 +00:00
|
|
|
#include "cis_param.h"
|
|
|
|
|
2024-02-21 09:44:32 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2024-02-22 02:31:24 +00:00
|
|
|
#include <algorithm>
|
2024-02-21 09:44:32 +00:00
|
|
|
#include <base/utils.h>
|
|
|
|
#include <json/gb_json.h>
|
|
|
|
#include <sane/sane_name.h>
|
|
|
|
#include <base/words.h>
|
2024-01-19 08:54:58 +00:00
|
|
|
|
2024-02-21 09:44:32 +00:00
|
|
|
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);
|
|
|
|
}
|
2024-02-22 02:31:24 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-23 07:59:31 +00:00
|
|
|
|
2024-02-22 02:31:24 +00:00
|
|
|
std::vector<CORDATA> load_old_correct_data(const char* file, std::vector<int>* dpis = nullptr)
|
2024-02-21 09:44:32 +00:00
|
|
|
{
|
|
|
|
std::vector<CORDATA> old;
|
|
|
|
std::string cont(utils::load_mini_file(file, nullptr));
|
|
|
|
gb_json *root = new gb_json();
|
2024-02-22 02:31:24 +00:00
|
|
|
std::vector<int> res;
|
2024-02-21 09:44:32 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2024-02-22 02:31:24 +00:00
|
|
|
if(std::find(res.begin(), res.end(), data.dpi) == res.end())
|
|
|
|
res.push_back(data.dpi);
|
2024-02-21 09:44:32 +00:00
|
|
|
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--;
|
|
|
|
}
|
2024-02-22 02:31:24 +00:00
|
|
|
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);
|
2024-02-21 09:44:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return std::move(old);
|
|
|
|
}
|
2024-02-23 07:59:31 +00:00
|
|
|
|
2024-02-22 02:31:24 +00:00
|
|
|
int save_correct_data(CORDATA& data, std::vector<int>& fixed_dpi, int init_dpi, bool init_clr)
|
|
|
|
{
|
|
|
|
correct::CONDDATA def;
|
|
|
|
int err = 0;
|
2024-02-23 07:59:31 +00:00
|
|
|
std::string root(CIS_CORRECT_DATA_PATH), cont(""),
|
|
|
|
clr(""), gray("");
|
2024-02-22 02:31:24 +00:00
|
|
|
gb_json *init = new gb_json();
|
2024-02-23 07:59:31 +00:00
|
|
|
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;
|
2024-02-22 02:31:24 +00:00
|
|
|
|
|
|
|
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)
|
2024-02-23 07:59:31 +00:00
|
|
|
key += clr;
|
2024-02-22 02:31:24 +00:00
|
|
|
else
|
2024-02-23 07:59:31 +00:00
|
|
|
key += gray;
|
2024-02-22 02:31:24 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-21 09:44:32 +00:00
|
|
|
};
|
2024-01-19 08:54:58 +00:00
|
|
|
|
|
|
|
namespace cis
|
|
|
|
{
|
2024-02-22 02:31:24 +00:00
|
|
|
std::vector<int> get_fixed_resolution(void)
|
|
|
|
{
|
|
|
|
std::vector<int> res;
|
|
|
|
|
|
|
|
res.push_back(300);
|
|
|
|
res.push_back(600);
|
|
|
|
|
|
|
|
return std::move(res);
|
|
|
|
}
|
|
|
|
|
2024-01-19 08:54:58 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-21 09:44:32 +00:00
|
|
|
|
|
|
|
void update_correct_data(int init_dpi, bool init_clr, bool force)
|
|
|
|
{
|
2024-02-22 02:31:24 +00:00
|
|
|
std::string src("/usr/local/huago/cameraparam.json"),
|
2024-02-21 09:44:32 +00:00
|
|
|
root(CIS_CORRECT_DATA_PATH);
|
|
|
|
uint64_t src_m = 0,
|
|
|
|
dst_m = 0;
|
2024-02-22 02:31:24 +00:00
|
|
|
std::vector<int> fixed_res; // (get_fixed_resolution());
|
|
|
|
std::vector<correct::CORDATA> old(correct::load_old_correct_data(src.c_str(), &fixed_res));
|
2024-02-21 09:44:32 +00:00
|
|
|
|
|
|
|
if(utils::get_file_time(src.c_str(), nullptr, &src_m, nullptr) && !force)
|
|
|
|
return;
|
|
|
|
|
2024-02-22 02:31:24 +00:00
|
|
|
std::sort(fixed_res.begin(), fixed_res.end());
|
2024-02-21 09:44:32 +00:00
|
|
|
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)
|
|
|
|
{
|
2024-02-22 02:31:24 +00:00
|
|
|
correct::save_correct_data(n, fixed_res, init_dpi, init_clr);
|
|
|
|
break;
|
2024-02-21 09:44:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2024-02-22 02:31:24 +00:00
|
|
|
correct::save_correct_data(n, fixed_res, init_dpi, init_clr);
|
|
|
|
break;
|
2024-02-21 09:44:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2024-02-23 07:59:31 +00:00
|
|
|
utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' Before: %s\n", v, child->to_string().c_str());
|
2024-02-21 09:44:32 +00:00
|
|
|
def->attach_text(&data[0]);
|
|
|
|
def->key() = "default";
|
|
|
|
def->release();
|
2024-02-23 07:59:31 +00:00
|
|
|
utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' After: %s\n", v, child->to_string().c_str());
|
2024-02-21 09:44:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2024-02-23 07:59:31 +00:00
|
|
|
utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' Before: %s\n", fn.c_str(), child->to_string().c_str());
|
2024-02-21 09:44:32 +00:00
|
|
|
def->attach_text(&data[0]);
|
|
|
|
def->key() = "default";
|
|
|
|
def->release();
|
2024-02-23 07:59:31 +00:00
|
|
|
utils::to_log(LOG_LEVEL_ALL, "Correction-data of '%s' After: %s\n", fn.c_str(), child->to_string().c_str());
|
2024-02-21 09:44:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
child->release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
last->release();
|
|
|
|
}
|
2024-01-19 08:54:58 +00:00
|
|
|
}
|
|
|
|
|