调整属性文件结构,添加图像处理框架

This commit is contained in:
gb 2023-11-10 14:38:12 +08:00
parent 6ca7d1674d
commit 9dff1ece70
31 changed files with 1440 additions and 232 deletions

View File

@ -6,8 +6,9 @@
#include "scanner_setting.h"
#include "scanner_manager.h"
#include "../../sdk/json/gb_json.h"
#include "user-opt/device_opt.h"
#include <sane_opt_json/device_opt.h>
#include <string.h>
#include <imgprc/imgprc_mgr.h>
#if defined(WIN32) || defined(_WIN64)
#include <direct.h>
@ -259,6 +260,7 @@ hg_scanner::hg_scanner(ScannerSerial serial, const char* dev_name, const char* m
hg_scanner::~hg_scanner()
{
close(true);
set_image_processor(nullptr);
hg_version_free_handle();
//if (thread_read_int_.get() && thread_read_int_->joinable())
@ -488,7 +490,7 @@ int hg_scanner::hg_version_init_handle()
if (!Dynamicopen_HGVersion_pHandle_ )
{
utils::to_log(LOG_LEVEL_DEBUG, "HGVersionlib_path open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY));
utils::to_log(LOG_LEVEL_DEBUG, "HGVersionlib_path open dll is error: %s\n", "SCANNER_ERR_INSUFFICIENT_MEMORY");
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
HGVersion_Init_ = (SDKHGVersion_Init_)dlsym(Dynamicopen_HGVersion_pHandle_, "HGVersion_CreateMgr");
@ -516,7 +518,7 @@ int hg_scanner::hg_version_init_handle()
//int l = GetLastError();
if (!Dynamicopen_HGVersion_pHandle_ )
{
utils::to_log(LOG_LEVEL_DEBUG, "Dynamicopen_HGVersion_pHandle_ open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY));
utils::to_log(LOG_LEVEL_DEBUG, "Dynamicopen_HGVersion_pHandle_ open dll is error: %s\n", "SCANNER_ERR_INSUFFICIENT_MEMORY");
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
HGVersion_Init_ = (SDKHGVersion_Init_) GetProcAddress(Dynamicopen_HGVersion_pHandle_, "HGVersion_CreateMgr");
@ -1061,6 +1063,7 @@ int hg_scanner::setting_color_mode(void* data, long* len)
val = 0,
ret = SCANNER_ERR_OK;
std::string str((char*)data);
char errbuf[40] = { 0 };
val = image_prc_param_.bits.color_mode = match_best_color_mode(str, NULL);
@ -1082,7 +1085,7 @@ int hg_scanner::setting_color_mode(void* data, long* len)
is_auto_matic_color = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? true :false; // 等于COLOR_MODE_AUTO_MATCH 的时候颜色模式需要变为2 彩色模式图像参数和硬件参数都如此
utils::to_log(LOG_LEVEL_DEBUG, "Change color mode from %s to %s = %s color is =%s\n", color_mode_string(old).c_str(), (char*)data, hg_scanner_err_name(ret),str.c_str());
utils::to_log(LOG_LEVEL_DEBUG, "Change color mode from %s to %s = %s color is =%s\n", color_mode_string(old).c_str(), (char*)data, hg_scanner_err_name(ret, errbuf), str.c_str());
if(ret == SCANNER_ERR_NOT_EXACT)
::strcpy((char*)data, str.c_str());
@ -1108,7 +1111,8 @@ int hg_scanner::setting_multi_out(void* data, long* len)
}
int hg_scanner::setting_multi_out_type(void* data, long* len)
{
int ret = SCANNER_ERR_OK;
char errbuf[40] = { 0 };
int ret = SCANNER_ERR_OK;
std::string str((char*)data);
@ -1116,7 +1120,7 @@ int hg_scanner::setting_multi_out_type(void* data, long* len)
image_prc_param_.bits.multi_out = match_best_multi_out(str,NULL);
save_multiout = str;
utils::to_log(LOG_LEVEL_DEBUG, "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_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "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_err_name(ret, errbuf));
/*if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW)
color = COLOR_MODE_256_GRAY;
@ -1196,6 +1200,7 @@ int hg_scanner::setting_paper(void* data, long* len)
int ret = SCANNER_ERR_OK, sub = SCANNER_ERR_OK,
val = 0,
old = image_prc_param_.bits.paper;
char errbuf[40] = { 0 };
val = image_prc_param_.bits.paper = switch_lateral(match_best_paper(paper, NULL), lateral_);
@ -1222,17 +1227,18 @@ int hg_scanner::setting_paper(void* data, long* len)
invoke_setting_xxx(&hg_scanner::setting_paper_check, &save_sizecheck, &l);
}
utils::to_log(LOG_LEVEL_DEBUG, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner_err_name(ret, errbuf));
return SCANNER_ERR_RELOAD_OPT_PARAM; // ret;
}
int hg_scanner::setting_paper_check(void* data, long* len)
{
bool use = *((bool*)data);
char errbuf[40] = { 0 };
int ret = on_paper_check_changed(use);
utils::to_log(LOG_LEVEL_DEBUG, "Change paper size-checking %s = %s\n", *((bool*)data) ? "enabled" : "disabled", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "Change paper size-checking %s = %s\n", *((bool*)data) ? "enabled" : "disabled", hg_scanner_err_name(ret, errbuf));
if (ret == SCANNER_ERR_DEVICE_NOT_SUPPORT)
{
*((bool*)data) = use;
@ -1246,8 +1252,9 @@ int hg_scanner::setting_page(void* data, long* len)
{
std::string val((char*)data);
int ret = SCANNER_ERR_OK;
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "Change page from %s to %s = %s\n", page_string(image_prc_param_.bits.page).c_str(), (char*)data, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "Change page from %s to %s = %s\n", page_string(image_prc_param_.bits.page).c_str(), (char*)data, hg_scanner_err_name(ret, errbuf));
image_prc_param_.bits.page = match_best_page(val, NULL);
return ret;
@ -1538,9 +1545,10 @@ int hg_scanner::setting_text_direction(void* data, long* len)
{
std::string str((char*)data);
int ret = SCANNER_ERR_OK;
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "Change text direction from '%s' to '%s' = %s\n", text_direction_string(image_prc_param_.bits.text_direction).c_str()
, (char*)data, hg_scanner_err_name(ret));
, (char*)data, hg_scanner_err_name(ret, errbuf));
image_prc_param_.bits.text_direction = match_best_text_direction(str, NULL);
if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO && ImagePrc_pHandle_)
@ -1656,8 +1664,10 @@ int hg_scanner::setting_img_quality(void* data, long* len)
std::string str((char*)data);
int ret = SCANNER_ERR_OK;
int old = is_quality_;
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "Change quality from '%s' to '%s' = %s\n", is_img_quality(is_quality_).c_str()
, (char*)data, hg_scanner_err_name(ret));
, (char*)data, hg_scanner_err_name(ret, errbuf));
is_quality_ = match_best_img_quality(str,NULL);
/*if (!check_resolution_and_quality(resolution_, is_img_quality(is_quality_).c_str()))
@ -1704,12 +1714,13 @@ int hg_scanner::setting_feedmode(void* data, long* len)
if (val == feedmode_)
return SCANNER_ERR_OK;
char errbuf[40] = { 0 };
int ret = on_set_feedmode(val);
if (ret == SCANNER_ERR_OK)
feedmode_ = val;
utils::to_log(LOG_LEVEL_DEBUG, "setfeedmode from '%s' to '%s' = %s\n", is_paper_strength(feedmode_).c_str()
, (char*)data, hg_scanner_err_name(ret));
, (char*)data, hg_scanner_err_name(ret, errbuf));
return ret;
}
int hg_scanner::setting_sleeptime(void* data, long* len)
@ -1751,12 +1762,13 @@ int hg_scanner::setting_sleeptime(void* data, long* len)
mintosec = val * 60;
}
int ret = set_sleep_time(mintosec);
char errbuf[40] = { 0 };
int ret = set_sleep_time(mintosec);
if (ret == SCANNER_ERR_OK)
sleeptime_ = val;
utils::to_log(LOG_LEVEL_DEBUG, "set sleeptime from (%s)min to (%s)min = %s\n", is_sleep_time(sleeptime_).c_str()
, (char*)data, hg_scanner_err_name(ret));
, (char*)data, hg_scanner_err_name(ret, errbuf));
return ret;
}
int hg_scanner::setting_auto_pick_paper(void* data, long* len)
@ -2303,8 +2315,9 @@ int hg_scanner::on_scann_error(int err)
utils::to_log(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_err_name(err), &e, NULL);
char errbuf[40] = { 0 };
return ui_ev_cb_((scanner_handle)this, SANE_EVENT_ERROR, (void*)hg_scanner_err_name(err, errbuf), &e, NULL);
}
int hg_scanner::try_third_app_handle_start(bool& handled)
{
@ -2660,6 +2673,18 @@ void hg_scanner::set_ui_callback(sane_callback cb, bool enable_async_io)
async_io_ = enable_async_io;
is_white_0_ = !async_io_;
}
void hg_scanner::set_image_processor(imgproc_mgr* proc)
{
if (img_processor_)
{
img_processor_->release();
}
img_processor_ = proc;
if (img_processor_)
{
img_processor_->add_ref();
}
}
void hg_scanner::set_dev_family(const char* family)
{
family_ = family ? family : "";
@ -2694,6 +2719,7 @@ int hg_scanner::close(bool force)
if (thread_devslock_handle_.get())
wait_devsislock_.notify();
//wait_read_int.notify();
if(!scan_life_)
{
std::lock_guard<std::mutex> lock(io_lock_);
@ -2908,7 +2934,8 @@ int hg_scanner::get_image_info(SANE_Parameters* ii)
ret = SCANNER_ERR_OK;
}
}
utils::to_log(LOG_LEVEL_DEBUG, "Get image info(%d * %d * %d) = %s\n", ii->pixels_per_line, ii->lines, imh.bits, hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "Get image info(%d * %d * %d) = %s\n", ii->pixels_per_line, ii->lines, imh.bits, hg_scanner_err_name(ret, errbuf));
return ret;
}

View File

@ -71,10 +71,10 @@ typedef HGResult(__stdcall* SDKHGVersion_Postlog_)(HGVersionMgr mgr, const HGCha
const HGChar* devType, const HGChar* devFW, HGBool isLock);
typedef HGResult(__stdcall* SDKHGVersion_Free_)(HGVersionMgr mgr);
class gb_json;
class device_option;
class imgproc_mgr;
#include <sane_opt_json/base_opt.h>
#include "../../sdk/hginclude/base_opt.h"
class hg_scanner : public sane_opt_provider
{
HGVersionMgr HGVersion_mgr_;
@ -98,6 +98,7 @@ class hg_scanner : public sane_opt_provider
sane_callback ui_ev_cb_;
imgproc_mgr* img_processor_ = nullptr;
do_when_born_and_dead<hg_scanner>* scan_life_;
std::unique_ptr<std::thread> thread_usb_read_;
@ -434,6 +435,7 @@ public:
int stop(void);
void set_ui_callback(sane_callback cb, bool enable_async_io);
void set_image_processor(imgproc_mgr* proc);
void set_dev_family(const char* family);
void set_read_over_with_no_data(bool no_data);
int reset_io(usb_io* io);

View File

@ -265,13 +265,15 @@ void hg_scanner_200::thread_handle_usb_read(void)
}
this_thread::sleep_for(chrono::milliseconds(2));
}
utils::to_log(LOG_LEVEL_DEBUG, "USB thread exit with code: %s, status = %s\n", hg_scanner_err_name(ret), hg_scanner_err_description(status_));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "USB thread exit with code: %s, status = %s\n", hg_scanner_err_name(ret, errbuf), hg_scanner_err_description(status_));
}
int hg_scanner_200::do_start(void)
{
bool handled = false;
int ret = try_third_app_handle_start(handled),
count = -1;
count = -1;
char errbuf[40] = { 0 };
// for third-sane-app invoking, added on 2022-05-19
if (handled)
@ -306,7 +308,7 @@ int hg_scanner_200::do_start(void)
ret = writeusb(usb);
io_->set_timeout(500);
}
utils::to_log(LOG_LEVEL_WARNING, "write start command = %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "write start command = %s\n", hg_scanner_err_name(ret, errbuf));
if(ret == SCANNER_ERR_OK)
{
@ -316,7 +318,7 @@ int hg_scanner_200::do_start(void)
}
else
status_ = ret;
utils::to_log(LOG_LEVEL_WARNING, "start result: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "start result: %s\n", hg_scanner_err_name(ret, errbuf));
return ret;
}
@ -465,7 +467,8 @@ int hg_scanner_200::writedown_device_configuration(bool type,setting_hardware::H
int ret = SCANNER_ERR_OK,
len = 0;
char errbuf[40] = { 0 };
if (!d)
d = &dsp_config_;
if (is_multiout)
@ -487,7 +490,7 @@ int hg_scanner_200::writedown_device_configuration(bool type,setting_hardware::H
ret = io_->write_bulk(&usbcb, &len);
}
utils::to_log(LOG_LEVEL_WARNING, "writedown_device_configuration is .(%s)\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "writedown_device_configuration is .(%s)\n", hg_scanner_err_name(ret, errbuf));
return ret;
}
@ -988,6 +991,7 @@ int hg_scanner_200::set_auto_flat(int data)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
char errbuf[40] = { 0 };
USBCB usbcb = { setting3288dsp::START_FLAT,data,0 };
int len = sizeof(usbcb);
int ret = SCANNER_ERR_OK;
@ -1005,7 +1009,7 @@ int hg_scanner_200::set_auto_flat(int data)
}
else
status_ = ret;
utils::to_log(LOG_LEVEL_WARNING, "set_auto_flat ret: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "set_auto_flat ret: %s\n", hg_scanner_err_name(ret, errbuf));
return ret;
}

File diff suppressed because one or more lines are too long

View File

@ -277,7 +277,8 @@ void hg_scanner_300::thread_handle_usb_read(void)
}
this_thread::sleep_for(chrono::milliseconds(10));
}
utils::to_log(LOG_LEVEL_DEBUG, "USB thread exit with code: %s, status = %s\n", hg_scanner_err_name(ret), hg_scanner_err_description(status_));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "USB thread exit with code: %s, status = %s\n", hg_scanner_err_name(ret, errbuf), hg_scanner_err_description(status_));
}
int hg_scanner_300::discard_all_images(void)
{
@ -453,20 +454,21 @@ int hg_scanner_300::get_scanner_status(USBCB &usb)
{
std::lock_guard<std::mutex> lock(io_lock_);
int ret = SCANNER_ERR_OK;
char errbuf[40] = { 0 };
usb = { setting3288dsp::GET_DSP_STATUS, 0, 0};
io_->set_timeout(2000);
ret = writeusb(usb);
if (ret != SCANNER_ERR_OK)
{
utils::to_log(LOG_LEVEL_WARNING, "get_scanner_status write usb: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "get_scanner_status write usb: %s\n", hg_scanner_err_name(ret, errbuf));
return ret;
}
ret = readusb(usb);
if (ret != SCANNER_ERR_OK)
{
utils::to_log(LOG_LEVEL_WARNING, "get_scanner_status read usb: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "get_scanner_status read usb: %s\n", hg_scanner_err_name(ret, errbuf));
status_ = ret;
return ret;
}
@ -479,14 +481,15 @@ int hg_scanner_300::get_img_data(std::shared_ptr<tiny_buffer> &imagedata)
ret = SCANNER_ERR_OK,
index = 0,
block = total;
char errbuf[40] = { 0 };
USBCB usb{ setting3288dsp::GET_IMAGE, 0, total};
{
std::lock_guard<std::mutex> lock(io_lock_);
ret = writeusb(usb);
if (ret != SCANNER_ERR_OK)
{
utils::to_log(LOG_LEVEL_WARNING, "get_img_data setting3288dsp::GET_IMAGE write usb: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "get_img_data setting3288dsp::GET_IMAGE write usb: %s\n", hg_scanner_err_name(ret, errbuf));
}
else
{
@ -511,12 +514,12 @@ int hg_scanner_300::get_img_data(std::shared_ptr<tiny_buffer> &imagedata)
if (ret != SCANNER_ERR_OK && ret != SCANNER_ERR_TIMEOUT)
{
utils::to_log(LOG_LEVEL_FATAL, "get_img_data read_data:%s!!! \n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_FATAL, "get_img_data read_data:%s!!! \n", hg_scanner_err_name(ret, errbuf));
break;
}
else if (ret == SCANNER_ERR_TIMEOUT && io_->get_timeout() > 3000)
{
utils::to_log(LOG_LEVEL_FATAL, "get_img_data read_data:%s!!! ,get_timeout is %d\n", hg_scanner_err_name(ret), io_->get_timeout());
utils::to_log(LOG_LEVEL_FATAL, "get_img_data read_data:%s!!! ,get_timeout is %d\n", hg_scanner_err_name(ret, errbuf), io_->get_timeout());
break;
}
@ -531,7 +534,7 @@ int hg_scanner_300::get_img_data(std::shared_ptr<tiny_buffer> &imagedata)
}
else
{
utils::to_log(LOG_LEVEL_DEBUG, "Read image data from USB err: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "Read image data from USB err: %s\n", hg_scanner_err_name(ret, errbuf));
stop();
string str = STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_ERR;
str = str + '-' + STATU_DESC_SCANNER_ERR_DEVICE_STOPPED;
@ -686,7 +689,8 @@ int hg_scanner_300::writedown_device_configuration(bool type,setting_hardware::H
{
printf_devconfig(d);
}
utils::to_log(LOG_LEVEL_WARNING, "writedown_device_configuration is .(%s)\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_WARNING, "writedown_device_configuration is .(%s)\n", hg_scanner_err_name(ret, errbuf));
return ret;
}
@ -1201,7 +1205,8 @@ int hg_scanner_300::set_firmware_upgrade(std::string str)
if (ret != SCANNER_ERR_OK)
{
utils::to_log(LOG_LEVEL_WARNING, "updata result read_bulk:%s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_WARNING, "updata result read_bulk:%s\n", hg_scanner_err_name(ret, errbuf));
//return ret;
}
if (result.u32_Data == 2 || result.u32_Data == 3)
@ -1327,7 +1332,8 @@ int hg_scanner_300::set_auto_flat(int data)
}
else
status_ = ret;
utils::to_log(LOG_LEVEL_WARNING, "set_auto_flat ret: %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_WARNING, "set_auto_flat ret: %s\n", hg_scanner_err_name(ret, errbuf));
return ret;
}
int hg_scanner_300::set_updata0303(void)

View File

@ -230,6 +230,7 @@ std::string hg_scanner_302::control_fetch(int addr, int val, int size)
int l = sizeof(val),
ret = 0;
std::string data("");
char errbuf[40] = { 0 };
ret = write_register(addr, val);
if (ret == SCANNER_ERR_OK)
@ -244,12 +245,12 @@ std::string hg_scanner_302::control_fetch(int addr, int val, int size)
}
else
{
utils::to_log(LOG_LEVEL_DEBUG, "control_fetch(%d, %d) - read_bulk = %s\n", addr, val, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "control_fetch(%d, %d) - read_bulk = %s\n", addr, val, hg_scanner_err_name(ret, errbuf));
data.clear();
}
}
else
utils::to_log(LOG_LEVEL_DEBUG, "control_fetch(%d, %d) = %s\n", addr, val, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "control_fetch(%d, %d) = %s\n", addr, val, hg_scanner_err_name(ret, errbuf));
return data;
}
@ -280,7 +281,8 @@ int hg_scanner_302::clr_roller_num(void)
return val;
else
{
utils::to_log(LOG_LEVEL_DEBUG, "clr_roller_num = %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "clr_roller_num = %s\n", hg_scanner_err_name(ret, errbuf));
return -1;
}
}
@ -294,7 +296,8 @@ int hg_scanner_302::get_sleep_time(void)
return val;
else
{
utils::to_log(LOG_LEVEL_DEBUG, "get_sleep_time = %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get_sleep_time = %s\n", hg_scanner_err_name(ret, errbuf));
return -1;
}
}
@ -306,7 +309,8 @@ int hg_scanner_302::get_scan_mode(void)
if (ret)
{
utils::to_log(LOG_LEVEL_DEBUG, "get scan mode error: %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get scan mode error: %s\n", hg_scanner_err_name(ret, errbuf));
status_ = ret;
return -1;
@ -322,7 +326,8 @@ int hg_scanner_302::get_status(void)
if (ret)
{
utils::to_log(LOG_LEVEL_DEBUG, "get status error: %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get status error: %s\n", hg_scanner_err_name(ret, errbuf));
status_ = ret;
return -1;
@ -338,7 +343,8 @@ bool hg_scanner_302::is_dev_tx(void)
if (ret)
{
utils::to_log(LOG_LEVEL_DEBUG, "is_dev_tx() error: %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "is_dev_tx() error: %s\n", hg_scanner_err_name(ret, errbuf));
status_ = ret;
return false;
@ -354,7 +360,8 @@ bool hg_scanner_302::is_dev_image_process_done(void)
if (ret)
{
utils::to_log(LOG_LEVEL_DEBUG, "is_dev_image_process_done() error: %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "is_dev_image_process_done() error: %s\n", hg_scanner_err_name(ret, errbuf));
status_ = ret;
return true;
@ -371,7 +378,8 @@ bool hg_scanner_302::is_dev_image_keep_last_paper(void)
if (ret)
{
utils::to_log(LOG_LEVEL_DEBUG, "is_dev_image_keep_last_paper() error: %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "is_dev_image_keep_last_paper() error: %s\n", hg_scanner_err_name(ret, errbuf));
status_ = ret;
return true;
@ -389,7 +397,8 @@ int hg_scanner_302::get_scanned_count(void)
return val;
else
{
utils::to_log(LOG_LEVEL_DEBUG, "get_scanned_count = %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get_scanned_count = %s\n", hg_scanner_err_name(ret, errbuf));
return -1;
}
}
@ -398,8 +407,9 @@ int hg_scanner_302::get_image_count(void)
std::lock_guard<std::mutex> lock(io_lock_);
int val = 0,
ret = read_register(setting3399::SR_IM_COUNT, &val);
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get_image_count() = %d, error: %s\n", val, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "get_image_count() = %d, error: %s\n", val, hg_scanner_err_name(ret, errbuf));
if (ret == SCANNER_ERR_OK)
return val;
@ -416,7 +426,8 @@ int hg_scanner_302::get_front_data_size(void)
return val;
else
{
utils::to_log(LOG_LEVEL_DEBUG, "get_front_data_size = %s\n", hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get_front_data_size = %s\n", hg_scanner_err_name(ret, errbuf));
return -1;
}
}
@ -487,7 +498,8 @@ int hg_scanner_302::writedown_device_configuration(bool type,setting_hardware::H
ret = write_register(setting3399::SR_CONFIG_SCAN_PARAM, dev_conf->value);
}
utils::to_log(LOG_LEVEL_DEBUG, "Writedown scanner configuration(0x%x) = %s\n", dev_conf->value, hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "Writedown scanner configuration(0x%x) = %s\n", dev_conf->value, hg_scanner_err_name(ret, errbuf));
return ret;
}
int hg_scanner_302::writedown_image_configuration(void)
@ -537,8 +549,9 @@ int hg_scanner_302::pop_first_image(void)
{
std::lock_guard<std::mutex> lock(io_lock_);
int ret = write_register(setting3399::SR_IM_POP, 1);
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "popup first image = %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "popup first image = %s\n", hg_scanner_err_name(ret, errbuf));
return ret;
}
@ -549,6 +562,7 @@ int hg_scanner_302::read_one_image_from_usb(SANE_Image_Statu statu)
off = 0,
ret = SCANNER_ERR_OK;
bool popimg = false;
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_ALL, "New image size: %u\n", total);
if (!waiting_for_memory_enough(total))
@ -595,7 +609,7 @@ int hg_scanner_302::read_one_image_from_usb(SANE_Image_Statu statu)
buff = buf->data(off, (unsigned int*)&r);
}
}
utils::to_log(LOG_LEVEL_DEBUG, "Read image from USB = %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "Read image from USB = %s\n", hg_scanner_err_name(ret, errbuf));
if (ret == SCANNER_ERR_OK)
{
//{
@ -610,17 +624,17 @@ int hg_scanner_302::read_one_image_from_usb(SANE_Image_Statu statu)
}
else
{
utils::to_log(LOG_LEVEL_FATAL, "save usb data failed: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_FATAL, "save usb data failed: %s\n", hg_scanner_err_name(ret, errbuf));
}
}
else
{
utils::to_log(LOG_LEVEL_DEBUG, "Read image data from USB err: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "Read image data from USB err: %s\n", hg_scanner_err_name(ret, errbuf));
}
}
else
{
utils::to_log(LOG_LEVEL_FATAL, "write command SR_IM_TX failed: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_FATAL, "write command SR_IM_TX failed: %s\n", hg_scanner_err_name(ret, errbuf));
}
}
if(popimg)
@ -914,7 +928,8 @@ void hg_scanner_302::thread_handle_usb_read(void)
to_cnt = 0,
count = 0;
bool go = true;
char errbuf[40] = { 0 };
while (run_ && go)
{
size = sizeof(buf);
@ -926,7 +941,7 @@ void hg_scanner_302::thread_handle_usb_read(void)
}
if (ret != SCANNER_ERR_OK && ret != SCANNER_ERR_TIMEOUT)
{
utils::to_log(LOG_LEVEL_DEBUG, "read-INT = %s: From(%d), Code(%d), Index(%d), size = %d\n", hg_scanner_err_name(ret),
utils::to_log(LOG_LEVEL_DEBUG, "read-INT = %s: From(%d), Code(%d), Index(%d), size = %d\n", hg_scanner_err_name(ret, errbuf),
info->From, info->Code, info->Img_Index, size);
}
@ -955,7 +970,7 @@ void hg_scanner_302::thread_handle_usb_read(void)
if (size == sizeof(buf))
{
ret = settings302::device_status_to_hg_err(info);
utils::to_log(LOG_LEVEL_DEBUG, "status from interrupt point is '%s'\n", hg_scanner_err_name(status_));
utils::to_log(LOG_LEVEL_DEBUG, "status from interrupt point is '%s'\n", hg_scanner_err_name(status_, errbuf));
if (ret != SCANNER_ERR_OK && ret != SCANNER_ERR_TIMEOUT && ret != SCANNER_ERR_DEVICE_STOPPED)
{
@ -1035,7 +1050,7 @@ void hg_scanner_302::thread_handle_usb_read(void)
this_thread::sleep_for(chrono::milliseconds(10));
}
utils::to_log(LOG_LEVEL_DEBUG, "USB thread exit with code: %s, status = %s\n", hg_scanner_err_name(ret), hg_scanner_err_name(status_));
utils::to_log(LOG_LEVEL_DEBUG, "USB thread exit with code: %s, status = %s\n", hg_scanner_err_name(ret, errbuf), hg_scanner_err_name(status_, errbuf));
}
int hg_scanner_302::do_start(void)
{
@ -1043,6 +1058,8 @@ int hg_scanner_302::do_start(void)
bool handled = false;
int ret = try_third_app_handle_start(handled),
val = 0;
char errbuf[40] = { 0 };
// for third-sane-app invoking, added on 2022-05-19
if (handled)
return ret;
@ -1081,11 +1098,11 @@ int hg_scanner_302::do_start(void)
else
{
ret = status_ = SCANNER_ERR_DEVICE_UNKNOWN_STATUS;
utils::to_log(LOG_LEVEL_WARNING, "The device is abnormal(%d) and can not be scanned : %s\n", val, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "The device is abnormal(%d) and can not be scanned : %s\n", val, hg_scanner_err_name(ret, errbuf));
//break;
}
utils::to_log(LOG_LEVEL_WARNING, "failed on SR_GET_ANDROID_STATE(%d) result: %s\n", val, hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "failed on SR_GET_ANDROID_STATE(%d) result: %s\n", val, hg_scanner_err_name(ret, errbuf));
return ret;
}
@ -1098,7 +1115,7 @@ int hg_scanner_302::do_start(void)
write_register(0x1000, count);
ret = write_command(setting3399::SC_START);
}
utils::to_log(LOG_LEVEL_WARNING, "start result: %s\n", hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "start result: %s\n", hg_scanner_err_name(ret, errbuf));
if (ret == SCANNER_ERR_OK)
{
@ -1109,7 +1126,7 @@ int hg_scanner_302::do_start(void)
else
{
status_ = ret;
utils::to_log(LOG_LEVEL_WARNING, "(Thread 0x%x)Send start command = %s\n", GetCurrentThreadId(), hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_WARNING, "(Thread 0x%x)Send start command = %s\n", GetCurrentThreadId(), hg_scanner_err_name(ret, errbuf));
}
return ret;
@ -1227,7 +1244,8 @@ int hg_scanner_302::get_sleep_time(int& data)
data = val;
}
utils::to_log(LOG_LEVEL_DEBUG, "get_sleep_time = %d with %s\n", data, hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "get_sleep_time = %d with %s\n", data, hg_scanner_err_name(ret, errbuf));
return ret;
}
int hg_scanner_302::set_sleep_time(int setsleepime)
@ -1235,7 +1253,8 @@ int hg_scanner_302::set_sleep_time(int setsleepime)
std::lock_guard<std::mutex> lock(io_lock_);
int ret = write_register(setting3399::SR_SET_SLEEPTIME, setsleepime);
utils::to_log(LOG_LEVEL_DEBUG, "set sleep time to %d = %s\n", setsleepime, hg_scanner_err_name(ret));
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "set sleep time to %d = %s\n", setsleepime, hg_scanner_err_name(ret, errbuf));
return ret;
}
@ -1268,13 +1287,14 @@ int hg_scanner_302::get_device_log(string &log)
{
std::lock_guard<std::mutex> lock(io_lock_);
int ret = SCANNER_ERR_OK;
char errbuf[40] = { 0 };
int len = log.size();
ret = write_register(setting3399::SR_SET_JSON_PATH, len);
if (ret == SCANNER_ERR_OK)
ret = io_->write_bulk(&log[0],&len);
utils::to_log(LOG_LEVEL_DEBUG, "log path:%s ret:%s\n", log.c_str(),hg_scanner_err_name(ret));
utils::to_log(LOG_LEVEL_DEBUG, "log path:%s ret:%s\n", log.c_str(),hg_scanner_err_name(ret, errbuf));
return ret;
}
int hg_scanner_302::set_devreboot(int data)

View File

@ -334,7 +334,7 @@ namespace hg_imgproc
if (!Dynamicopen_HGBase_pHandle_ || !Dynamicopen_HGImageprc_pHandle_)
{
utils::to_log(LOG_LEVEL_DEBUG, "auto txt open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY));
utils::to_log(LOG_LEVEL_DEBUG, "auto txt open dll is error: %s\n", "SCANNER_ERR_INSUFFICIENT_MEMORY");
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
@ -372,7 +372,7 @@ namespace hg_imgproc
if (!Dynamicopen_HGBase_pHandle_ || !Dynamicopen_HGImageprc_pHandle_)
{
utils::to_log(LOG_LEVEL_DEBUG, "auto txt open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY));
utils::to_log(LOG_LEVEL_DEBUG, "auto txt open dll is error: %s\n", "SCANNER_ERR_INSUFFICIENT_MEMORY");
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
ocrinit_ = (SDKHGImgProc_InitOCR_)GetProcAddress(Dynamicopen_HGImageprc_pHandle_, "HGImgProc_CreateOCRMgr");

View File

@ -0,0 +1,44 @@
#include "img_processor.h"
#include <json/gb_json.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// image_processor
image_processor::image_processor(const char* alg_name) : enabled_(true), ver_(0), pos_(0)
{
set_where(alg_name);
}
image_processor::~image_processor()
{}
bool image_processor::set_opt_json_text(char* txt)
{
gb_json* jsn = new gb_json();
bool ret = jsn->attach_text(txt);
if (ret)
{
gb_json* first = jsn->first_child();
if (first)
{
first->get_value("ver", ver_);
first->get_value("position", pos_);
if (!first->get_value("enabled", enabled_))
enabled_ = true;
first->release();
}
}
jsn->release();
if (ret)
sane_opt_provider::set_opt_json_text(txt);
return ret;
}

View File

@ -0,0 +1,29 @@
#pragma once
// image processor
//
// created on 2023-11-07
//
// ver: 1.0
//
// NOTE: the interface is for all algorithms are in ONE module
#include <imgprc/img_processor.h>
class decoder : public image_processor
{
public:
decoder();
protected:
virtual ~decoder();
bool set_opt_json_text(char* txt);
public:
virtual int set_value(const char* name, void* val) override;
virtual void enable(const char* name, bool able) override;
virtual int process(const std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out) override;
};

View File

@ -0,0 +1,102 @@
#include "fill_hole.h"
#include <json/gb_json.h>
#include <huagao/hgscanner_error.h>
#include <ImageApplyOutHole.h>
static std::string device_opt_json[] = {
"{\"is-rid-hole-l\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\"\\u7a7f\\u5b54\\u79fb\\u9664\\u2014\\u5de6\\u4fa7\",\"desc\":\"\\u7a7f\\u5b54\\u5728\\u7eb8\\u5f20\\u4e0a\\u7684\\u5de6\\u4fa7\",\"type\":\"bool\",\"pos\":10,\"fix-id\":34879,\"size\":4,\"cur\":false,\"default\":false},\"search-hole-range-l\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\" \\u5de6\\u4fa7\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"desc\":\"\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"type\":\"float\",\"pos\":10,\"fix-id\":34880,\"size\":8,\"cur\":0.000000,\"default\":0.000000,\"range\":{\"min\":0.000000,\"max\":0.500000,\"step\":0.050000},\"depend\":\"is-rid-hole-l==true\"},\"is-rid-hole-r\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\"\\u7a7f\\u5b54\\u79fb\\u9664\\u2014\\u53f3\\u4fa7\",\"desc\":\"\\u7a7f\\u5b54\\u5728\\u7eb8\\u5f20\\u4e0a\\u7684\\u53f3\\u4fa7\",\"type\":\"bool\",\"pos\":10,\"fix-id\":34881,\"size\":4,\"cur\":false,\"default\":false},\"search-hole-range-r\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\" \\u53f3\\u4fa7\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"desc\":\"\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"type\":\"float\",\"pos\":10,\"fix-id\":34882,\"size\":8,\"cur\":0.000000,\"default\":0.000000,\"range\":{\"min\":0.000000,\"max\":0.500000,\"step\":0.050000},\"depend\":\"is-rid-hole-r==true\"},\"is-rid-hole-t\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\"\\u7a7f\\u5b54\\u79fb\\u9664\\u2014\\u4e0a\\u4fa7\",\"desc\":\"\\u7a7f\\u5b54\\u5728\\u7eb8\\u5f20\\u7684\\u4e0a\\u90e8\",\"type\":\"bool\",\"pos\":10,\"fix-id\":34883,\"size\":4,\"cur\":false,\"default\":false},\"search-hole-range-t\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\" \\u4e0a\\u4fa7\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"desc\":\"\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"type\":\"float\",\"pos\":10,\"fix-id\":34884,\"size\":8,\"cur\":0.000000,\"default\":0.000000,\"range\":{\"min\":0.000000,\"max\":0.500000,\"step\":0.050000},\"depend\":\"is-rid-hole-t==true\"},\"is-rid-hole-b\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\"\\u7a7f\\u5b54\\u79fb\\u9664\\u2014\\u4e0b\\u4fa7\",\"desc\":\"\\u7a7f\\u5b54\\u5728\\u7eb8\\u5f20\\u7684\\u4e0b\\u90e8\",\"type\":\"bool\",\"pos\":10,\"fix-id\":34885,\"size\":4,\"cur\":false,\"default\":false},\"search-hole-range-b\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\" \\u4e0b\\u4fa7\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"desc\":\"\\u7a7f\\u5b54\\u641c\\u7d22\\u8303\\u56f4\\u5360\\u5e45\\u9762\\u6bd4\\u4f8b\",\"type\":\"float\",\"pos\":10,\"fix-id\":34886,\"size\":8,\"cur\":0.000000,\"default\":0.000000,\"range\":{\"min\":0.000000,\"max\":0.500000,\"step\":0.050000},\"depend\":\"is-rid-hole-b==true\"},\"hole-threshold\":{\"cat\":\"base\",\"group\":\"imgp\",\"title\":\"\\u5b54\\u6d1e\\u9608\\u503c\",\"desc\":\"\\u5b54\\u6d1e\\u50cf\\u7d20\\u5927\\u5c0f\\u9608\\u503c\\uff08\\u5c0f\\u4e8e\\u9608\\u503c\\u4e0d\\u5f53\\u4f5c\\u5b54\\u6d1e\\uff09\",\"type\":\"int\",\"unit\":\"pixel\",\"size\":4,\"cur\":50,\"default\":50,\"range\":{\"min\":5,\"max\":100,\"step\":1},\"depend\":\"is-rid-hole-l==true || is-rid-hole-r==true || is-rid-hole-t==true || is-rid-hole-b==true\"},\"resolution\":{\"cat\":\"base\",\"group\":\"base\",\"title\":\"\\u5206\\u8fa8\\u7387\",\"desc\":\"\\u8bbe\\u7f6e\\u626b\\u63cf\\u56fe\\u50cf\\u7684\\u5206\\u8fa8\\u7387\",\"type\":\"int\",\"pos\":10,\"fix-id\":34840,\"size\":4,\"cur\":200,\"default\":200,\"range\":{\"min\":100,\"max\":{\"default\":600,\"paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8\\u81ea\\u52a8\\u88c1\\u5207 || paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8 || paper==\\u4e09\\u8054\\u8bd5\\u5377\":500},\"step\":1}}}"
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// image_processor
hole_filler::hole_filler() : image_processor("hole_filler")
{
std::string json("");
for (auto& v : device_opt_json)
json += v;
set_opt_json_text(&json[0]);
}
hole_filler::~hole_filler()
{}
int hole_filler::set_value(const char* name, void* val)
{
int ret = SCANNER_ERR_OK; // SCANNER_ERR_DEVICE_NOT_SUPPORT;
if (strcmp(name, SANE_STD_OPT_NAME_RID_HOLE_T) == 0)
top_ = *(bool*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T) == 0)
top_ratio_ = *(double*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_RID_HOLE_B) == 0)
bottom_ = *(bool*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B) == 0)
bottom_ratio_ = *(double*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_RID_HOLE_L) == 0)
left_ = *(bool*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L) == 0)
left_ratio_ = *(double*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_RID_HOLE_R) == 0)
right_ = *(bool*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R) == 0)
right_ratio_ = *(double*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_RESOLUTION) == 0)
dpi_ = *(int*)val;
else if (strcmp(name, SANE_STD_OPT_NAME_HOLE_THRESHOLD) == 0)
threshold_ = *(int*)val;
else
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
return ret;
}
void hole_filler::enable(const char* name, bool able)
{
enabled_ = able;
}
int hole_filler::process(const std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out)
{
int ret = SCANNER_ERR_OK;
if (!enabled_ ||
(IS_DOUBLE_EQUAL(left_ratio_, .0f) && IS_DOUBLE_EQUAL(right_ratio_, .0f) &&
IS_DOUBLE_EQUAL(top_ratio_, .0f) && IS_DOUBLE_EQUAL(bottom_ratio_, .0f))
)
out = in;
else
{
cv::Vec4f ratio;
ratio[0] = top_ ? top_ratio_ : .0f;
ratio[1] = bottom_ ? bottom_ratio_ : .0f;
ratio[2] = left_ ? left_ratio_ : .0f;
ratio[3] = right_ ? right_ratio_ : .0f;
CImageApplyOutHole worker(dpi_ * 1.0f / 10, ratio, threshold_);
for (auto& v : in)
{
std::vector<cv::Mat> src;
PROCIMGINFO result;
src.push_back(v.img);
result.info = v.info;
worker.apply(src, result.info.paper_side != PAPER_SIDE_FRONT && result.info.paper_side != PAPER_SIDE_BACK);
if (src.size())
{
result.img = src[0];
out.push_back(result);
}
}
}
return ret;
}

View File

@ -0,0 +1,197 @@
#pragma once
// image processor
//
// created on 2023-11-07
//
// ver: 1.0
//
// NOTE: the interface is for all algorithms are in ONE module
#include <imgprc/img_processor.h>
class hole_filler : public image_processor
{
bool left_ = false;
double left_ratio_ = .0f;
bool right_ = false;
double right_ratio_ = .0f;
bool top_ = false;
double top_ratio_ = .0f;
bool bottom_ = false;
double bottom_ratio_ = .0f;
int dpi_ = 200;
int threshold_ = 50;
public:
hole_filler();
protected:
virtual ~hole_filler();
public:
virtual int set_value(const char* name, void* val) override;
virtual void enable(const char* name, bool able) override;
virtual int process(const std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out) override;
};
//{
// "is-rid-hole-l": {
// "cat": "base",
// "group": "imgp",
// "title": "穿孔移除—左侧",
// "desc": "穿孔在纸张上的左侧",
// "type": "bool",
// "pos": 10,
// "fix-id": 34879,
// "size": 4,
// "cur": false,
// "default": false
// },
// "search-hole-range-l": {
// "cat": "base",
// "group": "imgp",
// "title": " 左侧穿孔搜索范围占幅面比例",
// "desc": "穿孔搜索范围占幅面比例",
// "type": "float",
// "pos": 10,
// "fix-id": 34880,
// "size": 8,
// "cur": 0.000000,
// "default": 0.000000,
// "range": {
// "min": 0.000000,
// "max": 0.500000,
// "step": 0.050000
// },
// "depend": "is-rid-hole-l==true"
// },
// "is-rid-hole-r": {
// "cat": "base",
// "group": "imgp",
// "title": "穿孔移除—右侧",
// "desc": "穿孔在纸张上的右侧",
// "type": "bool",
// "pos": 10,
// "fix-id": 34881,
// "size": 4,
// "cur": false,
// "default": false
// },
// "search-hole-range-r": {
// "cat": "base",
// "group": "imgp",
// "title": " 右侧穿孔搜索范围占幅面比例",
// "desc": "穿孔搜索范围占幅面比例",
// "type": "float",
// "pos": 10,
// "fix-id": 34882,
// "size": 8,
// "cur": 0.000000,
// "default": 0.000000,
// "range": {
// "min": 0.000000,
// "max": 0.500000,
// "step": 0.050000
// },
// "depend": "is-rid-hole-r==true"
// },
// "is-rid-hole-t": {
// "cat": "base",
// "group": "imgp",
// "title": "穿孔移除—上侧",
// "desc": "穿孔在纸张的上部",
// "type": "bool",
// "pos": 10,
// "fix-id": 34883,
// "size": 4,
// "cur": false,
// "default": false
// },
// "search-hole-range-t": {
// "cat": "base",
// "group": "imgp",
// "title": " 上侧穿孔搜索范围占幅面比例",
// "desc": "穿孔搜索范围占幅面比例",
// "type": "float",
// "pos": 10,
// "fix-id": 34884,
// "size": 8,
// "cur": 0.000000,
// "default": 0.000000,
// "range": {
// "min": 0.000000,
// "max": 0.500000,
// "step": 0.050000
// },
// "depend": "is-rid-hole-t==true"
// },
// "is-rid-hole-b": {
// "cat": "base",
// "group": "imgp",
// "title": "穿孔移除—下侧",
// "desc": "穿孔在纸张的下部",
// "type": "bool",
// "pos": 10,
// "fix-id": 34885,
// "size": 4,
// "cur": false,
// "default": false
// },
// "search-hole-range-b": {
// "cat": "base",
// "group": "imgp",
// "title": " 下侧穿孔搜索范围占幅面比例",
// "desc": "穿孔搜索范围占幅面比例",
// "type": "float",
// "pos": 10,
// "fix-id": 34886,
// "size": 8,
// "cur": 0.000000,
// "default": 0.000000,
// "range": {
// "min": 0.000000,
// "max": 0.500000,
// "step": 0.050000
// },
// "depend": "is-rid-hole-b==true"
// },
// "hole-threshold": {
// "cat": "base",
// "group": "imgp",
// "title": "孔洞阈值",
// "desc": "孔洞像素大小阈值(小于阈值不当作孔洞)",
// "type": "int",
// "unit": "pixel",
// "size": 4,
// "cur": 50,
// "default": 50,
// "range": {
// "min": 5,
// "max": 100,
// "step": 1
// },
// "depend": "is-rid-hole-l==true || is-rid-hole-r==true || is-rid-hole-t==true || is-rid-hole-b==true"
// },
// "resolution": {
// "cat": "base",
// "group": "base",
// "title": "分辨率",
// "desc": "设置扫描图像的分辨率",
// "type": "int",
// "pos": 10,
// "fix-id": 34840,
// "size": 4,
// "cur": 200,
// "default": 200,
// "range": {
// "min": 100,
// "max": {
// "default": 600,
// "paper==最大扫描尺寸自动裁切 || paper==最大扫描尺寸 || paper==三联试卷": 500
// },
// "step": 1
// }
// }
//}

View File

@ -9,7 +9,8 @@
#include "user-opt/user.h"
#include "user-opt/offline_opt.h"
#include "user-opt/device_opt.h"
#include <sane_opt_json/device_opt.h>
#include <imgprc/imgprc_mgr.h>
#if !defined(WIN32) && !defined(_WIN64)
@ -218,12 +219,14 @@ bool hg_scanner_mgr::read_over_with_eof_ = true;
uint32_t hg_scanner_mgr::unique_img_id_ = 0;;
std::mutex hg_scanner_mgr::mutex_img_id;
hg_scanner_mgr::hg_scanner_mgr() : same_ind_(1), cf_name(""), dev_opts_(new device_option())
hg_scanner_mgr::hg_scanner_mgr() : same_ind_(1), cf_name("")
{
std::string cfgf(utils::get_local_data_path() + PATH_SEPARATOR + "config" + PATH_SEPARATOR + "debug.cfg");
char buf[260] = {0};
int l = GetPrivateProfileStringA("devs_name", "name", "", buf, _countof(buf) - 1, cfgf.c_str());
init_debug_config(cfgf.c_str());
buf[l] = 0;
cf_name = buf;
usb_manager::instance()->register_hotplug(&hg_scanner_mgr::usb_event_handle, this);
@ -239,8 +242,6 @@ hg_scanner_mgr::hg_scanner_mgr() : same_ind_(1), cf_name(""), dev_opts_(new devi
user_ = new hguser();
offline_ = new offline_opts(user_);
g_language = new lang_opt();
reset_device_opts();
}
hg_scanner_mgr::~hg_scanner_mgr()
{
@ -248,11 +249,13 @@ hg_scanner_mgr::~hg_scanner_mgr()
{
std::lock_guard<std::mutex> lock(mutex_dev_);
for (auto& v : online_devices_)
{
libusb_unref_device(v.dev);
if (v.dev_opts)
v.dev_opts->release();
}
online_devices_.clear();
}
dev_opts_->clear();
delete dev_opts_;
usb_manager::clear();
offline_->release();
@ -536,6 +539,8 @@ void hg_scanner_mgr::on_hgscanner_pnp(usb_event ev, libusb_device* device, int v
ols.dev = device;
ols.ind = index;
ols.scanner = NULL;
ols.dev_opts = nullptr;
ols.imgproc = nullptr;
ols.display_name = g_supporting_devices[ols.ind].name;
if (std::find(online_devices_.begin(), online_devices_.end(), ols.ind) != online_devices_.end())
{
@ -609,21 +614,23 @@ void hg_scanner_mgr::get_online_devices(std::vector<OLSCANNER>& devs)
devs = online_devices_;
}
void hg_scanner_mgr::reset_device_opts(sane_opt_provider* scanner)
void hg_scanner_mgr::init_debug_config(const char* cfg_file)
{
dev_opts_->clear();
// Four sources: offline, language, algorithm, scanner
dev_opts_->add(dynamic_cast<sane_opt_provider*>(offline_));
dev_opts_->add(dynamic_cast<sane_opt_provider*>(g_language));
if (scanner)
// dumping images ...
dump_img_path_ = utils::get_local_data_path() + PATH_SEPARATOR + "imgs";
if (GetPrivateProfileIntA("dump", "dumpusb", 0, cfg_file) == 1)
{
dev_opts_->add(scanner);
dev_opts_->restore(scanner);
}
}
char strbuf[260] = { 0 };
int getl = 0;
dump_img_ = true;
getl = GetPrivateProfileStringA("dump", "usb_path", "", strbuf, _countof(strbuf) - 1, cfg_file);
if (getl)
dump_img_path_ = strbuf;
}
}
void hg_scanner_mgr::set_appendix_info_for_about(SANE_About* about, char*& ptr, int& count, const char* key, const char* info, const char* url)
{
#ifdef BRAND_DISPLAY_ALL_EXPAND
@ -799,6 +806,22 @@ scanner_err hg_scanner_mgr::get_about_info(scanner_handle h, void* data, unsigne
return SCANNER_ERR_OK;
}
imgproc_mgr* hg_scanner_mgr::create_image_processor(device_option* devopts)
{
imgproc_mgr* proc = new imgproc_mgr(devopts, dump_img_, dump_img_path_.c_str());
std::string path(utils::get_module_full_path(MODULE_NAME_SCANNER));
size_t pos = path.rfind(PATH_SEPARATOR[0]);
if (pos++ == std::string::npos)
pos = 0;
path.erase(pos);
path += std::string("imgproc") + PATH_SEPARATOR;
// load image-processors ...
proc->load_processor(path.c_str());
return proc;
}
scanner_err hg_scanner_mgr::hg_scanner_enum(ScannerInfo* scanner_list, long* count, bool local_only)
{
@ -852,14 +875,39 @@ scanner_err hg_scanner_mgr::hg_scanner_open(scanner_handle* h, const char* name,
scanner->set_ui_callback(&hg_scanner_mgr::ui_default_callback, hg_scanner_mgr::async_io_enabled_);
scanner->set_dev_family(g_supporting_devices[it->ind].family.c_str());
scanner->set_read_over_with_no_data(hg_scanner_mgr::read_over_with_eof_);
reset_device_opts(dynamic_cast<sane_opt_provider*>(scanner));
}
{
std::lock_guard<std::mutex> lock(mutex_dev_);
std::vector<OLSCANNER>::iterator ptr = std::find(online_devices_.begin(), online_devices_.end(), name);
if (ptr != online_devices_.end())
{
if (ptr->scanner)
ptr->scanner->release();
ptr->scanner = (hg_scanner*)*h;
std::lock_guard<std::mutex> lock(mutex_dev_);
std::vector<OLSCANNER>::iterator ptr = std::find(online_devices_.begin(), online_devices_.end(), name);
if (ptr != online_devices_.end())
ptr->scanner = (hg_scanner*)*h;
auto userpriv = [this](int priv) -> bool
{
return user_->has_privilege(priv);
};
auto logger = [this](const char* msg) -> void
{
utils::to_log(LOG_LEVEL_DEBUG, "%s", msg);
};
if (ptr->dev_opts)
ptr->dev_opts->clear();
else
ptr->dev_opts = new device_option(userpriv, logger);
ptr->dev_opts->add(dynamic_cast<sane_opt_provider*>(offline_));
ptr->dev_opts->add(dynamic_cast<sane_opt_provider*>(g_language));
ptr->dev_opts->add(ptr->scanner);
ptr->dev_opts->restore(ptr->scanner);
ptr->imgproc = create_image_processor(ptr->dev_opts);
ptr->scanner->set_image_processor(ptr->imgproc);
ptr->dev_opts->add(ptr->imgproc);
}
}
}
else if(hg_scanner_mgr::last_open_msg_.length())
hg_scanner_mgr::ui_default_callback(nullptr, SANE_EVENT_ERROR, (void*)hg_scanner_mgr::last_open_msg_.c_str(), (unsigned int*)&ret, nullptr);
@ -874,17 +922,26 @@ scanner_err hg_scanner_mgr::hg_scanner_close(scanner_handle h, bool force)
{
{
std::lock_guard<std::mutex> lock(mutex_dev_);
for (size_t i = 0; i < online_devices_.size(); ++i)
for (auto& v : online_devices_)
{
if (online_devices_[i].scanner == h)
if (v.scanner == h)
{
online_devices_[i].scanner = NULL;
v.scanner = nullptr;
if (v.dev_opts)
{
v.dev_opts->clear();
v.dev_opts->release();
v.dev_opts = nullptr;
}
if (v.imgproc)
v.imgproc->release();
v.imgproc = nullptr;
break;
}
}
}
reset_device_opts();
SCAN_PTR(h)->close(force);
SCAN_PTR(h)->release();
//delete SCAN_PTR(h);
@ -897,33 +954,62 @@ scanner_err hg_scanner_mgr::hg_scanner_get_parameter(scanner_handle h, const cha
if (len)
{
std::string raw(dev_opts_->get_option_value(name == PARAM_ALL ? nullptr : name, type, nullptr, data));
if (*len < raw.length())
device_option* tmp = nullptr;
if (!h)
{
*len = raw.length();
device_option* tmp = new device_option();
err = SCANNER_ERR_INSUFFICIENT_MEMORY;
tmp->add(offline_);
tmp->add(g_language);
}
else
{
memcpy(data, raw.c_str(), raw.length());
if (*len > raw.length())
data[raw.length()] = 0;
*len = raw.length();
err = SCANNER_ERR_OK;
#if defined(_WIN32) && defined(_DEBUG)
if (name == PARAM_ALL)
{
err = SCANNER_ERR_DEVICE_NOT_FOUND;
std::lock_guard<std::mutex> lock(mutex_dev_);
for (auto& v : online_devices_)
{
std::string file(utils::get_local_data_path() + PATH_SEPARATOR + "Log" + PATH_SEPARATOR + "allopt.txt");
FILE* dst = fopen(file.c_str(), "wb");
if (dst)
if (v.scanner == h)
{
fwrite(raw.c_str(), 1, raw.length(), dst);
fclose(dst);
tmp = v.dev_opts;
if (tmp)
tmp->add_ref();
break;
}
}
}
if (tmp)
{
std::string raw(tmp->get_option_value(name == PARAM_ALL ? nullptr : name, type, nullptr, data));
if (*len < raw.length())
{
*len = raw.length();
err = SCANNER_ERR_INSUFFICIENT_MEMORY;
}
else
{
memcpy(data, raw.c_str(), raw.length());
if (*len > raw.length())
data[raw.length()] = 0;
*len = raw.length();
err = SCANNER_ERR_OK;
#if defined(_WIN32) && defined(_DEBUG)
if (name == PARAM_ALL)
{
std::string file(utils::get_local_data_path() + PATH_SEPARATOR + "Log" + PATH_SEPARATOR + "allopt.txt");
FILE* dst = fopen(file.c_str(), "wb");
if (dst)
{
fwrite(raw.c_str(), 1, raw.length(), dst);
fclose(dst);
}
}
#endif
}
tmp->release();
}
}
@ -933,79 +1019,104 @@ scanner_err hg_scanner_mgr::hg_scanner_set_parameter(scanner_handle h, const cha
{
scanner_err err = SCANNER_ERR_OK, se = SCANNER_ERR_OK;
std::string init("");
device_option* tmp = nullptr;
// do restore here ?
if (name && strcmp(name, SANE_STD_OPT_NAME_RESTORE) == 0)
if (!h)
{
sane_opt_provider* sop = dynamic_cast<sane_opt_provider*>(SCAN_PTR(h));
err = (scanner_err)dev_opts_->restore(sop);
utils::to_log(LOG_LEVEL_DEBUG, "Restore all options ...\n");
tmp = new device_option();
tmp->add(offline_);
tmp->add(g_language);
}
else
{
// 1 - paper option removes 'lateral' choices and add new option with name 'lateral'
// 2 - page option replaces 'single side' with 'front side' and 'back side'
//
// here to transfer them ...
std::string prev("");
bool lateral = false, restore_data = false;
if (to_default)
for (auto& v : online_devices_)
{
int size = 0;
init = dev_opts_->get_option_value(name, SANE_ACTION_GET_DEFAULT_VALUE, &size);
if (size > init.length())
if (v.scanner == h)
{
std::string t(std::move(init));
init.reserve(size);
memset(&init[0], 0, size);
memcpy(&init[0], &t[0], t.length());
tmp = v.dev_opts;
if (tmp)
tmp->add_ref();
break;
}
data = &init[0];
}
}
if (tmp)
{
// do restore here ?
if (name && strcmp(name, SANE_STD_OPT_NAME_RESTORE) == 0)
{
sane_opt_provider* sop = dynamic_cast<sane_opt_provider*>(SCAN_PTR(h));
err = (scanner_err)tmp->restore(sop);
utils::to_log(LOG_LEVEL_DEBUG, "Restore all options ...\n");
}
else
{
if (strcmp(name, SANE_STD_OPT_NAME_PAPER) == 0)
// 1 - paper option removes 'lateral' choices and add new option with name 'lateral'
// 2 - page option replaces 'single side' with 'front side' and 'back side'
//
// here to transfer them ...
std::string prev("");
bool lateral = false, restore_data = false;
if (to_default)
{
std::string hx(from_default_language("\346\250\252\345\220\221"));
char *lat = strstr((char*)data, hx.c_str()) ;
if (lat)
int size = 0;
init = tmp->get_option_value(name, SANE_ACTION_GET_DEFAULT_VALUE, &size);
if (size > init.length())
{
prev = (char*)data;
lateral = true;
restore_data = true;
*lat = 0;
std::string t(std::move(init));
init.reserve(size);
memset(&init[0], 0, size);
memcpy(&init[0], &t[0], t.length());
}
data = &init[0];
}
else
{
if (strcmp(name, SANE_STD_OPT_NAME_PAPER) == 0)
{
std::string hx(from_default_language("\346\250\252\345\220\221"));
char* lat = strstr((char*)data, hx.c_str());
if (lat)
{
prev = (char*)data;
lateral = true;
restore_data = true;
*lat = 0;
}
}
else if (strcmp(name, SANE_STD_OPT_NAME_PAGE) == 0)
{
if (strcmp((char*)data, from_default_language("\345\215\225\351\235\242")) == 0) // single side
{
prev = (char*)data;
restore_data = true;
strcpy((char*)data, from_default_language("\346\255\243\351\235\242")); // front side
utils::to_log(LOG_LEVEL_DEBUG, "compatible for old page option '%s' to '%s'.\n", prev.c_str(), (char*)data);
}
}
err = tmp->refine_data(name, data) ? SCANNER_ERR_NOT_EXACT : SCANNER_ERR_OK;
}
se = (scanner_err)tmp->update_data(name, data);
if (se != SCANNER_ERR_OK)
err = se;
else if (restore_data)
{
// here handle options paper and page are both string ...
strcpy((char*)data, prev.c_str());
if (lateral)
{
utils::to_log(LOG_LEVEL_DEBUG, "compatible for old paper option '%s', set lateral to '%s' additional.\n", prev.c_str(), lateral ? "true" : "false");
tmp->refine_data(SANE_STD_OPT_NAME_LATERAL, &lateral);
tmp->update_data(SANE_STD_OPT_NAME_LATERAL, &lateral);
}
}
else if (strcmp(name, SANE_STD_OPT_NAME_PAGE) == 0)
{
if (strcmp((char*)data, from_default_language("\345\215\225\351\235\242")) == 0) // single side
{
prev = (char*)data;
restore_data = true;
strcpy((char*)data, from_default_language("\346\255\243\351\235\242")); // front side
utils::to_log(LOG_LEVEL_DEBUG, "compatible for old page option '%s' to '%s'.\n", prev.c_str(), (char*)data);
}
}
err = dev_opts_->refine_data(name, data) ? SCANNER_ERR_NOT_EXACT : SCANNER_ERR_OK;
}
se = (scanner_err)dev_opts_->update_data(name, data);
if (se != SCANNER_ERR_OK)
err = se;
else if (restore_data)
{
// here handle options paper and page are both string ...
strcpy((char*)data, prev.c_str());
if (lateral)
{
utils::to_log(LOG_LEVEL_DEBUG, "compatible for old paper option '%s', set lateral to '%s' additional.\n", prev.c_str(), lateral ? "true" : "false");
dev_opts_->refine_data(SANE_STD_OPT_NAME_LATERAL, &lateral);
dev_opts_->update_data(SANE_STD_OPT_NAME_LATERAL, &lateral);
}
}
tmp->release();
}
return err;

View File

@ -41,14 +41,17 @@ class hguser;
class offline_opts;
class device_option;
class sane_opt_provider;
class imgproc_mgr;
class hg_scanner_mgr
{
typedef struct _online_scanner
{
libusb_device* dev; // the unique usb device
libusb_device* dev; // the unique usb device
int ind; // index in supporting scanners queue
hg_scanner* scanner;
device_option* dev_opts;
imgproc_mgr* imgproc;
std::string display_name;
bool operator==(const libusb_device* d)
@ -70,10 +73,13 @@ class hg_scanner_mgr
hguser* user_;
offline_opts* offline_;
device_option* dev_opts_;
static sane_callback event_callback_;
static bool async_io_enabled_;
// debug configuration
bool dump_img_ = false;
std::string dump_img_path_ = "";
static sane_callback event_callback_;
static bool async_io_enabled_;
static std::string last_open_msg_;
static std::string pe_path_;
@ -93,10 +99,11 @@ class hg_scanner_mgr
void on_hgscanner_pnp(usb_event ev, libusb_device* device, int vid, int pid, int usb_ver_h, int usb_ver_l, bool* retry); // usb_ver_h.usb_ver_l
void get_online_devices(std::vector<OLSCANNER>& devs);
void reset_device_opts(sane_opt_provider* scanner = nullptr);
void init_debug_config(const char* cfg_file);
void set_appendix_info_for_about(SANE_About* about, char*& ptr, int& count, const char* key, const char* info, const char* url);
scanner_err get_about_info(scanner_handle h, void* data, unsigned* len);
imgproc_mgr* create_image_processor(device_option* devopts);
string cf_name;
string url_en;

View File

@ -572,11 +572,12 @@ int usb_manager::open(libusb_device* device, usb_io** usbio, std::string* msg)
if (!usb->is_ready())
{
int err = usb->last_error();
char errbuf[40] = { 0 };
if (msg)
*msg = usb->init_error_msg();
usb->release();
utils::to_log(LOG_LEVEL_DEBUG, "Open %04x:%04x failed: %s\n", dev.vid, dev.pid, hg_scanner_err_name(err));
utils::to_log(LOG_LEVEL_DEBUG, "Open %04x:%04x failed: %s\n", dev.vid, dev.pid, hg_scanner_err_name(err, errbuf));
return err;
}
@ -952,8 +953,6 @@ int usb_io::write_bulk(void* buf, int* len)
err = usb_manager::usb_error_2_hg_err(libusb_bulk_transfer(handle_, endpoints_.bulk.out.port, data, *len, &t, to_));
//VLOG_MINI_6(LOG_LEVEL_DEBUG, "First write port %x bulk %d/%d = %s(timeout = %d, packet size = %x)\n", endpoints_.bulk.out.port, t, *len, hg_scanner_err_name((scanner_err)err).c_str(), to_, endpoints_.bulk.out.max_packet);
// printf("First write port %x bulk %d/%d = %s(timeout = %d, packet size = %x)\n", endpoints_.bulk.out.port, t, *len, hg_scanner_err_name((scanner_err)err).c_str(), to_, endpoints_.bulk.out.max_packet);
if (!on_io_error((scanner_err)err, &endpoints_.bulk.out))
{
*len = t;
@ -971,7 +970,6 @@ int usb_io::write_bulk(void* buf, int* len)
err = usb_manager::usb_error_2_hg_err(libusb_bulk_transfer(handle_, endpoints_.bulk.out.port, data, *len - total, &t, to_));
total += t;
}
//utils::to_log(LOG_LEVEL_DEBUG, "Last write bulk %d/%d = %s\n", total, *len, hg_scanner_err_name((scanner_err)err).c_str());
*len = total;
last_err_ = err;

View File

@ -5,7 +5,7 @@
// created on 2022-09-22
//
#include "base_opt.h"
#include <sane_opt_json/base_opt.h>
class hguser;
class offline_opts : public sane_opt_provider

View File

@ -16,6 +16,7 @@ aux_source_directory(${PROJECT_SOURCE_DIR} DIR_SRCS)
file(GLOB DIR_HEADS "${PROJECT_SOURCE_DIR}/*.h" "${PROJECT_SOURCE_DIR}/*.hpp"
"${PROJECT_SOURCE_DIR}/../../sdk/hginclude/*.h" "${PROJECT_SOURCE_DIR}/../../sdk/hginclude/*.cpp"
"${PROJECT_SOURCE_DIR}/../../sdk/json/*.h" "${PROJECT_SOURCE_DIR}/../../sdk/json/*.c*"
"${PROJECT_SOURCE_DIR}/../../sdk/sane_opt_json/*.h" "${PROJECT_SOURCE_DIR}/../../sdk/sane_opt_json/*.c*"
)
set(DIR_SRCS ${DIR_SRCS} ${DIR_HEADS})
if(COMMAND cmake_policy)

View File

@ -222,7 +222,7 @@ extern "C"
g_sane_name = name;
g_sane_ver = ver;
}
const char* hg_scanner_err_name(int err)
const char* hg_scanner_err_name(int err, char* buf)
{
RETURN_IF(err, SANE_STATUS_GOOD);
RETURN_IF(err, SANE_STATUS_UNSUPPORTED);
@ -283,15 +283,12 @@ extern "C"
RETURN_IF(err, SCANNER_ERR_DEVICE_MAYBE_IS_HOLE);
RETURN_IF(err, SCANNER_ERR_DEVICE_DEVS_BOOTING);
RETURN_IF(err, SCANNER_ERR_DEVICE_UNKNOWN_STATUS);
RETURN_IF(err, SCANNER_ERR_LANG_PAK_LOST);
RETURN_IF(err, SCANNER_ERR_THROW_EXCEPTION);
if (err == SCANNER_ERR_LANG_PAK_LOST)
return "SCANNER_ERR_LANG_PAK_LOST";
sprintf(buf, "Unknown error: 0x%X", err);
// NOTE: multi-thread unsafe here
static char g_unk_err[80] = { 0 };
sprintf(g_unk_err, "Unknown error: 0x%X", err);
return g_unk_err;
return buf;
}
const char* hg_scanner_err_description(int err)
{
@ -363,7 +360,7 @@ extern "C"
return "SCANNER_ERR_LANG_PAK_LOST";
// NOTE: multi-thread unsafe here
static char g_unk_err[80] = { 0 };
static char g_unk_err[128] = { 0 };
strcpy(g_unk_err, from_default_language(STATU_DESC_SCANNER_ERR_DEVICE_UNKNOWN_ERROR));
sprintf(g_unk_err + strlen(g_unk_err), ":0x%x", err);

View File

@ -24,7 +24,7 @@
#include <lang/app_language.h>
#include "../sdk/hginclude/utils.h"
#include <huagao/brand.h>
#include "../hgdriver/hgdev/user-opt/device_opt.h" // for readable_text(SANE_Value_Type type, void* value)
#include "../sdk/sane_opt_json/device_opt.h" // for readable_text(SANE_Value_Type type, void* value)
#ifndef SIGUSR1
#define SIGUSR1 10

View File

@ -428,7 +428,7 @@ extern "C"{
// Return: none
void hg_scanner_set_sane_info(const char* name, const char* ver);
const char* hg_scanner_err_name(int err);
const char* hg_scanner_err_name(int err, char* buf); // ensure the buf is at least 40 bytes length
const char* hg_scanner_err_description(int err);
bool hg_scanner_log_is_enable(int level);

View File

@ -0,0 +1,44 @@
#include "img_processor.h"
#include <json/gb_json.h>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// image_processor
image_processor::image_processor(const char* alg_name) : enabled_(true), ver_(0), pos_(0)
{
set_where(alg_name);
}
image_processor::~image_processor()
{}
bool image_processor::set_opt_json_text(char* txt)
{
gb_json* jsn = new gb_json();
bool ret = jsn->attach_text(txt);
if (ret)
{
gb_json* first = jsn->first_child();
if (first)
{
first->get_value("ver", ver_);
first->get_value("position", pos_);
if (!first->get_value("enabled", enabled_))
enabled_ = true;
first->release();
}
}
jsn->release();
if (ret)
sane_opt_provider::set_opt_json_text(txt);
return ret;
}

View File

@ -0,0 +1,84 @@
#pragma once
// image processor
//
// created on 2023-11-07
//
// ver: 1.0
//
// NOTE: the interface is for all algorithms are in ONE module
#include <sane_opt_json/base_opt.h>
#include "../../hgdriver/3rdparty/opencv/include/opencv2/opencv.hpp"
enum paper_side
{
PAPER_SIDE_UNKNOWN = 0,
PAPER_SIDE_FRONT, // single side, this is front
PAPER_SIDE_BACK, // single side, this is back
PAPER_SIDE_TOP, // VERT-compound sides, and front side is at top
PAPER_SIDE_BOTTOM, // VERT-compound sides, and front side is at bottom
PAPER_SIDE_LEFT, // HORZ-compound sides, and front side is at left
PAPER_SIDE_RIGHT, // HORZ-compound sides, and front side is at right
PAPER_SIDE_DSP, // G100/200 DSP data
};
/*
enum img_status
{
IMG_STATUS_OK = 0, // normal
IMG_STATUS_DOUBLE = 1 << 0, // double-feeded paper
IMG_STATUS_JAM = 1 << 1, // jammed paper
IMG_STATUS_STAPLE = 1 << 2, // staples on the paper
IMG_STATUS_SIZE_ERR = 1 << 3, // size check failed
IMG_STATUS_DOGEAR = 1 << 4, // paper has dogear - common
IMG_STATUS_DOGEAR_PARTIAL = 1 << 5, // dogear - scanned partial
IMG_STATUS_BLANK = 1 << 6, // blank image
};
*/
#pragma pack(push)
#pragma pack(1)
typedef struct _hg_img_info
{
uint32_t paper_ind : 16; // paper index in this turn/start, based ZERO. (image-collector set)
uint32_t new_img : 1; // 0 - partial data; 1 - new image data. (image-collector set)
uint32_t img_over : 1; // 0 - has data yet; 1 - END for the image. (image-collector set)
uint32_t paper_side : 4; // paper_side
uint32_t status : 10; // img_status
uint32_t split_ind : 4; // splitting order, from left to right and then top to bottom, based ZERO
uint32_t compress : 6; // compression type
uint32_t channels : 3;
uint32_t bits : 6;
uint32_t reserved : 13;
}HGIMGINFO;
typedef struct _proc_img_info_
{
HGIMGINFO info;
cv::Mat img;
}PROCIMGINFO, *LPPROCIMGINFO;
#pragma pack(pop)
class image_processor : public sane_opt_provider
{
protected:
bool enabled_;
int ver_;
int pos_;
public:
image_processor(const char* alg_name);
protected:
virtual ~image_processor();
bool set_opt_json_text(char* txt);
public:
bool is_enable(void) { return enabled_; }
int get_version(void) { return ver_; }
int get_position(void) { return pos_; }
virtual int process(const std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out) = 0;
};

373
sdk/imgprc/imgprc_mgr.cpp Normal file
View File

@ -0,0 +1,373 @@
#include "imgprc_mgr.h"
#include <json/gb_json.h>
#include <sane_opt_json/device_opt.h>
#include "../../../sdk/include/huagao/hgscanner_error.h"
#include <ImageMatQueue.h>
#include <huagaoxxx_warraper_ex.h>
#include <imgproc-pak/fill_hole.h>
static std::string device_opt_json[] = {
"{\"dumpimg\":{\"cat\":\"base\",\"group\":\"debug\",\"title\":\"\\u8f93\\u51fa\\u7b97\\u6cd5\\u4e2d\\u95f4\\u56fe\\u50cf\",\"desc\":\"\\u6bcf\\u4e2a\\u7b97\\u6cd5\\u6267\\u884c\\u540e\\uff0c\\u8f93\\u51fa\\u4e2d\\u95f4\\u7684\\u4e34\\u65f6\\u56fe\\u50cf\",\"type\":\"bool\",\"pos\":10,\"size\":4,\"cur\":false,\"default\":false},\"dump-path\":{\"cat\":\"base\",\"group\":\"debug\",\"title\":\"\\u4e2d\\u95f4\\u56fe\\u50cf\\u8f93\\u51fa\\u8def\\u5f84\",\"desc\":\"\\u6bcf\\u4e2a\\u7b97\\u6cd5\\u6267\\u884c\\u540e\\uff0c\\u8f93\\u51fa\\u4e2d\\u95f4\\u4e34\\u65f6\\u56fe\\u50cf\\u7684\\u5b58\\u653e\\u8def\\u5f84\",\"type\":\"string\",\"pos\":10,\"size\":260,\"cur\":\"\",\"default\":\"\",\"depend\":\"dumpimg==true\"}}"
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// imgproc_mgr
imgproc_mgr::imgproc_mgr(device_option* devopts
, bool dumpimg
, const char* dumpath)
: opts_(devopts), dump_path_(dumpath ? dumpath : "")
, dumpf_(dumpimg ? &imgproc_mgr::dump_real : &imgproc_mgr::dump_empty)
, dumpusbf_(dumpimg ? &imgproc_mgr::dump_usb_img_real : &imgproc_mgr::dump_usb_img_empty)
{
std::string text("");
gb_json *jsn = new gb_json();
for (auto& v : device_opt_json)
text += v;
if (jsn->attach_text(&text[0]))
{
gb_json* child = nullptr;
jsn->get_value(SANE_STD_OPT_NAME_DUMP_IMG, child);
if (child)
{
child->set_value("cur", dumpimg);
child->set_value("default", dumpimg);
child->release();
}
jsn->get_value(SANE_STD_OPT_NAME_DUMP_IMG_PATH, child);
if (child)
{
child->set_value("cur", dump_path_.c_str());
child->set_value("default", dump_path_.c_str());
child->release();
}
text = jsn->to_string();
}
jsn->release();
set_opt_json_text(&text[0]);
if (opts_)
opts_->add_ref();
else
opts_ = new device_option();
}
imgproc_mgr::~imgproc_mgr()
{
clear();
opts_->release();
}
std::vector<imgproc_mgr::DECDAT> imgproc_mgr::decode_before_simple(uint8_t* data, size_t bytes, HGIMGINFO* info)
{
std::vector<DECDAT> simple;
DECDAT in;
in.info = *info;
in.img.reset(new std::vector<char>(bytes));
memcpy(in.img->data(), data, bytes);
simple.push_back(in);
return std::move(simple);
}
std::vector<imgproc_mgr::DECDAT> imgproc_mgr::decode_before_g200dsp(uint8_t* data, size_t bytes, HGIMGINFO* info)
{
// pid == 0x100 || pid == 0x200
std::vector<DECDAT> g200dsp;
DECDAT f, b;
int line = 1024, off_f = 0, off_b = 0;
f.info = *info;
f.info.paper_side = PAPER_SIDE_FRONT;
f.img.reset(new std::vector<char>(bytes));
b.info = *info;
b.info.paper_side = PAPER_SIDE_BACK;
b.img.reset(new std::vector<char>(bytes));
for (int i = 0; i < bytes / line; ++i)
{
if (data[line - 1] == 0)
{
// this is back
memcpy(b.img->data() + off_b, data, line - 1);
off_b += line - 1;
}
else if (data[line - 1] == 0x0ff)
{
// this is front
memcpy(f.img->data() + off_f, data, line - 1);
off_f += line - 1;
}
data += line;
}
f.img->resize(off_f);
b.img->resize(off_b);
g200dsp.push_back(b);
g200dsp.push_back(f);
return std::move(g200dsp);
}
void imgproc_mgr::dump_real(const std::vector<PROCIMGINFO>& img, const char* after, int pos)
{
std::string root(dump_path_ + PATH_SEPARATOR);
std::vector<std::string> existing;
for (auto& v : img)
{
char name[128] = { 0 };
int ind = 0;
sprintf(name, "%04x-%d-%d-%04x-%s", v.info.paper_ind, v.info.paper_side, v.info.split_ind, pos, after);
while(std::find(existing.begin(), existing.end(), name) != existing.end())
sprintf(name, "%04x-%d-%d-%04x-%s(%d)", v.info.paper_ind, v.info.paper_side, v.info.split_ind, pos, after, ++ind);
existing.push_back(name);
cv::imwrite((root + name + ".jpg").c_str(), v.img);
}
}
void imgproc_mgr::dump_empty(const std::vector<PROCIMGINFO>& img, const char* after, int pos)
{}
std::string imgproc_mgr::dump_usb_img_real(uint8_t* data, size_t bytes, HGIMGINFO* info, const char* tail)
{
std::string root(dump_path_ + PATH_SEPARATOR);
char name[128] = { 0 };
const char *tail_leader = "";
FILE *dst = nullptr;
int ind = 0;
if (tail && *tail)
tail_leader = "-";
else
tail = "";
sprintf(name, "%04x-usb%s%s", info->paper_ind, tail_leader, tail);
{
// check repeat ...
dst = fopen((root + name + ".jpg").c_str(), "rb");
while (dst)
{
fclose(dst);
sprintf(name, "%04x-usb%s%s(%d)", info->paper_ind, tail_leader, tail, ++ind);
dst = fopen((root + name + ".jpg").c_str(), "rb");
}
}
dst = fopen((root + name + ".jpg").c_str(), "wb");
if (dst)
{
fwrite(data, 1, bytes, dst);
fclose(dst);
utils::to_log(LOG_LEVEL_DEBUG, "Temporary file '%s' OK.\n", (root + name + ".jpg").c_str());
}
else
{
utils::to_log(LOG_LEVEL_DEBUG, "Temporary file '%s' failed with err: %d\n", (root + name + ".jpg").c_str(), errno);
}
return std::move(root + name + ".jpg");
}
std::string imgproc_mgr::dump_usb_img_empty(uint8_t* data, size_t bytes, HGIMGINFO* info, const char* tail)
{
return "";
}
int imgproc_mgr::decode(HGIMGINFO* info, uint8_t* data, size_t bytes, std::vector<PROCIMGINFO>& result)
{
std::vector<DECDAT> tmp(info->paper_side == PAPER_SIDE_DSP ? imgproc_mgr::decode_before_g200dsp(data, bytes, info) : imgproc_mgr::decode_before_simple(data, bytes, info));
int ret = SCANNER_ERR_OK;
(this->*dumpusbf_)(data, bytes, info, nullptr);
for (auto& v : tmp)
{
PROCIMGINFO pii;
try
{
cv::ImreadModes rmc = info->channels > 1 ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE;
if (v.img->at(0) == 0x89 && v.img->at(1) == 'P' && v.img->at(2) == 'N' && v.img->at(2) == 'G')
rmc = cv::IMREAD_GRAYSCALE;
memset(&pii.info, 0, sizeof(pii.info));
pii.info = v.info;
pii.img = cv::imdecode(*v.img, rmc);
if (pii.img.empty())
{
std::string f(dump_usb_img_real((uint8_t*)&(*v.img)[0], v.img->size(), info, "error"));
utils::to_log(LOG_LEVEL_WARNING, "Warning: decode failure, source content save to file '%s'\n", f.c_str());
}
else
{
if (info->paper_side == PAPER_SIDE_LEFT || info->paper_side == PAPER_SIDE_RIGHT)
{
PROCIMGINFO front(pii);
front.info.paper_side = PAPER_SIDE_FRONT;
if (info->paper_side == PAPER_SIDE_LEFT)
{
front.img = pii.img(cv::Rect(0, 0, pii.img.cols / 2, pii.img.rows));
pii.img = pii.img(cv::Rect(pii.img.cols / 2, 0, pii.img.cols / 2, pii.img.rows));
}
else
{
front.img = pii.img(cv::Rect(pii.img.cols / 2, 0, pii.img.cols / 2, pii.img.rows));
pii.img = pii.img(cv::Rect(0, 0, pii.img.cols / 2, pii.img.rows));
}
result.push_back(front);
pii.info.paper_side = PAPER_SIDE_BACK;
}
else if (info->paper_side == PAPER_SIDE_TOP || info->paper_side == PAPER_SIDE_BOTTOM)
{
PROCIMGINFO front(pii);
front.info.paper_side = PAPER_SIDE_FRONT;
if (info->paper_side == PAPER_SIDE_TOP)
{
front.img = pii.img(cv::Rect(0, 0, pii.img.cols, pii.img.rows / 2));
pii.img = pii.img(cv::Rect(0, pii.img.rows / 2, pii.img.cols, pii.img.rows / 2));
}
else
{
front.img = pii.img(cv::Rect(0, pii.img.rows / 2, pii.img.cols, pii.img.rows / 2));
pii.img = pii.img(cv::Rect(0, 0, pii.img.cols, pii.img.rows / 2));
}
result.push_back(front);
pii.info.paper_side = PAPER_SIDE_BACK;
}
result.push_back(pii);
}
}
catch (const std::exception& e)
{
utils::to_log(LOG_LEVEL_FATAL, "FATAL: exception occurs when decode image %d-%d failed with reason '%s'!\n", info->paper_ind, pii.info.paper_side, e.what());
std::string f(dump_usb_img_real((uint8_t*)&(*v.img)[0], v.img->size(), info, "decode"));
utils::to_log(LOG_LEVEL_WARNING, "FATAL: decode image %d-%d failed, source content save to file '%s'\n", info->paper_ind, pii.info.paper_side, f.c_str());
//throw(e); // continue the error handling
ret = SCANNER_ERR_THROW_EXCEPTION;
break; // fatal occurs, stop
}
catch (...)
{
utils::to_log(LOG_LEVEL_FATAL, "FATAL: exception occurs when decode image %d-%d failed\n", info->paper_ind, pii.info.paper_side);
std::string f(dump_usb_img_real((uint8_t*)&(*v.img)[0], v.img->size(), info, "decode"));
utils::to_log(LOG_LEVEL_WARNING, "FATAL: decode image %d-%d failed, source content save to file '%s'\n", info->paper_ind, pii.info.paper_side, f.c_str());
ret = SCANNER_ERR_THROW_EXCEPTION;
break; // fatal occurs, stop
}
}
tmp.clear();
char errbuf[40] = { 0 };
utils::to_log(LOG_LEVEL_DEBUG, "Decode %u bytes to %u picture(s) = %s\n", bytes, result.size(), hg_scanner_err_name(ret, errbuf));
(this->*dumpf_)(result, "decode", 10);
return ret;
}
bool imgproc_mgr::sort_processor_by_pos(image_processor* l, image_processor* r)
{
return l->get_position() < r->get_position();
}
int imgproc_mgr::set_value(const char* name, void* val)
{
int ret = SCANNER_ERR_OK;
if (strcmp(name, SANE_STD_OPT_NAME_DUMP_IMG) == 0)
{
if (*(bool*)val)
{
dumpf_ = &imgproc_mgr::dump_real;
dumpusbf_ = &imgproc_mgr::dump_usb_img_real;
}
else
{
dumpf_ = &imgproc_mgr::dump_empty;
dumpusbf_ = &imgproc_mgr::dump_usb_img_empty;
}
}
else if (strcmp(name, SANE_STD_OPT_NAME_DUMP_IMG_PATH) == 0)
dump_path_ = (char*)val;
else
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
return ret;
}
int imgproc_mgr::load_processor(const char* path)
{
int ret = SCANNER_ERR_OK;
hole_filler* holer = new hole_filler();
opts_->add(holer);
holer->release();
std::sort(processors_.begin(), processors_.end(), &imgproc_mgr::sort_processor_by_pos);
return ret;
}
int imgproc_mgr::clear(void)
{
for (auto& v : processors_)
v->release();
processors_.clear();
return 0;
}
int imgproc_mgr::process(HGIMGINFO* info, uint8_t* data, size_t bytes, std::vector<PROCIMGINFO>& out)
{
std::vector<PROCIMGINFO> mid[2], in, *src = &in, * dst = &mid[0];
int ret = decode(info, data, bytes, in), sn = 0;
if (ret == SCANNER_ERR_OK)
{
for (auto& v : processors_)
{
if (v->is_enable())
{
try
{
ret = v->process(*src, *dst);
(this->*dumpf_)(*dst, v->from().c_str(), v->get_position());
if (ret)
break;
src = dst;
sn ^= 1;
dst = &mid[sn];
}
catch (const std::exception& e)
{
ret = SCANNER_ERR_THROW_EXCEPTION;
utils::to_log(LOG_LEVEL_DEBUG, "FATAL: image %d process '%s' throws exception: %s!\n", info->paper_ind, v->from().c_str(), e.what());
std::string f(dump_usb_img_real(data, bytes, info, v->from().c_str()));
utils::to_log(LOG_LEVEL_WARNING, "FATAL: process image %d failed on '%s', source content save to file '%s'\n", info->paper_ind, v->from().c_str(), f.c_str());
break;
}
catch (...)
{
ret = SCANNER_ERR_THROW_EXCEPTION;
utils::to_log(LOG_LEVEL_DEBUG, "FATAL: image process '%s' throws unknown exception!\n", v->from().c_str());
std::string f(dump_usb_img_real(data, bytes, info, v->from().c_str()));
utils::to_log(LOG_LEVEL_WARNING, "FATAL: process image %d failed on '%s', source content save to file '%s'\n", info->paper_ind, v->from().c_str(), f.c_str());
break;
}
}
}
}
out = *src;
return ret;
}

86
sdk/imgprc/imgprc_mgr.h Normal file
View File

@ -0,0 +1,86 @@
#pragma once
// image processor
//
// created on 2023-11-07
//
// ver: 1.0
//
// NOTE: the interface is for all algorithms are in ONE module
#include "img_processor.h"
#include <hginclude/utils.h> // for refer
#include <vector>
typedef std::shared_ptr<std::vector<char>> dcptr;
class device_option;
class imgproc_mgr : public sane_opt_provider
{
typedef struct _decode_data
{
HGIMGINFO info;
dcptr img;
}DECDAT;
std::string dump_path_ = "";
bool duplex_ = true;
bool xchg_fb_ = false;
std::vector<image_processor*> processors_;
device_option* opts_;
void(imgproc_mgr::* dumpf_)(const std::vector<PROCIMGINFO>& img, const char* after, int pos) = nullptr;
std::string(imgproc_mgr::* dumpusbf_)(uint8_t* data, size_t bytes, HGIMGINFO* info, const char* tail) = nullptr;
static bool sort_processor_by_pos(image_processor* l, image_processor* r);
void dump_real(const std::vector<PROCIMGINFO>& img, const char* after, int pos);
void dump_empty(const std::vector<PROCIMGINFO>& img, const char* after, int pos);
std::string dump_usb_img_real(uint8_t* data, size_t bytes, HGIMGINFO* info, const char* tail);
std::string dump_usb_img_empty(uint8_t* data, size_t bytes, HGIMGINFO* info, const char* tail);
int decode(HGIMGINFO* info, uint8_t* data, size_t bytes, std::vector<PROCIMGINFO>& result);
public:
imgproc_mgr(device_option* devopts, bool dumpimg, const char* dumpath);
static std::vector<DECDAT> decode_before_simple(uint8_t* data, size_t bytes, HGIMGINFO* info);
static std::vector<DECDAT> decode_before_g200dsp(uint8_t* data, size_t bytes, HGIMGINFO* info);
protected:
virtual ~imgproc_mgr();
public:
virtual int set_value(const char* name, void* val) override;
public:
int load_processor(const char* path); // outer-modules path
int clear(void);
int process(HGIMGINFO* info, uint8_t* data, size_t bytes, std::vector<PROCIMGINFO>& out);
};
//{
// "dumpimg": {
// "cat": "base",
// "group": "debug",
// "title": "输出算法中间图像",
// "desc": "每个算法执行后,输出中间的临时图像",
// "type": "bool",
// "pos": 10,
// "size": 4,
// "cur": false,
// "default": false
// },
// "dump-path": {
// "cat": "base",
// "group": "debug",
// "title": "中间图像输出路径",
// "desc": "每个算法执行后,输出中间临时图像的存放路径",
// "type": "string",
// "pos": 10,
// "size": 260,
// "cur": "",
// "default": "",
// "depend": "dumpimg==true"
// }
//}

View File

@ -1,6 +1,6 @@
#include "base_opt.h"
#include "../json/gb_json.h"
#include <json/gb_json.h>
#include "../../../sdk/include/huagao/hgscanner_error.h"

View File

@ -2,7 +2,7 @@
#include <huagao/hgscanner_error.h>
#include "../../../sdk/hginclude/huagaoxxx_warraper_ex.h"
#include "../../../sdk/hginclude/base_opt.h"
#include "base_opt.h"
#include <lang/app_language.h>
#include <string.h>
#include <algorithm>
@ -1007,6 +1007,18 @@ void device_option::insert_option(gb_json* opt, sane_opt_provider* from, const c
origin_->remove(vo);
if (src_.count(existing->key()))
{
// disable discarded options ...
sane_opt_provider* next = src_[existing->key()]->get_following(existing->key().c_str());
src_[existing->key()]->enable(existing->key().c_str(), false);
while (next)
{
next->enable(existing->key().c_str(), false);
sane_opt_provider* n = next->get_following(existing->key().c_str());
next->release();
next = n;
}
src_[existing->key()]->release();
src_.erase(existing->key());
}
@ -1109,18 +1121,19 @@ void device_option::insert_option(gb_json* opt, sane_opt_provider* from, const c
}
{
write_log("SANE-OPT: option '%s' queue: %s", opt->key().c_str(), src_[opt->key().c_str()]->from().c_str());
std::string logi("SANE-OPT: option '");
logi += opt->key() + "' queue: " + src_[opt->key().c_str()]->from();
sane_opt_provider* next = src_[opt->key().c_str()]->get_following(opt->key().c_str());
while (next)
{
write_log(" -> %s", next->from().c_str());
logi += " -> " + next->from();
sane_opt_provider* next1 = next;
next = next->get_following(opt->key().c_str());
next1->release();
}
write_log("\n");
write_log("%s\n", logi.c_str());
}
}
else
@ -1128,6 +1141,9 @@ void device_option::insert_option(gb_json* opt, sane_opt_provider* from, const c
// discard new option ...
write_log("SANE-OPT: discard %s::%s(ver: %d) for %s::%s(ver: %d) existed!\n", from->from().c_str(), opt->key().c_str(), vn
, src_[existing->key()]->from().c_str(), existing->key().c_str(), vo);
// disable discarded option
from->enable(existing->key().c_str(), false);
}
existing->release();
@ -1221,6 +1237,20 @@ void device_option::init_depends(gb_json* opt)
range->release();
}
else if (opt->get_value("default", dpnd))
{
if (dpnd.find("=") == 0)
{
// consitant with another option ...
dpnd.erase(0, 1);
condition_value* rv = new condition_value();
rv->set_value(nullptr, dpnd.c_str(), this);
init_value_[opt->key()] = rv;
if (std::find(master_opts_.begin(), master_opts_.end(), dpnd)
== master_opts_.end())
master_opts_.push_back(dpnd);
}
}
// visible
range = nullptr;
@ -1671,7 +1701,19 @@ int device_option::update_data(const char* name, void* value, bool reorder_if_ne
err = SCANNER_ERR_OK;
if (src_.count(name))
{
err = src_[name]->set_value(name, value);
sane_opt_provider* opt = src_[name];
opt->add_ref();
while (opt)
{
int r = opt->set_value(name, value);
if (r)
err = r;
sane_opt_provider* next = opt->get_following(name);
opt->release();
opt = next;
}
}
if (err == SCANNER_ERR_OK || err == SCANNER_ERR_NOT_EXACT

View File

@ -16,10 +16,11 @@
#include "simple_logic.h"
#include <json/gb_json.h>
#include <hginclude/utils.h>
class sane_opt_provider;
class device_option
class device_option : public refer
{
gb_json* origin_;
gb_json* now_;

View File

@ -17,6 +17,7 @@
#define START_SCAN_IN_THREAD
#pragma comment(lib, "user32.lib")
#if !defined(WIN32) && !defined(_WIN64)
@ -786,13 +787,15 @@ int scanner::thread_start(void)
dpi_ = dpi;
utils::to_log(LOG_LEVEL_DEBUG, "start scanning with DPI %d\r\n", dpi_);
scan_working_ = false;
ret = sane_helper_->invoke_sane_start(handle_);
// the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ...
if (ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
ret = sane_helper_->invoke_sane_start(handle_);
// wait until at least ONE picture returned, so we need not this - 2023-11-07
//if (ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
// ret = sane_helper_->invoke_sane_start(handle_);
if (ret == SANE_STATUS_GOOD)
if (ret == SANE_STATUS_GOOD || ret == SCANNER_ERR_DEVICE_DOUBLE_FEEDING)
{
/*if (indicator_.get() && !IsWindowVisible(indicator_->hwnd()))
indicator_->show(true);*/
@ -812,11 +815,21 @@ int scanner::thread_start(void)
// display error message on progress UI, may be closed immediately by APP, so we hide progress UI and call message_box ...
//
#ifdef START_SCAN_IN_THREAD
if (callback::show_progress_ui && is_bIndicator && ui_notify)
if (callback::show_progress_ui && is_bIndicator && ui_notify)
{
int ev = SANE_EVENT_WORKING;
ui_notify(SANE_EVENT_SCAN_FINISHED, (void *)sane_helper_->invoke_sane_strstatus((SANE_Status)ret), ret);
if (!scan_working_) // scan working thread would trigger the finish event, so here check this flag
{
ui_notify(SANE_EVENT_SCAN_FINISHED, (void*)sane_helper_->invoke_sane_strstatus((SANE_Status)ret), ret);
// block ?
while (!is_scanning_)
{
MSG msg = { 0 };
PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
}
}
}
else
#endif
@ -1293,7 +1306,6 @@ COM_API_IMPLEMENT(scanner, bool, ui_show_setting(HWND parent, bool with_scan, bo
COM_API_IMPLEMENT(scanner, bool, ui_show_progress(HWND parent, bool bIndicator))
{
bIndicator = false;
is_bIndicator = bIndicator;
ui_notify = std::function<void(int, void*, int)>();
auto ui_process = [this](ui_result res)
@ -1347,6 +1359,7 @@ int scanner::handle_device_event(int ev_code, void* data, unsigned int* len)
{
if (ev_code == SANE_EVENT_WORKING)
{
scan_working_ = true;
img_ind_ = 0;
if (callback::show_progress_ui && is_bIndicator)
ui_notify(ev_code, data, *len);

View File

@ -78,6 +78,7 @@ class scanner : public ISaneInvoker, virtual public refer
int thread_start(void);
std::unique_ptr<std::thread> thread_starting_;
bool scan_working_ = false;
template<class T>