code_device/hgdriver/hgdev/hg_scanner.cpp

2503 lines
62 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "hg_scanner.h"
#include "../../sdk/hginclude/hg_log.h"
#include "sane/sane_option_definitions.h"
#ifdef WIN32
#include "scanner_manager.h"
#include <direct.h>
#endif
static int ui_default_callback(scanner_handle, int, void*, unsigned int*, void*)
{
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// hg_scanner
hg_scanner::hg_scanner(ScannerSerial serial
, const char* dev_name, usb_io* io)
: name_(dev_name ? dev_name : ""), io_(io), status_(HG_ERR_NOT_START)
, scan_count_(-1), run_(true), paper_size_(TwSS::A4), erase_bkg_range_(10)
, noise_range_(30), omit_empty_level_(50), resolution_(200), rid_hole_range_(.1f)
, bright_(128), contrast_(4), gamma_(1.0f), threshold_(40), anti_noise_(8), margin_(5)
, fractate_level_(50), ui_ev_cb_(ui_default_callback), scan_life_(NULL)
, notify_setting_result_(false), user_cancel_(false), cb_mem_(true), test_1_paper_(false)
, setting_count_(0),img_type_(""), online_(false),is_quality_(-1)
{
custom_gamma_val_ = new SANE_Gamma;
memset(custom_gamma_val_, 0, sizeof(SANE_Gamma));
#ifdef MAPPING_FUNCTION_IN_BASE
init_setting_map(setting_map_, ARRAY_SIZE(setting_map_));
#endif
paper_size_mm_.cx = 210;
paper_size_mm_.cy = 297;
custom_gamma_val_->pt_count_r = custom_gamma_val_->pt_count_g = custom_gamma_val_->pt_count_b = 0;
for (int i = 0; i < ARRAY_SIZE(custom_gamma_val_->table); ++i)
custom_gamma_val_->table[i] = i & 0x0ff;
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "%s(%s) constructed\n", name_.c_str(), hg_log::format_ptr(this).c_str());
image_prc_param_.value = 0;
if (io_)
{
io_->add_ref();
status_ = io_->last_error();
online_ = status_ == HG_ERR_OK;
}
wait_usb_.set_debug_info("USB");
wait_img_.set_debug_info("Image");
thread_usb_read_.reset(new std::thread(&hg_scanner::thread_handle_usb, this));
thread_img_handle_.reset(new std::thread(&hg_scanner::thread_image_handle, this));
}
hg_scanner::~hg_scanner()
{
close(true);
if (thread_usb_read_.get() && thread_usb_read_->joinable())
thread_usb_read_->join();
if (thread_img_handle_.get() && thread_img_handle_->joinable())
thread_img_handle_->join();
delete custom_gamma_val_;
name_.insert(0, "\350\256\276\345\244\207");
name_ += "\345\267\262\347\273\217\345\205\263\351\227\255\343\200\202";
notify_ui_working_status(name_.c_str(), SANE_EVENT_SCANNER_CLOSED);
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "%s(%s) destroyed.\n", name_.c_str(), hg_log::format_ptr(this).c_str());
}
std::string hg_scanner::strerr(hg_err err)
{
RETURN_IF(err, HG_ERR_OK);
RETURN_IF(err, HG_ERR_INVALID_PARAMETER);
RETURN_IF(err, HG_ERR_INSUFFICIENT_MEMORY);
RETURN_IF(err, HG_ERR_ACCESS_DENIED);
RETURN_IF(err, HG_ERR_IO_PENDING);
RETURN_IF(err, HG_ERR_NOT_EXACT);
RETURN_IF(err, HG_ERR_CONFIGURATION_CHANGED);
RETURN_IF(err, HG_ERR_NOT_OPEN);
RETURN_IF(err, HG_ERR_NOT_START);
RETURN_IF(err, HG_ERR_NO_DATA);
RETURN_IF(err, HG_ERR_HAS_DATA_YET);
RETURN_IF(err, HG_ERR_OUT_OF_RANGE);
RETURN_IF(err, HG_ERR_IO);
RETURN_IF(err, HG_ERR_TIMEOUT);
RETURN_IF(err, HG_ERR_CREATE_FILE_FAILED);
RETURN_IF(err, HG_ERR_WRITE_FILE_FAILED);
RETURN_IF(err, HG_ERR_OPENED_BY_OTHER_PROCESS);
// 2USB错误
RETURN_IF(err, HG_ERR_USB_INIT_FAILED);
RETURN_IF(err, HG_ERR_USB_REGISTER_PNP_FAILED);
RETURN_IF(err, HG_ERR_USB_CLAIM_INTERFACE_FAILED);
// 3硬件错误
RETURN_IF(err, HG_ERR_DEVICE_NOT_FOUND);
RETURN_IF(err, HG_ERR_DEVICE_NOT_SUPPORT);
RETURN_IF(err, HG_ERR_DEVICE_BUSY);
RETURN_IF(err, HG_ERR_DEVICE_STOPPED);
RETURN_IF(err, HG_ERR_DEVICE_COVER_OPENNED);
RETURN_IF(err, HG_ERR_DEVICE_NO_PAPER);
RETURN_IF(err, HG_ERR_DEVICE_FEEDING_PAPER);
RETURN_IF(err, HG_ERR_DEVICE_DOUBLE_FEEDING);
RETURN_IF(err, HG_ERR_DEVICE_PAPER_JAMMED);
RETURN_IF(err, HG_ERR_DEVICE_STAPLE_ON);
RETURN_IF(err, HG_ERR_DEVICE_PAPER_SKEW);
RETURN_IF(err, HG_ERR_DEVICE_SIZE_CHECK);
RETURN_IF(err, HG_ERR_DEVICE_DOGEAR);
RETURN_IF(err, HG_ERR_DEVICE_NO_IMAGE);
RETURN_IF(err, HG_ERR_DEVICE_SCANN_ERROR);
char unk[80];
sprintf(unk, "\346\234\252\347\237\245\351\224\231\350\257\257\357\274\2320x%x", err);
return unk;
}
std::string hg_scanner::error_description(hg_err err)
{
RETURN_DESC_IF(err, HG_ERR_OK);
RETURN_DESC_IF(err, HG_ERR_INVALID_PARAMETER);
RETURN_DESC_IF(err, HG_ERR_INSUFFICIENT_MEMORY);
RETURN_DESC_IF(err, HG_ERR_ACCESS_DENIED);
RETURN_DESC_IF(err, HG_ERR_IO_PENDING);
RETURN_DESC_IF(err, HG_ERR_NOT_EXACT);
RETURN_DESC_IF(err, HG_ERR_CONFIGURATION_CHANGED);
RETURN_DESC_IF(err, HG_ERR_NOT_OPEN);
RETURN_DESC_IF(err, HG_ERR_NOT_START);
RETURN_DESC_IF(err, HG_ERR_NO_DATA);
RETURN_DESC_IF(err, HG_ERR_HAS_DATA_YET);
RETURN_DESC_IF(err, HG_ERR_OUT_OF_RANGE);
RETURN_DESC_IF(err, HG_ERR_IO);
RETURN_DESC_IF(err, HG_ERR_TIMEOUT);
RETURN_DESC_IF(err, HG_ERR_CREATE_FILE_FAILED);
RETURN_DESC_IF(err, HG_ERR_WRITE_FILE_FAILED);
RETURN_DESC_IF(err, HG_ERR_OPENED_BY_OTHER_PROCESS);
// 2USB错误
RETURN_DESC_IF(err, HG_ERR_USB_INIT_FAILED);
RETURN_DESC_IF(err, HG_ERR_USB_REGISTER_PNP_FAILED);
RETURN_DESC_IF(err, HG_ERR_USB_CLAIM_INTERFACE_FAILED);
// 3硬件错误
RETURN_DESC_IF(err, HG_ERR_DEVICE_NOT_FOUND);
RETURN_DESC_IF(err, HG_ERR_DEVICE_NOT_SUPPORT);
RETURN_DESC_IF(err, HG_ERR_DEVICE_BUSY);
RETURN_DESC_IF(err, HG_ERR_DEVICE_STOPPED);
RETURN_DESC_IF(err, HG_ERR_DEVICE_COVER_OPENNED);
RETURN_DESC_IF(err, HG_ERR_DEVICE_NO_PAPER);
RETURN_DESC_IF(err, HG_ERR_DEVICE_FEEDING_PAPER);
RETURN_DESC_IF(err, HG_ERR_DEVICE_DOUBLE_FEEDING);
RETURN_DESC_IF(err, HG_ERR_DEVICE_PAPER_JAMMED);
RETURN_DESC_IF(err, HG_ERR_DEVICE_STAPLE_ON);
RETURN_DESC_IF(err, HG_ERR_DEVICE_PAPER_SKEW);
RETURN_DESC_IF(err, HG_ERR_DEVICE_SIZE_CHECK);
RETURN_DESC_IF(err, HG_ERR_DEVICE_DOGEAR);
RETURN_DESC_IF(err, HG_ERR_DEVICE_NO_IMAGE);
RETURN_DESC_IF(err, HG_ERR_DEVICE_SCANN_ERROR);
char unk[80];
sprintf(unk, "\346\234\252\347\237\245\351\224\231\350\257\257\357\274\2320x%x", err);
return unk;
}
std::string hg_scanner::temporary_file(char* tail, char* head)
{
std::string path("/tmp/");
char buf[128];
FILE* src = NULL;
unsigned int ind = 1;
if (!head || *head == 0)
head = (char*)"scan";
if (!tail)
tail = (char*)"";
#ifdef WIN32
char me[MAX_PATH] = { 0 }, * n = NULL;
GetModuleFileNameA(NULL, me, _countof(me) - 1);
n = strrchr(me, '\\');
if (n++ == NULL)
n = me;
*n = 0;
path = me;
path += "img_tmp\\";
mkdir(path.c_str());
#endif
srand(time(NULL));
sprintf(buf, "%s%s", head, tail);
while ((src = fopen((path + buf).c_str(), "rb")))
{
fclose(src);
sprintf(buf, "%s(%u)%s", head, ind++, tail);
}
return path + buf;
}
int hg_scanner::save_2_tempory_file(std::shared_ptr<std::vector<char>> data, std::string* path_file, unsigned int index)
{
char head[40] = { 0 };
std::string file("");
FILE* dst = nullptr;
int ret = HG_ERR_OK;
sprintf(head, "scan_%06u", index);
file = hg_scanner::temporary_file((char*)".jpg", (char*)head);
dst = fopen(file.c_str(), "wb+");
if (dst)
{
ENOSPC; EROFS; strerror(errno);
size_t wrote = fwrite(data->data(), 1, data->size(), dst);
if (wrote == data->size())
{
if (path_file)
*path_file = file;
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "--->Wrote %u bytes to file '%s'\n", wrote, file.c_str());
}
else
{
ret = HG_ERR_WRITE_FILE_FAILED;
HG_VLOG_MINI_3(HG_LOG_LEVEL_FATAL, "Failed in writting file(%u/%u) '%s'\n", wrote, data->size(), file.c_str());
}
fclose(dst);
}
else
{
ret = HG_ERR_CREATE_FILE_FAILED;
HG_VLOG_MINI_1(HG_LOG_LEVEL_FATAL, "Failed in creating file '%s'\n", file.c_str());
}
return ret;
}
void hg_scanner::init_setting_map(int* setting_map, int count)
{
for (int i = 0; i < count; ++i)
setting_map[i] = -1;
}
void hg_scanner::set_setting_map(int sn, const char* title)
{
std::string val(title);
int empty = 0;
while (empty < val.length() && val[empty] == ' ')
empty++;
val.erase(0, empty);
//HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "title: '%s', val: '%s'\n", title, val.c_str());
if (val == OPTION_TITLE_HFMRSZ)
setting_map_[HG_BASE_SETTING_INDEX_RESTORE_DEFAULT_SETTINGS] = sn;
else if (val == OPTION_TITLE_BZ)
setting_map_[HG_BASE_SETTING_INDEX_HELP] = sn;
else if (val == OPTION_TITLE_YSMS)
setting_map_[HG_BASE_SETTING_INDEX_COLOR_MODE] = sn;
else if (val == OPTION_TITLE_DLSC)
setting_map_[HG_BASE_SETTING_INDEX_MULTI_OUT] = sn;
else if (val == OPTION_TITLE_HDHHBTX_CS)
setting_map_[HG_BASE_SETTING_INDEX_ERASE_COLOR] = sn;
else if (val == OPTION_TITLE_24WCSTX_DLSCCH)
setting_map_[HG_BASE_SETTING_INDEX_ERASE_MULTI_OUT_RED] = sn;
else if (val == OPTION_TITLE_24WCSTX_DTKCH)
setting_map_[HG_BASE_SETTING_INDEX_ERASE_ANSWER_RED] = sn;
else if (val == OPTION_TITLE_BJYC)
setting_map_[HG_BASE_SETTING_INDEX_ERASE_BACKGROUND] = sn;
else if (val == OPTION_TITLE_BJSCFDFW)
setting_map_[HG_BASE_SETTING_INDEX_ERASE_BACKGROUND_RANGE] = sn;
else if (val == OPTION_TITLE_HBTXZDYH)
setting_map_[HG_BASE_SETTING_INDEX_NOISE_OPTIMIZE] = sn;
else if (val == OPTION_TITLE_ZDYHCC)
setting_map_[HG_BASE_SETTING_INDEX_NOISE_OPTIMIZE_SIZE] = sn;
else if (val == OPTION_TITLE_ZZCC)
setting_map_[HG_BASE_SETTING_INDEX_PAPER] = sn;
else if (val == OPTION_TITLE_CCJC)
setting_map_[HG_BASE_SETTING_INDEX_PAPER_SIZE_CHECK] = sn;
else if (val == OPTION_TITLE_ZDYSMQY)
setting_map_[HG_BASE_SETTING_INDEX_IS_CUSTOM_AREA] = sn;
else if (val == OPTION_TITLE_SMQYZCmm)
setting_map_[HG_BASE_SETTING_INDEX_CUSTOM_AREA_LEFT] = sn;
else if (val == OPTION_TITLE_SMQYYCmm)
setting_map_[HG_BASE_SETTING_INDEX_CUSTOM_AREA_RIGHT] = sn;
else if (val == OPTION_TITLE_SMQYSCmm)
setting_map_[HG_BASE_SETTING_INDEX_CUSTOM_AREA_TOP] = sn;
else if (val == OPTION_TITLE_SMQYXCmm)
setting_map_[HG_BASE_SETTING_INDEX_CUSTOM_AREA_BOTTOM] = sn;
else if (val == OPTION_TITLE_SMYM)
setting_map_[HG_BASE_SETTING_INDEX_PAGE] = sn;
else if (val == OPTION_TITLE_TGKBYLMD)
setting_map_[HG_BASE_SETTING_INDEX_PAGE_OMIT_EMPTY_LEVEL] = sn;
else if (val == OPTION_TITLE_FBL)
setting_map_[HG_BASE_SETTING_INDEX_RESOLUTION] = sn;
else if (val == OPTION_TITLE_HZ)
setting_map_[HG_BASE_SETTING_INDEX_IMG_QUALITY] = sn;
else if (val == OPTION_TITLE_JHZFM)
setting_map_[HG_BASE_SETTING_INDEX_EXCHANGE] = sn;
else if (val == OPTION_TITLE_TXCF)
setting_map_[HG_BASE_SETTING_INDEX_SPLIT] = sn;
else if (val == OPTION_TITLE_ZDJP)
setting_map_[HG_BASE_SETTING_INDEX_AUTO_CORRECT] = sn;
else if (val == OPTION_TITLE_CKYC)
setting_map_[HG_BASE_SETTING_INDEX_RID_HOLE] = sn;
else if (val == OPTION_TITLE_CKSSFWZFMBL)
setting_map_[HG_BASE_SETTING_INDEX_RID_HOLE_RANGE] = sn;
else if (val == OPTION_TITLE_QYSDQX)
setting_map_[HG_BASE_SETTING_INDEX_IS_CUSTOM_GAMMA] = sn;
else if (val == OPTION_TITLE_LDZ)
setting_map_[HG_BASE_SETTING_INDEX_BRIGHT] = sn;
else if (val == OPTION_TITLE_DBD)
setting_map_[HG_BASE_SETTING_INDEX_CONTRAST] = sn;
else if (val == OPTION_TITLE_GMZ)
setting_map_[HG_BASE_SETTING_INDEX_GAMMA] = sn;
else if (val == OPTION_TITLE_RHYMH)
setting_map_[HG_BASE_SETTING_INDEX_SHARPEN] = sn;
else if (val == OPTION_TITLE_SSYZ)
setting_map_[HG_BASE_SETTING_INDEX_DARK_SAMPLE] = sn;
else if (val == OPTION_TITLE_XCHK)
setting_map_[HG_BASE_SETTING_INDEX_ERASE_BLACK_FRAME] = sn;
else if (val == OPTION_TITLE_YZ)
setting_map_[HG_BASE_SETTING_INDEX_THRESHOLD] = sn;
else if (val == OPTION_TITLE_BJKZDJ)
setting_map_[HG_BASE_SETTING_INDEX_ANTI_NOISE_LEVEL] = sn;
else if (val == OPTION_TITLE_BYSJ)
setting_map_[HG_BASE_SETTING_INDEX_MARGIN] = sn;
else if (val == OPTION_TITLE_BJTCFS)
setting_map_[HG_BASE_SETTING_INDEX_FILL_BACKGROUND] = sn;
else if (val == OPTION_TITLE_FZST)
setting_map_[HG_BASE_SETTING_INDEX_PERMEATE] = sn;
else if (val == OPTION_TITLE_FZSTDJ)
setting_map_[HG_BASE_SETTING_INDEX_PERMEATE_LV] = sn;
else if (val == OPTION_TITLE_QCMW)
setting_map_[HG_BASE_SETTING_INDEX_REMOVE_MORR] = sn;
else if (val == OPTION_TITLE_CWKS)
setting_map_[HG_BASE_SETTING_INDEX_ERROR_EXTENTION] = sn;
else if (val == OPTION_TITLE_CWW)
setting_map_[HG_BASE_SETTING_INDEX_REMOVE_TXTTURE] = sn;
else if (val == OPTION_TITLE_CSBJC)
setting_map_[HG_BASE_SETTING_INDEX_ULTRASONIC_CHECK] = sn;
else if (val == OPTION_TITLE_ZDJC)
setting_map_[HG_BASE_SETTING_INDEX_STAPLE_CHECK] = sn;
else if (val == OPTION_TITLE_SMZS)
setting_map_[HG_BASE_SETTING_INDEX_SCAN_MODE] = sn;
else if (val == OPTION_TITLE_SMSL)
setting_map_[HG_BASE_SETTING_INDEX_SCAN_COUNT] = sn;
else if (val == OPTION_TITLE_WGFX)
setting_map_[HG_BASE_SETTING_INDEX_TEXT_DIRECTION] = sn;
else if (val == OPTION_TITLE_BMXZ180)
setting_map_[HG_BASE_SETTING_INDEX_ROTATE_BKG_180] = sn;
else if (val == OPTION_TITLE_ZJJC)
setting_map_[HG_BASE_SETTING_INDEX_FRACTATE_CHECK] = sn;
else if (val == OPTION_TITLE_ZJDX)
setting_map_[HG_BASE_SETTING_INDEX_FRACTATE_CHECK_LEVEL] = sn;
else if (val == OPTION_TITLE_WXJC)
setting_map_[HG_BASE_SETTING_INDEX_SKEW_CHECK] = sn;
else if (val == OPTION_TITLE_WXRRD)
setting_map_[HG_BASE_SETTING_INDEX_SKEW_CHECK_LEVEL] = sn;
}
void hg_scanner::thread_handle_usb(void)
{
while (run_)
{
wait_usb_.wait();
if (!run_)
break;
if (scan_life_)
{
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
if (scan_life_)
{
HG_LOG(HG_LOG_LEVEL_FATAL, "image process is still running!\n");
continue;
}
}
scan_life_ = new do_when_born_and_dead<hg_scanner>(this, &hg_scanner::working_begin, &hg_scanner::working_done, NULL);
usb_img_index_ = 0;
thread_handle_usb_read();
if (scan_life_->release() == 0)
scan_life_ = NULL;
}
}
void hg_scanner::thread_image_handle(void)
{
while (run_)
{
wait_img_.wait();
if (!run_)
break;
scan_life_->add_ref();
thread_handle_image_process();
if (scan_life_->release() == 0)
scan_life_ = NULL;
}
}
void hg_scanner::get_range(int setting_no, std::vector<std::string>& range, std::string& def_val, bool& is_range/*range or list*/)
{
char sn[20];
std::string type("");
sprintf(sn, "%d", setting_no);
range.clear();
if (setting_jsn_.at(sn).contains("range"))
{
setting_jsn_.at(sn).at("type").get_to(type);
is_range = !setting_jsn_.at(sn).at("range").is_array();
if (is_range)
{
if (type == "int")
{
int l = 0, u = 0;
setting_jsn_.at(sn).at("range").at("min").get_to(l);
setting_jsn_.at(sn).at("range").at("max").get_to(u);
char str[20];
sprintf(str, "%d", l);
range.push_back(str);
sprintf(str, "%d", u);
range.push_back(str);
}
else
{
double l = .0f, u = .0f;
setting_jsn_.at(sn).at("range").at("min").get_to(l);
setting_jsn_.at(sn).at("range").at("max").get_to(u);
char str[40];
sprintf(str, "%f", l);
range.push_back(str);
sprintf(str, "%f", u);
range.push_back(str);
}
}
else
{
char str[40];
for (int i = 0; i < setting_jsn_.at(sn).at("range").size(); ++i)
{
if (type == "int")
{
int v = 0;
setting_jsn_.at(sn).at("range").at(i).get_to(v);
sprintf(str, "%d", v);
range.push_back(str);
}
else if(type == "float")
{
double v = 0;
setting_jsn_.at(sn).at("range").at(i).get_to(v);
sprintf(str, "%f", v);
range.push_back(str);
}
else
{
std::string v("");
setting_jsn_.at(sn).at("range").at(i).get_to(v);
range.push_back(v);
}
}
}
}
if (type == "int")
{
int v = 0;
setting_jsn_.at(sn).at("default").get_to(v);
sprintf(sn, "%d", v);
def_val = sn;
}
else if (type == "float")
{
double v = 0;
setting_jsn_.at(sn).at("default").get_to(v);
sprintf(sn, "%f", v);
def_val = sn;
}
else if(type == "string")
setting_jsn_.at(sn).at("default").get_to(def_val);
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "setting %d has %d range(s) and default value is '%s'\n", setting_no, range.size(), def_val.c_str());
}
bool hg_scanner::check_range(int setting_no, bool& val)
{
std::vector<std::string> range;
std::string init(""), in(val ? "true" : "false");
bool is_range = false;;
get_range(setting_no, range, init, is_range);
if (range.size() == 0)
return true;
for (int i = 0; i < range.size(); ++i)
{
if (in == range[i])
return true;
}
val = init == "true" ? true : false;
return false;
}
bool hg_scanner::check_range(int setting_no, int& val)
{
std::vector<std::string> range;
std::string init("");
bool is_range = false;;
get_range(setting_no, range, init, is_range);
if (range.size() == 0)
return true;
if (is_range && range.size() == 2)
{
if (val >= atoi(range[0].c_str()) && val <= atoi(range[1].c_str()))
return true;
if(val < atoi(range[0].c_str()))
val = atoi(range[0].c_str());
else
val = atoi(range[1].c_str());
return false;
}
else if (!is_range)
{
for (int i = 0; i < range.size(); ++i)
{
if (atoi(range[i].c_str()) == val)
return true;
}
}
val = atoi(init.c_str());
return false;
}
bool hg_scanner::check_range(int setting_no, double& val)
{
std::vector<std::string> range;
std::string init("");
bool is_range = false;;
get_range(setting_no, range, init, is_range);
if (range.size() == 0)
return true;
if (is_range && range.size() == 2)
{
if (val >= atof(range[0].c_str()) && val <= atof(range[1].c_str()))
return true;
if (val < atof(range[0].c_str()))
val = atof(range[0].c_str());
else
val = atof(range[1].c_str());
return false;
}
else if (!is_range)
{
for (int i = 0; i < range.size(); ++i)
{
if (fabs(atof(range[i].c_str()) - val) < .000001)
return true;
}
}
val = atof(init.c_str());
return false;
}
bool hg_scanner::check_range(int setting_no, std::string& val)
{
std::vector<std::string> range;
std::string init(""), in(val);
bool is_range = false;;
get_range(setting_no, range, init, is_range);
if (range.size() == 0)
return true;
for (int i = 0; i < range.size(); ++i)
{
if (in == range[i])
return true;
}
val = init;
return false;
}
int hg_scanner::restore(int setting_no)
{
char key[20];
int sn = setting_no;
std::string val("");
sprintf(key, "%d", setting_no);
setting_jsn_.at(key).at("name").get_to(val);
if (val == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
custom_gamma_val_->pt_count_r = custom_gamma_val_->pt_count_g = custom_gamma_val_->pt_count_b = 0;
for (int i = 0; i < ARRAY_SIZE(custom_gamma_val_->table); ++i)
custom_gamma_val_->table[i] = i & 0x0ff;
return HG_ERR_OK;
}
setting_jsn_.at(key).at("type").get_to(val);
if (val == "string")
{
val = "";
setting_jsn_.at(key).at("default").get_to(val);
char* buf = NULL;
int size = 0;
setting_jsn_.at(key).at("size").get_to(size);
buf = (char*)malloc(size + 4);
bzero(buf, size + 4);
strcpy(buf, val.c_str());
sn = set_setting(sn, buf, val.length());
free(buf);
}
else if (val == "int")
{
int v = 0;
setting_jsn_.at(key).at("default").get_to(v);
sn = set_setting(sn, (char*)&v, sizeof(v));
}
else if (val == "float")
{
double v = .0f;
setting_jsn_.at(key).at("default").get_to(v);
sn = set_setting(sn, (char*)&v, sizeof(v));
}
else if (val == "bool")
{
bool v = false;
setting_jsn_.at(key).at("default").get_to(v);
sn = set_setting(sn, (char*)&v, sizeof(v));
}
else
sn = HG_ERR_OK;
return sn;
}
bool hg_scanner::get_default_value(void* buf, json* jsn)
{
std::string type("");
jsn->at("name").get_to(type);
if (type == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
SANE_Int* gma = (SANE_Int*)buf;
for (size_t i = 0; i < sizeof(custom_gamma_val_); ++i)
gma[i] = i & 0x0ff;
return true;
}
jsn->at("type").get_to(type);
if (type == "bool")
{
bool v = false;
jsn->at("default").get_to(v);
*((SANE_Bool*)buf) = v;
}
else if (type == "int")
{
int v = 0;
jsn->at("default").get_to(v);
*((SANE_Int*)buf) = v;
}
else if (type == "float")
{
double v = 0;
jsn->at("default").get_to(v);
*((SANE_Fixed*)buf) = SANE_FIX(v);
}
else if (type == "string")
{
type = "";
jsn->at("default").get_to(type);
strcpy((char*)buf, type.c_str());
}
else
return false;
return true;
}
bool hg_scanner::is_to_file(void)
{
return resolution_ > 200
|| paper_size_ == TwSS::USStatement
|| paper_size_ == TwSS::MaxSize
|| paper_size_ == TwSS::Trigeminy;
}
void hg_scanner::thread_handle_image_process(void)
{
while (run_ && !user_cancel_)
{
std::shared_ptr<std::vector<char>> buffer;
if (imgs_.Size() == 0 && paths_.Size() == 0)
{
if (wait_usb_.is_waiting())
break;
this_thread::sleep_for(chrono::milliseconds(30));
continue;
}
if (is_to_file())
{
std::string file(paths_.Take());
FILE* src = fopen(file.c_str(), "rb+");
if (src)
{
unsigned length = 0;
fseek(src, 0, SEEK_END);
length = ftell(src);
fseek(src, 0, SEEK_SET);
buffer.reset(new std::vector<char>);
buffer->resize(length);
fread(buffer->data(), 1, length, src);
fclose(src);
remove(file.c_str());
}
else
{
HG_VLOG_MINI_1(HG_LOG_LEVEL_FATAL, "FATAL: open tempory image file '%s' failed.\n", file.c_str());
}
}
else
{
buffer = imgs_.Take();
}
image_process(buffer);
}
}
void hg_scanner::working_begin(void*)
{
final_img_index_ = 0;
notify_ui_working_status(STATU_DESC_SCAN_WORKING, SANE_EVENT_WORKING, HG_ERR_OK);
}
void hg_scanner::working_done(void*)
{
imgs_.Clear();
while (paths_.Size())
{
remove(paths_.Take().c_str());
}
switch (status_)
{
case HG_ERR_OK:
notify_ui_working_status(STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_BUSY:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_PC_BUSY, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_STOPPED:
notify_ui_working_status(STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_COVER_OPENNED:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_COVER_OPENNED, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_NO_PAPER:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_NO_PAPER, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_FEEDING_PAPER:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_FEEDING_PAPER, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_NOT_FOUND:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_NOT_FOUND, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_SLEEPING:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_SLEEPING, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_COUNT_MODE:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_COUNT_MODE, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_DOUBLE_FEEDING:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_DOUBLE_FEEDING, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_PAPER_JAMMED:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_PAPER_JAMMED, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_STAPLE_ON:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_STAPLE_ON, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_PAPER_SKEW:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_PAPER_SKEW, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_SIZE_CHECK:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_SIZE_CHECK, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_DOGEAR:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_DOGEAR, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_NO_IMAGE:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_NO_IMAGE, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_SCANN_ERROR:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_SCANN_ERROR, SANE_EVENT_SCAN_FINISHED, status_);
break;
case HG_ERR_DEVICE_PC_BUSY:
notify_ui_working_status(STATU_DESC_HG_ERR_DEVICE_PC_BUSY, SANE_EVENT_SCAN_FINISHED, status_);
break;
default:
notify_ui_working_status(user_cancel_ ? STATU_DESC_SCAN_CANCELED : STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_);
break;
}
//notify_ui_working_status(STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_);
if (test_1_paper_)
{
HG_LOG(HG_LOG_LEVEL_DEBUG_INFO, "scanning mode: finished testing ONE paper, restore to normal scanning.\n");
}
else
{
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "scanned %d picture(s) and finished with error %s.\n", final_img_index_, hg_scanner::strerr((hg_err)status_).c_str());
}
test_1_paper_ = false;
}
void hg_scanner::reset_custom_area_range(int paper)
{
if (paper == PAPER_A3)
{
paper_size_mm_.cx = 297;
paper_size_mm_.cy = 420;
}
else if (paper == PAPER_A4)
{
paper_size_mm_.cx = 210;
paper_size_mm_.cy = 297;
}
else if (paper == PAPER_A4_LATERAL)
{
paper_size_mm_.cx = 297;
paper_size_mm_.cy = 210;
}
else if (paper == PAPER_A5)
{
paper_size_mm_.cx = 148;
paper_size_mm_.cy = 210;
}
else if (paper == PAPER_A5_LATERAL)
{
paper_size_mm_.cx = 210;
paper_size_mm_.cy = 148;
}
else if (paper == PAPER_A6)
{
paper_size_mm_.cx = 105;
paper_size_mm_.cy = 148;
}
else if (paper == PAPER_A6_LATERAL)
{
paper_size_mm_.cx = 148;
paper_size_mm_.cy = 105;
}
else if (paper == PAPER_B4)
{
paper_size_mm_.cx = 250;
paper_size_mm_.cy = 353;
}
else if (paper == PAPER_B5)
{
paper_size_mm_.cx = 176;
paper_size_mm_.cy = 250;
}
else if (paper == PAPER_B6)
{
paper_size_mm_.cx = 125;
paper_size_mm_.cy = 176;
}
else if (paper == PAPER_B5_LATERAL)
{
paper_size_mm_.cx = 250;
paper_size_mm_.cy = 176;
}
else if (paper == PAPER_B6_LATERAL)
{
paper_size_mm_.cx = 176;
paper_size_mm_.cy = 125;
}
else
{
paper_size_mm_.cx = 210;
paper_size_mm_.cy = 297;
}
}
int hg_scanner::setting_restore(void* data)
{
// restore ...
int count = 0;
setting_jsn_.at("option_count").get_to(count);
notify_setting_result_ = false;
for (int i = 1; i < count; ++i)
restore(i);
notify_setting_result_ = true;
return HG_ERR_CONFIGURATION_CHANGED;
}
int hg_scanner::setting_help(void* data)
{
int ret = HG_ERR_OK;
if (name_ == "华高扫描仪—G100") //保留
{
/* code */
}
std::string helpfile = helpfile_;
std::string com = "xdg-open ";//注意空格保留
#ifdef WIN32
FILE* src = fopen(helpfile.c_str(), "rb");
if (src)
fclose(src);
else
#else
if (access(helpfile.c_str(),F_OK) == -1)
#endif
{
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO,"App_Help_pdf path is:%s\r\n",hg_scanner::strerr((hg_err)ret).c_str());
ret = HG_ERR_OPEN_FILE_FAILED;
return ret ;
}
com += helpfile;
system(com.c_str());
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO,"App_Help_pdf path is:%s system is:%d\r\n",helpfile.c_str());
return ret;
}
int hg_scanner::setting_color_mode(void* data)
{
std::string str((char*)data);
int old = image_prc_param_.bits.color_mode,
sub = HG_ERR_OK,
val = 0,
ret = HG_ERR_OK;
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_COLOR_MODE], str);
val = image_prc_param_.bits.color_mode = match_best_color_mode(str, NULL);
sub = on_color_mode_changed(val);
image_prc_param_.bits.color_mode = val;
if (sub == HG_ERR_NOT_EXACT)
{
image_prc_param_.bits.color_mode = old;
str = color_mode_string(image_prc_param_.bits.color_mode);
ret = HG_ERR_NOT_EXACT;
}
else if (sub)
{
ret = sub;
image_prc_param_.bits.color_mode = old;
}
else if (!exact)
{
ret = HG_ERR_NOT_EXACT;
}
is_auto_matic_color = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? true :false; // 等于COLOR_MODE_AUTO_MATCH 的时候颜色模式需要变为2 彩色模式图像参数和硬件参数都如此
HG_VLOG_MINI_4(HG_LOG_LEVEL_DEBUG_INFO, "Change color mode from %s to %s = %s color is =%s\n", color_mode_string(old).c_str(), (char*)data, hg_scanner::strerr((hg_err)ret).c_str(),str.c_str());
if(ret == HG_ERR_NOT_EXACT)
strcpy((char*)data, str.c_str());
return ret;
}
int hg_scanner::setting_multi_out(void *data)
{
int ret = HG_ERR_OK;
if(image_prc_param_.bits.color_mode != 2)
{
ret = HG_ERR_INVALID_PARAMETER;
return ret;
}
std::string str((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_MULTI_OUT], str);
image_prc_param_.bits.multi_out = match_best_multi_out(str,NULL);
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "set multi_out type from %s to %s = %s\n", multi_out_string(image_prc_param_.bits.multi_out).c_str(), (char*)data, hg_scanner::strerr((hg_err)ret).c_str());
return ret;
}
int hg_scanner::setting_rid_color(void* data)
{
std::string str((char*)data);
int ret = HG_ERR_OK,
color = -1,
old = image_prc_param_.bits.rid_color;
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_ERASE_COLOR], str);
image_prc_param_.bits.rid_color = match_best_rid_color(str, NULL);
on_color_mode_changed(color);
if (!exact)
{
ret = HG_ERR_NOT_EXACT;
strcpy((char*)data, str.c_str());
}
return ret;
}
int hg_scanner::setting_rid_multi_red(void* data)
{
image_prc_param_.bits.rid_red = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_rid_answer_red(void* data)
{
image_prc_param_.bits.rid_answer_red = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_erase_background(void* data)
{
image_prc_param_.bits.erase_bakground = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_erase_background_range(void* data)
{
int ret = HG_ERR_OK;
erase_bkg_range_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_ERASE_BACKGROUND_RANGE], erase_bkg_range_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = erase_bkg_range_;
}
return ret;
}
int hg_scanner::setting_noise_optimize(void* data)
{
image_prc_param_.bits.noise_optimize = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_noise_optimize_range(void* data)
{
int ret = HG_ERR_OK;
noise_range_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_NOISE_OPTIMIZE_SIZE], noise_range_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = noise_range_;
}
return ret;
}
int hg_scanner::setting_paper(void* data)
{
std::string paper((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_PAPER], paper);
int ret = HG_ERR_OK, sub = HG_ERR_OK,
val = 0,
old = image_prc_param_.bits.paper;
val = image_prc_param_.bits.paper = match_best_paper(paper, NULL);
sub = on_paper_changed(val);
image_prc_param_.bits.paper = val;
if (sub == HG_ERR_NOT_EXACT)
{
ret = sub;
paper = paper_string(image_prc_param_.bits.paper);
}
else if (sub)
{
ret = sub;
image_prc_param_.bits.paper = old;
}
else if (!exact)
ret = HG_ERR_NOT_EXACT;
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner::strerr((hg_err)ret).c_str());
if(ret == HG_ERR_NOT_EXACT)
strcpy((char*)data, paper.c_str());
if(old != image_prc_param_.bits.paper)
reset_custom_area_range(image_prc_param_.bits.paper);
return ret;
}
int hg_scanner::setting_paper_check(void* data)
{
bool use = *((bool*)data);
int ret = on_paper_check_changed(use);
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "Change paper size-checking %s = %s\n", *((bool*)data) ? "enabled" : "disabled", hg_scanner::strerr((hg_err)ret).c_str());
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_page(void* data)
{
std::string val((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_PAGE], val);
int ret = exact ? HG_ERR_OK : HG_ERR_NOT_EXACT;
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "Change page from %s to %s = %s\n", page_string(image_prc_param_.bits.page).c_str(), (char*)data, hg_scanner::strerr((hg_err)ret).c_str());
image_prc_param_.bits.page = match_best_page(val, NULL);
if (!exact)
strcpy((char*)data, val.c_str());
return ret;
}
int hg_scanner::setting_page_omit_empty(void* data)
{
int ret = HG_ERR_OK;
omit_empty_level_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_PAGE_OMIT_EMPTY_LEVEL], omit_empty_level_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = omit_empty_level_;
}
return ret;
}
int hg_scanner::setting_resolution(void* data)
{
int ret = HG_ERR_OK,
old = resolution_,
sub = HG_ERR_OK;
resolution_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_RESOLUTION], resolution_))
ret = HG_ERR_NOT_EXACT;
sub = on_resolution_changed(resolution_);
if (sub == HG_ERR_NOT_EXACT)
ret = sub;
else if (sub)
ret = sub;
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "Change resolution from %d to %d = %s\n", old, *((int*)data), hg_scanner::strerr((hg_err)ret).c_str());
*((int*)data) = resolution_;
return ret;
}
int hg_scanner::setting_exchagnge(void* data)
{
image_prc_param_.bits.exchange = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_split_image(void* data)
{
image_prc_param_.bits.split = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_automatic_skew(void* data)
{
// automatic_skew_detection_ = *((bool*)data);
image_prc_param_.bits.automatic_skew = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_rid_hole(void* data)
{
image_prc_param_.bits.rid_hole = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_rid_hoe_range(void* data)
{
int ret = HG_ERR_OK;
rid_hole_range_ = *((double*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_RID_HOLE_RANGE], rid_hole_range_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = rid_hole_range_;
}
rid_hole_range_*=100;
HG_VLOG_MINI_1(HG_LOG_LEVEL_WARNING, "rid_hole_range_ = %f\r\n", rid_hole_range_);
return ret;
}
int hg_scanner::setting_bright(void* data)
{
int ret = HG_ERR_OK;
bright_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_BRIGHT], bright_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = bright_;
}
return ret;
}
int hg_scanner::setting_contrast(void* data)
{
int ret = HG_ERR_OK;
contrast_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_CONTRAST], contrast_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = contrast_;
}
return ret;
}
int hg_scanner::setting_gamma(void* data)
{
int ret = HG_ERR_OK;
gamma_ = *((double*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_GAMMA], gamma_))
{
ret = HG_ERR_NOT_EXACT;
*((double*)data) = gamma_;
}
return ret;
}
int hg_scanner::setting_sharpen(void* data)
{
std::string str((char*)data);
int ret = HG_ERR_OK;
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_SHARPEN], str);
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "Change sharpen from %s to %s = ", sharpen_string(image_prc_param_.bits.sharpen).c_str(), (char*)data);
image_prc_param_.bits.sharpen = match_best_sharpen(str, NULL);
if (!exact)
{
strcpy((char*)data, str.c_str());
ret = HG_ERR_NOT_EXACT;
}
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "%d\n", ret);
return ret;
}
int hg_scanner::setting_dark_sample(void* data)
{
image_prc_param_.bits.dark_sample = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_erase_black_frame(void* data)
{
image_prc_param_.bits.erase_black_frame = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_threshold(void* data)
{
int ret = HG_ERR_OK;
threshold_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_THRESHOLD], threshold_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = threshold_;
}
return ret;
}
int hg_scanner::setting_anti_noise(void* data)
{
int ret = HG_ERR_OK;
anti_noise_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_ANTI_NOISE_LEVEL], anti_noise_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = anti_noise_;
}
return ret;
}
int hg_scanner::setting_margin(void* data)
{
int ret = HG_ERR_OK;
margin_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_MARGIN], margin_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = margin_;
}
return ret;
}
int hg_scanner::setting_filling_background(void* data)
{
std::string str((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_FILL_BACKGROUND], str);
int ret = exact ? HG_ERR_OK : HG_ERR_NOT_EXACT;
image_prc_param_.bits.fill_background = match_best_fill_background(str, NULL);
if (!exact)
{
strcpy((char*)data, str.c_str());
ret = HG_ERR_NOT_EXACT;
}
return ret;
}
int hg_scanner::setting_is_permeate(void* data)
{
image_prc_param_.bits.is_permeate = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_is_permeate_lv(void* data)
{
int ret = HG_ERR_OK;
std::string str((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_PERMEATE_LV], str);
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "Change is_permeate_lv from %s to %s = ", is_permaeate_string(image_prc_param_.bits.is_permeate_lv_).c_str(), (char*)data);
image_prc_param_.bits.is_permeate_lv_ = match_best_permaeate_lv(str, NULL);
if (!exact)
{
strcpy((char*)data, str.c_str());
ret = HG_ERR_NOT_EXACT;
}
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "%d\n", ret);
return ret;
}
int hg_scanner::setting_remove_morr(void* data)
{
image_prc_param_.bits.remove_morr = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_error_extention(void* data)
{
image_prc_param_.bits.error_extention = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_remove_texture(void* data)
{
image_prc_param_.bits.remove_txtture = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_ultrasonic_check(void* data)
{
bool use = *((bool*)data);
int ret = on_ultrasonic_check_changed(use);
if (ret)
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_staple_check(void* data)
{
bool use = *((bool*)data);
int ret = on_staple_check_changed(use);
if (ret)
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_scan_mode(void* data)
{
std::string str((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_SCAN_MODE], str);
int ret = exact ? HG_ERR_OK : HG_ERR_NOT_EXACT;
if (strcmp(str.c_str(), OPTION_VALUE_SMZS_LXSM) == 0)
{
scan_count_ = -1;
}
else
{
char key[20];
sprintf(key, "%d", setting_map_[HG_BASE_SETTING_INDEX_SCAN_COUNT]);
setting_jsn_.at(key).at("cur").get_to(scan_count_);
}
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "set scanning pages to %d\n", scan_count_);
return ret;
}
int hg_scanner::setting_scan_count(void* data)
{
int ret = HG_ERR_OK;
char key[20];
std::string val("");
sprintf(key, "%d", setting_map_[HG_BASE_SETTING_INDEX_SCAN_MODE]);
setting_jsn_.at(key).at("cur").get_to(val);
if (val == OPTION_VALUE_SMZS_LXSM)
{
scan_count_ = -1;
}
else
{
scan_count_ = *((int*)data);
}
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "set scanning pages to %d\n", scan_count_);
return ret;
}
int hg_scanner::setting_text_direction(void* data)
{
std::string str((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_TEXT_DIRECTION], str);
int ret = exact ? HG_ERR_OK : HG_ERR_NOT_EXACT;
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "Change text direction from '%s' to '%s' = %s\n", text_direction_string(image_prc_param_.bits.text_direction).c_str()
, (char*)data, hg_scanner::strerr((hg_err)ret).c_str());
image_prc_param_.bits.text_direction = match_best_text_direction(str, NULL);
if (!exact)
strcpy((char*)data, str.c_str());
return ret;
}
int hg_scanner::setting_rotate_bkg_180(void* data)
{
image_prc_param_.bits.rotate_back_180 = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_fractate_check(void* data)
{
image_prc_param_.bits.fractate_check = *((bool*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_fractate_check_level(void* data)
{
int ret = HG_ERR_OK;
fractate_level_ = *((int*)data);
if (!check_range(setting_map_[HG_BASE_SETTING_INDEX_FRACTATE_CHECK_LEVEL], fractate_level_))
{
ret = HG_ERR_NOT_EXACT;
*((int*)data) = fractate_level_;
}
return ret;
}
int hg_scanner::setting_skew_check(void* data)
{
bool use = *((bool*)data);
int ret = on_skew_check_changed(use);
if (ret)
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_skew_check_level(void* data)
{
int level = *((int*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_SKEW_CHECK_LEVEL], level);
int ret = exact ? HG_ERR_OK : HG_ERR_NOT_EXACT,
sub = on_skew_check_level_changed(level);
if (sub)
{
ret = sub;
}
if (ret)
*((int*)data) = level;
return ret;
}
int hg_scanner::setting_is_custom_gamma(void* data)
{
SANE_Bool* v = (SANE_Bool*)data;
custom_gamma_ = *v == SANE_TRUE;
return HG_ERR_OK;
}
int hg_scanner::setting_custom_gamma_data(void* data)
{
SANE_Gamma* gamma = (SANE_Gamma*)data;
memcpy(custom_gamma_val_, gamma, sizeof(*custom_gamma_val_));
return HG_ERR_OK;
}
int hg_scanner::setting_is_custom_area(void* data)
{
SANE_Bool* v = (SANE_Bool*)data;
custom_area_ = *v == SANE_TRUE;
return HG_ERR_OK;
}
int hg_scanner::setting_custom_area_left(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_lt_x_ = *((double*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_custom_area_top(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_lt_y_ = *((double*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_custom_area_right(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_br_x_ = *((double*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_custom_area_bottom(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_br_y_ = *((double*)data);
return HG_ERR_OK;
}
int hg_scanner::setting_img_quality(void *data)
{
std::string str((char*)data);
bool exact = check_range(setting_map_[HG_BASE_SETTING_INDEX_IMG_QUALITY], str);
int ret = exact ? HG_ERR_OK : HG_ERR_NOT_EXACT;
HG_VLOG_MINI_3(HG_LOG_LEVEL_DEBUG_INFO, "Change quality from '%s' to '%s' = %s\n", is_img_quality(is_quality_).c_str()
, (char*)data, hg_scanner::strerr((hg_err)ret).c_str());
is_quality_ = match_best_img_quality(str,NULL);
return HG_ERR_OK;
}
int hg_scanner::on_color_mode_changed(int& color_mode)
{
return HG_ERR_OK;
}
int hg_scanner::on_paper_changed(int& paper)
{
return HG_ERR_OK;
}
int hg_scanner::on_paper_check_changed(bool& check)
{
return HG_ERR_OK;
}
int hg_scanner::on_resolution_changed(int& dpi)
{
return HG_ERR_OK;
}
int hg_scanner::on_ultrasonic_check_changed(bool& check)
{
return HG_ERR_OK;
}
int hg_scanner::on_staple_check_changed(bool& check)
{
return HG_ERR_OK;
}
int hg_scanner::on_skew_check_changed(bool& check)
{
return HG_ERR_OK;
}
int hg_scanner::on_skew_check_level_changed(int& check)
{
return HG_ERR_OK;
}
void hg_scanner::on_device_reconnected(void)
{
std::lock_guard<std::mutex> lock(io_lock_);
HG_VLOG_MINI_2(HG_LOG_LEVEL_DEBUG_INFO, "%04x:%04x reconnected.\n", io_->get_vid(), io_->get_pid());
}
int hg_scanner::set_setting_value(int setting_no, void* data, int len)
{
return HG_ERR_OK;
}
int hg_scanner::on_scanner_closing(bool force)
{
return HG_ERR_OK;
}
void hg_scanner::thread_handle_usb_read(void)
{
}
void hg_scanner::init_settings(const char* json_setting_text)
{
setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text);
int count = 0;
notify_setting_result_ = false;
setting_jsn_.at("option_count").get_to(count);
for (int sn = 1; sn < count; ++sn)
{
char key[20];
std::string val("");
sprintf(key, "%d", sn);
setting_jsn_.at(key).at("name").get_to(val);
if (val == KNOWN_OPT_NAME_CUSTOM_GAMMA)
continue;
#ifdef MAPPING_FUNCTION_IN_BASE
setting_jsn_.at(key).at("title").get_to(val);
set_setting_map(sn, val.c_str());
#endif
setting_jsn_.at(key).at("type").get_to(val);
if (val == "string")
{
val = "";
setting_jsn_.at(key).at("default").get_to(val);
char* buf = NULL;
int size = 0;
setting_jsn_.at(key).at("size").get_to(size);
buf = (char*)malloc(size + 4);
bzero(buf, size + 4);
strcpy(buf, val.c_str());
set_setting(sn, buf, val.length());
free(buf);
}
else if (val == "int")
{
int v = 0;
setting_jsn_.at(key).at("default").get_to(v);
set_setting(sn, (char*)&v, sizeof(v));
}
else if (val == "float")
{
double v = .0f;
setting_jsn_.at(key).at("default").get_to(v);
set_setting(sn, (char*)&v, sizeof(v));
}
else if (val == "bool")
{
bool v = false;
setting_jsn_.at(key).at("default").get_to(v);
set_setting(sn, (char*)&v, sizeof(v));
}
}
setting_count_ = count;
notify_setting_result_ = true;
}
int hg_scanner::on_scann_error(int err)
{
status_ = err;
HG_VLOG_MINI_1(HG_LOG_LEVEL_FATAL, "[xxx]Device status: 0x%x\n", err);
unsigned int e = err;
return ui_ev_cb_((scanner_handle)this, SANE_EVENT_ERROR, (void*)hg_scanner::strerr((hg_err)err).c_str(), &e, NULL);
}
int hg_scanner::notify_ui_working_status(const char* msg, int ev, int status)
{
unsigned int s = status;
return ui_ev_cb_((scanner_handle)this, ev, (void*)msg, &s, NULL);
}
bool hg_scanner::waiting_for_memory_enough(unsigned need_bytes)
{
return true; // disable the memory control - added on 2022-03-22
bool ret = true;
if(cb_mem_)
{
int ret = ui_ev_cb_((scanner_handle)this, SANE_EVENT_IS_MEMORY_ENOUGH, NULL, &need_bytes, NULL);
if (ret == HG_ERR_INSUFFICIENT_MEMORY)
{
user_cancel_ = true;
status_ = HG_ERR_INSUFFICIENT_MEMORY;
ret = false;
}
else if (ret == HG_ERR_NOT_ANY_MORE)
cb_mem_ = false;
}
else
{
need_bytes *= 4;
void* buf = malloc(need_bytes);
bool first = true;
while (!buf && !user_cancel_)
{
if (first)
{
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "Memory is too small for aquiring image(%u bytes), wait for ENOUGH ...\n", need_bytes);
notify_ui_working_status(STATU_DESC_WAIT_FOR_MEM);
first = false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(30));
buf = malloc(need_bytes);
}
if (!first)
{
if (buf)
{
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "waited for memory need(%u)\n", need_bytes);
}
else
{
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "canceled by user while waiting for memory need(%u)\n", need_bytes);
}
}
ret = (!user_cancel_) && (buf != NULL);
if (buf)
free(buf);
}
return ret;
}
void hg_scanner::copy_to_sane_image_header(SANE_Parameters* header, int w, int h, int line_bytes, int channels)
{
if (channels == 3)
header->format = SANE_FRAME_RGB;
else
header->format = SANE_FRAME_GRAY;
header->depth = 8; // 此处指每一个颜色分量的位深我们的扫描仪固定为“8”
header->last_frame = true; // 一幅图片如果各个分量相互分离则最后一个分量的时候设置为true。彩色图像RGB时也只有一“帧”所以也为true
header->pixels_per_line = w;
header->lines = h;
header->bytes_per_line = line_bytes;
}
int hg_scanner::save_usb_data(std::shared_ptr<std::vector<char>> data)
{
int ret = HG_ERR_OK;
usb_img_index_++;
HG_VLOG_MINI_1(HG_LOG_LEVEL_DEBUG_INFO, "USB read one picture with %u bytes\n", data->size());
if (is_to_file())
{
std::string file("");
ret = hg_scanner::save_2_tempory_file(data, &file, usb_img_index_);
if (ret == HG_ERR_OK)
paths_.Put(file);
}
else
{
imgs_.Put(data);
#ifdef SAVE_TO_FILE
hg_scanner::save_2_tempory_file(data, NULL, usb_img_index_);
#endif
}
if (wait_img_.is_waiting())
wait_img_.notify();
return ret;
}
int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf)
{
final_img_index_++;
if (async_io_)
{
SANE_Image img;
copy_to_sane_image_header(&img.header, head->width, head->height, head->line_bytes, head->channels);
img.data = (unsigned char*)buf;
img.bytes = head->total_bytes;
return ui_ev_cb_((scanner_handle)this, SANE_EVENT_IMAGE_OK, &img, &final_img_index_, NULL);
}
final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes);
return HG_ERR_OK;
}
int hg_scanner::reset_io(usb_io* io)
{
online_ = false;
if (!io)
return HG_ERR_INVALID_PARAMETER;
{
std::lock_guard<std::mutex> lock(io_lock_);
usb_io* old = io_;
io->add_ref();
io_ = io;
status_ = io_->last_error();
online_ = status_ == HG_ERR_OK;
if (old)
old->release();
}
on_device_reconnected();
return HG_ERR_OK;
}
int hg_scanner::io_disconnected(void)
{
std::lock_guard<std::mutex> lock(io_lock_);
online_ = false;
io_->on_disconnected();
return HG_ERR_OK;
}
void hg_scanner::set_ui_callback(sane_callback cb, bool enable_async_io)
{
ui_ev_cb_ = cb ? cb : ui_default_callback;
async_io_ = enable_async_io;
}
int hg_scanner::get_pid(void)
{
std::lock_guard<std::mutex> lock(io_lock_);
return io_->get_pid();
}
int hg_scanner::get_vid(void)
{
std::lock_guard<std::mutex> lock(io_lock_);
return io_->get_vid();
}
int hg_scanner::close(bool force)
{
int ret = on_scanner_closing(force);
online_ = false;
if (ret == HG_ERR_OK)
{
run_ = false;
wait_usb_.notify();
wait_img_.notify();
if(!scan_life_)
{
std::lock_guard<std::mutex> lock(io_lock_);
if (io_)
{
io_->close();
io_->release();
io_ = NULL;
}
}
else if (io_)
{
HG_LOG(HG_LOG_LEVEL_WARNING, "close scanner: USB thread or Image thread is still running.\n");
io_->close();
io_->release();
io_ = NULL;
}
status_ = HG_ERR_NOT_OPEN;
}
return ret;
}
int hg_scanner::set_setting(int setting_no, void* data, int len)
{
// NOTE: the array of 'func' must be ONE to ONE of the HG_BASE_SETTING_INDEX_xxx
int(hg_scanner:: * func[])(void*) = { &hg_scanner::setting_restore
, &hg_scanner::setting_help
, &hg_scanner::setting_color_mode
, &hg_scanner::setting_multi_out
, &hg_scanner::setting_rid_color
, &hg_scanner::setting_rid_multi_red
, &hg_scanner::setting_rid_answer_red
, &hg_scanner::setting_erase_background
, &hg_scanner::setting_erase_background_range
, &hg_scanner::setting_noise_optimize
, &hg_scanner::setting_noise_optimize_range
, &hg_scanner::setting_paper
, &hg_scanner::setting_paper_check
, &hg_scanner::setting_is_custom_area
, &hg_scanner::setting_custom_area_left
, &hg_scanner::setting_custom_area_right
, &hg_scanner::setting_custom_area_top
, &hg_scanner::setting_custom_area_bottom
, &hg_scanner::setting_page
, &hg_scanner::setting_page_omit_empty
, &hg_scanner::setting_resolution
, &hg_scanner::setting_img_quality
, &hg_scanner::setting_exchagnge
, &hg_scanner::setting_split_image
, &hg_scanner::setting_automatic_skew
, &hg_scanner::setting_rid_hole
, &hg_scanner::setting_rid_hoe_range
, &hg_scanner::setting_is_custom_gamma // 2022-05-05
, &hg_scanner::setting_bright
, &hg_scanner::setting_contrast
, &hg_scanner::setting_gamma
, &hg_scanner::setting_custom_gamma_data
, &hg_scanner::setting_sharpen
, &hg_scanner::setting_dark_sample
, &hg_scanner::setting_erase_black_frame
, &hg_scanner::setting_threshold
, &hg_scanner::setting_anti_noise
, &hg_scanner::setting_margin
, &hg_scanner::setting_filling_background
, &hg_scanner::setting_is_permeate
, &hg_scanner::setting_is_permeate_lv
, &hg_scanner::setting_remove_morr
, &hg_scanner::setting_error_extention
, &hg_scanner::setting_remove_texture
, &hg_scanner::setting_ultrasonic_check
, &hg_scanner::setting_staple_check
, &hg_scanner::setting_scan_mode
, &hg_scanner::setting_scan_count
, &hg_scanner::setting_text_direction
, &hg_scanner::setting_rotate_bkg_180
, &hg_scanner::setting_fractate_check
, &hg_scanner::setting_fractate_check_level
, &hg_scanner::setting_skew_check
, &hg_scanner::setting_skew_check_level
};
bool hit = false;
int ret = HG_ERR_OUT_OF_RANGE;
char sn[20];
sprintf(sn, "%d", setting_no);
for (size_t i = 0; i < ARRAY_SIZE(func); ++i)
{
if (setting_map_[i] == setting_no)
{
ret = (this->*func[i])(data);
hit = true;
break;
}
}
if (!hit)
{
HG_VLOG_MINI_1(HG_LOG_LEVEL_WARNING, "Setting %d is not found in base setting functions.\n", setting_no);
ret = set_setting_value(setting_no, data, len);
}
if (ret == HG_ERR_OK || ret == HG_ERR_NOT_EXACT || ret == HG_ERR_CONFIGURATION_CHANGED)
{
std::string type(""), name("");
setting_jsn_.at(sn).at("type").get_to(type);
setting_jsn_.at(sn).at("title").get_to(name);
if (type == "string")
{
setting_jsn_.at(sn).at("cur") = (char*)data;
type = (char*)data;
}
else if (type == "int")
{
setting_jsn_.at(sn).at("cur") = *((int*)data);
sprintf(sn, "%d", *((int*)data));
type = sn;
}
else if (type == "float")
{
setting_jsn_.at(sn).at("cur") = *((double*)data);
sprintf(sn, "%f", *((double*)data));
type = sn;
}
else if (type == "bool")
{
setting_jsn_.at(sn).at("cur") = *((bool*)data);
type = *((bool*)data) ? "true" : "false";
}
if (notify_setting_result_)
{
name.insert(0, "设置 “");
name += "” 值为“";
name += type + "” 成功。";
notify_ui_working_status(name.c_str());
}
}
else if (notify_setting_result_)
{
std::string name("");
if (setting_jsn_.contains(sn))
{
setting_jsn_.at(sn).at("title").get_to(name);
}
else
name = std::string("设置项") + sn;
name.insert(0, "设置 “");
name += "” 值失败: " + hg_scanner::strerr((hg_err)ret);
notify_ui_working_status(name.c_str());
}
return ret;
}
int hg_scanner::get_setting(int setting_no, char* json_txt_buf, int* len)
{
if (!len)
return HG_ERR_INVALID_PARAMETER;
if (setting_no == 0)
{
int count = 0;
setting_jsn_.at("option_count").get_to(count);
*len = count;
return HG_ERR_OK;
}
if (setting_count_ <= setting_no || setting_no < 0)
return HG_ERR_OUT_OF_RANGE;
char sn[20];
std::string text(""), name(""), tag("");
int add = 0;
bool is_gamma = false, is_area_x = false, is_area_y = false;
sprintf(sn, "%d", setting_no);
if (!setting_jsn_.contains(sn))
HG_VLOG_MINI_2(HG_LOG_LEVEL_FATAL, "!!!option(%d - %s) is not found.\n", setting_no, sn);
text = setting_jsn_.at(sn).dump();
setting_jsn_.at(sn).at("name").get_to(name);
if (name == KNOWN_OPT_NAME_CUSTOM_GAMMA)
{
is_gamma = true;
add = 4 * sizeof(custom_gamma_val_);
}
else if (name == KNOWN_OPT_NAME_CUSTOM_AREA_LEFT || name == KNOWN_OPT_NAME_CUSTOM_AREA_RIGHT)
{
is_area_x = true;
add = 20;
}
else if (name == KNOWN_OPT_NAME_CUSTOM_AREA_TOP || name == KNOWN_OPT_NAME_CUSTOM_AREA_BOTTOM)
{
is_area_y = true;
add = 20;
}
if (*len <= text.length() + add)
{
*len = text.length() + 8 + add;
return HG_ERR_INSUFFICIENT_MEMORY;
}
if (is_gamma)
{
name = "";
add = 3 * 256;
sprintf(sn, "[%u", custom_gamma_val_->table[0]);
name += sn;
for (int i = 1; i < add; ++i)
{
sprintf(sn, ",%u", custom_gamma_val_->table[i]);
name += sn;
}
name += "]";
tag = "\"cur\":";
}
else if (is_area_x)
{
sprintf(sn, "%u.0", paper_size_mm_.cx);
name = sn;
tag = "\"max\":";
}
else if (is_area_y)
{
sprintf(sn, "%u.0", paper_size_mm_.cy);
name = sn;
tag = "\"max\":";
}
if (!tag.empty())
{
size_t pos = text.find(tag), end = pos;
if (pos != std::string::npos)
{
pos += tag.length();
end = pos;
while (end < text.length())
{
if (text[end] == ',' || text[end] == '}' || text[end] == ']' || text[end] == '\r' || text[end] == '\n')
break;
end++;
}
if (end > pos)
text.replace(pos, end - pos, name);
else
text.insert(end, name);
}
}
strcpy(json_txt_buf, text.c_str());
*len = text.length();
return HG_ERR_OK;
}
std::string hg_scanner::name(void)
{
return name_;
}
int hg_scanner::status(void)
{
return status_;
}
bool hg_scanner::is_online(void)
{
return online_;
}
int hg_scanner::start(void)
{
user_cancel_ = false;
return status_;
}
int hg_scanner::get_image_info(SANE_Parameters* ii)
{
int ret = HG_ERR_OK;
IMH imh;
bzero(&imh, sizeof(imh));
while ((!wait_img_.is_waiting() || !wait_usb_.is_waiting()) && final_imgs_.Size() <= 0)
this_thread::sleep_for(chrono::milliseconds(10));
if (final_imgs_.Size() <= 0)
ret = HG_ERR_NO_DATA;
else
{
if (!final_imgs_.front(&imh))
ret = HG_ERR_NO_DATA;
else
copy_to_sane_image_header(ii, imh.width, imh.height, imh.line_bytes, imh.channels);
}
HG_VLOG_MINI_4(HG_LOG_LEVEL_DEBUG_INFO, "Get image info(%d * %d * %d) = %s\n", ii->pixels_per_line, ii->lines, imh.bits, hg_scanner::strerr((hg_err)ret).c_str());
return ret;
}
int hg_scanner::read_image_data(unsigned char* buf, int* len)
{
if (!len)
return HG_ERR_INVALID_PARAMETER;
if (!buf)
{
IMH imh;
final_imgs_.front(&imh);
*len = imh.bytes;
return HG_ERR_INSUFFICIENT_MEMORY;
}
if (final_imgs_.Size() > 0)
{
int fetch = *len;
bool over = false;
final_imgs_.fetch_front(buf, len, &over);
return over ? HG_ERR_NO_DATA : HG_ERR_OK;
}
else
return HG_ERR_NO_DATA;
}
int hg_scanner::stop(void)
{
user_cancel_ = true;
return status_;
}
int hg_scanner::reset(void)
{
return status_;
}
int hg_scanner::device_io_control(unsigned long code, void* data, unsigned* len)
{
if (code == IO_CTRL_CODE_RESTORE_SETTINGS)
{
setting_restore(data);
return HG_ERR_CONFIGURATION_CHANGED;
}
else if (code == IO_CTRL_CODE_GET_DEFAULT_VALUE)
{
char* jsn_txt = NULL;
int size = 0;
json jsn;
int ret = get_setting(*len, jsn_txt, &size);
if (ret == HG_ERR_INSUFFICIENT_MEMORY)
{
jsn_txt = (char*)malloc(size + 4);
bzero(jsn_txt, size + 4);
get_setting(*len, jsn_txt, &size);
jsn = jsonconfig::load_json_from_text(jsn_txt);
free(jsn_txt);
if (get_default_value(data, &jsn))
ret = HG_ERR_OK;
else
ret = HG_ERR_DATA_DAMAGED;
}
return ret;
}
else if (code == IO_CTRL_CODE_CLEAR_ROLLER_COUNT)
{
int count = get_roller_num();
if (len)
*len = count;
return clear_roller_num();
}
else if (code == IO_CTRL_CODE_SET_FINAL_IMAGE_FORMAT)
{
SANE_FinalImgFormat* fmt = (SANE_FinalImgFormat*)data;
return set_final_image_format(fmt);
}
else if(code == IO_CTRL_CODE_TEST_SINGLE)
{
return set_leaflet_scan();
}
else if (code == IO_CTRL_CODE_SET_AUTO_COLOR_TYPE)
{
return set_auto_color_type();
}
else if(code == IO_CTRL_CODE_GET_HARDWARE_VERSION)
{
std::string fw = get_firmware_version();
if (*len < fw.size())
{
*len = fw.size();
return HG_ERR_INSUFFICIENT_MEMORY;
}
char* buf = strcpy((char*)data, fw.c_str());
if (buf)
{
return HG_ERR_OK;
}
return HG_ERR_DATA_DAMAGED;
}
else if(code == IO_CTRL_CODE_GET_SERIAL)
{
std::string ser = get_serial_num();
if (*len < ser.size())
{
*len = ser.size();
return HG_ERR_INSUFFICIENT_MEMORY;
}
char* buf = strcpy((char*)data, ser.c_str());
if (buf)
{
return HG_ERR_OK;
}
return HG_ERR_DATA_DAMAGED;
}
else if (code == IO_CTRL_CODE_GET_HARDWARE_VERSION)
{
std::string ip = get_ip();
if (*len < ip.size())
{
*len = ip.size();
return HG_ERR_INSUFFICIENT_MEMORY;
}
char* buf = strcpy((char*)data, ip.c_str());
if (buf)
{
return HG_ERR_OK;
}
return HG_ERR_DATA_DAMAGED;
}
else if (code == IO_CTRL_CODE_GET_PAPER_ON)
{
return get_scanner_paperon((SANE_Bool*)data);
}
else if(code == IO_CTRL_CODE_GET_POWER_LEVEL)
{
int val = 0,
ret = HG_ERR_OK;
if (*len < sizeof(int *))
{
*len = sizeof(int *);
return HG_ERR_INSUFFICIENT_MEMORY;
}
ret = get_sleep_time(val);
if (ret == HG_ERR_OK)
{
*((int *)data) = val;
}
return ret;
}
else if(code == IO_CTRL_CODE_SET_POWER_LEVEL)
{
int val = *((int*)data);
int sleeptime = 0;
switch (val)
{
case SANE_POWER_NONE:
sleeptime = 0;
break;
case SANE_POWER_MINUTES_5:
sleeptime = 300;
break;
case SANE_POWER_MINUTES_10:
sleeptime = 600;
break;
case SANE_POWER_MINUTES_20:
sleeptime = 1200;
break;
case SANE_POWER_MINUTES_30:
sleeptime = 1800;
break;
case SANE_POWER_MINUTES_60:
sleeptime = 3600;
break;
case SANE_POWER_MINUTES_120:
sleeptime = 7200;
break;
case SANE_POWER_MINUTES_240:
sleeptime = 14400;
break;
default:
sleeptime = 0;
break;
}
return set_sleep_time(sleeptime);
}
else if (code == IO_CTRL_CODE_GET_CUSTOM_GAMMA)
{
SANE_Gamma* v = (SANE_Gamma*)data;
memcpy(v, custom_gamma_val_, sizeof(*custom_gamma_val_));
return HG_ERR_OK;
}
else if (code == IO_CTRL_CODE_SET_CUSTOM_GAMMA)
{
SANE_Gamma* v = (SANE_Gamma*)data;
memcpy(custom_gamma_val_, v, sizeof(*custom_gamma_val_));
return HG_ERR_OK;
}
return HG_ERR_DEVICE_NOT_SUPPORT;
}
std::string hg_scanner::get_firmware_version(void)
{
return BRAND_DEVICE_NOT_SUPPORT;
}
std::string hg_scanner::get_serial_num(void)
{
return BRAND_DEVICE_NOT_SUPPORT;
}
std::string hg_scanner::get_ip(void)
{
return BRAND_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_roller_num(void)
{
return -2;
}
int hg_scanner::clear_roller_num(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_history_count(void)
{
return -2;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
int hg_scanner::set_leaflet_scan(void)
{
return HG_ERR_NO_DATA;
}
int hg_scanner::get_abuot_info(void)
{
return HG_ERR_NO_DATA;
}
int hg_scanner::restore_default_setting(void)
{
return HG_ERR_NO_DATA;
}
int hg_scanner::set_final_image_format(SANE_FinalImgFormat* fmt)
{
switch (fmt->img_format)
{
case SANE_IMAGE_TYPE_BMP:
img_type_ = ".bmp";
break;
case SANE_IMAGE_TYPE_PNG:
img_type_ = ".png";
break;
case SANE_IMAGE_TYPE_JPG:
img_type_ = ".jpg";
break;
case SANE_IMAGE_TYPE_TIFF:
return HG_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_WEBP:
return HG_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_PDF:
return HG_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_GIF:
return HG_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_SVG:
return HG_ERR_INVALID_PARAMETER;
default:
img_type_ = "";
break;
}
return HG_ERR_OK;
}
int hg_scanner::get_compression_format(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_compression_format(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_auto_color_type(void)
{
is_auto_matic_color = true;
return HG_ERR_OK;
}
int hg_scanner::get_device_code(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_sleep_time(int& getsleepime)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_sleep_time(int sleeptime)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_dogear_distance(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_dogear_distance(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_scanner_paperon(SANE_Bool* paperon)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_scan_when_paper_on(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_scan_when_paper_on(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_scan_with_hole(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_scan_with_hole(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_scan_is_sleep(void)
{
return HG_ERR_DEVICE_NOT_SUPPORT;
}