#include "hg_scanner.h" #include "../wrapper/hg_log.h" #include "sane/sane_option_definitions.h" #include "scanner_setting.h" #include "scanner_manager.h" #if defined(WIN32) || defined(_WIN64) #include #endif #if defined(WIN32) || defined(_WIN64) static int load_dll(const wchar_t* path_dll, HMODULE* dll) { HMODULE h = LoadLibraryW(path_dll); int ret = GetLastError(); wchar_t info[128] = { 0 }; swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret); OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str()); if (!h && ret == ERROR_MOD_NOT_FOUND) { std::wstring dir(path_dll); size_t pos = dir.rfind(L'\\'); wchar_t path[MAX_PATH] = { 0 }; GetDllDirectoryW(_countof(path) - 1, path); if (pos != std::wstring::npos) dir.erase(pos); OutputDebugStringW((L"[TWAIN]Load: try change directory to " + dir + L"\r\n").c_str()); SetDllDirectoryW(dir.c_str()); h = LoadLibraryW(path_dll); ret = GetLastError(); swprintf_s(info, _countof(info) - 1, L" = %d\r\n", ret); OutputDebugStringW((L"[TWAIN]Load: " + std::wstring(path_dll) + info).c_str()); OutputDebugStringW((L"[TWAIN]Load: restore directory to " + std::wstring(path) + L"\r\n").c_str()); SetDllDirectoryW(path); } if (dll) *dll = h; return ret; } static int strToWchar(string str, wchar_t* s) { if (str.empty() || !s) { return -1; } size_t size = str.length(); //获取缓冲区大小,并申请空间,缓冲区大小按字符计算 int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), size, NULL, 0); wchar_t* buffer = new wchar_t[size + 1]; MultiByteToWideChar(CP_ACP, 0, str.c_str(), size, buffer, len); buffer[len] = '\0'; wcscpy(s, buffer); if (!buffer || !s) return -1; delete[]buffer; buffer = NULL; return 0; } #endif static int ui_default_callback(scanner_handle, int, void*, unsigned int*, void*) { return 0; } static std::string bmp_821(unsigned char* bits/*bits data*/, int w, int h, int* lbytes/*in/out 行字节*/, bool line_align_4/*是否行对齐4字节*/, int threashold/*黑白像素阈值*/, bool reverse/*是否反色输出*/) { static unsigned int g_bmp8_pallete[] = { 0x00000000, 0x00800000, 0x00008000, 0x00808000, 0x00000080, 0x00800080, 0x00008080, 0x00c0c0c0, 0x00c0dcc0, 0x00a6caf0, 0x00402000, 0x00602000, 0x00802000, 0x00a02000, 0x00c02000, 0x00e02000 , 0x00004000, 0x00204000, 0x00404000, 0x00604000, 0x00804000, 0x00a04000, 0x00c04000, 0x00e04000, 0x00006000, 0x00206000, 0x00406000, 0x00606000, 0x00806000, 0x00a06000, 0x00c06000, 0x00e06000 , 0x00008000, 0x00208000, 0x00408000, 0x00608000, 0x00808000, 0x00a08000, 0x00c08000, 0x00e08000, 0x0000a000, 0x0020a000, 0x0040a000, 0x0060a000, 0x0080a000, 0x00a0a000, 0x00c0a000, 0x00e0a000 , 0x0000c000, 0x0020c000, 0x0040c000, 0x0060c000, 0x0080c000, 0x00a0c000, 0x00c0c000, 0x00e0c000, 0x0000e000, 0x0020e000, 0x0040e000, 0x0060e000, 0x0080e000, 0x00a0e000, 0x00c0e000, 0x00e0e000 , 0x00000040, 0x00200040, 0x00400040, 0x00600040, 0x00800040, 0x00a00040, 0x00c00040, 0x00e00040, 0x00002040, 0x00202040, 0x00402040, 0x00602040, 0x00802040, 0x00a02040, 0x00c02040, 0x00e02040 , 0x00004040, 0x00204040, 0x00404040, 0x00604040, 0x00804040, 0x00a04040, 0x00c04040, 0x00e04040, 0x00006040, 0x00206040, 0x00406040, 0x00606040, 0x00806040, 0x00a06040, 0x00c06040, 0x00e06040 , 0x00008040, 0x00208040, 0x00408040, 0x00608040, 0x00808040, 0x00a08040, 0x00c08040, 0x00e08040, 0x0000a040, 0x0020a040, 0x0040a040, 0x0060a040, 0x0080a040, 0x00a0a040, 0x00c0a040, 0x00e0a040 , 0x0000c040, 0x0020c040, 0x0040c040, 0x0060c040, 0x0080c040, 0x00a0c040, 0x00c0c040, 0x00e0c040, 0x0000e040, 0x0020e040, 0x0040e040, 0x0060e040, 0x0080e040, 0x00a0e040, 0x00c0e040, 0x00e0e040 , 0x00000080, 0x00200080, 0x00400080, 0x00600080, 0x00800080, 0x00a00080, 0x00c00080, 0x00e00080, 0x00002080, 0x00202080, 0x00402080, 0x00602080, 0x00802080, 0x00a02080, 0x00c02080, 0x00e02080 , 0x00004080, 0x00204080, 0x00404080, 0x00604080, 0x00804080, 0x00a04080, 0x00c04080, 0x00e04080, 0x00006080, 0x00206080, 0x00406080, 0x00606080, 0x00806080, 0x00a06080, 0x00c06080, 0x00e06080 , 0x00008080, 0x00208080, 0x00408080, 0x00608080, 0x00808080, 0x00a08080, 0x00c08080, 0x00e08080, 0x0000a080, 0x0020a080, 0x0040a080, 0x0060a080, 0x0080a080, 0x00a0a080, 0x00c0a080, 0x00e0a080 , 0x0000c080, 0x0020c080, 0x0040c080, 0x0060c080, 0x0080c080, 0x00a0c080, 0x00c0c080, 0x00e0c080, 0x0000e080, 0x0020e080, 0x0040e080, 0x0060e080, 0x0080e080, 0x00a0e080, 0x00c0e080, 0x00e0e080 , 0x000000c0, 0x002000c0, 0x004000c0, 0x006000c0, 0x008000c0, 0x00a000c0, 0x00c000c0, 0x00e000c0, 0x000020c0, 0x002020c0, 0x004020c0, 0x006020c0, 0x008020c0, 0x00a020c0, 0x00c020c0, 0x00e020c0 , 0x000040c0, 0x002040c0, 0x004040c0, 0x006040c0, 0x008040c0, 0x00a040c0, 0x00c040c0, 0x00e040c0, 0x000060c0, 0x002060c0, 0x004060c0, 0x006060c0, 0x008060c0, 0x00a060c0, 0x00c060c0, 0x00e060c0 , 0x000080c0, 0x002080c0, 0x004080c0, 0x006080c0, 0x008080c0, 0x00a080c0, 0x00c080c0, 0x00e080c0, 0x0000a0c0, 0x0020a0c0, 0x0040a0c0, 0x0060a0c0, 0x0080a0c0, 0x00a0a0c0, 0x00c0a0c0, 0x00e0a0c0 , 0x0000c0c0, 0x0020c0c0, 0x0040c0c0, 0x0060c0c0, 0x0080c0c0, 0x00a0c0c0, 0x00fffbf0, 0x00a0a0a4, 0x00808080, 0x00ff0000, 0x0000ff00, 0x00ffff00, 0x000000ff, 0x00ff00ff, 0x0000ffff, 0x00ffffff }; int l = (w + 31) / 32 * 4, size = l * h, line_bytes = (w + 3) / 4 * 4; std::string f(""); unsigned char* data = nullptr, mask = reverse ? -1 : 0; unsigned int* pallete = g_bmp8_pallete; if (!line_align_4) { l = (w + 7) / 8; size = l * h; } if (lbytes && *lbytes) line_bytes = *lbytes; f.resize(size); data = (unsigned char*)&f[0]; for (int i = 0; i < h; ++i) { unsigned char v = 0, *dst = data; for (int j = 0; j < w; ++j) { v <<= 1; unsigned char pixel = ((pallete[bits[j]] & 0x0ff) + ((pallete[bits[j]] >> 8) & 0x0ff) + ((pallete[bits[j]] >> 16) & 0x0ff)) / 3; if (pixel >= threashold) v |= 1; if ((j + 1) % 8 == 0) { *dst++ = v ^ mask; v = 0; } } if (w % 8) { v ^= mask; v <<= 8 - (w % 8); *dst++ = v; } data += l; bits += line_bytes; } if (lbytes) *lbytes = l; return f; } static bool is_firstopen_ = true; //第二次打开设备就不在去获取和设置设备锁定状态 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // hg_scanner hg_scanner::hg_scanner(ScannerSerial serial, const char* dev_name, usb_io* io,int pid) : name_(dev_name ? dev_name : ""), io_(io), status_(SCANNER_ERR_NOT_START), serial_(serial) , scan_count_(-1), run_(true), paper_size_(TwSS::A4), erase_bkg_range_(10), read_over_with_no_data_(false) , noise_range_(30), omit_empty_level_(50), resolution_(200), rid_hole_range_(10.0f) , 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) , img_type_(""), online_(false),is_quality_(-1),is_color_fill(false),is_multiout(false),save_multiout(hg_log::lang_load(ID_OPTION_VALUE_DLSCLX_CS_HD_HB)) , final_img_index_(0), custom_area_(false),save_sizecheck(false), bw_threshold_(128), custom_gamma_(false) , double_paper_handle_(0), keep_watermark_(false), save_feedmode_type_(false), feedmode_(1), sleeptime_(-1),split3399_(0) , async_io_(false), is_white_0_(true), isremove_left_hole(false), isremove_right_hole(false), isremove_top_hole(false), isremove_low_hole(false) , isremove_left_hole_threshold(0), isremove_right_hole_threshold(0), isremove_top_hole_threshold(0), isremove_low_hole_threshold(0) , dump_usb_path_(""),is_kernelsnap_211209_(false),dump_img_(&hg_scanner::dump_image_empty), is_kernelsnap_220830_(false),is_kernelsnap3288_221106_(false) , is_kernelsnap_221027_(false), memory_size_(2000/*USB+JPEG压缩及图像处理图队列,总共1GB*/), isx86_Advan_(true), stop_fatal_(SCANNER_ERR_OK), is_auto_paper_scan(false) , size_check(false), save_sleeptime_type_(false), is_kernelsnap_devsislock(false), is_checksum_strat_scan(false), is_cis_image(false) , is_dpi_color_check(false),save_dpi_color_check_val(0.0f), is_auto_falt(false),HGVersion_mgr_(NULL), HGVersion_Init_(NULL) , HGVersion_Islock_(NULL), HGVersion_Postlog_(NULL), HGVersion_Free_(NULL), Dynamicopen_HGVersion_pHandle_(NULL),pid_(pid), fetching_id_(-1) , is_kernelsnap3288_230210_(false) { #if !defined(_WIN32) && !defined(_WIN64) &&defined(x86_64) isx86_Advan_ = false; #endif init_setting_func_map(); final_path_ = hg_log::ini_get("path", "final_img"); if(final_path_.empty()) final_path_ = hg_log::local_data_path() + PATH_SEPARATOR + "imgs"; if (hg_log::ini_get("dump", "dumpusb") == "1") { dump_usb_path_ = hg_log::ini_get("dump", "usb_path"); if (dump_usb_path_.empty()) dump_usb_path_ = final_path_; if (!dump_usb_path_.empty()) dump_img_ = &hg_scanner::dump_image_real; } std::string mem = hg_log::ini_get("mem", "max_img"); if (!mem.empty()) { memory_size_ = std::stoi(mem); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Get the config file --->memory_size_ set is :%lld", memory_size_); } std::string adv = hg_log::ini_get("cpu", "advanced"); if (!adv.empty()) { isx86_Advan_ = adv == "0" ? false : true; VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Get the config file --->isx86_Advan_ set is :%d", isx86_Advan_); } if (hg_log::create_folder(final_path_.c_str())) { VLOG_MINI_1(LOG_LEVEL_WARNING, "temporary image folder: %s\n", final_path_.c_str()); final_path_ += PATH_SEPARATOR; } else { VLOG_MINI_1(LOG_LEVEL_WARNING, "create temporary image folder failed: %s\n", final_path_.c_str()); final_path_ = ""; } custom_gamma_val_ = new SANE_Gamma; memset(custom_gamma_val_, 0, sizeof(SANE_Gamma)); 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; VLOG_MINI_2(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_ == SCANNER_ERR_OK; } wait_usb_.set_debug_info("USB"); wait_img_.set_debug_info("Image"); wait_usb_result_.set_debug_info("start"); wait_usb_.set_debug_info("Devsislock"); 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)); #ifdef OEM_HUAGAO thread_devslock_handle_.reset(new std::thread(&hg_scanner::thread_devslock_handle, this)); #endif ImagePrc_pHandle_ = hg_imgproc::init(pid_, isx86_Advan_);; } hg_scanner::~hg_scanner() { close(true); hg_version_free_handle(); 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(); #ifdef OEM_HUAGAO if (thread_devslock_handle_.get() && thread_devslock_handle_->joinable()) thread_devslock_handle_->join(); #endif delete custom_gamma_val_; hg_imgproc::release(ImagePrc_pHandle_); name_.insert(0, hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_DEVS)); name_ += hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_IS_CLOSE); notify_ui_working_status(name_.c_str(), SANE_EVENT_SCANNER_CLOSED); VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "%s(%s) destroyed.\n", name_.c_str(), hg_log::format_ptr(this).c_str()); } 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*)""; #if defined(WIN32) || defined(_WIN64) 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> data, std::string* path_file, unsigned int index) { char head[40] = { 0 }; std::string file(""); FILE* dst = nullptr; int ret = SCANNER_ERR_OK; sprintf(head, "usb_%05u", index); if(!path_file || path_file->empty()) file = hg_scanner::temporary_file((char*)".jpg", (char*)head); dst = fopen(file.c_str(), "wb"); if (dst) { size_t wrote = fwrite(data->data(), 1, data->size(), dst); if (wrote == data->size()) { if (path_file) *path_file = file; VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "--->Wrote %u bytes to file '%s'\n", wrote, file.c_str()); } else { ret = SCANNER_ERR_WRITE_FILE_FAILED; VLOG_MINI_3(LOG_LEVEL_FATAL, "Failed in writting file(%u/%u) '%s'\n", wrote, data->size(), file.c_str()); } fclose(dst); } else { ret = SCANNER_ERR_CREATE_FILE_FAILED; VLOG_MINI_1(LOG_LEVEL_FATAL, "Failed in creating file '%s'\n", file.c_str()); } return ret; } void hg_scanner::thread_devslock_handle(void) { int ret = SCANNER_ERR_OK; wait_devsislock_.wait(); while (is_firstopen_ && is_kernelsnap_devsislock) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); ret = set_server_blacklist_lock(); hg_version_free_handle(); is_firstopen_ = false; } } 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_) { LOG_INFO(LOG_LEVEL_FATAL, "image process is still running!\n"); continue; } } scan_life_ = new do_when_born_and_dead(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; } } int hg_scanner::hg_version_init_handle() { int ret = SCANNER_ERR_OK; #ifndef WIN32 #ifdef OEM_HANWANG string libname = "libhwdriver.so"; #elif defined(OEM_LISICHENG) string libname = "liblscdriver.so"; #elif defined(OEM_CANGTIAN) string libname = "libctsdriver.so"; #elif defined(OEM_ZHONGJING) string libname = "libzjdriver.so"; #else string libname = "libhgdriver.so"; #endif string scanner_path = hg_log::get_module_full_path(libname.c_str()); if (scanner_path.empty()) { return SCANNER_ERR_OUT_OF_RANGE; } scanner_path = scanner_path.substr(0, scanner_path.size() - libname.size()); string HGVersionlib_path = scanner_path + HGVERSION_LIBNANE; if (access(HGVersionlib_path.c_str(), F_OK) != 0) { return SCANNER_ERR_OUT_OF_RANGE; } printf("HGVersionlib_path:%s \r\n", HGVersionlib_path.c_str()); Dynamicopen_HGVersion_pHandle_ = dlopen(HGVersionlib_path.c_str(), RTLD_LAZY); if (!Dynamicopen_HGVersion_pHandle_ ) { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "HGVersionlib_path open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY)); return SCANNER_ERR_INSUFFICIENT_MEMORY; } HGVersion_Init_ = (SDKHGVersion_Init_)dlsym(Dynamicopen_HGVersion_pHandle_, "HGVersion_CreateMgr"); HGVersion_Islock_ = (SDKHGVersion_Islock_)dlsym(Dynamicopen_HGVersion_pHandle_, "HGVersion_BlackListCheck"); HGVersion_Postlog_ = (SDKHGVersion_Postlog_)dlsym(Dynamicopen_HGVersion_pHandle_, "HGVersion_PostDeviceLockInfo"); HGVersion_Free_ = (SDKHGVersion_Free_)dlsym(Dynamicopen_HGVersion_pHandle_, "HGVersion_DestroyMgr"); #else string scanner_path = hg_log::get_module_full_path("scanner.dll"); scanner_path = scanner_path.substr(0, scanner_path.size() - strlen("scanner.dll")); string HGVersionlib_path = scanner_path + HGVERSION_LIBNANE; wchar_t* Prclibbuffer = new wchar_t[HGVersionlib_path.length() + 1]; ret = strToWchar(HGVersionlib_path, Prclibbuffer); if (ret == -1) return SCANNER_ERR_INSUFFICIENT_MEMORY; load_dll(Prclibbuffer, &Dynamicopen_HGVersion_pHandle_); //windows下可能会找不到他所在的依赖库导致直接打开动态库的时候找不到模块 if (Prclibbuffer) { delete []Prclibbuffer; Prclibbuffer = NULL; } //int l = GetLastError(); if (!Dynamicopen_HGVersion_pHandle_ ) { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Dynamicopen_HGVersion_pHandle_ open dll is error: %s\n", hg_scanner_err_name(SCANNER_ERR_INSUFFICIENT_MEMORY)); return SCANNER_ERR_INSUFFICIENT_MEMORY; } HGVersion_Init_ = (SDKHGVersion_Init_) GetProcAddress(Dynamicopen_HGVersion_pHandle_, "HGVersion_CreateMgr"); HGVersion_Islock_ = (SDKHGVersion_Islock_) GetProcAddress(Dynamicopen_HGVersion_pHandle_, "HGVersion_BlackListCheck"); HGVersion_Postlog_ = (SDKHGVersion_Postlog_) GetProcAddress(Dynamicopen_HGVersion_pHandle_, "HGVersion_PostDeviceLockInfo"); HGVersion_Free_ = (SDKHGVersion_Free_) GetProcAddress(Dynamicopen_HGVersion_pHandle_, "HGVersion_DestroyMgr"); #endif if (!HGVersion_Init_ ||!HGVersion_Islock_ || !HGVersion_Postlog_ || !HGVersion_Free_) { return SCANNER_ERR_INVALID_PARAMETER; } HGVersion_Init_(&HGVersion_mgr_); return ret; } int hg_scanner::set_server_blacklist_lock() { if (!HGVersion_mgr_) { return SCANNER_ERR_INVALID_PARAMETER; } char snbuffer[20]; char fvbuffer[15]; char pidbuffer[5]; SANE_Bool scan_islock = false; memset(snbuffer, 0, sizeof(snbuffer)); memset(fvbuffer, 0, sizeof(fvbuffer)); memset(pidbuffer, 0, sizeof(pidbuffer)); HGBool islock = false; string sn = get_serial_num(); string fv = get_firmware_version(); if (fv.empty() || sn.empty()) return -1; strcpy(snbuffer, sn.c_str()); strcpy(fvbuffer, fv.c_str()); sprintf(pidbuffer, "%0x", pid_); //优先从机器设备上进行校验 int ret = HGVersion_Islock_(HGVersion_mgr_, snbuffer, &islock); int islock_file = 0; if (ret != 0) //服务器没有连接到网络 { ret = get_dev_islock_file(islock_file); is_checksum_strat_scan = islock_file <= 0 ? true : false; //使用校验码来进行扫描,以后只会使用这种方法进行扫描 VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "net is 404 , devs list is:%d\n", islock_file); } else if (!islock) { ret = HGVersion_Postlog_(HGVersion_mgr_, pidbuffer, snbuffer, fv.substr(0, 4).c_str(), fvbuffer, islock); //发送日志到服务,第三个参数随意字符串但不能为NULL is_checksum_strat_scan = true; set_dev_islock_file(0); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "use checksum start scan:%d\n", islock); } else { ret = HGVersion_Postlog_(HGVersion_mgr_, pidbuffer, snbuffer, fv.substr(0, 4).c_str(), fvbuffer, islock); //发送日志到服务,第三个参数随意字符串但不能为NULL is_checksum_strat_scan = false; set_dev_islock_file(1); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "devs is lock:%d\n", islock); } return 0 ; } void hg_scanner::hg_version_free_handle() { int ret = 0; if (HGVersion_mgr_) { int ret = HGVersion_Free_(HGVersion_mgr_); HGVersion_mgr_ = NULL; } if (Dynamicopen_HGVersion_pHandle_) { #if (!defined WIN32) ret = dlclose(Dynamicopen_HGVersion_pHandle_); #else ret = FreeLibrary(Dynamicopen_HGVersion_pHandle_); #endif Dynamicopen_HGVersion_pHandle_ = NULL; } } void hg_scanner::dump_image_empty(hg_imgproc::HIMGPRC himg, const char* desc) {} void hg_scanner::dump_image_real(hg_imgproc::HIMGPRC himg, const char* desc) { char sn[40] = { 0 }; sprintf(sn, "_%03d.jpg", final_img_index_ + 1); hg_imgproc::dump_2_file(himg, (dump_usb_path_ + PATH_SEPARATOR + desc + sn).c_str()); } void hg_scanner::init_setting_func_map(void) { setting_map_[SANE_STD_OPT_NAME_RESTORE] = &hg_scanner::setting_restore; setting_map_[SANE_STD_OPT_NAME_HELP] = &hg_scanner::setting_help; setting_map_[SANE_STD_OPT_NAME_COLOR_MODE] = &hg_scanner::setting_color_mode; setting_map_[SANE_STD_OPT_NAME_IS_MULTI_OUT] = &hg_scanner::setting_multi_out; setting_map_[SANE_STD_OPT_NAME_MULTI_OUT_TYPE] = &hg_scanner::setting_multi_out_type; setting_map_[SANE_STD_OPT_NAME_FILTER] = &hg_scanner::setting_rid_color; setting_map_[SANE_STD_OPT_NAME_RID_MULTIOUT_RED] = &hg_scanner::setting_rid_multi_red; setting_map_[SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED] = &hg_scanner::setting_rid_answer_red; setting_map_[SANE_STD_OPT_NAME_ERASE_BACKGROUND] = &hg_scanner::setting_erase_background; setting_map_[SANE_STD_OPT_NAME_BKG_COLOR_RANGE] = &hg_scanner::setting_erase_background_range; setting_map_[SANE_STD_OPT_NAME_NOISE_OPTIMIZE] = &hg_scanner::setting_noise_optimize; setting_map_[SANE_STD_OPT_NAME_NOISE_SIZE] = &hg_scanner::setting_noise_optimize_range; setting_map_[SANE_STD_OPT_NAME_PAPER] = &hg_scanner::setting_paper; setting_map_[SANE_STD_OPT_NAME_SIZE_CHECK] = &hg_scanner::setting_paper_check; setting_map_[SANE_STD_OPT_NAME_PAGE] = &hg_scanner::setting_page; setting_map_[SANE_STD_OPT_NAME_DISCARD_BLANK_SENS] = &hg_scanner::setting_page_omit_empty; setting_map_[SANE_STD_OPT_NAME_RESOLUTION] = &hg_scanner::setting_resolution; setting_map_[SANE_STD_OPT_NAME_EXCHANGE] = &hg_scanner::setting_exchagnge; setting_map_[SANE_STD_OPT_NAME_SPLIT] = &hg_scanner::setting_split_image; setting_map_[SANE_STD_OPT_NAME_ANTI_SKEW] = &hg_scanner::setting_automatic_skew; setting_map_[SANE_STD_OPT_NAME_RID_HOLE] = &hg_scanner::setting_rid_hole; setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE] = &hg_scanner::setting_rid_hoe_range; setting_map_[SANE_STD_OPT_NAME_BRIGHTNESS] = &hg_scanner::setting_bright; setting_map_[SANE_STD_OPT_NAME_CONTRAST] = &hg_scanner::setting_contrast; setting_map_[SANE_STD_OPT_NAME_GAMMA] = &hg_scanner::setting_gamma; setting_map_[SANE_STD_OPT_NAME_SHARPEN] = &hg_scanner::setting_sharpen; setting_map_[SANE_STD_OPT_NAME_DARK_SAMPLE] = &hg_scanner::setting_dark_sample; setting_map_[SANE_STD_OPT_NAME_ERASE_BLACK_FRAME] = &hg_scanner::setting_erase_black_frame; setting_map_[SANE_STD_OPT_NAME_THRESHOLD] = &hg_scanner::setting_threshold; setting_map_[SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL] = &hg_scanner::setting_anti_noise; setting_map_[SANE_STD_OPT_NAME_MARGIN] = &hg_scanner::setting_margin; setting_map_[SANE_STD_OPT_NAME_FILL_BKG_MODE] = &hg_scanner::setting_filling_background; setting_map_[SANE_STD_OPT_NAME_IS_ANTI_PERMEATE] = &hg_scanner::setting_is_permeate; setting_map_[SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL] = &hg_scanner::setting_is_permeate_lv; setting_map_[SANE_STD_OPT_NAME_RID_MORR] = &hg_scanner::setting_remove_morr; setting_map_[SANE_STD_OPT_NAME_ERROR_EXTENSION] = &hg_scanner::setting_error_extention; setting_map_[SANE_STD_OPT_NAME_RID_GRID] = &hg_scanner::setting_remove_texture; setting_map_[SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK] = &hg_scanner::setting_ultrasonic_check; setting_map_[SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE] = &hg_scanner::setting_go_on_when_double_checked; setting_map_[SANE_STD_OPT_NAME_IS_CHECK_STAPLE] = &hg_scanner::setting_staple_check; setting_map_[SANE_STD_OPT_NAME_SCAN_MODE] = &hg_scanner::setting_scan_mode; setting_map_[SANE_STD_OPT_NAME_SCAN_COUNT] = &hg_scanner::setting_scan_count; setting_map_[SANE_STD_OPT_NAME_TEXT_DIRECTION] = &hg_scanner::setting_text_direction; setting_map_[SANE_STD_OPT_NAME_IS_ROTATE_BKG_180] = &hg_scanner::setting_rotate_bkg_180; setting_map_[SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR] = &hg_scanner::setting_fractate_check; setting_map_[SANE_STD_OPT_NAME_DOG_EAR_SIZE] = &hg_scanner::setting_fractate_check_level; setting_map_[SANE_STD_OPT_NAME_IS_CHECK_ASKEW] = &hg_scanner::setting_skew_check; setting_map_[SANE_STD_OPT_NAME_ASKEW_RANGE] = &hg_scanner::setting_skew_check_level; setting_map_[SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA] = &hg_scanner::setting_is_custom_gamma; setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA] = &hg_scanner::setting_is_custom_area; setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT] = &hg_scanner::setting_custom_area_left; setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT] = &hg_scanner::setting_custom_area_right; setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_TOP] = &hg_scanner::setting_custom_area_top; setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM] = &hg_scanner::setting_custom_area_bottom; setting_map_[SANE_STD_OPT_NAME_IMAGE_QUALITY] = &hg_scanner::setting_img_quality; setting_map_[SANE_STD_OPT_NAME_IS_FILL_COLOR] = &hg_scanner::setting_color_fill; setting_map_[SANE_STD_OPT_NAME_IS_PHOTO_MODE] = &hg_scanner::setting_keep_watermark; setting_map_[SANE_STD_OPT_NAME_BINARY_THRESHOLD] = &hg_scanner::setting_black_white_threshold; setting_map_[SANE_STD_OPT_NAME_REVERSE_01] = &hg_scanner::setting_white_pixel_0; setting_map_[SANE_STD_OPT_NAME_FEED_STRENGTH] = &hg_scanner::setting_feedmode; setting_map_[SANE_STD_OPT_NAME_TIME_TO_SLEEP] = &hg_scanner::setting_sleeptime; setting_map_[SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH] = &hg_scanner::setting_auto_pick_paper; setting_map_[SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE] = &hg_scanner::setting_auto_pick_paper_threshold; setting_map_[SANE_STD_OPT_NAME_WAIT_TO_SCAN] = &hg_scanner::setting_auto_paper_scan; setting_map_[SANE_STD_OPT_NAME_RID_HOLE_L] = &hg_scanner::setting_isremove_left_hole; setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L] = &hg_scanner::setting_isremove_left_hole_threshold; setting_map_[SANE_STD_OPT_NAME_RID_HOLE_R] = &hg_scanner::setting_isremove_right_hole; setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R] = &hg_scanner::setting_isremove_right_hole_threshold; setting_map_[SANE_STD_OPT_NAME_RID_HOLE_T] = &hg_scanner::setting_isremove_top_hole; setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T] = &hg_scanner::setting_isremove_top_hole_threshold; setting_map_[SANE_STD_OPT_NAME_RID_HOLE_B] = &hg_scanner::setting_isremove_low_hole; setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B] = &hg_scanner::setting_isremove_low_hole_threshold; setting_map_[SANE_STD_OPT_NAME_FOLD_TYPE] = &hg_scanner::setting_fold_type; } std::string hg_scanner::setting_name_from(const char* n_or_id, int* id) { if (IS_PTR_NUMBER(n_or_id)) { if (id) *id = (long long)n_or_id; if ((unsigned long)n_or_id < jsn_children_.size()) return jsn_children_[(unsigned long)n_or_id]; else return ""; } else if (id) { *id = std::distance(jsn_children_.begin(), std::find(jsn_children_.begin(), jsn_children_.end(), n_or_id)); } return n_or_id; } void hg_scanner::get_range(const char* name, std::vector& range, std::string& def_val, bool& is_range/*range or list*/) { std::string type(""); range.clear(); if (setting_jsn_.at(name).contains("range")) { setting_jsn_.at(name).at("type").get_to(type); is_range = !setting_jsn_.at(name).at("range").is_array(); if (is_range) { if (type == "int") { int l = 0, u = 0; setting_jsn_.at(name).at("range").at("min").get_to(l); setting_jsn_.at(name).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(name).at("range").at("min").get_to(l); setting_jsn_.at(name).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(name).at("range").size(); ++i) { if (type == "int") { int v = 0; setting_jsn_.at(name).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(name).at("range").at(i).get_to(v); sprintf(str, "%f", v); range.push_back(str); } else { std::string v(""); if (setting_jsn_.at(name).at("range").at(i).is_number()) { int id = 0; setting_jsn_.at(name).at("range").at(i).get_to(id); v = hg_log::lang_load(id); } else setting_jsn_.at(name).at("range").at(i).get_to(v); range.push_back(v); } } } } if (type == "int") { int v = 0; char sn[20] = { 0 }; setting_jsn_.at(name).at("default").get_to(v); sprintf(sn, "%d", v); def_val = sn; } else if (type == "float") { double v = 0; char sn[20] = { 0 }; setting_jsn_.at(name).at("default").get_to(v); sprintf(sn, "%f", v); def_val = sn; } else if (type == "string") { def_val = get_setting_item_string(name, "default"); } //VLOG_MINI_3(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(const char* name, bool& val) { std::vector range; std::string init(""), in(val ? "true" : "false"); bool is_range = false;; get_range(name, 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(const char* name, int& val) { std::vector range; std::string init(""); bool is_range = false;; get_range(name, 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(const char* name, double& val) { std::vector range; std::string init(""); bool is_range = false;; get_range(name, 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(const char* name, std::string& val) { std::vector range; std::string init(""), in(val); bool is_range = false;; get_range(name, 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; } bool hg_scanner::check_paper_and_resolution(int res, int paper) { if (res == 600) { if (paper == PAPER_MAX_SIZE || paper == PAPER_MAX_SIZE_CLIP || paper == PAPER_TRIGEMINY) { VLOG_MINI_2(LOG_LEVEL_WARNING, "resolution '%d' is in-compatible with paper '%s'\n", res, paper_string(paper).c_str()); return false; } } return true; } bool hg_scanner::check_resolution_and_quality(int res, const char* quality) { if (res == 600 && strcmp(quality, hg_log::lang_load(ID_OPTION_VALUE_HZ_SDYX)) == 0) { VLOG_MINI_2(LOG_LEVEL_WARNING, "resolution '%d' is in-compatible with quality '%s'\n", res, quality); return false; } return true; } int hg_scanner::restore(const char* name) { std::string val(""); int ret = SCANNER_ERR_OK; setting_jsn_.at(name).at("type").get_to(val); if (val == "string") { val = get_setting_item_string(name, "default"); char* buf = NULL; int size = 0; setting_jsn_.at(name).at("size").get_to(size); buf = (char*)malloc(size + 4); if (buf) { bzero(buf, size + 4); strcpy(buf, val.c_str()); ret = set_setting(name, buf, val.length()); free(buf); } else return SCANNER_ERR_INSUFFICIENT_MEMORY; } else if (val == "int") { int v = 0; setting_jsn_.at(name).at("default").get_to(v); ret = set_setting(name, (char*)&v, sizeof(v)); } else if (val == "float") { double v = .0f; setting_jsn_.at(name).at("default").get_to(v); ret = set_setting(name, (char*)&v, sizeof(v)); } else if (val == "bool") { bool v = false; setting_jsn_.at(name).at("default").get_to(v); ret = set_setting(name, (char*)&v, sizeof(v)); } return ret; } bool hg_scanner::get_default_value(void* buf, json* jsn) { std::string type(""); 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 = ""; if (jsn->at("default").is_number()) { int n = 0; jsn->at("default").get_to(n); type = hg_log::lang_load(n); } else 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_) while (run_) { std::shared_ptr tiny_buffer; if (imgs_.Size() == 0) { if (wait_usb_.is_waiting()) break; this_thread::sleep_for(chrono::milliseconds(30)); continue; } uint32_t id = -1; tiny_buffer = imgs_.Take(&id); if (tiny_buffer->swap()) { try { if (!ImagePrc_pHandle_) { VLOG_MINI_1(LOG_LEVEL_FATAL, "Get Image Process is NULL pid is %d.\n",pid_); stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; stop(); break; } image_process(tiny_buffer, id); } catch (const std::exception& e) { if (is_dpi_color_check) { is_dpi_color_check = false; stop_fatal_ = SCANNER_ERR_DEVICE_DISTORTION; } else stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; VLOG_MINI_1(LOG_LEVEL_ALL, "is opencv Fatal: %s\n", e.what()); stop(); break; } catch (...) { VLOG_MINI_1(LOG_LEVEL_FATAL, "FATAL: Insufficient memory when proecss image with %d bytes.\n", tiny_buffer->size()); stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; stop(); } } else { VLOG_MINI_1(LOG_LEVEL_FATAL, "Reload USB data '%s' failed!\n", tiny_buffer->file().c_str()); } } } void hg_scanner::working_begin(void*) { stop_fatal_ = SCANNER_ERR_OK; final_img_index_ = 0; status_ = SCANNER_ERR_OK; notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCAN_WORKING), SANE_EVENT_WORKING, SCANNER_ERR_OK); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "[%s] scanning ...\n", hg_log::current_time().c_str()); } void hg_scanner::working_done(void*) { imgs_.Clear(); if(user_cancel_) final_imgs_.clear(); if (status_ == SCANNER_ERR_OK && stop_fatal_) status_ = stop_fatal_; switch (status_) { case SCANNER_ERR_OK: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCAN_STOPPED), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_BUSY: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_PC_BUSY), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_STOPPED: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCAN_STOPPED), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_COVER_OPENNED: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_COVER_OPENNED), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_NO_PAPER: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_NO_PAPER), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_FEEDING_PAPER: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_FEEDING_PAPER), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_NOT_FOUND: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_NOT_FOUND), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_SLEEPING: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_SLEEPING), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_COUNT_MODE: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_COUNT_MODE), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_DOUBLE_FEEDING: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_DOUBLE_FEEDING), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_PAPER_JAMMED: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_PAPER_JAMMED), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_STAPLE_ON: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_STAPLE_ON), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_PAPER_SKEW: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_PAPER_SKEW), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_SIZE_CHECK: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_SIZE_CHECK), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_DOGEAR: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_DOGEAR), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_NO_IMAGE: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_NO_IMAGE), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_SCANN_ERROR: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_SCANN_ERROR), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_PC_BUSY: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_PC_BUSY), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_INSUFFICIENT_MEMORY: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_INSUFFICIENT_MEMORY), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_TIMEOUT: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_TIMEOUT), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_ISLOCK: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_ISLOCK), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_AUTO_FAIL_OVER: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_AUTO_FAIL_OVER), SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_DISTORTION: notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_DISTORTION), SANE_EVENT_SCAN_FINISHED, status_); break; default: notify_ui_working_status(user_cancel_ ? hg_log::lang_load(ID_STATU_DESC_SCAN_CANCELED) : hg_log::lang_load(ID_STATU_DESC_SCAN_STOPPED), SANE_EVENT_SCAN_FINISHED, status_); break; } if (test_1_paper_) { LOG_INFO(LOG_LEVEL_DEBUG_INFO, "scanning mode: finished testing ONE paper, restore to normal scanning.\n"); } else { VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "[%s] scanned %d picture(s) and finished with error %s.\n", hg_log::current_time().c_str(), final_img_index_, hg_scanner_err_name(status_)); } 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; } // adjust custom area data ... float v = reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT, custom_area_lt_x_, .0f, paper_size_mm_.cx, .0f, paper_size_mm_.cx); reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT, custom_area_br_x_, .0f, paper_size_mm_.cx, v, paper_size_mm_.cx); v = reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_TOP, custom_area_lt_y_, .0f, paper_size_mm_.cy, .0f, paper_size_mm_.cy); reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM, custom_area_br_y_, .0f, paper_size_mm_.cy, v, paper_size_mm_.cy); } float hg_scanner::reset_custom_area_jsn_value(const char* name, double& var, float range_l, float range_u, float value_l, float value_u) { custom_area_br_y_; if (setting_jsn_.contains(name)) { float v = .0f, tmp = .0f; setting_jsn_.at(name).at("cur").get_to(v); tmp = v; if (v < value_l) v = value_l; else if (v > value_u) v = value_u; if (!IS_DOUBLE_EQUAL(tmp, v)) setting_jsn_.at(name).at("cur") = v; value_l = v; setting_jsn_.at(name).at("default").get_to(v); tmp = v; if (v < range_l) v = range_l; else if (v > range_u) v = range_u; if (!IS_DOUBLE_EQUAL(tmp, v)) setting_jsn_.at(name).at("default") = v; if (var < range_l) var = range_l; else if (var > range_u) var = range_u; if (setting_jsn_.at(name).contains("range")) { float lower = range_l, upper = range_u; if (setting_jsn_.at(name).at("range").contains("min")) { setting_jsn_.at(name).at("range").at("min").get_to(lower); tmp = lower; if (lower < range_l) lower = range_l; else if (lower > range_u) lower = range_u; if (!IS_DOUBLE_EQUAL(lower, tmp)) setting_jsn_.at(name).at("range").at("min") = lower; } if (setting_jsn_.at(name).at("range").contains("max")) { setting_jsn_.at(name).at("range").at("max").get_to(upper); tmp = upper; if (upper < lower) upper = lower; else if (upper > range_u) upper = range_u; if (!IS_DOUBLE_EQUAL(upper, tmp)) setting_jsn_.at(name).at("range").at("max") = upper; } } } return value_l; } int hg_scanner::set_color_change(void) { // if (/* condition */) // { // /* code */ // } return SCANNER_ERR_OK; } int hg_scanner::hgpaper_to_devspaper(Paper_Map papermap[], int len, int& paper, bool* exact, TwSS* type) { int ind = 0; bool good = true, * r = exact ? exact : &good; for (int i = 0; i < len; ++i) { if (paper == papermap[i].paper) { ind = i; break; } } if (paper == papermap[ind].paper) *r = true; else *r = false; paper = papermap[ind].paper; if (type) *type = papermap[ind].type; return ind; } int hg_scanner::invoke_setting_xxx(int(hg_scanner::*func)(void*), void* data) { int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT; auto it = setting_map_.begin(); while (it != setting_map_.end()) { if (it->second == func) { ret = set_setting(it->first.c_str(), data, 0); break; } ++it; } return ret; } int hg_scanner::setting_restore(void* data) { // restore ... notify_setting_result_ = false; for (auto& v : setting_map_) { if (setting_jsn_.contains(v.first.c_str())) { std::string t(""); setting_jsn_.at(v.first.c_str()).at("type").get_to(t); if (t != "group" && t != "button") restore(v.first.c_str()); } } notify_setting_result_ = true; return SCANNER_ERR_CONFIGURATION_CHANGED; } int hg_scanner::setting_help(void* data) { int ret = SCANNER_ERR_OK; std::string helpfile = helpfile_; std::string com = "xdg-open ";//注意空格保留 printf("helpfile = %s\r\n",helpfile.c_str()); #if defined(WIN32) || defined(_WIN64) com = ""; helpfile.insert(0, hg_log::get_scanner_path()); FILE* src = fopen(helpfile.c_str(), "rb"); if (src) fclose(src); else #else if (access(helpfile.c_str(),F_OK) == -1) #endif { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO,"App_Help_pdf path is:%s system is:%d\r\n",helpfile.c_str()); ret = SCANNER_ERR_OPEN_FILE_FAILED; return ret ; } com += helpfile; #if defined(WIN32) || defined(_WIN64) ShellExecuteA(NULL, "Open", com.c_str(), NULL, NULL, SW_SHOWNORMAL); #else system(com.c_str()); #endif VLOG_MINI_1(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 = SCANNER_ERR_OK, val = 0, ret = SCANNER_ERR_OK; bool exact = check_range(SANE_STD_OPT_NAME_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 == SCANNER_ERR_NOT_EXACT) { image_prc_param_.bits.color_mode = old; str = color_mode_string(image_prc_param_.bits.color_mode); ret = SCANNER_ERR_NOT_EXACT; } else if (sub) { ret = sub; image_prc_param_.bits.color_mode = old; } else if (!exact) { ret = SCANNER_ERR_NOT_EXACT; } is_auto_matic_color = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? true :false; // 等于COLOR_MODE_AUTO_MATCH 的时候颜色模式需要变为2 彩色模式图像参数和硬件参数都如此 VLOG_MINI_4(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_err_name(ret),str.c_str()); if(ret == SCANNER_ERR_NOT_EXACT) strcpy((char*)data, str.c_str()); return SCANNER_ERR_RELOAD_OPT_PARAM; // ret; } int hg_scanner::setting_multi_out(void* data) { is_multiout = *((bool*)data); int val = image_prc_param_.bits.color_mode; VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "image_prc_param_.bits.multi_out %d\n", image_prc_param_.bits.multi_out); //if (is_multiout) //{ // if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW) // val = COLOR_MODE_256_GRAY; // else // val = COLOR_MODE_24_BITS; //} //on_color_mode_changed(val); return SCANNER_ERR_RELOAD_OPT_PARAM; // SCANNER_ERR_OK; } int hg_scanner::setting_multi_out_type(void* data) { int ret = SCANNER_ERR_OK; std::string str((char*)data); bool exact = check_range(SANE_STD_OPT_NAME_MULTI_OUT_TYPE, str); int color; image_prc_param_.bits.multi_out = match_best_multi_out(str,NULL); save_multiout = str; VLOG_MINI_3(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_err_name(ret)); /*if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW) color = COLOR_MODE_256_GRAY; else color = COLOR_MODE_24_BITS; on_color_mode_changed(color);*/ return SCANNER_ERR_RELOAD_OPT_PARAM; // ret; } int hg_scanner::setting_rid_color(void* data) { std::string str((char*)data); int ret = SCANNER_ERR_OK, old = image_prc_param_.bits.rid_color; bool exact = check_range(SANE_STD_OPT_NAME_FILTER, str); image_prc_param_.bits.rid_color = match_best_rid_color(str, NULL); int color = image_prc_param_.bits.color_mode; on_color_mode_changed(color); if (!exact) { ret = SCANNER_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 SCANNER_ERR_OK; } int hg_scanner::setting_rid_answer_red(void* data) { image_prc_param_.bits.rid_answer_red = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_erase_background(void* data) { image_prc_param_.bits.erase_bakground = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_erase_background_range(void* data) { int ret = SCANNER_ERR_OK; erase_bkg_range_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_BKG_COLOR_RANGE, erase_bkg_range_)) { ret = SCANNER_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 SCANNER_ERR_OK; } int hg_scanner::setting_noise_optimize_range(void* data) { int ret = SCANNER_ERR_OK; noise_range_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_NOISE_SIZE, noise_range_)) { ret = SCANNER_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(SANE_STD_OPT_NAME_PAPER, paper); int ret = SCANNER_ERR_OK, sub = SCANNER_ERR_OK, val = 0, old = image_prc_param_.bits.paper; val = image_prc_param_.bits.paper = match_best_paper(paper, NULL); // check 600 dpi ... if (!check_paper_and_resolution(resolution_, val)) { image_prc_param_.bits.paper = old; strcpy((char*)data, paper_string(old).c_str()); return SCANNER_ERR_DEVICE_NOT_SUPPORT; } sub = on_paper_changed(val); image_prc_param_.bits.paper = val; if (sub == SCANNER_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 = SCANNER_ERR_NOT_EXACT; if (save_sizecheck) { //setting_paper_check(0,(void*)&save_sizecheck); invoke_setting_xxx(&hg_scanner::setting_paper_check, &save_sizecheck); } VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner_err_name(ret)); if(ret == SCANNER_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 SCANNER_ERR_RELOAD_OPT_PARAM; // ret; } int hg_scanner::setting_paper_check(void* data) { bool use = *((bool*)data); int ret = on_paper_check_changed(use); VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Change paper size-checking %s = %s\n", *((bool*)data) ? "enabled" : "disabled", hg_scanner_err_name(ret)); *((bool*)data) = use; save_sizecheck = use; return ret; } int hg_scanner::setting_page(void* data) { std::string val((char*)data); bool exact = check_range(SANE_STD_OPT_NAME_PAGE, val); int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT; VLOG_MINI_3(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_err_name(ret)); 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 = SCANNER_ERR_OK; omit_empty_level_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_DISCARD_BLANK_SENS, omit_empty_level_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = omit_empty_level_; } return ret; } int hg_scanner::setting_resolution(void* data) { int ret = SCANNER_ERR_OK, old = resolution_, sub = SCANNER_ERR_OK; resolution_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_RESOLUTION, resolution_)) { *(int*)data = resolution_; ret = SCANNER_ERR_NOT_EXACT; } // check paper ... if (!check_paper_and_resolution(resolution_, image_prc_param_.bits.paper)) { resolution_ = old; *((int*)data) = old; return SCANNER_ERR_NOT_EXACT; } /*if (!check_resolution_and_quality(resolution_, is_img_quality(is_quality_).c_str())) { if (resolution_ == 600 && old < 300) { char buf[128] = { 0 }; strcpy(buf, OPTION_VALUE_HZ_HZYX); resolution_ = old; invoke_setting_xxx(&hg_scanner::setting_img_quality, buf); resolution_ = 600; ret = SCANNER_ERR_CONFIGURATION_CHANGED; } else { resolution_ = old; *((int*)data) = old; return SCANNER_ERR_DEVICE_NOT_SUPPORT; } }*/ sub = on_resolution_changed(resolution_); if (sub == SCANNER_ERR_NOT_EXACT) ret = sub; else if (sub) ret = sub; VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change resolution from %d to %d = %s\n", old, *((int*)data), hg_scanner_err_name(ret)); //*((int*)data) = resolution_; return SCANNER_ERR_RELOAD_OPT_PARAM; // ret; } int hg_scanner::setting_exchagnge(void* data) { image_prc_param_.bits.exchange = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_split_image(void* data) { image_prc_param_.bits.split = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_automatic_skew(void* data) { // automatic_skew_detection_ = *((bool*)data); image_prc_param_.bits.automatic_skew = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_rid_hole(void* data) { image_prc_param_.bits.rid_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_rid_hoe_range(void* data) { int ret = SCANNER_ERR_OK; rid_hole_range_ = *((double*)data); if (!check_range(SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE, rid_hole_range_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = rid_hole_range_; } rid_hole_range_*=100; VLOG_MINI_1(LOG_LEVEL_WARNING, "rid_hole_range_ = %f\r\n", rid_hole_range_); return ret; } int hg_scanner::setting_bright(void* data) { int ret = SCANNER_ERR_OK; bright_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_BRIGHTNESS, bright_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = bright_; } return ret; } int hg_scanner::setting_contrast(void* data) { int ret = SCANNER_ERR_OK; contrast_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_CONTRAST, contrast_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = contrast_; } return ret; } int hg_scanner::setting_gamma(void* data) { int ret = SCANNER_ERR_OK; gamma_ = *((double*)data); if (!check_range(SANE_STD_OPT_NAME_GAMMA, gamma_)) { ret = SCANNER_ERR_NOT_EXACT; *((double*)data) = gamma_; } return ret; } int hg_scanner::setting_sharpen(void* data) { std::string str((char*)data); int ret = SCANNER_ERR_OK; bool exact = check_range(SANE_STD_OPT_NAME_SHARPEN, str); VLOG_MINI_2(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 = SCANNER_ERR_NOT_EXACT; } VLOG_MINI_1(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 SCANNER_ERR_OK; } int hg_scanner::setting_erase_black_frame(void* data) { image_prc_param_.bits.erase_black_frame = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_threshold(void* data) { int ret = SCANNER_ERR_OK; threshold_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_THRESHOLD, threshold_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = threshold_; } return ret; } int hg_scanner::setting_anti_noise(void* data) { int ret = SCANNER_ERR_OK; anti_noise_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL, anti_noise_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = anti_noise_; } return ret; } int hg_scanner::setting_margin(void* data) { int ret = SCANNER_ERR_OK; margin_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_MARGIN, margin_)) { ret = SCANNER_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(SANE_STD_OPT_NAME_FILL_BKG_MODE, str); int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT; image_prc_param_.bits.fill_background = match_best_fill_background(str, NULL); if (!exact) { strcpy((char*)data, str.c_str()); ret = SCANNER_ERR_NOT_EXACT; } return ret; } int hg_scanner::setting_is_permeate(void* data) { image_prc_param_.bits.is_permeate = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_is_permeate_lv(void* data) { int ret = SCANNER_ERR_OK; std::string str((char*)data); bool exact = check_range(SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL, str); VLOG_MINI_2(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 = SCANNER_ERR_NOT_EXACT; } VLOG_MINI_1(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 SCANNER_ERR_OK; } int hg_scanner::setting_error_extention(void* data) { image_prc_param_.bits.error_extention = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_remove_texture(void* data) { image_prc_param_.bits.remove_txtture = *((bool*)data); return SCANNER_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_go_on_when_double_checked(void* data) { bool ok = true; std::string val((char*)data); double_paper_handle_ = double_paper_flag_from_option_value(val, &ok); // 此处需要通知设备双张处理方式 !!! // OPTION_VALUE_SZTPCL_xxx 共4种选择,目前只支持出现双张后停止的两种方式 // 若要上传出现双张的图片,请确保双张信号在图片之前发出来 !!! if(ok) return SCANNER_ERR_OK; else { strcpy((char*)data, val.c_str()); return SCANNER_ERR_NOT_EXACT; } } 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(SANE_STD_OPT_NAME_SCAN_MODE, str); int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT; if (strcmp(str.c_str(), hg_log::lang_load(ID_OPTION_VALUE_SMZS_LXSM)) == 0) { scan_count_ = -1; } else { setting_jsn_.at(SANE_STD_OPT_NAME_SCAN_COUNT).at("cur").get_to(scan_count_); } VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "set scanning pages to %d\n", scan_count_); return ret; } int hg_scanner::setting_scan_count(void* data) { int ret = SCANNER_ERR_OK; std::string val(get_setting_item_string(SANE_STD_OPT_NAME_SCAN_MODE, "cur")); if (val == hg_log::lang_load(ID_OPTION_VALUE_SMZS_LXSM)) { scan_count_ = -1; } else { scan_count_ = *((int*)data); } VLOG_MINI_1(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(SANE_STD_OPT_NAME_TEXT_DIRECTION, str); int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT; VLOG_MINI_3(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_err_name(ret)); image_prc_param_.bits.text_direction = match_best_text_direction(str, NULL); if (!exact) strcpy((char*)data, str.c_str()); if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO && ImagePrc_pHandle_) { hg_imgproc::init_auto_txt_hanld(ImagePrc_pHandle_); } else if (image_prc_param_.bits.text_direction != TEXT_DIRECTION_AUTO && ImagePrc_pHandle_) { hg_imgproc::free_auto_txt_hanld(ImagePrc_pHandle_); } return ret; } int hg_scanner::setting_rotate_bkg_180(void* data) { image_prc_param_.bits.rotate_back_180 = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_fractate_check(void* data) { image_prc_param_.bits.fractate_check = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_fractate_check_level(void* data) { int ret = SCANNER_ERR_OK; fractate_level_ = *((int*)data); if (!check_range(SANE_STD_OPT_NAME_DOG_EAR_SIZE, fractate_level_)) { ret = SCANNER_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(SANE_STD_OPT_NAME_ASKEW_RANGE, level); int ret = exact ? SCANNER_ERR_OK : SCANNER_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) { custom_gamma_ = *((bool*)data); return SCANNER_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 SCANNER_ERR_OK; } int hg_scanner::setting_is_custom_area(void* data) { custom_area_ = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_custom_area_left(void* data) { SANE_Fixed* v = (SANE_Fixed*)data; custom_area_lt_x_ = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_custom_area_top(void* data) { SANE_Fixed* v = (SANE_Fixed*)data; custom_area_lt_y_ = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_custom_area_right(void* data) { SANE_Fixed* v = (SANE_Fixed*)data; custom_area_br_x_ = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_custom_area_bottom(void* data) { SANE_Fixed* v = (SANE_Fixed*)data; custom_area_br_y_ = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_img_quality(void* data) { std::string str((char*)data); bool exact = check_range(SANE_STD_OPT_NAME_IMAGE_QUALITY, str); int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT; int old = is_quality_; VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change quality from '%s' to '%s' = %s\n", is_img_quality(is_quality_).c_str() , (char*)data, hg_scanner_err_name(ret)); is_quality_ = match_best_img_quality(str,NULL); /*if (!check_resolution_and_quality(resolution_, is_img_quality(is_quality_).c_str())) { is_quality_ = old; strcpy((char*)data, is_img_quality(is_quality_).c_str()); return SCANNER_ERR_DEVICE_NOT_SUPPORT; }*/ return SCANNER_ERR_OK; } int hg_scanner::setting_color_fill(void* data) { is_color_fill = *((bool *)data); return SCANNER_ERR_OK; } int hg_scanner::setting_keep_watermark(void* data) { keep_watermark_ = *(bool*)data; on_pic_type(keep_watermark_); return SCANNER_ERR_OK; } int hg_scanner::setting_black_white_threshold(void* data) { bw_threshold_ = (unsigned char)(*(SANE_Int*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_white_pixel_0(void* data) { is_white_0_ = *(bool*)data; return SCANNER_ERR_OK; } int hg_scanner::setting_feedmode(void* data) { std::string str((char *)data); int val = match_best_paper_strength(str,NULL); if (val == feedmode_) return SCANNER_ERR_OK; int ret = on_set_feedmode(val); if (ret == SCANNER_ERR_OK) feedmode_ = val; VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "setfeedmode from '%s' to '%s' = %s\n", is_paper_strength(feedmode_).c_str() , (char*)data, hg_scanner_err_name(ret)); return ret; } int hg_scanner::setting_sleeptime(void* data) { std::string str((char *)data); int val = match_best_sleep_time(str,0); int mintosec = 0; switch (val) { case SLEEP_TIME_0MIN: val = -1; //不休眠 -1 break; case SLEEP_TIME_5MIN: val = 5; break; case SLEEP_TIME_10MIN: val = 10; break; case SLEEP_TIME_30MIN: val = 30; break; case SLEEP_TIME_60MIN: val = 60; break; case SLEEP_TIME_120MIN: val = 120; break; case SLEEP_TIME_240MIN: val = 240; break; } if (val == sleeptime_) return SCANNER_ERR_OK; mintosec = val ; if (val != -1) { mintosec = val * 60; } int ret = set_sleep_time(mintosec); if (ret == SCANNER_ERR_OK) sleeptime_ = val; VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "set sleeptime from (%s)min to (%s)min = %s\n", is_sleep_time(sleeptime_).c_str() , (char*)data, hg_scanner_err_name(ret)); return ret; } int hg_scanner::setting_auto_pick_paper(void* data) { int ret = SCANNER_ERR_OK; bool isautopic = *((bool *)data); ret = on_pick_paper(isautopic); return ret; } int hg_scanner::setting_auto_pick_paper_threshold(void* data) { int ret = SCANNER_ERR_OK; double threshold = *((double*)data); ret = on_pick_paper_threshold(threshold); return ret; } int hg_scanner::setting_auto_paper_scan(void* data) { is_auto_paper_scan = *((bool *)data); if (!is_kernelsnap_220430_ && is_auto_paper_scan) { is_auto_paper_scan = *(bool*)data = false; notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_NOT_SUPPORTED), SANE_EVENT_ERROR, status_); return SCANNER_ERR_DEVICE_NOT_SUPPORT; } if (!is_auto_paper_scan) { on_is_auto_paper(is_auto_paper_scan); } return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_left_hole(void* data) { isremove_left_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_right_hole(void* data) { isremove_right_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_top_hole(void* data) { isremove_top_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_low_hole(void* data) { isremove_low_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_left_hole_threshold(void* data) { isremove_left_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_right_hole_threshold(void* data) { isremove_right_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_top_hole_threshold(void* data) { isremove_top_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_isremove_low_hole_threshold(void* data) { isremove_low_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_fold_type(void* data) { string str((char*)data); bool exact = NULL; int val = match_best_fold_type(str, 0); fold_type_ = val; return SCANNER_ERR_OK; } int hg_scanner::on_color_mode_changed(int& color_mode) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_paper_changed(int& paper) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_paper_check_changed(bool& check) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_resolution_changed(int& dpi) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_ultrasonic_check_changed(bool& check) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_staple_check_changed(bool& check) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_skew_check_changed(bool& check) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_skew_check_level_changed(int& check) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_set_feedmode(int feedmode) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_get_feedmode(int &feedmode) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_pic_type(bool& pic) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_pick_paper(bool autostrength) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_pick_paper_threshold(double threshold) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_is_auto_paper(bool isautopaper) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_cis_get_image(bool isautopaper) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } void hg_scanner::on_device_reconnected(void) { std::lock_guard lock(io_lock_); VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "%04x:%04x reconnected.\n", io_->get_vid(), io_->get_pid()); } int hg_scanner::set_setting_value(const char* name, void* data, int len) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::on_scanner_closing(bool force) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } void hg_scanner::thread_handle_usb_read(void) { } void hg_scanner::thread_handle_islock_read(void) { } void hg_scanner::adjust_color(hg_imgproc::HIMGPRC handle) { int tableLength = 0; // ZERO length perform color-adjust only unsigned char buffer1[256 * 3]; if (custom_gamma_) { if (img_conf_.pixtype == COLOR_MODE_BLACK_WHITE || img_conf_.pixtype == COLOR_MODE_256_GRAY) { tableLength = 256; memcpy(buffer1, custom_gamma_val_->table, tableLength); } else { // convert R[256] + G[256] + B[256] to BGR[256] ... tableLength = 256 * 3; for (int i = 0; i < 256; ++i) { buffer1[i * 3 + 0] = custom_gamma_val_->table[256 * 2 + i]; buffer1[i * 3 + 1] = custom_gamma_val_->table[256 * 1 + i]; buffer1[i * 3 + 2] = custom_gamma_val_->table[256 * 0 + i]; } } } hg_imgproc::adjust_color(handle, buffer1, tableLength); } hg_imgproc::IMGPRCPARAM hg_scanner::get_image_process_object(int model) { hg_imgproc::IMGPRCPARAM param; hg_imgproc::HIMGPRC handle = nullptr; //float bright = img_conf_.brightness, // contrast = img_conf_.contrast; bzero(¶m, sizeof(param)); param.bits = 8; //image_prc_param_.bits.color_mode == COLOR_MODE_256_GRAY || image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE param.black_white = image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE; if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW && is_multiout) param.channels = 1; else if ((image_prc_param_.bits.multi_out == MULTI_OUT_ALL || image_prc_param_.bits.multi_out == MULTI_COLOR_AND_GRAY ||image_prc_param_.bits.multi_out== MULTI_COLOR_AND_BW) && is_multiout) param.channels = 3; else param.channels = (image_prc_param_.bits.color_mode == COLOR_MODE_24_BITS || image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH) ? 3 : 1; param.color_mode = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? 2 : image_prc_param_.bits.color_mode; param.double_side = img_conf_.is_duplex; param.dpi = img_conf_.resolution_dst; param.cis_image = is_cis_image; //img_conf_.brightness = (float)bright_; //img_conf_.contrast = (float)contrast_; return param; } SANE_Image_Statu hg_scanner::last_usb_image_statu(int err) { SANE_Image_Statu statu = SANE_Image_Statu_OK; if (!is_continue_when_double_paper(double_paper_handle_) && is_save_img_when_double_paper(double_paper_handle_)) { if (err == SCANNER_ERR_DEVICE_DOUBLE_FEEDING) statu = SANE_Image_Statu_Double; //else if (err == SCANNER_ERR_DEVICE_PAPER_JAMMED) //statu = SANE_Image_Statu_Jammed; } return statu; } void hg_scanner::init_settings(const char* json_setting_text) { jsn_children_.clear(); setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text, &jsn_children_); VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ...\n", jsn_children_.size() - 1); notify_setting_result_ = false; for (size_t i = 1; i < jsn_children_.size(); ++i) { std::string v(jsn_children_[i]); if (!setting_jsn_.contains(v.c_str())) continue; std::string val(""); change_string_2_lang_id(v.c_str(), "title"); change_string_2_lang_id(v.c_str(), "desc"); setting_jsn_.at(v.c_str()).at("type").get_to(val); if (val == "string") { change_string_2_lang_id(v.c_str(), "cur"); change_string_2_lang_id(v.c_str(), "default"); if (setting_jsn_.at(v.c_str()).contains("range")) { for (int i = 0; i < setting_jsn_.at(v.c_str()).at("range").size(); ++i) { int id = -1; setting_jsn_.at(v.c_str()).at("range").at(i).get_to(val); id = lang_get_string_id(val.c_str(), true); if (id == -1) { VLOG_MINI_1(LOG_LEVEL_WARNING, "LANGUAGE-ERR: lost item ID of '%s'\n", val.c_str()); } else setting_jsn_.at(v.c_str()).at("range")[i] = id; } } val = get_setting_item_string(v.c_str(), "default"); char* buf = NULL; int size = 0; setting_jsn_.at(v.c_str()).at("size").get_to(size); buf = (char*)malloc(size + 4); bzero(buf, size + 4); strcpy(buf, val.c_str()); set_setting(v.c_str(), buf, val.length()); free(buf); } else if (val == "int") { int n = 0; setting_jsn_.at(v.c_str()).at("default").get_to(n); set_setting(v.c_str(), (char*)&n, sizeof(n)); } else if (val == "float") { double d = .0f; setting_jsn_.at(v.c_str()).at("default").get_to(d); set_setting(v.c_str(), (char*)&d, sizeof(d)); } else if (val == "bool") { bool b = false; setting_jsn_.at(v.c_str()).at("default").get_to(b); set_setting(v.c_str(), (char*)&b, sizeof(b)); } } VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ... OK\n", jsn_children_.size() - 1); if (lang_get_cur_code_page() != DEFAULT_CODE_PAGE) on_language_changed(); notify_setting_result_ = true; } int hg_scanner::init_settings(int pid) { char rel_path[80] = { 0 }; std::string root(hg_log::get_scanner_path()), jsn(""); int ret = 0; sprintf(rel_path, "%ssettings%s%04x.hsc", PATH_SEPARATOR, PATH_SEPARATOR, pid); root += rel_path; ret = load_scanner_setting(root.c_str(), jsn); VLOG_MINI_2(LOG_LEVEL_WARNING, "Apply '%s' setting: %d\n", root.c_str(), ret); if (ret) return SCANNER_ERR_DATA_DAMAGED; init_settings(jsn.c_str()); return SCANNER_ERR_OK; } void hg_scanner::change_string_2_lang_id(const char* name, const char* key) { std::string val(""); int id = -1; if (setting_jsn_.at(name).contains(key)) { setting_jsn_.at(name).at(key).get_to(val); id = lang_get_string_id(val.c_str(), true); if (id == -1) { VLOG_MINI_1(LOG_LEVEL_WARNING, "LANGUAGE-ERR: lost item ID of '%s'\n", val.c_str()); } else setting_jsn_.at(name).at(key) = id; } } std::string hg_scanner::get_setting_item_string(const char* name, const char* key) { std::string ret(""); if (setting_jsn_.at(name).at(key).is_number()) { int n = -1; setting_jsn_.at(name).at(key).get_to(n); ret = hg_log::lang_load(n); } else { setting_jsn_.at(name).at(key).get_to(ret); } return std::move(ret); } int hg_scanner::on_scann_error(int err) { status_ = err; VLOG_MINI_1(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); } int hg_scanner::try_third_app_handle_start(bool& handled) { int ret = SCANNER_ERR_OK; handled = !async_io_; if (handled) { while (wait_usb_result_.try_wait()) std::this_thread::sleep_for(std::chrono::milliseconds(3)); if (!wait_img_.is_waiting() || !wait_usb_.is_waiting() || final_imgs_.size()) { while (final_imgs_.size() == 0) { if (wait_img_.is_waiting() && wait_usb_.is_waiting()) break; std::this_thread::sleep_for(std::chrono::milliseconds(3)); } if (final_imgs_.size() == 0) { final_img_index_ = 0; if (user_cancel_) handled = false; else ret = SCANNER_ERR_DEVICE_NO_PAPER; } } else if (final_img_index_) { final_img_index_ = 0; if (user_cancel_) handled = false; else ret = SCANNER_ERR_DEVICE_NO_PAPER; } else handled = false; } return ret; } int hg_scanner::try_third_app_after_start(int err) { if (!async_io_) { while (wait_img_.is_waiting() && !wait_usb_.is_waiting()) std::this_thread::sleep_for(std::chrono::milliseconds(10)); if (wait_img_.is_waiting() && wait_usb_.is_waiting()) err = status_; } return err; } std::shared_ptr hg_scanner::aquire_memory(int size, bool from_usb) { std::string lead(from_usb ? "usb" : "imgp"), ext(from_usb ? "jpg" : "dat"); unsigned int ind = from_usb ? usb_img_index_ : final_img_index_; std::shared_ptr mem(new tiny_buffer(size, final_path_.c_str(), lead.c_str(), ext.c_str(), ind)); if (!mem->data(0, (unsigned int*)&size)) { mem.reset(); LOG_INFO(LOG_LEVEL_FATAL, "Can't aquire enough memory, working must be stopped!\n"); notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_INSUFFICIENT_MEMORY), SANE_EVENT_ERROR, SCANNER_ERR_INSUFFICIENT_MEMORY); stop(); } return mem; } 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 == SCANNER_ERR_INSUFFICIENT_MEMORY) { user_cancel_ = true; status_ = SCANNER_ERR_INSUFFICIENT_MEMORY; ret = false; } else if (ret == SCANNER_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) { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Memory is too small for aquiring image(%u bytes), wait for ENOUGH ...\n", need_bytes); notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_WAIT_FOR_MEM)); first = false; } std::this_thread::sleep_for(std::chrono::milliseconds(30)); buf = malloc(need_bytes); } if (!first) { if (buf) { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "waited for memory need(%u)\n", need_bytes); } else { VLOG_MINI_1(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, int bits) { if (channels == 3) header->format = SANE_FRAME_RGB; else header->format = SANE_FRAME_GRAY; header->depth = bits >= 8 ? 8 : bits; // 此处指每一个颜色分量的位深,我们的扫描仪固定为“8” header->last_frame = SANE_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 data) { int ret = SCANNER_ERR_OK; unsigned int bytes = data->size(); usb_img_index_++; VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "USB read one picture with %u bytes\n", data->size()); if (dump_usb_path_.length()) { char name[80] = { 0 }; FILE* dst = nullptr; sprintf(name, "%susb_img_%03u.jpg", PATH_SEPARATOR, usb_img_index_); if ((dst = fopen((dump_usb_path_ + name).c_str(), "wb"))) { unsigned int off = 0, len = bytes; unsigned char* buf = data->data(off, &len); while (buf) { fwrite(buf, 1, len, dst); off += len; if (off >= bytes) break; len = bytes - off; buf = data->data(off, &len); } fclose(dst); } } if (!data->swap()) { ret = SCANNER_ERR_OPEN_FILE_FAILED; } else { int num = 0; float Memoryusae = .0f; // hg_log::GetAppMemoryUsage();; size_t que_size = 0; imgs_.Size(&que_size); Memoryusae = que_size / 1024.0f / 1024.0f; if (async_io_) Memoryusae *= 10; else Memoryusae += final_imgs_.mem_usage() / 1024.0f / 1024.0f; while (Memoryusae >= memory_size_ && !user_cancel_ && num < 20)//三个条件以防止卡死 { std::this_thread::sleep_for(std::chrono::milliseconds(500)); //Memoryusae = hg_log::GetAppMemoryUsage(); imgs_.Size(&que_size); Memoryusae = que_size / 1024.0f / 1024.0f; if (async_io_) Memoryusae *= 10; else Memoryusae += final_imgs_.mem_usage() / 1024.0f / 1024.0f; if(num++ == 0) VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Memory Usage is Too big:%f ,Please wait -_- ...\r\n", Memoryusae); } if (num && Memoryusae >= memory_size_ && !user_cancel_) { VLOG_MINI_1(LOG_LEVEL_WARNING, "Warning: memory usage(%.2fMB) maybe leading exception!\r\n", Memoryusae); } imgs_.Put(data, data->size(), hg_scanner_mgr::unique_id()); if (wait_img_.is_waiting()) wait_img_.notify(); } if((serial_ != G10039Serial && serial_ != G20039Serial) || (usb_img_index_ & 1)) ui_ev_cb_((scanner_handle)this, SANE_EVENT_USB_DATA_RECEIVED, NULL, &bytes, NULL); return ret; } int hg_scanner::save_final_image(hg_imgproc::LPIMGHEAD head, void* buf, uint32_t id) { std::string bw(""); final_img_index_++; bool is_1bit = false; if (image_prc_param_.bits.multi_out == MULTI_OUT_ALL && is_multiout) { if(final_img_index_%3 == 0) is_1bit = true; } else if ((image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW||image_prc_param_.bits.multi_out == MULTI_COLOR_AND_BW) && is_multiout) { if(final_img_index_%2 == 0) is_1bit = true; } if ((image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE && !is_multiout) || (is_1bit && is_multiout)) { int old = head->line_bytes; /*/ bw = bmp_821((unsigned char*)buf, head->width, head->height, &head->line_bytes, async_io_, bw_threshold_, is_white_0_); /*/ bw = hg_imgproc::bmp8_2_1bit((unsigned char*)buf, head->width, head->height, head->line_bytes, bw_threshold_, is_white_0_, async_io_); head->line_bytes = bw.length() / head->height;////////*////////// buf = &bw[0]; head->channels = head->bits = 1; head->total_bytes = head->line_bytes * head->height; VLOG_MINI_5(LOG_LEVEL_DEBUG_INFO, "convert to 1-bit bmp(%d * %d), total = %u, len = %u , black_white_image_threshold_ =%d\n", head->width, head->height, head->total_bytes, bw.length(), bw_threshold_); } if (async_io_) { SANE_Image img; ZERO_STRUCT(&img); copy_to_sane_image_header(&img.header, head->width, head->height, head->line_bytes, head->channels, head->bits); img.data = (unsigned char*)buf; img.bytes = head->total_bytes; img.flag.statu = head->statu; img.flag.dpi = resolution_; img.src_id = id; if (img.flag.statu) { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "some error with final image: %s\n", hg_scanner_image_statu_name(img.flag.statu)); } return ui_ev_cb_((scanner_handle)this, SANE_EVENT_IMAGE_OK, &img, &final_img_index_, NULL); } if (final_imgs_.put(head->width, head->height, head->bits, head->channels, head->line_bytes, buf, head->total_bytes , final_path_.c_str(), "final", "dat", final_img_index_, id)) return SCANNER_ERR_OK; else return SCANNER_ERR_INSUFFICIENT_MEMORY; } void hg_scanner::adjust_filling_hole(LPSCANCONF conf) { int maxval = 0; #define SET_FILL_HOLE(member, me) \ conf->fillholeratio_##member = isremove_##me##_hole ? isremove_##me##_hole_threshold * 100 + .5f : 0; \ if(conf->fillholeratio_##member < 0) \ conf->fillholeratio_##member = 0; \ else if(conf->fillholeratio_##member > 50) \ conf->fillholeratio_##member = 50; \ if(maxval < conf->fillholeratio_##member) \ maxval = conf->fillholeratio_##member; SET_FILL_HOLE(up, top); SET_FILL_HOLE(down, low); SET_FILL_HOLE(left, left); SET_FILL_HOLE(right, right); if (maxval) { conf->fillhole.is_fillhole = true; conf->fillhole.fillholeratio = maxval; } } int hg_scanner::is_running(void) { if (!scan_life_) return THREAD_RUNNING_IDLE; int run = THREAD_RUNNING_IDLE; if (!wait_usb_.is_waiting()) run |= THREAD_RUNNING_USB; if (!wait_img_.is_waiting()) run |= THREAD_RUNNING_IMAGE; return run; } int hg_scanner::reset_io(usb_io* io) { online_ = false; if (!io) return SCANNER_ERR_INVALID_PARAMETER; { std::lock_guard lock(io_lock_); usb_io* old = io_; io->add_ref(); io_ = io; status_ = io_->last_error(); online_ = status_ == SCANNER_ERR_OK; if (old) old->release(); } on_device_reconnected(); return SCANNER_ERR_OK; } int hg_scanner::io_disconnected(void) { std::lock_guard lock(io_lock_); online_ = false; io_->on_disconnected(); return SCANNER_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; is_white_0_ = !async_io_; } void hg_scanner::set_read_over_with_no_data(bool no_data) { read_over_with_no_data_ = no_data; } int hg_scanner::get_pid(void) { std::lock_guard lock(io_lock_); return io_->get_pid(); } int hg_scanner::get_vid(void) { std::lock_guard lock(io_lock_); return io_->get_vid(); } int hg_scanner::close(bool force) { int ret = on_scanner_closing(force); online_ = false; if (ret == SCANNER_ERR_OK) { run_ = false; wait_usb_.notify(); wait_img_.notify(); wait_devsislock_.notify(); if(!scan_life_) { std::lock_guard lock(io_lock_); if (io_) { io_->close(); io_->release(); io_ = NULL; } } else if (io_) { LOG_INFO(LOG_LEVEL_WARNING, "close scanner: USB thread or Image thread is still running.\n"); io_->close(); while (scan_life_) std::this_thread::sleep_for(std::chrono::milliseconds(5)); io_->release(); io_ = NULL; } status_ = SCANNER_ERR_NOT_OPEN; } return ret; } int hg_scanner::set_setting(const char* name, void* data, int len) { int ret = SCANNER_ERR_OUT_OF_RANGE; bool hit = false; std::string real_n(setting_name_from(name)); if (real_n.empty()) return ret; hit = setting_map_.count(real_n) > 0; if (hit) { ret = (this->*setting_map_[real_n])(data); } else { VLOG_MINI_1(LOG_LEVEL_WARNING, "Setting '%s' is not found in base setting functions.\n", name); ret = set_setting_value(real_n.c_str(), data, len); } if (ret == SCANNER_ERR_OK || ret == SCANNER_ERR_NOT_EXACT || ret == SCANNER_ERR_CONFIGURATION_CHANGED || ret == SCANNER_ERR_RELOAD_IMAGE_PARAM || ret == SCANNER_ERR_RELOAD_OPT_PARAM) { std::string type(""), name(get_setting_item_string(real_n.c_str(), "title")); setting_jsn_.at(real_n).at("type").get_to(type); // setting_jsn_.at(real_n).at("title").get_to(name); if (type == "string") { int id = lang_get_string_id((char*)data, false); if (id == -1) setting_jsn_.at(real_n).at("cur") = (char*)data; else setting_jsn_.at(real_n).at("cur") = id; type = (char*)data; } else if (type == "int") { char sn[20] = { 0 }; setting_jsn_.at(real_n).at("cur") = *((int*)data); sprintf(sn, "%d", *((int*)data)); type = sn; } else if (type == "float") { char sn[20] = { 0 }; setting_jsn_.at(real_n).at("cur") = *((double*)data); sprintf(sn, "%f", *((double*)data)); type = sn; } else if (type == "bool") { setting_jsn_.at(real_n).at("cur") = *((bool*)data); type = *((bool*)data) ? "true" : "false"; } /*if (notify_setting_result_) { name.insert(0, "\350\256\276\347\275\256 \""); name += "\" \345\200\274\344\270\272\""; name += type + "\" \346\210\220\345\212\237\343\200\202"; notify_ui_working_status(name.c_str()); }*/ } else if (notify_setting_result_) { /*std::string n(""); if (setting_jsn_.contains(real_n)) { setting_jsn_.at(real_n).at("title").get_to(n); } else n = std::string("\350\256\276\347\275\256\351\241\271") + real_n; n.insert(0, "\350\256\276\347\275\256 \""); n += std::string("\" \345\200\274\345\244\261\350\264\245: ") + hg_scanner_err_name(ret); notify_ui_working_status(n.c_str());*/ } return ret; } int hg_scanner::get_setting(const char* name, char* json_txt_buf, int* len, int* id) { if (!len) return SCANNER_ERR_INVALID_PARAMETER; std::string real_n(setting_name_from(name, id)); if (name == nullptr) { *len = setting_jsn_.size(); return SCANNER_ERR_OK; } else if (real_n.empty()) { return SCANNER_ERR_OUT_OF_RANGE; } else if (!setting_jsn_.contains(real_n)) { VLOG_MINI_1(LOG_LEVEL_FATAL, "!!!option(%s) is not found.\n", real_n.c_str()); return SCANNER_ERR_OUT_OF_RANGE; } else { //json_name.find(real_n) //auto it = json_name.find(real_n); //if (it != json_name.end()) //{ // int i = it->second; // // const char* load = hg_log::lang_load(i); // if (*load) // { // setting_jsn_.at(real_n).at("title") = load; // } // //} std::string text(setting_jsn_.at(real_n).dump()); text.insert(0, "\"" + real_n + "\":"); if (*len <= text.length()) { *len = text.length() + 8; return SCANNER_ERR_INSUFFICIENT_MEMORY; } else { strcpy(json_txt_buf, text.c_str()); *len = text.length(); return SCANNER_ERR_OK; } } } std::string hg_scanner::name(void) { return name_; } int hg_scanner::status(void) { if (!wait_usb_.is_waiting() || !wait_img_.is_waiting()) return SCANNER_ERR_DEVICE_BUSY; else return status_; } bool hg_scanner::is_online(void) { return online_; } void hg_scanner::on_language_changed(void) { // change the 'size' member of string settings ... for (size_t i = 1; i < jsn_children_.size(); ++i) { std::string v(jsn_children_[i]); if (!setting_jsn_.contains(v.c_str())) continue; std::string val(""); setting_jsn_.at(v.c_str()).at("type").get_to(val); if (val != "string") continue; if (setting_jsn_.at(v.c_str()).contains("range")) { int old = 0, now = 0; setting_jsn_.at(v.c_str()).at("size").get_to(old); for (int i = 0; i < setting_jsn_.at(v.c_str()).at("range").size(); ++i) { int id = -1; if (setting_jsn_.at(v.c_str()).at("range").at(i).is_number()) { setting_jsn_.at(v.c_str()).at("range").at(i).get_to(id); val = hg_log::lang_load(id); } else setting_jsn_.at(v.c_str()).at("range").at(i).get_to(val); if (now < val.length()) now = val.length(); } now += 15; now /= 8; now *= 8; if (now > old) { setting_jsn_.at(v.c_str()).at("size") = now; VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change size of '%s' from %d to %d\n", v.c_str(), old, now); } } } } int hg_scanner::start(void) { user_cancel_ = false; return status_; } int hg_scanner::get_image_info(SANE_Parameters* ii) { int ret = SCANNER_ERR_OK; IMH imh; fetching_id_ = -1; bzero(&imh, sizeof(imh)); bzero(ii, sizeof(*ii)); 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 = SCANNER_ERR_NO_DATA; else { if (!final_imgs_.front(&imh)) ret = SCANNER_ERR_NO_DATA; else { copy_to_sane_image_header(ii, imh.width, imh.height, imh.line_bytes, imh.channels, imh.bits); fetching_id_ = imh.src_id; } } if (ret == SCANNER_ERR_NO_DATA /*&& final_img_index_ == 0*/) { //if (status_ != SCANNER_ERR_OK && status_ != SCANNER_ERR_DEVICE_BUSY) // ret = SCANNER_ERR_NO_DATA; //else { ii->depth = image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE ? 1 : 8; ii->last_frame = SANE_TRUE; ii->format = image_prc_param_.bits.color_mode == COLOR_MODE_24_BITS || image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? SANE_FRAME_RGB : SANE_FRAME_GRAY; SIZE paper = paper_size(image_prc_param_.bits.paper); ii->pixels_per_line = paper.cx * 1.0f / 25.4 * resolution_ + .5f; ii->lines = paper.cy * 1.0f / 25.4 * resolution_ + .5f; ii->bytes_per_line = ii->format == SANE_FRAME_RGB ? ii->pixels_per_line * 3 : ii->pixels_per_line; if (ii->bytes_per_line > ii->pixels_per_line) imh.bits = 24; else imh.bits = 8; ret = SCANNER_ERR_OK; } } VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "Get image info(%d * %d * %d) = %s\n", ii->pixels_per_line, ii->lines, imh.bits, hg_scanner_err_name(ret)); return ret; } int hg_scanner::read_image_data(unsigned char* buf, int* len) { if (!len) return SCANNER_ERR_INVALID_PARAMETER; if (!buf) { IMH imh; final_imgs_.front(&imh); *len = imh.bytes; return SCANNER_ERR_INSUFFICIENT_MEMORY; } if (final_imgs_.size() > 0) { int fetch = *len; bool over = false; final_imgs_.fetch_front(buf, len, &over); if (over) { if (read_over_with_no_data_) return SCANNER_ERR_NO_DATA; } return SCANNER_ERR_OK; } else { *len = 0; return SCANNER_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) { //SANE_Bool devs_status = false; //int ret = get_scan_is_sleep(devs_status); //if (ret == SCANNER_ERR_OK) //{ // if (!devs_status) // { // if (pid_ == 0x239 || pid_ == 0x402) // { // set_notify_sleep(); // } // return SCANNER_ERR_DEVICE_SLEEPING; // } //} if (code == IO_CTRL_CODE_RESTORE_SETTINGS) { int ret = invoke_setting_xxx(&hg_scanner::setting_restore, data); if (ret == SCANNER_ERR_OK) ret = SCANNER_ERR_CONFIGURATION_CHANGED; return ret; } else if (code == IO_CTRL_CODE_GET_DEFAULT_VALUE) { if (*len == 0) { *len = setting_jsn_.size(); return SCANNER_ERR_OK; } else if (*len > setting_jsn_.size()) { return SCANNER_ERR_OUT_OF_RANGE; } else if(*len < jsn_children_.size()) { if (get_default_value(data, &setting_jsn_.at(jsn_children_[*len]))) return SCANNER_ERR_OK; else return SCANNER_ERR_DATA_DAMAGED; } else { return SCANNER_ERR_DATA_DAMAGED; } } else if (code == IO_CTRL_CODE_SET_CLEAR_ROLLER_COUNT) { int val = 0, ret = get_roller_num(val); if (len) *len = val; return set_clear_roller_num(); } else if (code == IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT) { SANE_FinalImgFormat* fmt = (SANE_FinalImgFormat*)data; if (!fmt) { *len = sizeof(SANE_FinalImgFormat); return SCANNER_ERR_INSUFFICIENT_MEMORY; } if (img_type_ == ".bmp") fmt->img_format = SANE_IMAGE_TYPE_BMP; else if (img_type_ == ".jpg") fmt->img_format = SANE_IMAGE_TYPE_JPG; else if (img_type_ == ".png") fmt->img_format = SANE_IMAGE_TYPE_PNG; else if (img_type_ == ".gif") fmt->img_format = SANE_IMAGE_TYPE_GIF; else fmt->img_format = SANE_IMAGE_TYPE_BMP; return SCANNER_ERR_OK; } 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_GET_FINAL_COMPRESSION) { *(int*)data = SANE_COMPRESSION_NONE; return SCANNER_ERR_OK; } else if (code == IO_CTRL_CODE_SET_FINAL_COMPRESSION) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } 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 (fw.empty()) { return SCANNER_ERR_NO_DATA; } if (*len < fw.size() + 1) { *len = fw.size() + 1; return SCANNER_ERR_INSUFFICIENT_MEMORY; } if (data && fw.length()) strcpy((char*)data, fw.c_str()); return SCANNER_ERR_OK; } else if(code == IO_CTRL_CODE_GET_SERIAL) { std::string ser = get_serial_num(); if (*len < ser.size() + 1) { *len = ser.size() + 1; return SCANNER_ERR_INSUFFICIENT_MEMORY; } if(data && ser.length()) strcpy((char*)data, ser.c_str()); return SCANNER_ERR_OK; } else if (code == IO_CTRL_CODE_GET_IP) { std::string ip = get_ip(); if (*len < ip.size() + 1) { *len = ip.size() + 1; return SCANNER_ERR_INSUFFICIENT_MEMORY; } if(data && ip.length()) strcpy((char*)data, ip.c_str()); return SCANNER_ERR_OK; } 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 = SCANNER_ERR_OK; if (*len < sizeof(int *)) { *len = sizeof(int *); return SCANNER_ERR_INSUFFICIENT_MEMORY; } ret = get_sleep_time(val); if (ret == SCANNER_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 SLEEP_TIME_0MIN: if (pid_ == 0x300 || pid_ == 0x400) val = INT_MAX; //3288不休眠 else val = -1; //不休眠 -1 3399 break; case SLEEP_TIME_5MIN: val = 5; break; case SLEEP_TIME_10MIN: val = 10; break; case SLEEP_TIME_30MIN: val = 30; break; case SLEEP_TIME_60MIN: val = 60; break; case SLEEP_TIME_120MIN: val = 120; break; case SLEEP_TIME_240MIN: val = 240; break; case SANE_POWER_SHUTDOWN: return set_devshtudown(); case SANE_POWER_RESTART: return set_devreboot(val); default: val = -1; break; } sleeptime = val; if (val != -1 && val != INT_MAX) { sleeptime = val * 60; } 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_)); if (len) *len = image_prc_param_.bits.color_mode; return SCANNER_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 SCANNER_ERR_OK; } else if(code == IO_CTRL_CODE_DISPLAY_APP_HELP) { //setting_help(data); return SCANNER_ERR_OK; } else if (code == IO_CTRL_CODE_GET_IMAGE_QUEUE_COUNT) { *len = final_imgs_.size(); return wait_img_.is_waiting() && wait_usb_.is_waiting() ? SCANNER_ERR_NO_DATA : SCANNER_ERR_OK; } else if (code == IO_CTRL_CODE_GET_PAPER_SIZE) { std::string name((char*)data); int paper = match_best_paper(name, NULL); SIZE size = paper_size(paper); *len = (size.cx & 0x0ffff) | ((size.cy & 0x0ffff) << 16); return SCANNER_ERR_OK; } else if (code == IO_CTRL_CODE_CONVERT_IMAGE_FORMAT) { SANE_ImageFormatConvert *conv = (SANE_ImageFormatConvert*)data; void* threshold = conv->dst.fmt.compress.detail; int ret = SCANNER_ERR_OK; conv->dst.fmt.compress.detail = (void*)bw_threshold_; ret = hg_imgproc::convert_image_file(conv); conv->dst.fmt.compress.detail = threshold; return ret; } else if (code == IO_CTRL_CODE_FREE_MEMORY) { free_memory(data); return SCANNER_ERR_OK; } else if(code == IO_CTRL_CODE_GET_LOG_FILE && len && *len == LOG_FILE_DEVICE) { string str; int ret = get_device_log(str); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "str = %d\n", str.length()); *(char*)data = 0; if (ret != SCANNER_ERR_OK) { return ret; } strcpy((char*)data, str.c_str()); return 0; } else if(code == IO_CTRL_CODE_SET_SCAN_LOCK_CHECK_VAL) { string str = (char*)data; return set_scan_lock_check_val(str); } else if (code == IO_CTRL_CODE_SET_SCAN_LOCK) { SANE_Bool set_islock = *((SANE_Bool *)data); //set_scan_islock(set_islock); return SCANNER_ERR_DEVICE_NOT_SUPPORT; } else if (code == IO_CTRL_CODE_GET_SCAN_ISLOCK) { SANE_Bool islock = *((SANE_Bool*)data); int ret = get_scan_islock(islock); *((SANE_Bool*)data) = islock; VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "io ctrl islock:%d\r\n", *((SANE_Bool*)data)); return ret; } else if (code == IO_CTRL_CODE_SET_FIRMWARE_UPGRADE) { string str = (char*)data; return set_firmware_upgrade(str); } else if (code == IO_CTRL_CODE_GET_HISTORY_SCAN_NUM) { int num = 0; int ret = get_history_scan_count(num); (*(int*)data) = num; return ret; } else if (code == IO_CTRL_CODE_GET_CLEAN_PAPER_ROAD) { return set_clean_paper_road(); } else if (code == IO_CTRL_CODE_GET_ROLLER_NUM) { int num = 0; int ret = get_roller_num(num); (*(int*)data) = num; return ret; } else if (code == IO_CTRL_CODE_SET_FEEDMODE) { return on_set_feedmode(*((int*)data)); } else if (code == IO_CTRL_CODE_SET_SKEW_CHECK) { return on_skew_check_changed(*((bool*)data)); } else if (code == IO_CTRL_CODE_SET_SKEW_CHECK_VAL) { return on_skew_check_level_changed(*((int*)data)); } else if (code == IO_CTRL_CODE_GET_IS_MODE) { return get_scan_mode(*((bool*)data)); } else if (code == IO_CTRL_CODE_SET_ULTRASONIC_MODULE) { return on_ultrasonic_check_changed(*((bool*)data)); } else if (code == IO_CTRL_CODE_SET_SPEED_MODE) { return set_speed_mode(*((int*)data)); } else if (code == IO_CTRL_CODE_GET_SPEED_MODE) { return get_speed_mode(*((int*)data)); } else if (code == IO_CTRL_CODE_SET_CIS_IMAGE) { return on_cis_get_image(*((bool*)data)); } else if(code == IO_CTRL_CODE_GET_IMAGE) { return start();; } else if (code == IO_CTRL_CODE_SET_DISTORTION_IMAGE) { return set_distortion_image(*((bool*)data)); } else if(code == IO_CTRL_CODE_GET_DISTORTION_CHECK_VAL) { if (distortion_val.h > 0) { *(SANE_DISTORTION_VAL*)data = distortion_val; } return SCANNER_ERR_OK; //return get_distortion_check_val(*((int*)data)); } else if(code == IO_CTRL_CODE_SET_DISTORTION_CHECK_VAL) { return set_distortion_check_val(*((int*)data)); } else if (code == IO_CTRL_CODE_GET_DISTORTION_DEVS_CHECK_VAL) { return get_devs_distortion_check_val(*((int*)data)); } else if(code == IO_CTRL_CODE_SET_DEVS_REBOOT) { return set_devreboot(*((int*)data)); } else if (code == IO_CTRL_CODE_SET_AUTO_FALT) { is_auto_falt = true; return set_auto_flat(); } else if (code == IO_CTRL_CODE_SET_COLOR) { return setting_color_mode(data); } else if (code == IO_CTRL_CODE_SET_DPI) { return setting_resolution(data); } else if (code == IO_CTRL_CODE_SET_VIDPID) { int num = *((int*)data); return set_vid_pid(num); } else if (code == IO_CTRL_CODE_SET_SERIAL) { string str = (char*)data; return set_serial_num((char*)data); } else if (code == IO_CTRL_CODE_GET_VIDPID) { int num = 0; int ret = get_vid_pid(num); (*(int*)data) = num; return ret; } return SCANNER_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; } std::string hg_scanner::get_device_model(void) { return BRAND_DEVICE_NOT_SUPPORT; } int hg_scanner::get_roller_num(int &val) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_device_log(string &log) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_devreboot(int data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_devshtudown() { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_clear_roller_num(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_history_scan_count(int &num) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_scan_islock(SANE_Bool set_islock) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scan_islock(SANE_Bool& islock) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_scan_lock_check_val(string check_str) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_firmware_upgrade(std::string filename) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_clean_paper_road() { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_dev_islock_file(int& islockfile) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_dev_islock_file(int islockfile) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scan_mode(bool& type) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_speed_mode(int data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_speed_mode(int& data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_distortion_image(bool type) { is_dpi_color_check = type; int ret = SCANNER_ERR_OK; if (type) { ret = set_leaflet_scan(); } return ret; } int hg_scanner::get_distortion_check_val(int &val) { val = *(int*)&save_dpi_color_check_val; //val = ; if (val != 0) { return SCANNER_ERR_NO_DATA; } return 0; } int hg_scanner::set_distortion_check_val(int data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_devs_distortion_check_val(int& data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_auto_flat(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_serial_num(string str) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_vid_pid(int data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_vid_pid(int& data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } ////////////////////////////////////////////////////////////////////////////////////////////////////// int hg_scanner::set_leaflet_scan(void) { return SCANNER_ERR_NO_DATA; } int hg_scanner::get_abuot_info(void) { return SCANNER_ERR_NO_DATA; } int hg_scanner::restore_default_setting(void) { return SCANNER_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 SCANNER_ERR_INVALID_PARAMETER; case SANE_IMAGE_TYPE_WEBP: return SCANNER_ERR_INVALID_PARAMETER; case SANE_IMAGE_TYPE_PDF: return SCANNER_ERR_INVALID_PARAMETER; case SANE_IMAGE_TYPE_GIF: return SCANNER_ERR_INVALID_PARAMETER; case SANE_IMAGE_TYPE_SVG: return SCANNER_ERR_INVALID_PARAMETER; default: img_type_ = ".bmp"; break; } return SCANNER_ERR_OK; } int hg_scanner::get_compression_format(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_compression_format(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_auto_color_type(void) { is_auto_matic_color = true; return SCANNER_ERR_OK; } int hg_scanner::get_device_code(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_sleep_time(int& data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_sleep_time(int data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_notify_sleep() { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scanner_paperon(SANE_Bool& paperon) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scan_is_sleep(SANE_Bool& data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id) { if (!buffer.get() || !ImagePrc_pHandle_) { return; } int ret = SCANNER_ERR_OK; hg_imgproc::IMGPRCPARAM param = get_image_process_object(pid_); hg_imgproc::IMGHEAD ih; int err = SCANNER_ERR_OK, index = 0; void* buf = NULL; hg_imgproc::load_buffer(ImagePrc_pHandle_, buffer); hg_imgproc::decode(ImagePrc_pHandle_, pid_, &img_conf_, ¶m); (this->*dump_img_)(ImagePrc_pHandle_, "decode"); if (is_dpi_color_check) { CISTestImageProcess::CISTestResult res; err = hg_imgproc::cis_test_image(ImagePrc_pHandle_, res); distortion_val.h = res.h; distortion_val.w = res.w; distortion_val.scaleXY = res.scaleXY; save_dpi_color_check_val = res.scaleXY; is_dpi_color_check = false; VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Set distortion val is:h:%f w:%f distortion val is:%f\n", distortion_val.h, distortion_val.w, distortion_val.scaleXY); } else if (param.cis_image || (img_conf_.papertype == TwSS::MaxSize && pid_ == 0x0300 && is_kernelsnap3288_230210_)) { printf("cis 原图测试无需任何算法\r\n"); } else { if ((isremove_left_hole || isremove_right_hole || isremove_top_hole || isremove_low_hole) && (pid_ != 0x239 && pid_ != 0x439)) { //ret = hg_imgproc::fillhole(ImagePrc_pHandle_, isremove_top_hole_threshold, isremove_low_hole_threshold, isremove_left_hole_threshold, isremove_right_hole_threshold); double left = isremove_left_hole ? isremove_left_hole_threshold : 0; double right = isremove_right_hole ? isremove_right_hole_threshold : 0; double top = isremove_top_hole ? isremove_top_hole_threshold : 0; double low = isremove_low_hole ? isremove_low_hole_threshold : 0; ret = hg_imgproc::fillhole(ImagePrc_pHandle_, top, low, left, right); (this->*dump_img_)(ImagePrc_pHandle_, "fillhole"); VLOG_MINI_1(LOG_LEVEL_WARNING, "Image proc fillhole is:%d\n", ret); } if (pid_ != 0x239 && pid_ != 0x439) { float dpi3288 = 0.0; if (is_kernelsnap3288_221106_ && pid_==0x300) dpi3288 = (img_conf_.resolution_dst >= 300) ? 300 : 200; else if (is_kernelsnap3288_230210_ && pid_==0x300) dpi3288 = (img_conf_.resolution_dst == 600) ? 600 : (img_conf_.resolution_dst < 600 && img_conf_.resolution_dst >= 300) ? 300 : 200; else dpi3288 = 200; ret = hg_imgproc::auto_crop(ImagePrc_pHandle_, dpi3288); (this->*dump_img_)(ImagePrc_pHandle_, "auto_crop"); } if ((img_conf_.is_autodiscradblank_normal || img_conf_.is_autodiscradblank_vince) && (pid_ != 0x239 && pid_ != 0x439)) { ret = hg_imgproc::discardBlank(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "discardBlank"); } if (img_conf_.fadeback) //239 { hg_imgproc::fadeback(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "fadeback"); } if ( (((img_conf_.resolution_dst != img_conf_.resolution_native) && (pid_ == 0x300 || pid_ == 0x0400)) && !is_kernelsnap3288_221106_ && !is_kernelsnap3288_230210_ ) || (pid_ == 0x300 && is_kernelsnap3288_221106_ && img_conf_.resolution_dst != 200 && img_conf_.resolution_dst != 300) || (pid_ == 0x300 && is_kernelsnap3288_230210_ && img_conf_.resolution_dst != 200 && img_conf_.resolution_dst != 300 && img_conf_.resolution_dst != 600)) { float dpi3288 = 0.0; dpi3288 = (img_conf_.resolution_dst >= 300 && (is_kernelsnap3288_221106_ || is_kernelsnap3288_230210_)) ? 300 : 200; hg_imgproc::resolution_change(ImagePrc_pHandle_, dpi3288); (this->*dump_img_)(ImagePrc_pHandle_, "resolution_change"); } if ((img_conf_.cropRect.enable && !img_conf_.is_autocrop) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::croprect(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "resolution_change"); } if ((img_conf_.filter != ColorFilter::FILTER_NONE && (image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE || image_prc_param_.bits.color_mode == COLOR_MODE_256_GRAY)) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::channel(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "filter"); } { adjust_color(ImagePrc_pHandle_); //色调曲线 普通dsp版本需要矫正颜色 (this->*dump_img_)(ImagePrc_pHandle_, "adjust_color"); } if ((img_conf_.pixtype == COLOR_MODE_24_BITS && img_conf_.hsvcorrect) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::answerSheetFilterRed(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "answerSheetFilterRed"); } if ((img_conf_.refuseInflow) && (pid_ != 0x239 && pid_ != 0x439)) { int lv = 5; if (image_prc_param_.bits.is_permeate_lv_ == 0) lv = 5; else if (image_prc_param_.bits.is_permeate_lv_ == 1) lv = 15; else if (image_prc_param_.bits.is_permeate_lv_ == 2) lv = 25; else if (image_prc_param_.bits.is_permeate_lv_ == 3) lv = 35; else if (image_prc_param_.bits.is_permeate_lv_ == 4) lv = 45; hg_imgproc::antiInflow(ImagePrc_pHandle_, lv); (this->*dump_img_)(ImagePrc_pHandle_, "antiInflow"); } if ((img_conf_.colorCorrection && img_conf_.pixtype != COLOR_MODE_BLACK_WHITE) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::colorCorrection(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "colorCorrection"); } if (((img_conf_.imageRotateDegree != TEXT_DIRECTION_0 || img_conf_.is_backrotate180) && (!img_conf_.is_autotext)) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::orentation(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "orentation"); } if ((img_conf_.removeMorr) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::textureRemove(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "textureRemove"); } if ((img_conf_.detachnoise.is_detachnoise) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::nosieDetach(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "nosieDetach"); } if ((img_conf_.pixtype == COLOR_MODE_BLACK_WHITE) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::errorextention(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "errorextention"); } if (((img_conf_.en_fold && pid_ != 0x239 && pid_ != 0x439))) { hg_imgproc::fold(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "fold"); } if (img_conf_.multi_output_red && img_conf_.pixtype == COLOR_MODE_24_BITS)//239 { err = hg_imgproc::multi_out_red(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "multi_out_red"); } if ((img_conf_.sharpen) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::sharpenType(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "sharpenType"); } if (image_prc_param_.bits.split) //239 { split3399_++; err = hg_imgproc::split(ImagePrc_pHandle_,split3399_); (this->*dump_img_)(ImagePrc_pHandle_, "split"); } if (!img_conf_.splitImage && !img_conf_.multi_output_red && !is_multiout) //239 { if (img_conf_.automaticcolor) { hg_imgproc::auto_matic_color(ImagePrc_pHandle_, img_conf_.automaticcolortype); (this->*dump_img_)(ImagePrc_pHandle_, "auto_matic_color"); } } if (img_conf_.is_autotext)//239 { //hg_imgproc::ocr_auto_txtdirect(ImagePrc_pHandle_); hg_imgproc::tesseract_auto_txtdirect(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "ocr_auto_txtdirect"); } if (is_quality_ == IMG_SPEED && resolution_ >= 300)//239 { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "set resolution_ is :%d\n", resolution_) err = hg_imgproc::quality(ImagePrc_pHandle_, resolution_); (this->*dump_img_)(ImagePrc_pHandle_, "quality"); } if (is_multiout)//239 { int multi_out = img_conf_.multiOutput; err = hg_imgproc::multi_out(ImagePrc_pHandle_, multi_out); (this->*dump_img_)(ImagePrc_pHandle_, "multi_out"); } } hg_imgproc::final(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "final"); while (hg_imgproc::get_final_data(ImagePrc_pHandle_, &ih, &buf, index++) == SCANNER_ERR_OK) { VLOG_MINI_5(LOG_LEVEL_DEBUG_INFO, "Final picture %d (%d * %d * %d) with %u bytes!\n", index , ih.width, ih.height, ih.bits * ih.channels, ih.total_bytes); if (!img_type_.empty()) { std::vectorbmpdata; //cv::imencode(img_type_,*((cv::Mat*)buf),bmpdata); hg_imgproc::imgtypechange(ImagePrc_pHandle_, img_type_, buf, bmpdata); if (bmpdata.empty()) { status_ = SCANNER_ERR_NO_DATA; return; } buf = bmpdata.data(); ih.total_bytes = bmpdata.size(); VLOG_MINI_6(LOG_LEVEL_DEBUG_INFO, "Set img type is:%s Final picture %d (%d * %d * %d) with %u bytes!\n", img_type_.c_str(), index , ih.width, ih.height, ih.bits * ih.channels, ih.total_bytes); } if (id == -1) id = hg_scanner_mgr::unique_id(); save_final_image(&ih, buf, id); id = -1; } } int hg_scanner::image_configuration(SCANCONF& ic) { int ret = 0; ic.papertype = paper_size_; if (is_lateral(image_prc_param_.bits.paper)) ic.paperAlign = Rot270; else ic.paperAlign = Rot0; //{ //子类处理 //ic.en_sizecheck = dev_conf_.params_3399.enable_sizecheck; //if (image_prc_param_.bits.text_direction != TEXT_DIRECTION_AUTO) // ic.imageRotateDegree = (float)image_prc_param_.bits.text_direction; //else // ic.imageRotateDegree = 0; //ic.imageRotateDegree *= 90.0f; //} ic.is_duplex = (image_prc_param_.bits.page == PAGE_DOUBLE || image_prc_param_.bits.page == PAGE_OMIT_EMPTY || image_prc_param_.bits.page == PAGE_OMIT_EMPTY_RECEIPT || image_prc_param_.bits.page == PAGE_FOLIO); if (is_dpi_color_check) { ic.is_duplex = false; } ic.en_fold = (image_prc_param_.bits.page == PAGE_FOLIO); ic.pixtype = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? 2 : image_prc_param_.bits.color_mode; ic.automaticcolor = is_auto_matic_color; ic.automaticcolortype = 1;// ic.pixtype; //存疑 ic.resolution_dst = (resolution_ >= 300) ? (is_quality_ == IMG_SPEED ? 200 : resolution_) : resolution_; //if (resolution_ >= 300) //{ // if (is_quality_ == IMG_SPEED) // ic.resolution_dst = 200; // else // ic.resolution_dst = resolution_; //} //else // ic.resolution_dst = resolution_; ic.resolution_native = 200.0f; ic.gamma = (float)gamma_; { //子类处理 /*ic.contrast = (contrast_ - 4) * 333.0; ic.brightness = (bright_ - 128) * (2000.0 / 254.0);*/ } ic.threshold = threshold_; ic.is_autocontrast = 0; //无参数 ic.is_autocrop = (ic.papertype == TwSS::None || ic.papertype == TwSS::USStatement); ic.is_autodiscradblank_normal = image_prc_param_.bits.page == PAGE_OMIT_EMPTY; ic.discardblank_percent = omit_empty_level_; ic.is_autodiscradblank_vince = image_prc_param_.bits.page == PAGE_OMIT_EMPTY_RECEIPT; ic.is_switchfrontback = image_prc_param_.bits.exchange; ic.autodescrew = image_prc_param_.bits.automatic_skew; ic.multi_output_red = image_prc_param_.bits.rid_red; //之前加上可能导致超时,或者未知错误不可描述。 ic.hsvcorrect = image_prc_param_.bits.rid_answer_red; ic.sharpen = image_prc_param_.bits.sharpen; //ic.enhance_color = image_prc_param_.bits.rid_color; //加这个会有问题 ic.fillbackground = image_prc_param_.bits.erase_black_frame; ic.is_convex = (image_prc_param_.bits.fill_background == FILL_BKG_CONVEX_POLYGON); if (ic.resolution_dst == 300) ic.noise = anti_noise_ * 1.5; else if (ic.resolution_dst == 600) ic.noise = anti_noise_ * 3; else ic.noise = anti_noise_; ic.indent = margin_; ic.AutoCrop_threshold = threshold_; { //子类处理 //if (test_1_paper_) //{ // LOG_INFO(LOG_LEVEL_DEBUG_INFO, "scanning mode: testing ONE paper ...\n"); // ic.scannum = ic.is_duplex ? 2 : 1; //} //else //{ // if (scan_count_ == -1) // ic.scannum = -1; // else // ic.scannum = (ic.is_duplex ? scan_count_ * 2 : scan_count_); //} } ic.is_backrotate180 = image_prc_param_.bits.rotate_back_180; ic.is_dogeardetection = image_prc_param_.bits.fractate_check; { //子类处理 //ic.hardwarecaps.en_skrewdetect = dev_conf_.params_3399.screw_detect_enable; //ic.hardwarecaps.en_doublefeed = dev_conf_.params_3399.ultrasonic_enable; //ic.hardwarecaps.en_stapledetect = dev_conf_.params_3399.staple_enbale; //ic.hardwarecaps.skrewdetectlevel = dev_conf_.params_3399.screw_detect_level; //ic.hardwarecaps.is_autopaper = dev_conf_.params_3399.is_autopaper; } ic.hardwarecaps.capturepixtype = 0; //暂无参数 获取图像类型 ic.hardwarecaps.lowpowermode = LowPowerMode::Min_None; //暂无参数 设置休眠时间 两个参数3399未使用 ic.fillhole.is_fillhole = image_prc_param_.bits.rid_hole; ic.fillhole.fillholeratio = rid_hole_range_; ic.detachnoise.is_detachnoise = image_prc_param_.bits.noise_optimize; ic.detachnoise.detachnoise = noise_range_; ic.is_autotext = image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO ? 1 : 0; ic.isfillcolor = is_color_fill; ic.refuseInflow = image_prc_param_.bits.is_permeate; ic.colorCorrection = 0; ic.removeMorr = image_prc_param_.bits.remove_morr; ic.errorExtention = image_prc_param_.bits.error_extention;// ic.textureRemove = image_prc_param_.bits.remove_txtture;// ic.splitImage = image_prc_param_.bits.split; { ic.cropRect.enable = custom_area_; int height = (custom_area_br_y_ * ic.resolution_dst) / 25.4 - (custom_area_lt_y_ * ic.resolution_dst / 25.4); int width = (custom_area_br_x_ * ic.resolution_dst) / 25.4 - (custom_area_lt_x_ * ic.resolution_dst / 25.4); ic.cropRect.height = height; ic.cropRect.width = width; ic.cropRect.x = custom_area_lt_x_ * ic.resolution_dst / 25.4; ic.cropRect.y = custom_area_lt_y_ * ic.resolution_dst / 25.4; } ic.multiOutput = (MultiOutput)image_prc_param_.bits.multi_out; ic.normalCrop = image_prc_param_.bits.dark_sample; ic.dogeardistabce = fractate_level_; ic.fadeback = image_prc_param_.bits.erase_bakground; ic.fadebackrange = erase_bkg_range_; ic.isuoloadexceptionimage = pid_ == 0x0439 ? false : (double_paper_handle_ & DOUBLE_PAPER_SAVE_IMG) == DOUBLE_PAPER_SAVE_IMG; adjust_filling_hole(&ic); ic.fold_concatmode = fold_type_; //多流输出优先级最高 if (is_multiout) { ic.pixtype = image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW ? COLOR_MODE_256_GRAY : COLOR_MODE_24_BITS; ic.filter = 3; ic.hsvcorrect = 0; ic.multi_output_red = 0; ic.fadeback = false; ic.sharpen = 0; ic.removeMorr = 0; ic.textureRemove = 0; ic.errorExtention = 0; ic.detachnoise.is_detachnoise = 0; } else if (image_prc_param_.bits.color_mode == COLOR_MODE_24_BITS) { ic.filter = 3; ic.errorExtention = 0; ic.detachnoise.is_detachnoise = 0; } else if (image_prc_param_.bits.color_mode == COLOR_MODE_256_GRAY) { int filter_clr[] = { 3, 0, 1, 2, 5, 6, 7 }; ic.filter = filter_clr[image_prc_param_.bits.rid_color]; if (ic.filter != 3) { ic.pixtype = 2; } ic.multi_output_red = 0; ic.hsvcorrect = 0; ic.fadeback = false; ic.errorExtention = 0; ic.detachnoise.is_detachnoise = 0; } else if (image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE) { int filter_clr[] = { 3, 0, 1, 2, 5, 6, 7 }; ic.filter = filter_clr[image_prc_param_.bits.rid_color]; if (ic.filter != 3) { ic.pixtype = 2; } ic.multi_output_red = 0; ic.hsvcorrect = 0; ic.fadeback = false; ic.sharpen = 0; ic.removeMorr = 0; ic.textureRemove = 0; } else if (image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH) { ic.pixtype = 2; ic.filter = 3; ic.hsvcorrect = 0; ic.multi_output_red = 0; ic.fadeback = false; ic.sharpen = 0; ic.removeMorr = 0; ic.textureRemove = 0; ic.errorExtention = 0; ic.detachnoise.is_detachnoise = 0; } //自定义裁切 if (image_prc_param_.bits.paper == PAPER_AUTO_MATCH || image_prc_param_.bits.paper == PAPER_MAX_SIZE || image_prc_param_.bits.paper == PAPER_MAX_SIZE_CLIP || image_prc_param_.bits.paper == PAPER_TRIGEMINY ) { ic.cropRect.enable = false; } img_conf_ = ic; VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.pixtype=%d", ic.pixtype); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.papertype=%d", ic.papertype); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.AutoCrop_threshold=%d", ic.AutoCrop_threshold); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.autodescrew=%d", ic.autodescrew); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.automaticcolor=%d", ic.automaticcolor); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.brightness=%f", ic.brightness); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.contrast=%f", ic.contrast); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.en_fold=%d", ic.en_fold); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.en_sizecheck=%d", ic.en_sizecheck); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.enhance_color=%d", ic.enhance_color); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.fillbackground=%d", ic.fillbackground); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.filter=%d", ic.filter); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.gamma=%f", ic.gamma); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.hardwarecaps.capturepixtype=%d", ic.hardwarecaps.capturepixtype); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.hardwarecaps.en_doublefeed=%d", ic.hardwarecaps.en_doublefeed); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.hsvcorrect=%d", ic.hsvcorrect); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.imageRotateDegree=%f", ic.imageRotateDegree); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.indent=%d", 5); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_autocontrast=%d", ic.is_autocontrast); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_autocrop=%d", ic.is_autocrop); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_autodiscradblank_normal=%d", ic.is_autodiscradblank_normal); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_autodiscradblank_vince=%d", ic.is_autodiscradblank_vince); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.isfillcolor=%d", ic.isfillcolor); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_autotext=%d", ic.is_autotext); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_backrotate180=%d", ic.is_backrotate180); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_convex=%d", ic.is_convex); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_duplex=%d", ic.is_duplex); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_switchfrontback=%d", ic.is_switchfrontback); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.is_dogeardetection=%d", ic.is_dogeardetection); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.fillhole.multi_output_red=%d", ic.multi_output_red); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.noise=%d", ic.noise); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.pixtype=%d", ic.pixtype); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.resolution_dst=%f", ic.resolution_dst); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.resolution_native=%f", ic.resolution_native); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.scannum=%d", ic.scannum); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.sharpen=%d", ic.sharpen); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.discardblank_percent=%d", ic.discardblank_percent); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.detachnoise.is_detachnoise=%d", ic.detachnoise.is_detachnoise); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.detachnoise.detachnoise=%d\r ", ic.detachnoise.detachnoise); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.detachnoise.refuseInflow=%d\r ", ic.refuseInflow); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.detachnoise.refuseInflow=%d\r ", ic.refuseInflow); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.removeMorr=%d\r ", ic.removeMorr); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.errorExtention=%d\r ", ic.errorExtention); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.textureRemove=%d\r\n ", ic.refuseInflow); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.fillhole.is_fillhole=%d\r\n ", ic.fillhole.is_fillhole); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.ic.fillhole.fillholeratio=%d\r\n ", ic.fillhole.fillholeratio); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.fadeback=%d\r\n ", ic.fadeback); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.cropRect.enable=%d\r ", ic.cropRect.enable); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.cropRect.width=%d\r\n ", ic.cropRect.width); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.cropRect.height=%d\r\n ", ic.cropRect.height); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.cropRect.x=%d\r\n ", ic.cropRect.x); VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "\n ic.cropRect.y=%d\r\n ", ic.cropRect.y); return ret; }