#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 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; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // hg_scanner hg_scanner::hg_scanner(ScannerSerial serial , const char* dev_name, usb_io* io) : 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) , setting_count_(0),img_type_(""), online_(false),is_quality_(-1),is_color_fill(false),is_multiout(false),save_multiout(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), pid_(0), dump_img_(&hg_scanner::dump_image_empty), is_kernelsnap_220830_(false) { final_path_ = hg_log::ini_get("paths", "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; } 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"); 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)); ImagePrc_pHandle_ = hg_imgproc::init(pid_);; } hg_scanner::~hg_scanner() { close(true); if (thread_usb_read_.get() && thread_usb_read_->joinable()) thread_usb_read_->join(); if (thread_img_handle_.get() && thread_img_handle_->joinable()) thread_img_handle_->join(); delete custom_gamma_val_; hg_imgproc::release(ImagePrc_pHandle_); name_.insert(0, "\350\256\276\345\244\207\342\200\234"); name_ += "\342\200\235\345\267\262\347\273\217\345\205\263\351\227\255\343\200\202"; notify_ui_working_status(name_.c_str(), SANE_EVENT_SCANNER_CLOSED); 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::set_setting_map(int sn, const char* name) { std::string val(name); //VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "title: '%s', val: '%s'\n", title, val.c_str()); if (val == SANE_STD_OPT_NAME_RESTORE) setting_map_[sn] = &hg_scanner::setting_restore; else if (val == SANE_STD_OPT_NAME_HELP) setting_map_[sn] = &hg_scanner::setting_help; else if (val == SANE_STD_OPT_NAME_COLOR_MODE) setting_map_[sn] = &hg_scanner::setting_color_mode; else if (val == SANE_STD_OPT_NAME_IS_MULTI_OUT) setting_map_[sn] = &hg_scanner::setting_multi_out; else if (val == SANE_STD_OPT_NAME_MULTI_OUT_TYPE) setting_map_[sn] = &hg_scanner::setting_multi_out_type; else if (val == SANE_STD_OPT_NAME_FILTER) setting_map_[sn] = &hg_scanner::setting_rid_color; else if (val == SANE_STD_OPT_NAME_RID_MULTIOUT_RED) setting_map_[sn] = &hg_scanner::setting_rid_multi_red; else if (val == SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED) setting_map_[sn] = &hg_scanner::setting_rid_answer_red; else if (val == SANE_STD_OPT_NAME_ERASE_BACKGROUND) setting_map_[sn] = &hg_scanner::setting_erase_background; else if (val == SANE_STD_OPT_NAME_BKG_COLOR_RANGE) setting_map_[sn] = &hg_scanner::setting_erase_background_range; else if (val == SANE_STD_OPT_NAME_NOISE_OPTIMIZE) setting_map_[sn] = &hg_scanner::setting_noise_optimize; else if (val == SANE_STD_OPT_NAME_NOISE_SIZE) setting_map_[sn] = &hg_scanner::setting_noise_optimize_range; else if (val == SANE_STD_OPT_NAME_PAPER) setting_map_[sn] = &hg_scanner::setting_paper; else if (val == SANE_STD_OPT_NAME_SIZE_CHECK) setting_map_[sn] = &hg_scanner::setting_paper_check; else if (val == SANE_STD_OPT_NAME_CUSTOM_AREA) setting_map_[sn] = &hg_scanner::setting_is_custom_area; else if (val == SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT) setting_map_[sn] = &hg_scanner::setting_custom_area_left; else if (val == SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT) setting_map_[sn] = &hg_scanner::setting_custom_area_right; else if (val == SANE_STD_OPT_NAME_CUSTOM_AREA_TOP) setting_map_[sn] = &hg_scanner::setting_custom_area_top; else if (val == SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM) setting_map_[sn] = &hg_scanner::setting_custom_area_bottom; else if (val == SANE_STD_OPT_NAME_PAGE) setting_map_[sn] = &hg_scanner::setting_page; else if (val == SANE_STD_OPT_NAME_DISCARD_BLANK_SENS) setting_map_[sn] = &hg_scanner::setting_page_omit_empty; else if (val == SANE_STD_OPT_NAME_RESOLUTION) setting_map_[sn] = &hg_scanner::setting_resolution; else if (val == SANE_STD_OPT_NAME_IMAGE_QUALITY) setting_map_[sn] = &hg_scanner::setting_img_quality; else if (val == SANE_STD_OPT_NAME_EXCHANGE) setting_map_[sn] = &hg_scanner::setting_exchagnge; else if (val == SANE_STD_OPT_NAME_SPLIT) setting_map_[sn] = &hg_scanner::setting_split_image; else if (val == SANE_STD_OPT_NAME_ANTI_SKEW) setting_map_[sn] = &hg_scanner::setting_automatic_skew; else if (val == SANE_STD_OPT_NAME_RID_HOLE) setting_map_[sn] = &hg_scanner::setting_rid_hole; else if (val == SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE) setting_map_[sn] = &hg_scanner::setting_rid_hoe_range; else if (val == SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA) setting_map_[sn] = &hg_scanner::setting_is_custom_gamma; else if (val == SANE_STD_OPT_NAME_BRIGHTNESS) setting_map_[sn] = &hg_scanner::setting_bright; else if (val == SANE_STD_OPT_NAME_CONTRAST) setting_map_[sn] = &hg_scanner::setting_contrast; else if (val == SANE_STD_OPT_NAME_GAMMA) setting_map_[sn] = &hg_scanner::setting_gamma; else if (val == SANE_STD_OPT_NAME_SHARPEN) setting_map_[sn] = &hg_scanner::setting_sharpen; else if (val == SANE_STD_OPT_NAME_DARK_SAMPLE) setting_map_[sn] = &hg_scanner::setting_dark_sample; else if (val == SANE_STD_OPT_NAME_ERASE_BLACK_FRAME) setting_map_[sn] = &hg_scanner::setting_erase_black_frame; else if (val == SANE_STD_OPT_NAME_THRESHOLD) setting_map_[sn] = &hg_scanner::setting_threshold; else if (val == SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL) setting_map_[sn] = &hg_scanner::setting_anti_noise; else if (val == SANE_STD_OPT_NAME_MARGIN) setting_map_[sn] = &hg_scanner::setting_margin; else if (val == SANE_STD_OPT_NAME_FILL_BKG_MODE) setting_map_[sn] = &hg_scanner::setting_filling_background; else if (val == SANE_STD_OPT_NAME_IS_ANTI_PERMEATE) setting_map_[sn] = &hg_scanner::setting_is_permeate; else if (val == SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL) setting_map_[sn] = &hg_scanner::setting_is_permeate_lv; else if (val == SANE_STD_OPT_NAME_RID_MORR) setting_map_[sn] = &hg_scanner::setting_remove_morr; else if (val == SANE_STD_OPT_NAME_ERROR_EXTENSION) setting_map_[sn] = &hg_scanner::setting_error_extention; else if (val == SANE_STD_OPT_NAME_RID_GRID) setting_map_[sn] = &hg_scanner::setting_remove_texture; else if (val == SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK) setting_map_[sn] = &hg_scanner::setting_ultrasonic_check; else if (val == SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE) setting_map_[sn] = &hg_scanner::setting_go_on_when_double_checked; else if (val == SANE_STD_OPT_NAME_IS_CHECK_STAPLE) setting_map_[sn] = &hg_scanner::setting_staple_check; else if (val == SANE_STD_OPT_NAME_SCAN_MODE) { setting_map_[sn] = &hg_scanner::setting_scan_mode; id_scan_mode_ = sn; } else if (val == SANE_STD_OPT_NAME_SCAN_COUNT) { setting_map_[sn] = &hg_scanner::setting_scan_count; id_scan_count_ = sn; } else if (val == SANE_STD_OPT_NAME_TEXT_DIRECTION) setting_map_[sn] = &hg_scanner::setting_text_direction; else if (val == SANE_STD_OPT_NAME_IS_ROTATE_BKG_180) setting_map_[sn] = &hg_scanner::setting_rotate_bkg_180; else if (val == SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR) setting_map_[sn] = &hg_scanner::setting_fractate_check; else if (val == SANE_STD_OPT_NAME_DOG_EAR_SIZE) setting_map_[sn] = &hg_scanner::setting_fractate_check_level; else if (val == SANE_STD_OPT_NAME_IS_CHECK_ASKEW) setting_map_[sn] = &hg_scanner::setting_skew_check; else if (val == SANE_STD_OPT_NAME_ASKEW_RANGE) setting_map_[sn] = &hg_scanner::setting_skew_check_level; else if (val == SANE_STD_OPT_NAME_IS_FILL_COLOR) setting_map_[sn] = &hg_scanner::setting_color_fill; else if(val == SANE_STD_OPT_NAME_BINARY_THRESHOLD) setting_map_[sn] = &hg_scanner::setting_black_white_threshold; else if(val == SANE_STD_OPT_NAME_REVERSE_01) setting_map_[sn] = &hg_scanner::setting_white_pixel_0; else if(val == SANE_STD_OPT_NAME_IS_PHOTO_MODE) setting_map_[sn] = &hg_scanner::setting_keep_watermark; else if (val == SANE_STD_OPT_NAME_TIME_TO_SLEEP) setting_map_[sn] = &hg_scanner::setting_setsleeptime; else if (val == SANE_STD_OPT_NAME_FEED_STRENGTH) setting_map_[sn] = &hg_scanner::setting_setfeedmode; else if (val == SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH) setting_map_[sn] = &hg_scanner::setting_set_auto_pick_paper; else if (val == SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE) setting_map_[sn] = &hg_scanner::setting_set_auto_pick_paper_threshold; else if (val == SANE_STD_OPT_NAME_WAIT_TO_SCAN) setting_map_[sn] = &hg_scanner::setting_set_auto_paper_scan; else if (val == SANE_STD_OPT_NAME_RID_HOLE_L) setting_map_[sn] = &hg_scanner::setting_set_isremove_left_hole; else if (val == SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L) setting_map_[sn] = &hg_scanner::setting_set_isremove_left_hole_threshold; else if (val == SANE_STD_OPT_NAME_RID_HOLE_R) setting_map_[sn] = &hg_scanner::setting_set_isremove_right_hole; else if (val == SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R) setting_map_[sn] = &hg_scanner::setting_set_isremove_right_hole_threshold; else if (val == SANE_STD_OPT_NAME_RID_HOLE_T) setting_map_[sn] = &hg_scanner::setting_set_isremove_top_hole; else if (val == SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T) setting_map_[sn] = &hg_scanner::setting_set_isremove_top_hole_threshold; else if (val == SANE_STD_OPT_NAME_RID_HOLE_B) setting_map_[sn] = &hg_scanner::setting_set_isremove_low_hole; else if (val == SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B) setting_map_[sn] = &hg_scanner::setting_set_isremove_low_hole_threshold; else if (val == SANE_STD_OPT_NAME_FOLD_TYPE) setting_map_[sn] = &hg_scanner::setting_set_fold_type; } 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; } } 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::get_range(int setting_no, std::vector& range, std::string& def_val, bool& is_range/*range or list*/) { char sn[20]; std::string type(""); sprintf(sn, "%d", setting_no); range.clear(); if (setting_jsn_.at(sn).contains("range")) { setting_jsn_.at(sn).at("type").get_to(type); is_range = !setting_jsn_.at(sn).at("range").is_array(); if (is_range) { if (type == "int") { int l = 0, u = 0; setting_jsn_.at(sn).at("range").at("min").get_to(l); setting_jsn_.at(sn).at("range").at("max").get_to(u); char str[20]; sprintf(str, "%d", l); range.push_back(str); sprintf(str, "%d", u); range.push_back(str); } else { double l = .0f, u = .0f; setting_jsn_.at(sn).at("range").at("min").get_to(l); setting_jsn_.at(sn).at("range").at("max").get_to(u); char str[40]; sprintf(str, "%f", l); range.push_back(str); sprintf(str, "%f", u); range.push_back(str); } } else { char str[40]; for (int i = 0; i < setting_jsn_.at(sn).at("range").size(); ++i) { if (type == "int") { int v = 0; setting_jsn_.at(sn).at("range").at(i).get_to(v); sprintf(str, "%d", v); range.push_back(str); } else if(type == "float") { double v = 0; setting_jsn_.at(sn).at("range").at(i).get_to(v); sprintf(str, "%f", v); range.push_back(str); } else { std::string v(""); setting_jsn_.at(sn).at("range").at(i).get_to(v); range.push_back(v); } } } } if (type == "int") { int v = 0; setting_jsn_.at(sn).at("default").get_to(v); sprintf(sn, "%d", v); def_val = sn; } else if (type == "float") { double v = 0; setting_jsn_.at(sn).at("default").get_to(v); sprintf(sn, "%f", v); def_val = sn; } else if(type == "string") setting_jsn_.at(sn).at("default").get_to(def_val); //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(int setting_no, bool& val) { std::vector range; std::string init(""), in(val ? "true" : "false"); bool is_range = false;; get_range(setting_no, range, init, is_range); if (range.size() == 0) return true; for (int i = 0; i < range.size(); ++i) { if (in == range[i]) return true; } val = init == "true" ? true : false; return false; } bool hg_scanner::check_range(int setting_no, int& val) { std::vector range; std::string init(""); bool is_range = false;; get_range(setting_no, range, init, is_range); if (range.size() == 0) return true; if (is_range && range.size() == 2) { if (val >= atoi(range[0].c_str()) && val <= atoi(range[1].c_str())) return true; if(val < atoi(range[0].c_str())) val = atoi(range[0].c_str()); else val = atoi(range[1].c_str()); return false; } else if (!is_range) { for (int i = 0; i < range.size(); ++i) { if (atoi(range[i].c_str()) == val) return true; } } val = atoi(init.c_str()); return false; } bool hg_scanner::check_range(int setting_no, double& val) { std::vector range; std::string init(""); bool is_range = false;; get_range(setting_no, range, init, is_range); if (range.size() == 0) return true; if (is_range && range.size() == 2) { if (val >= atof(range[0].c_str()) && val <= atof(range[1].c_str())) return true; if (val < atof(range[0].c_str())) val = atof(range[0].c_str()); else val = atof(range[1].c_str()); return false; } else if (!is_range) { for (int i = 0; i < range.size(); ++i) { if (fabs(atof(range[i].c_str()) - val) < .000001) return true; } } val = atof(init.c_str()); return false; } bool hg_scanner::check_range(int setting_no, std::string& val) { std::vector range; std::string init(""), in(val); bool is_range = false;; get_range(setting_no, range, init, is_range); if (range.size() == 0) return true; for (int i = 0; i < range.size(); ++i) { if (in == range[i]) return true; } val = init; return false; } 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, 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(int setting_no) { char key[20]; int sn = setting_no; std::string val(""); sprintf(key, "%d", setting_no); setting_jsn_.at(key).at("type").get_to(val); if (val == "string") { val = ""; setting_jsn_.at(key).at("default").get_to(val); char* buf = NULL; int size = 0; setting_jsn_.at(key).at("size").get_to(size); buf = (char*)malloc(size + 4); bzero(buf, size + 4); strcpy(buf, val.c_str()); sn = set_setting(sn, buf, val.length()); free(buf); } else if (val == "int") { int v = 0; setting_jsn_.at(key).at("default").get_to(v); sn = set_setting(sn, (char*)&v, sizeof(v)); } else if (val == "float") { double v = .0f; setting_jsn_.at(key).at("default").get_to(v); sn = set_setting(sn, (char*)&v, sizeof(v)); } else if (val == "bool") { bool v = false; setting_jsn_.at(key).at("default").get_to(v); sn = set_setting(sn, (char*)&v, sizeof(v)); } else sn = SCANNER_ERR_OK; return sn; } 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 = ""; 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; } tiny_buffer = imgs_.Take(); if (tiny_buffer->swap()) { try { if (ImagePrc_pHandle_) { image_process(tiny_buffer); } else { VLOG_MINI_1(LOG_LEVEL_FATAL, "Get Image Process is NULL pid is %d.\n",pid_); status_ = SCANNER_ERR_INSUFFICIENT_MEMORY; stop(); break; } } catch (...) { VLOG_MINI_1(LOG_LEVEL_FATAL, "FATAL: Insufficient memory when proecss image with %d bytes.\n", tiny_buffer->size()); status_ = SCANNER_ERR_INSUFFICIENT_MEMORY; stop(); break; } } else { VLOG_MINI_1(LOG_LEVEL_FATAL, "Reload USB data '%s' failed!\n", tiny_buffer->file().c_str()); } } } void hg_scanner::working_begin(void*) { final_img_index_ = 0; status_ = SCANNER_ERR_OK; notify_ui_working_status(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(); switch (status_) { case SCANNER_ERR_OK: notify_ui_working_status(STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_BUSY: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_PC_BUSY, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_STOPPED: notify_ui_working_status(STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_COVER_OPENNED: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_COVER_OPENNED, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_NO_PAPER: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_NO_PAPER, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_FEEDING_PAPER: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_FEEDING_PAPER, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_NOT_FOUND: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_NOT_FOUND, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_SLEEPING: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_SLEEPING, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_COUNT_MODE: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_COUNT_MODE, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_DOUBLE_FEEDING: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_DOUBLE_FEEDING, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_PAPER_JAMMED: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_PAPER_JAMMED, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_STAPLE_ON: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_STAPLE_ON, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_PAPER_SKEW: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_PAPER_SKEW, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_SIZE_CHECK: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_SIZE_CHECK, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_DOGEAR: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_DOGEAR, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_NO_IMAGE: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_NO_IMAGE, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_SCANN_ERROR: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_SCANN_ERROR, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_PC_BUSY: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_PC_BUSY, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_INSUFFICIENT_MEMORY: notify_ui_working_status(STATU_DESC_SCANNER_ERR_INSUFFICIENT_MEMORY, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_TIMEOUT: notify_ui_working_status(STATU_DESC_SCANNER_ERR_TIMEOUT, SANE_EVENT_SCAN_FINISHED, status_); break; case SCANNER_ERR_DEVICE_ISLOCK: notify_ui_working_status(STATU_DESC_SCANNER_ERR_DEVICE_ISLOCK, SANE_EVENT_SCAN_FINISHED, status_); break; default: notify_ui_working_status(user_cancel_ ? STATU_DESC_SCAN_CANCELED : STATU_DESC_SCAN_STOPPED, SANE_EVENT_SCAN_FINISHED, status_); break; } 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; } } 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::image_configuration(LPSCANCONF ic) { int len = sizeof(ic), ret = SCANNER_ERR_OK; bzero(ic, len); ic->papertype = paper_size_; if (is_lateral(image_prc_param_.bits.paper)) ic->paperAlign = Rot270; // else if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO) // ic->paperAlign = AutoTextOrientation; else ic->paperAlign = Rot0; ic->en_sizecheck = size_check; 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 (image_prc_param_.bits.page == PAGE_FOLIO) { ic->en_fold = fold_type_; } else { ic->en_fold = 0; } 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; //存疑 if (resolution_ >= 300) { if (is_quality_ == IMG_SPEED) { ic->resolution_dst = 200; } else if (is_quality_ == IMG_QUALITY) { 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_ >= 70 ? 70 : 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 = (double_paper_handle_ & DOUBLE_PAPER_SAVE_IMG) == DOUBLE_PAPER_SAVE_IMG; adjust_filling_hole(ic); int filter_clr[] = { 3, 0, 1, 2, 5, 6, 7 }; if (image_prc_param_.bits.color_mode == COLOR_MODE_24_BITS || image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH) ic->filter = 3; else { ic->filter = filter_clr[image_prc_param_.bits.rid_color]; // if(ic->filter != 3) // ic->pixtype = 2; ic->hsvcorrect = 0; ic->multi_output_red = 0; ic->multiOutput = MultiOutput::Unused; } //多留输出的处理 if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW && is_multiout) { ic->pixtype = 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) { ic->pixtype = 2; } if (is_multiout) { 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 (ic->pixtype == 0) { ic->hsvcorrect = 0; ic->multi_output_red = 0; ic->fadeback = false; ic->sharpen = 0; ic->removeMorr = 0; ic->textureRemove = 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; } { std::lock_guard lock(io_lock_); ret = io_->write_bulk(&ic, &len); this_thread::sleep_for(chrono::milliseconds(500)); io_->set_timeout(2000);//必要延时 } VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "Write-down 0x%x bytes image process parameters\n", len); 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->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); img_conf_ = *ic; return ret; } int hg_scanner::invoke_setting_xxx(int(hg_scanner::*func)(int, 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, data, 0); // ret = (this->*it->second)(it->first, data); break; } ++it; } return ret; } int hg_scanner::setting_restore(int sn, void* data) { // restore ... int count = 0; setting_jsn_.at("option_count").get_to(count); notify_setting_result_ = false; for (int i = 1; i < count; ++i) restore(i); notify_setting_result_ = true; return SCANNER_ERR_CONFIGURATION_CHANGED; } int hg_scanner::setting_help(int sn, 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(int sn, 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(sn, 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 ret; } int hg_scanner::setting_multi_out(int sn, 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 ", 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_OK; } int hg_scanner::setting_multi_out_type(int sn, void*data) { int ret = SCANNER_ERR_OK; std::string str((char*)data); bool exact = check_range(sn, 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 ret; } int hg_scanner::setting_rid_color(int sn, void* data) { std::string str((char*)data); int ret = SCANNER_ERR_OK, color = -1, old = image_prc_param_.bits.rid_color; bool exact = check_range(sn, str); image_prc_param_.bits.rid_color = match_best_rid_color(str, NULL); 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(int sn, void* data) { image_prc_param_.bits.rid_red = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_rid_answer_red(int sn, void* data) { image_prc_param_.bits.rid_answer_red = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_erase_background(int sn, void* data) { image_prc_param_.bits.erase_bakground = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_erase_background_range(int sn, void* data) { int ret = SCANNER_ERR_OK; erase_bkg_range_ = *((int*)data); if (!check_range(sn, erase_bkg_range_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = erase_bkg_range_; } return ret; } int hg_scanner::setting_noise_optimize(int sn, void* data) { image_prc_param_.bits.noise_optimize = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_noise_optimize_range(int sn, void* data) { int ret = SCANNER_ERR_OK; noise_range_ = *((int*)data); if (!check_range(sn, noise_range_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = noise_range_; } return ret; } int hg_scanner::setting_paper(int sn, void* data) { std::string paper((char*)data); bool exact = check_range(sn, 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 ret; } int hg_scanner::setting_paper_check(int sn, 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(int sn, void* data) { std::string val((char*)data); bool exact = check_range(sn, 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(int sn, void* data) { int ret = SCANNER_ERR_OK; omit_empty_level_ = *((int*)data); if (!check_range(sn, omit_empty_level_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = omit_empty_level_; } return ret; } int hg_scanner::setting_resolution(int sn, void* data) { int ret = SCANNER_ERR_OK, old = resolution_, sub = SCANNER_ERR_OK; resolution_ = *((int*)data); if (!check_range(sn, 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_DEVICE_NOT_SUPPORT; } 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 ret; } int hg_scanner::setting_exchagnge(int sn, void* data) { image_prc_param_.bits.exchange = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_split_image(int sn, void* data) { image_prc_param_.bits.split = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_automatic_skew(int sn, 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(int sn, void* data) { image_prc_param_.bits.rid_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_rid_hoe_range(int sn, void* data) { int ret = SCANNER_ERR_OK; rid_hole_range_ = *((double*)data); if (!check_range(sn, 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(int sn, void* data) { int ret = SCANNER_ERR_OK; bright_ = *((int*)data); if (!check_range(sn, bright_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = bright_; } return ret; } int hg_scanner::setting_contrast(int sn, void* data) { int ret = SCANNER_ERR_OK; contrast_ = *((int*)data); if (!check_range(sn, contrast_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = contrast_; } return ret; } int hg_scanner::setting_gamma(int sn, void* data) { int ret = SCANNER_ERR_OK; gamma_ = *((double*)data); if (!check_range(sn, gamma_)) { ret = SCANNER_ERR_NOT_EXACT; *((double*)data) = gamma_; } return ret; } int hg_scanner::setting_sharpen(int sn, void* data) { std::string str((char*)data); int ret = SCANNER_ERR_OK; bool exact = check_range(sn, 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(int sn, void* data) { image_prc_param_.bits.dark_sample = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_erase_black_frame(int sn, void* data) { image_prc_param_.bits.erase_black_frame = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_threshold(int sn, void* data) { int ret = SCANNER_ERR_OK; threshold_ = *((int*)data); if (!check_range(sn, threshold_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = threshold_; } return ret; } int hg_scanner::setting_anti_noise(int sn, void* data) { int ret = SCANNER_ERR_OK; anti_noise_ = *((int*)data); if (!check_range(sn, anti_noise_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = anti_noise_; } return ret; } int hg_scanner::setting_margin(int sn, void* data) { int ret = SCANNER_ERR_OK; margin_ = *((int*)data); if (!check_range(sn, margin_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = margin_; } return ret; } int hg_scanner::setting_filling_background(int sn, void* data) { std::string str((char*)data); bool exact = check_range(sn, 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(int sn, void* data) { image_prc_param_.bits.is_permeate = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_is_permeate_lv(int sn, void* data) { int ret = SCANNER_ERR_OK; std::string str((char*)data); bool exact = check_range(sn, 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(int sn, void* data) { image_prc_param_.bits.remove_morr = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_error_extention(int sn, void* data) { image_prc_param_.bits.error_extention = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_remove_texture(int sn, void* data) { image_prc_param_.bits.remove_txtture = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_ultrasonic_check(int sn, 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(int sn, 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(int sn, 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(int sn, void* data) { std::string str((char*)data); bool exact = check_range(sn, str); int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT; if (strcmp(str.c_str(), OPTION_VALUE_SMZS_LXSM) == 0) { scan_count_ = -1; } else { char key[20]; sprintf(key, "%d", id_scan_count_); setting_jsn_.at(key).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(int sn, void* data) { int ret = SCANNER_ERR_OK; std::string val(""); if (id_scan_mode_ != -1) { char key[20]; sprintf(key, "%d", id_scan_mode_); setting_jsn_.at(key).at("cur").get_to(val); } if (val == OPTION_VALUE_SMZS_LXSM) { scan_count_ = -1; } else { scan_count_ = *((int*)data); } VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "set scanning pages to %d\n", scan_count_); return ret; } int hg_scanner::setting_text_direction(int sn, void* data) { std::string str((char*)data); bool exact = check_range(sn, 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(int sn, void* data) { image_prc_param_.bits.rotate_back_180 = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_fractate_check(int sn, void* data) { image_prc_param_.bits.fractate_check = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_fractate_check_level(int sn, void* data) { int ret = SCANNER_ERR_OK; fractate_level_ = *((int*)data); if (!check_range(sn, fractate_level_)) { ret = SCANNER_ERR_NOT_EXACT; *((int*)data) = fractate_level_; } return ret; } int hg_scanner::setting_skew_check(int sn, 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(int sn, void* data) { int level = *((int*)data); bool exact = check_range(sn, 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(int sn, void* data) { custom_gamma_ = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_custom_gamma_data(int sn, 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(int sn, void* data) { custom_area_ = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_custom_area_left(int sn, 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(int sn, 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(int sn, 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(int sn, void* data) { SANE_Fixed* v = (SANE_Fixed*)data; custom_area_br_y_ = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_img_quality(int sn, void *data) { std::string str((char*)data); bool exact = check_range(sn, 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(int sn, void*data) { is_color_fill = *((bool *)data); return SCANNER_ERR_OK; } int hg_scanner::setting_keep_watermark(int sn, void* data) { keep_watermark_ = *(bool*)data; on_pic_type(keep_watermark_); return SCANNER_ERR_OK; } int hg_scanner::setting_black_white_threshold(int sn, void* data) { bw_threshold_ = (unsigned char)(*(SANE_Int*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_white_pixel_0(int sn, void* data) { is_white_0_ = *(bool*)data; return SCANNER_ERR_OK; } int hg_scanner::setting_setfeedmode(int sn, 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_setsleeptime(int sn, 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_set_auto_pick_paper(int sn, void* data) { int ret = SCANNER_ERR_OK; bool isautopic = *((bool *)data); ret = on_pick_paper(isautopic); return ret; } int hg_scanner:: setting_set_auto_pick_paper_threshold(int sn, void* data) { int ret = SCANNER_ERR_OK; double threshold = *((double*)data); ret = on_pick_paper_threshold(threshold); return ret; } int hg_scanner:: setting_set_auto_paper_scan(int sn, void* data) { is_auto_paper_scan = *((bool *)data); if (!is_auto_paper_scan) { on_is_auto_paper(is_auto_paper_scan); } return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_left_hole(int sn, void* data) { isremove_left_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_right_hole(int sn, void* data) { isremove_right_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_top_hole(int sn, void* data) { isremove_top_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_low_hole(int sn, void* data) { isremove_low_hole = *((bool*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_left_hole_threshold(int sn, void* data) { isremove_left_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_right_hole_threshold(int sn, void* data) { isremove_right_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_top_hole_threshold(int sn, void* data) { isremove_top_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_isremove_low_hole_threshold(int sn, void* data) { isremove_low_hole_threshold = *((double*)data); return SCANNER_ERR_OK; } int hg_scanner::setting_set_fold_type(int sn, 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) { int ret = SCANNER_ERR_OK; if ((((color_mode == COLOR_MODE_24_BITS || color_mode == COLOR_MODE_AUTO_MATCH) && !is_color_type_) || ((color_mode != COLOR_MODE_24_BITS && color_mode != COLOR_MODE_AUTO_MATCH) && is_color_type_)) && color_mode != -1) { is_color_type_ ^= 1; } if (image_prc_param_.bits.rid_color != RID_COLOR_NONE &&(image_prc_param_.bits.color_mode == COLOR_MODE_256_GRAY || image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE) ) { is_color_type_ = 1; } if(image_prc_param_.bits.rid_color != RID_COLOR_NONE && (image_prc_param_.bits.color_mode == COLOR_MODE_256_GRAY || image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE) && color_mode == -1) { is_color_type_ = 1; } else if (image_prc_param_.bits.rid_color == RID_COLOR_NONE && (image_prc_param_.bits.color_mode == COLOR_MODE_256_GRAY || image_prc_param_.bits.color_mode == COLOR_MODE_BLACK_WHITE) && color_mode == -1) { is_color_type_ = 0; } if (is_multiout) { is_color_type_ = 1; // if (/* condition */) // { // /* code */ // } } return SCANNER_ERR_OK; } int hg_scanner::on_paper_changed(int& paper) { return SCANNER_ERR_OK; } int hg_scanner::on_paper_check_changed(bool& check) { return SCANNER_ERR_OK; } int hg_scanner::on_resolution_changed(int& dpi) { return SCANNER_ERR_OK; } int hg_scanner::on_ultrasonic_check_changed(bool& check) { return SCANNER_ERR_OK; } int hg_scanner::on_staple_check_changed(bool& check) { return SCANNER_ERR_OK; } int hg_scanner::on_skew_check_changed(bool& check) { return SCANNER_ERR_OK; } int hg_scanner::on_skew_check_level_changed(int& check) { return SCANNER_ERR_OK; } int hg_scanner::on_set_feedmode(int feedmode) { return SCANNER_ERR_OK; } int hg_scanner::on_get_feedmode(int &feedmode) { return SCANNER_ERR_OK; } int hg_scanner::on_pic_type(bool& pic) { return SCANNER_ERR_OK; } int hg_scanner::on_pick_paper(bool autostrength) { return SCANNER_ERR_OK; } int hg_scanner::on_pick_paper_threshold(double threshold) { return SCANNER_ERR_OK; } int hg_scanner::on_is_auto_paper(bool isautopaper) { return SCANNER_ERR_OK; } 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(int setting_no, void* data, int len) { return SCANNER_ERR_OK; } int hg_scanner::on_scanner_closing(bool force) { return SCANNER_ERR_OK; } void hg_scanner::thread_handle_usb_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; param.black_white = img_conf_.pixtype == COLOR_MODE_BLACK_WHITE; param.channels = img_conf_.pixtype == COLOR_MODE_24_BITS ? 3 : 1; param.color_mode = img_conf_.pixtype; param.double_side = img_conf_.is_duplex; param.dpi = img_conf_.resolution_dst; img_conf_.brightness = (float)bright_; img_conf_.contrast = (float)contrast_; img_conf_.brightness = bright; img_conf_.contrast = 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) { setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text); int count = 0; notify_setting_result_ = false; setting_jsn_.at("option_count").get_to(count); for (int sn = 1; sn < count; ++sn) { char key[20]; std::string val(""); sprintf(key, "%d", sn); #ifdef MAPPING_FUNCTION_IN_BASE setting_jsn_.at(key).at("name").get_to(val); set_setting_map(sn, val.c_str()); #endif setting_jsn_.at(key).at("type").get_to(val); if (val == "string") { val = ""; setting_jsn_.at(key).at("default").get_to(val); char* buf = NULL; int size = 0; setting_jsn_.at(key).at("size").get_to(size); buf = (char*)malloc(size + 4); bzero(buf, size + 4); strcpy(buf, val.c_str()); set_setting(sn, buf, val.length()); free(buf); } else if (val == "int") { int v = 0; setting_jsn_.at(key).at("default").get_to(v); set_setting(sn, (char*)&v, sizeof(v)); } else if (val == "float") { double v = .0f; setting_jsn_.at(key).at("default").get_to(v); set_setting(sn, (char*)&v, sizeof(v)); } else if (val == "bool") { bool v = false; setting_jsn_.at(key).at("default").get_to(v); set_setting(sn, (char*)&v, sizeof(v)); } } setting_count_ = count; notify_setting_result_ = true; } int hg_scanner::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; } 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(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(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 { imgs_.Put(data); 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) { 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 (img_conf_.pixtype == 0 || (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; 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_)) 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(); 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(int setting_no, void* data, int len) { bool hit = setting_map_.count(setting_no) > 0; int ret = SCANNER_ERR_OUT_OF_RANGE; char sn[20]; sprintf(sn, "%d", setting_no); if (hit) { ret = (this->*setting_map_[setting_no])(setting_no, data); } else { VLOG_MINI_1(LOG_LEVEL_WARNING, "Setting %d is not found in base setting functions.\n", setting_no); ret = set_setting_value(setting_no, data, len); } if (ret == SCANNER_ERR_OK || ret == SCANNER_ERR_NOT_EXACT || ret == SCANNER_ERR_CONFIGURATION_CHANGED) { std::string type(""), name(""); setting_jsn_.at(sn).at("type").get_to(type); setting_jsn_.at(sn).at("title").get_to(name); if (type == "string") { setting_jsn_.at(sn).at("cur") = (char*)data; type = (char*)data; } else if (type == "int") { setting_jsn_.at(sn).at("cur") = *((int*)data); sprintf(sn, "%d", *((int*)data)); type = sn; } else if (type == "float") { setting_jsn_.at(sn).at("cur") = *((double*)data); sprintf(sn, "%f", *((double*)data)); type = sn; } else if (type == "bool") { setting_jsn_.at(sn).at("cur") = *((bool*)data); type = *((bool*)data) ? "true" : "false"; } if (notify_setting_result_) { name.insert(0, "\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 name(""); if (setting_jsn_.contains(sn)) { setting_jsn_.at(sn).at("title").get_to(name); } else name = std::string("\350\256\276\347\275\256\351\241\271") + sn; name.insert(0, "\350\256\276\347\275\256 \""); name += std::string("\" \345\200\274\345\244\261\350\264\245: ") + hg_scanner_err_name(ret); notify_ui_working_status(name.c_str()); } return ret; } int hg_scanner::get_setting(int setting_no, char* json_txt_buf, int* len) { if (!len) return SCANNER_ERR_INVALID_PARAMETER; if (setting_no == 0) { int count = 0; setting_jsn_.at("option_count").get_to(count); *len = count; return SCANNER_ERR_OK; } if (setting_count_ <= setting_no || setting_no < 0) return SCANNER_ERR_OUT_OF_RANGE; char sn[20]; std::string text(""), name(""), tag(""); int add = 0; bool is_gamma = false, is_area_x = false, is_area_y = false; sprintf(sn, "%d", setting_no); if (!setting_jsn_.contains(sn)) VLOG_MINI_2(LOG_LEVEL_FATAL, "!!!option(%d - %s) is not found.\n", setting_no, sn); text = setting_jsn_.at(sn).dump(); setting_jsn_.at(sn).at("name").get_to(name); if (name == SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT || name == SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT) { is_area_x = true; add = 20; } else if (name == SANE_STD_OPT_NAME_CUSTOM_AREA_TOP || name == SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM) { is_area_y = true; add = 20; } else if (name == SANE_STD_OPT_NAME_FEED_STRENGTH) { std::string strfeed(""); if (!save_feedmode_type_) { on_get_feedmode(feedmode_); } switch (feedmode_) { case 0: strfeed = OPTION_VALUE_FZQD_R; break; case 1: strfeed = OPTION_VALUE_FZQD_YB; break; case 2: strfeed = OPTION_VALUE_FZQD_Q; break; } setting_jsn_.at(sn).at("cur")= strfeed; text = setting_jsn_.at(sn).dump(); } else if (name == SANE_STD_OPT_NAME_TIME_TO_SLEEP) { std::string strtime(""); if (!save_sleeptime_type_) { get_sleep_time(sleeptime_); } switch (sleeptime_) { case -1: strtime = OPTION_VALUE_XMSJ_BXM;; break; case 5: strtime = OPTION_VALUE_XMSJ_WFZ; break; case 10: strtime = OPTION_VALUE_XMSJ_SFZ; break; case 30: strtime = OPTION_VALUE_XMSJ_BXS; break; case 60: strtime = OPTION_VALUE_XMSJ_YXS; break; case 120: strtime = OPTION_VALUE_XMSJ_LXS; break; case 240: strtime = OPTION_VALUE_XMSJ_SXS; break; } setting_jsn_.at(sn).at("cur") = strtime; text = setting_jsn_.at(sn).dump(); } else if (name == SANE_STD_OPT_NAME_WAIT_TO_SCAN) { if(user_cancel_ && is_auto_paper_scan) { //setting_jsn_.at(sn).at("cur") = false; //text = setting_jsn_.at(sn).dump(); } } else if (name == SANE_STD_OPT_NAME_REVERSE_01) { setting_jsn_.at(sn).at("cur") = is_white_0_; text = setting_jsn_.at(sn).dump(); } if (*len <= text.length() + add) { *len = text.length() + 8 + add; return SCANNER_ERR_INSUFFICIENT_MEMORY; } setting_jsn_.at(sn).at("name").get_to(name); if (is_gamma) { name = ""; add = 3 * 256; sprintf(sn, "[%u", custom_gamma_val_->table[0]); name += sn; for (int i = 1; i < add; ++i) { sprintf(sn, ",%u", custom_gamma_val_->table[i]); name += sn; } name += "]"; tag = "\"cur\":"; } else if (is_area_x) { sprintf(sn, "%u.0", paper_size_mm_.cx); name = sn; tag = "\"max\":"; } else if (is_area_y) { sprintf(sn, "%u.0", paper_size_mm_.cy); name = sn; tag = "\"max\":"; } if (!tag.empty()) { size_t pos = text.find(tag), end = pos; if (pos != std::string::npos) { pos += tag.length(); end = pos; while (end < text.length()) { if (text[end] == ',' || text[end] == '}' || text[end] == ']' || text[end] == '\r' || text[end] == '\n') break; end++; } if (end > pos) text.replace(pos, end - pos, name); else text.insert(end, name); } } strcpy(json_txt_buf, text.c_str()); *len = text.length(); return 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_; } 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; 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); } 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) { 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) { char* jsn_txt = NULL; int size = 0; json jsn; int ret = get_setting(*len, jsn_txt, &size); if (ret == SCANNER_ERR_INSUFFICIENT_MEMORY) { jsn_txt = (char*)malloc(size + 4); bzero(jsn_txt, size + 4); get_setting(*len, jsn_txt, &size); jsn = jsonconfig::load_json_from_text(jsn_txt); free(jsn_txt); if (get_default_value(data, &jsn)) ret = SCANNER_ERR_OK; else ret = SCANNER_ERR_DATA_DAMAGED; } return ret; } else if (code == IO_CTRL_CODE_CLEAR_ROLLER_COUNT) { int count = get_roller_num(); if (len) *len = count; return clear_roller_num(); } else if (code == IO_CTRL_CODE_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 (*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_HARDWARE_VERSION) { 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 SANE_POWER_NONE: sleeptime = 0; break; case SANE_POWER_MINUTES_5: sleeptime = 300; break; case SANE_POWER_MINUTES_10: sleeptime = 600; break; case SANE_POWER_MINUTES_20: sleeptime = 1200; break; case SANE_POWER_MINUTES_30: sleeptime = 1800; break; case SANE_POWER_MINUTES_60: sleeptime = 3600; break; case SANE_POWER_MINUTES_120: sleeptime = 7200; break; case SANE_POWER_MINUTES_240: sleeptime = 14400; break; case SANE_POWER_SHUTDOWN: set_devshtudown(); break; case SANE_POWER_RESTART: set_devreboot(); break; default: sleeptime = 0; break; } return set_sleep_time(sleeptime); } else if (code == IO_CTRL_CODE_GET_CUSTOM_GAMMA) { SANE_Gamma* v = (SANE_Gamma*)data; memcpy(v, custom_gamma_val_, sizeof(*custom_gamma_val_)); 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); } 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; 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); } else if (code == IO_CTRL_CODE_GET_SCAN_ISLOCK) { SANE_Bool islock = *((SANE_Bool*)data); get_scan_islock(&islock); *((SANE_Bool*)data) = islock; } 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; } int hg_scanner::get_roller_num(void) { return -2; } int hg_scanner::get_device_log(string &log) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_devreboot() { return -2; } int hg_scanner::set_devshtudown() { return -2; } int hg_scanner::clear_roller_num(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_history_count(void) { return -2; } int hg_scanner::set_scan_islock(SANE_Bool set_islock) { return -2; } int hg_scanner::get_scan_islock(SANE_Bool* islock) { return -2; } int hg_scanner::set_scan_lock_check_val(string check_str) { return -2; } ////////////////////////////////////////////////////////////////////////////////////////////////////// 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& getsleepime) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_sleep_time(int sleeptime) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::notify_sleep() { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_dogear_distance(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_dogear_distance(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scanner_paperon(SANE_Bool* paperon) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_scan_when_paper_on(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scan_when_paper_on(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scan_with_hole(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::set_scan_with_hole(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } int hg_scanner::get_scan_is_sleep(void) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } void hg_scanner::image_process(std::shared_ptr& buffer) { 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 ((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); (this->*dump_img_)(ImagePrc_pHandle_, "fillhole"); } if (pid_ != 0x239 && pid_ != 0x439) { ret = hg_imgproc::auto_crop(ImagePrc_pHandle_); (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_ != 0x239 && pid_ != 0x439)) { hg_imgproc::resolution_change(ImagePrc_pHandle_); (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 && (img_conf_.pixtype == COLOR_MODE_BLACK_WHITE || img_conf_.pixtype == COLOR_MODE_256_GRAY)) && (pid_ != 0x239 && pid_ != 0x439)) { hg_imgproc::channel(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "channel"); } if (pid_ != 0x239 && pid_ != 0x439) { adjust_color(ImagePrc_pHandle_); (this->*dump_img_)(ImagePrc_pHandle_, "channel"); } 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 && (pid_ == 0x239 || pid_ == 0x439)) && resolution_ >= 300)//239 { 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); } save_final_image(&ih, buf); } }