diff --git a/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp b/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp index 20976a7..a453a90 100644 --- a/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp +++ b/hgdriver/ImageProcess/ImageApplyAutoCrop.cpp @@ -193,22 +193,28 @@ void CImageApplyAutoCrop::autoCrop_desaskew_fillBlank(cv::Mat& src, cv::Mat& dst cv::Mat dstROI; if (isDesaskew && rect.angle != 0) { + cv::RotatedRect rect_temp = rect; + if (rect_temp.size.width > dst.cols) + rect_temp.size.width = dst.cols; + if (rect_temp.size.height > dst.rows) + rect_temp.size.height = dst.rows; + cv::Point2f srcTri[4], dstTri[3]; - rect.points(srcTri); + rect_temp.points(srcTri); srcTri[0].x -= 1; srcTri[1].x -= 1; srcTri[2].x -= 1; - int w = rect.size.width; - int h = rect.size.height; + int w = rect_temp.size.width; + int h = rect_temp.size.height; int x = (dst.cols - w) / 2; int y = (dst.rows - h) / 2; - dstTri[0] = cv::Point2f(x, y + h); - dstTri[1] = cv::Point2f(x, y); - dstTri[2] = cv::Point2f(x + w, y); + dstTri[0] = cv::Point2f(0, h); + dstTri[1] = cv::Point2f(0, 0); + dstTri[2] = cv::Point2f(w, 0); dstROI = dst(cv::Rect(x, y, w, h) & cv::Rect(0, 0, dst.cols, dst.rows)); - myWarpAffine(src, dstROI, cv::getAffineTransform(srcTri, dstTri), dstROI.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(0)); + myWarpAffine(src, dstROI, cv::getAffineTransform(srcTri, dstTri), dstROI.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, blankColor); } else { diff --git a/hgdriver/ImageProcess/ImageApplyAutoCrop.h b/hgdriver/ImageProcess/ImageApplyAutoCrop.h index 1f68256..8f940b0 100644 --- a/hgdriver/ImageProcess/ImageApplyAutoCrop.h +++ b/hgdriver/ImageProcess/ImageApplyAutoCrop.h @@ -35,7 +35,8 @@ 2023/05/23 v1.5.6 修复纯黑图找不到外界轮廓会导致崩溃的BUG。 2023/11/02 v1.6 优化抗噪能力。采用自适应背景色二值化。 2023/12/05 v1.6.1 替换获取背景色方案;修复固定幅面裁切纠偏的坐标计算BUG。 - * 版本号:v1.6.1 + 2023/12/06 v1.6.2 修复固定幅面裁切纠偏的坐标计算BUG。 + * 版本号:v1.6.2 * ==================================================== */ diff --git a/hgdriver/ImageProcess/ImageProcess_Public.cpp b/hgdriver/ImageProcess/ImageProcess_Public.cpp index d8a7001..f70024c 100644 --- a/hgdriver/ImageProcess/ImageProcess_Public.cpp +++ b/hgdriver/ImageProcess/ImageProcess_Public.cpp @@ -207,31 +207,45 @@ namespace hg cv::Scalar getBackGroundColor(const cv::Mat& image, const cv::Mat& mask, int threshold) { - cv::Scalar bgc; - cv::Mat mv[3]; - cv::split(image, mv); float range[] = { 0, 256 }; const float* ranges = { range }; - int histSize = 256; - - cv::Mat hist[3]; - double min, max; - cv::Point maxLoc; - for (int i = 0; i < 3; i++) + cv::Scalar bgc; + if (image.channels() == 3) { - cv::calcHist(&mv[i], 1, 0, mask, hist[i], 1, &histSize, &ranges); + cv::Mat mv[3]; + cv::split(image, mv); + cv::Mat hist[3]; + for (int i = 0; i < 3; i++) + { + cv::calcHist(&mv[i], 1, 0, mask, hist[i], 1, &histSize, &ranges); + + int index_max = 0; + int max_value = 0; + for (size_t j = threshold; j < 256; j++) + if (hist[i].at(j) > max_value) + { + index_max = j; + max_value = hist[i].at(j); + } + + bgc[i] = index_max; + } + } + else + { + cv::Mat hist; + cv::calcHist(&image, 1, 0, mask, hist, 1, &histSize, &ranges); int index_max = 0; - int max_value = 0; + int max_value = 0; for (size_t j = threshold; j < 256; j++) - if (hist[i].at(j) > max_value) + if (hist.at(j) > max_value) { index_max = j; - max_value = hist[i].at(j); + max_value = hist.at(j); } - - bgc[i] = index_max; + bgc = cv::Scalar::all(index_max); } return bgc; diff --git a/hgdriver/ImageProcess/ImageProcess_Public.h b/hgdriver/ImageProcess/ImageProcess_Public.h index 632a8b8..a0627f4 100644 --- a/hgdriver/ImageProcess/ImageProcess_Public.h +++ b/hgdriver/ImageProcess/ImageProcess_Public.h @@ -11,7 +11,8 @@ * 2023/12/01 v1.4 getBackGroundColor㷨 * 2023/12/02 v1.4.1 getBackGroundColorthresholdֵ * 2023/12/04 v1.4.2 opencv汾ӿڡ - * 汾ţv1.4.2 + * 2023/12/05 v1.4.3 getBackGroundColorֵ֧ͨͼ񱳾ɫʶ + * 汾ţv1.4.3 * ==================================================== */ diff --git a/hgdriver/hgdev/common_setting.h b/hgdriver/hgdev/common_setting.h index 398e333..beed805 100644 --- a/hgdriver/hgdev/common_setting.h +++ b/hgdriver/hgdev/common_setting.h @@ -622,6 +622,7 @@ typedef struct _scan_conf double discare_meanth; /**< 调过空白页文稿底色阈值>*/ bool en_contaminationdetection; /**< 脏污检测使能>*/ bool detect_size_diascard_blank; /**< 基于压缩图像大小跳过空白页使能*/ + int refuseInflow_level; /**< 防止渗透等级*/ uint32_t reserve[1024]; /**< 预留4096字节做协议扩展*/ }SCANCONF ,*LPSCANCONF; //图像参数设置 -OVER diff --git a/hgdriver/hgdev/hg_scanner.cpp b/hgdriver/hgdev/hg_scanner.cpp index caeb1bc..be193f6 100644 --- a/hgdriver/hgdev/hg_scanner.cpp +++ b/hgdriver/hgdev/hg_scanner.cpp @@ -204,6 +204,30 @@ hg_scanner::hg_scanner(ScannerSerial serial, const char* dev_name, usb_io* io, i { VLOG_MINI_1(LOG_LEVEL_WARNING, "temporary image folder: %s\n", final_path_.c_str()); final_path_ += PATH_SEPARATOR; + + // delete previous failed images, check the name as pattern '%04d-xxx.jpg' + std::vector files; + hg_log::get_foler_files((final_path_ + "failedimgs").c_str(), files); + for (auto& v : files) + { + size_t pos = v.rfind(PATH_SEPARATOR[0]); + std::string name(""); + char num[20] = { 0 }; + + if (pos == std::string::npos) + name = v; + else + name = v.substr(pos + 1); + sprintf(num, "%04d-", atoi(name.c_str())); + if (name.find(num) == 0) + { + pos = name.rfind('.'); + if(pos != std::string::npos && STRICMP(name.c_str() + pos, ".jpg") == 0) + remove(v.c_str()); + } + } + rmdir((final_path_ + "failedimgs").c_str()); + hg_log::create_folder((final_path_ + "failedimgs").c_str()); } else { @@ -1070,13 +1094,15 @@ void hg_scanner::thread_handle_image_process(void) if (!ImagePrc_pHandle_) { VLOG_MINI_1(LOG_LEVEL_FATAL, "[thread_handle_image_process]:Get Image Process is NULL pid is %d.\n", pid_); - stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; + stop_fatal_ = SCANNER_ERR_IMAGE_PROC_FATAL; do_stop(); invoke_stop = true; break; } } - image_process(tiny_buffer, id); + invoke_stop = !image_process(tiny_buffer, id); + if (invoke_stop) + break; } catch (const std::exception& e) { @@ -1084,21 +1110,25 @@ void hg_scanner::thread_handle_image_process(void) { is_dpi_color_check = false; stop_fatal_ = SCANNER_ERR_DEVICE_DISTORTION; - } - else + } + else if (e.what() && strstr(e.what(), "Insufficient ")) stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; + else + stop_fatal_ = SCANNER_ERR_IMAGE_PROC_FATAL; VLOG_MINI_1(LOG_LEVEL_FATAL, "[thread_handle_image_process]:is opencv Fatal and stop scanner: %s\n", e.what()); do_stop(); invoke_stop = true; + save_exception_image(tiny_buffer, id, "opencv-excep"); break; } catch (...) { VLOG_MINI_1(LOG_LEVEL_FATAL, "[thread_handle_image_process]:stop scanner!!! Insufficient memory when proecss image with %d bytes.\n", tiny_buffer->size()); - stop_fatal_ = SCANNER_ERR_INSUFFICIENT_MEMORY; + stop_fatal_ = SCANNER_ERR_IMAGE_PROC_FATAL; do_stop(); invoke_stop = true; + save_exception_image(tiny_buffer, id, "opencv-excep"); break; } } @@ -3664,6 +3694,7 @@ int hg_scanner::save_usb_data(std::shared_ptr data) } if (!data->swap()) { + VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "USB packet(%04d) swap failed.\n", usb_img_index_); ret = SCANNER_ERR_OPEN_FILE_FAILED; } else @@ -3699,7 +3730,7 @@ int hg_scanner::save_usb_data(std::shared_ptr data) { VLOG_MINI_1(LOG_LEVEL_WARNING, "Warning: memory usage(%.2fMB) maybe leading exception!\r\n", Memoryusae); } - imgs_.Put(data, data->size(), hg_scanner_mgr::unique_id()); + imgs_.Put(data, data->size(), usb_img_index_); if (wait_img_.is_waiting()) wait_img_.notify(); } @@ -5147,24 +5178,62 @@ int hg_scanner::get_scan_is_sleep(SANE_Bool& data) { return SCANNER_ERR_DEVICE_NOT_SUPPORT; } -void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id) +void hg_scanner::save_exception_image(std::shared_ptr& buffer, int sn, const char* desc) +{ + char name[128] = { 0 }; + FILE* dst = nullptr; + + sprintf(name, "%04d-%s.jpg", sn, desc); + dst = fopen((final_path_ + "failedimgs" + PATH_SEPARATOR + name).c_str(), "wb"); + if (dst) + { + unsigned int off = 0, + len = buffer->size(), + size = len; + unsigned char* mem = buffer->data(off, &size); + while (mem) + { + fwrite(mem, 1, size, dst); + off += size; + if (off >= len) + break; + else + { + size = len - off; + mem = buffer->data(off, &size); + } + } + fclose(dst); + } +} +bool hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id) { if (!buffer.get() || !ImagePrc_pHandle_) { - return; + VLOG_MINI_1(LOG_LEVEL_FATAL, "process image %d fatal: data is empty or image-process object is not initialized, stop scanning ...\n", id); + do_stop(); + return false; } 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; + std::string fimg(final_path_ + "failedimgs" + PATH_SEPARATOR); void* buf = NULL; hg_imgproc::load_buffer(ImagePrc_pHandle_, buffer); int imgStatus = buffer->get_image_statu(); - hg_imgproc::decode(ImagePrc_pHandle_, pid_, &img_conf_, ¶m, correction_image_map_); + err = hg_imgproc::decode(ImagePrc_pHandle_, pid_, &img_conf_, ¶m, correction_image_map_); (this->*dump_img_)(ImagePrc_pHandle_, "decode"); + if (err != SCANNER_ERR_OK) + { + save_exception_image(buffer, id, "decode"); + VLOG_MINI_2(LOG_LEVEL_FATAL, "Decode image(%d) with bytes %u failed, stop scanning.\n", id, buffer->size()); + do_stop(); + return false; + } if (is_dpi_color_check) { @@ -5293,18 +5362,7 @@ void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id if ((img_conf_.refuseInflow) && (pid_ != 0x239 && pid_ != 0x439)) { - int lv = image_prc_param_.bits.is_permeate_lv_; //image_prc_param_.bits.is_permeate_lv_ = 0 1 2 3 4 - - if (0 == lv) - lv = 20; - else if (1 == lv) - lv = 30; - else if (2 == lv) - lv = 40; - else if (3 == lv) - lv = 50; - else if (4 == lv) - lv = 60; + int lv = image_prc_param_.bits.is_permeate_lv_ * 10 + 20; //image_prc_param_.bits.is_permeate_lv_ = 0 1 2 3 4 hg_imgproc::antiInflow(ImagePrc_pHandle_, lv); (this->*dump_img_)(ImagePrc_pHandle_, "antiInflow"); @@ -5392,7 +5450,7 @@ void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id if (is_multiout)//239 { int multi_out = img_conf_.multiOutput; - err = hg_imgproc::multi_out(ImagePrc_pHandle_, multi_out); + err = hg_imgproc::multi_out(ImagePrc_pHandle_, multi_out, bw_threshold_); (this->*dump_img_)(ImagePrc_pHandle_, "multi_out"); } } @@ -5412,7 +5470,9 @@ void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id if (bmpdata.empty()) { status_ = SCANNER_ERR_NO_DATA; - return; + VLOG_MINI_1(LOG_LEVEL_FATAL, "process image %d fatal: image data is empty! stop scanning ...\n", id); + do_stop(); + return false; } buf = bmpdata.data(); ih.total_bytes = bmpdata.size(); @@ -5425,6 +5485,8 @@ void hg_scanner::image_process(std::shared_ptr& buffer, uint32_t id save_final_image(&ih, buf, id); id = -1; } + + return true; } int hg_scanner::image_configuration(SCANCONF& ic) { @@ -5541,6 +5603,7 @@ int hg_scanner::image_configuration(SCANCONF& ic) 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.refuseInflow_level = image_prc_param_.bits.is_permeate_lv_ * 10 + 20; ic.colorCorrection = 0; ic.removeMorr = image_prc_param_.bits.remove_morr; ic.errorExtention = image_prc_param_.bits.error_extention;// diff --git a/hgdriver/hgdev/hg_scanner.h b/hgdriver/hgdev/hg_scanner.h index eb514a4..a73a77f 100644 --- a/hgdriver/hgdev/hg_scanner.h +++ b/hgdriver/hgdev/hg_scanner.h @@ -130,7 +130,8 @@ class hg_scanner void working_begin(void*); void working_done(void*); - void image_process(std::shared_ptr& buffer, uint32_t id); + void save_exception_image(std::shared_ptr& buffer, int sn, const char* desc); + bool image_process(std::shared_ptr& buffer, uint32_t id); // 返回true - continue; false - exit and invoked do_stop void reset_custom_area_range(int paper); float reset_custom_area_jsn_value(const char* name, double& var, float range_l, float range_u, float value_l, float value_u); // return cur value int set_color_change(void); diff --git a/hgdriver/hgdev/hg_scanner_200.cpp b/hgdriver/hgdev/hg_scanner_200.cpp index a7f0edc..76bb0a4 100644 --- a/hgdriver/hgdev/hg_scanner_200.cpp +++ b/hgdriver/hgdev/hg_scanner_200.cpp @@ -217,7 +217,20 @@ void hg_scanner_200::thread_handle_usb_read(void) } io_->set_timeout(200); - pop_image(); + ret = pop_image(); + if (ret != SCANNER_ERR_OK) + { + hg_log::log(LOG_LEVEL_FATAL, "Try ONCE pop_firt_image after 100ms ...\n"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ret = pop_image(); + if (ret) + { + hg_log::log(LOG_LEVEL_FATAL, "pop_firt_image failed, stop scanning!\n"); + do_stop(); + status_ = ret; + break; + } + } sw.reset(); first = false; } diff --git a/hgdriver/hgdev/hg_scanner_239.cpp b/hgdriver/hgdev/hg_scanner_239.cpp index a9b3a4b..034d086 100644 --- a/hgdriver/hgdev/hg_scanner_239.cpp +++ b/hgdriver/hgdev/hg_scanner_239.cpp @@ -719,6 +719,7 @@ int hg_scanner_239::read_one_image_from_usb(SANE_Image_Statu statu) ret = SCANNER_ERR_INSUFFICIENT_MEMORY; else // if (ret == SCANNER_ERR_OK) { + io_->set_timeout(1000); std::lock_guard lock(io_lock_); // write reading command @@ -726,7 +727,7 @@ int hg_scanner_239::read_one_image_from_usb(SANE_Image_Statu statu) buf->set_image_statu(statu); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + //std::this_thread::sleep_for(std::chrono::milliseconds(10)); r = total; if (ret == SCANNER_ERR_OK) { @@ -791,8 +792,15 @@ int hg_scanner_239::read_one_image_from_usb(SANE_Image_Statu statu) } if (is_scanner_err_ok) { - pop_first_image(); + ret = pop_first_image(); + if (ret != SCANNER_ERR_OK) + { + hg_log::log(LOG_LEVEL_FATAL, "Try ONCE pop_firt_image after 100ms ...\n"); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ret = pop_first_image(); + } } + return ret; } int hg_scanner_239::discard_all_images(void) @@ -1358,7 +1366,7 @@ void hg_scanner_239::thread_get_dves_image(void) if (sw.elapsed_s() > 120 && !is_auto_scan()) { status_ = ret; - notify_ui_working_status(from_default_language(STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, ret); // 取图通信超时 + notify_ui_working_status(from_default_language(STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, ret); // 鍙栧浘閫氫俊瓒呮椂 VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "get image time out:%s\n", hg_scanner_err_name(status_)); break; } @@ -1367,10 +1375,10 @@ void hg_scanner_239::thread_get_dves_image(void) { if ((get_status() & 0x03) == 0) { - do_stop(); + int err = do_stop(); is_quit_wait_paper_scan = true;//标记待纸扫描时间到了自动结束 notify_ui_working_status(from_default_language(STATU_DESC_SCANNER_ERR_DEVICE_EXIT_WAIT_SCAN), SANE_EVENT_ERROR, status_); - VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "auto paper scan exit :%s\n", from_default_language(STATU_DESC_SCANNER_ERR_DEVICE_EXIT_WAIT_SCAN)); + VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "auto paper scan exit :%s\n", hg_scanner_err_description(err)); } else sw1.reset(); diff --git a/hgdriver/hgdev/hg_scanner_300.cpp b/hgdriver/hgdev/hg_scanner_300.cpp index a5ebfd3..30175f8 100644 --- a/hgdriver/hgdev/hg_scanner_300.cpp +++ b/hgdriver/hgdev/hg_scanner_300.cpp @@ -89,7 +89,7 @@ hg_scanner_300::hg_scanner_300(const char* dev_name,int pid, usb_io* io) : { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "hg_scanner_300(%s) constructing ...\n", hg_log::format_ptr(this).c_str()); dsp_config.value = 0; - dsp_config.params_3288.enableLed = 1; //默认? + dsp_config.params_3288.enableLed = 1; //默认值 dsp_config.params_3288.isCorrect = 1; int ret = initdevice(); @@ -118,7 +118,7 @@ hg_scanner_300::hg_scanner_300(const char* dev_name,int pid, usb_io* io) : firmware_sup_log_export_G300_ = year_date.compare("230430") >= 0 ? true : false; #ifndef MAPPING_FUNCTION_IN_BASE - init_setting_map(setting_map_, ARRAY_SIZE(setting_map_));//优先初始? + init_setting_map(setting_map_, ARRAY_SIZE(setting_map_));//优先初始化 #endif if (init_settings(pid_)) @@ -159,11 +159,11 @@ void hg_scanner_300::thread_handle_usb_read(void) } //printf("usb.u32_Data = %d ret = %d\r\n",usb.u32_Data,ret); - //如果设备出现卡纸 或者双张等设备信息问题,需要等到设备进行发送stop才能停止?所以始终以 "停止" 消息为结束信? - //如果有图的情况下,并且卡纸或双张等,设备会先发送卡纸双张信息。所以接受到错误信息之后,仍需要把图像取出来? + //如果设备出现卡纸 或者双张等设备信息问题,需要等到设备进行发送stop才能停止。 所以始终以 "停止" 消息为结束信号 + //如果有图的情况下,并且卡纸或双张等,设备会先发送卡纸双张信息。所以接受到错误信息之后,仍需要把图像取出来。 if (ret == SCANNER_ERR_DEVICE_STOPPED) { - status_ = !savestatus_.empty() ? savestatus_[0] : SCANNER_ERR_OK;//以第一个消息为? + status_ = !savestatus_.empty() ? savestatus_[0] : SCANNER_ERR_OK;//以第一个消息为准 savestatus_.clear(); if (user_cancel_) { @@ -240,7 +240,7 @@ void hg_scanner_300::thread_handle_usb_read(void) VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s\n", hg_scanner_err_description(status_)); break; } - if (sw.elapsed_ms() > 30000 && img_conf_.resolution_dst != 600)//防止状态信息一直取不上来导致卡? + if (sw.elapsed_ms() > 30000 && img_conf_.resolution_dst != 600)//防止状态信息一直取不上来导致卡死 { if ((img_conf_.papertype == TwSS::MaxSize || img_conf_.papertype == TwSS::USStatement) && pid_ == 0x0300 && firmware_sup_dpi_600) { @@ -248,30 +248,30 @@ void hg_scanner_300::thread_handle_usb_read(void) } else { - if (!savestatus_.empty())//以第一个消息为? + if (!savestatus_.empty())//以第一个消息为准 { status_ = savestatus_[0]; } savestatus_.clear(); hg_log::log(LOG_LEVEL_WARNING, "Get Status TimeOut,get image out 30S\n"); - notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 鍙栧浘閫氫俊瓒呮? + notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 閸欐牕娴橀柅姘繆鐡掑懏妞? break; } } if (sw.elapsed_s() > 130) { - if (!savestatus_.empty())//以第一个消息为? + if (!savestatus_.empty())//以第一个消息为准 { status_ = savestatus_[0]; } savestatus_.clear(); hg_log::log(LOG_LEVEL_WARNING, "MaxSize TimeOut,Get Image 130s\n"); - notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 鍙栧浘閫氫俊瓒呮? + notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 閸欐牕娴橀柅姘繆鐡掑懏妞? break; } if (ret == SCANNER_ERR_OK && usb.u32_Count > 0) { - int totalNum = usb.u32_Count & 0x3fffffff; // 2022-08-04: 兼容Android,默认图片大小均?GB以内 + int totalNum = usb.u32_Count & 0x3fffffff; // 2022-08-04: 兼容Android,默认图片大小均在1GB以内 VLOG_MINI_2(LOG_LEVEL_WARNING, "Get Scaner Image Size:%d bytes,Image Num[%d]\n", totalNum,img_num); img_num++; if (totalNum) @@ -382,7 +382,7 @@ int hg_scanner_300::do_start(void) { return ret; } - if (is_devs_sleep_)//设备在睡眠的状态当中获取固件是失败的,所以在这个地方进行标志位设置。(总感觉不保险? + if (is_devs_sleep_)//设备在睡眠的状态当中获取固件是失败的,所以在这个地方进行标志位设置。(总感觉不保险) { is_devs_sleep_ = false; set_kernelsnap_ver(); @@ -807,7 +807,7 @@ int hg_scanner_300::initdevice() if (status_ != SCANNER_ERR_DEVICE_SLEEPING) { set_kernelsnap_ver(); - is_devs_sleep_ = false; // 睡眠唤醒 客户提前点击设置这边固件版本?还没有做判断? + is_devs_sleep_ = false; // 睡眠唤醒 客户提前点击设置这边固件版本号 还没有做判断的 } return status_; } @@ -839,7 +839,7 @@ void hg_scanner_300::writedown_image_configuration(void) // ic.hardwarecaps.is_autopaper = dsp_config_.params_dsp.is_autopaper; ic.hardwarecaps.capturepixtype = 0; //暂无参数 获取图像类型 - ic.hardwarecaps.lowpowermode = LowPowerMode::Min_None; //暂无参数 设置休眠时间 两个参数3399未使? + ic.hardwarecaps.lowpowermode = LowPowerMode::Min_None; //暂无参数 设置休眠时间 两个参数3399未使用 image_configuration(ic); } void hg_scanner_300::printf_devconfig(setting_hardware::HGSCANCONF_3288 *d) @@ -980,7 +980,7 @@ int hg_scanner_300::get_correction_image(int inx , int dpi, int mode) cv::Mat white_mat; cv::Mat black_mat;; - for (size_t i = 0; i < 2; i++) //黑白一起保存下? + for (size_t i = 0; i < 2; i++) //黑白一起保存下来 { vector imagedata; @@ -1022,7 +1022,7 @@ int hg_scanner_300::get_correction_image(int inx , int dpi, int mode) if (mat.empty()) { VLOG_MINI_1(LOG_LEVEL_WARNING, "get_correction_image image is NULL:%d\n", image_info.info.params.status); - return SCANNER_ERR_NO_DATA; //只要有一张图没有 直接退? + return SCANNER_ERR_NO_DATA; //只要有一张图没有 直接退了 } float f = 0.0; @@ -1055,7 +1055,7 @@ std::string hg_scanner_300::get_firmware_version() { char buf[20] = { 0 }; int ret = SCANNER_ERR_OK, - len = 10; //协议定义长度?0 100 200 =8 + len = 10; //协议定义长度为10 100 200 =8 USBCB cmd = { setting3288dsp::GET_FW_VERSION,len,0,}; { diff --git a/hgdriver/hgdev/hg_scanner_306.cpp b/hgdriver/hgdev/hg_scanner_306.cpp index c948c7d..99b9968 100644 --- a/hgdriver/hgdev/hg_scanner_306.cpp +++ b/hgdriver/hgdev/hg_scanner_306.cpp @@ -84,7 +84,7 @@ hg_scanner_306::hg_scanner_306(const char* dev_name,int pid, usb_io* io) : { VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "hg_scanner_306(%s) constructing ...\n", hg_log::format_ptr(this).c_str()); dsp_config.value = 0; - dsp_config.params_7010.enableLed = 1; //默认? + dsp_config.params_7010.enableLed = 1; //默认值 dsp_config.params_7010.isCorrect = 1; int ret = get_device_type(firmware_sup_device_7010); @@ -101,7 +101,7 @@ hg_scanner_306::hg_scanner_306(const char* dev_name,int pid, usb_io* io) : } #ifndef MAPPING_FUNCTION_IN_BASE - init_setting_map(setting_map_, ARRAY_SIZE(setting_map_));//优先初始? + init_setting_map(setting_map_, ARRAY_SIZE(setting_map_));//优先初始化 #endif if (init_settings(pid_)) init_settings((jsontext1 + jsontext2 + jsontext3).c_str()); @@ -136,11 +136,11 @@ void hg_scanner_306::thread_handle_usb_read(void) } //printf("usb.u32_Data = %d ret = %d\r\n",usb.u32_Data,ret); - //如果设备出现卡纸 或者双张等设备信息问题,需要等到设备进行发送stop才能停止?所以始终以 "停止" 消息为结束信? - //如果有图的情况下,并且卡纸或双张等,设备会先发送卡纸双张信息。所以接受到错误信息之后,仍需要把图像取出来? + //如果设备出现卡纸 或者双张等设备信息问题,需要等到设备进行发送stop才能停止。 所以始终以 "停止" 消息为结束信号 + //如果有图的情况下,并且卡纸或双张等,设备会先发送卡纸双张信息。所以接受到错误信息之后,仍需要把图像取出来。 if (ret == SCANNER_ERR_DEVICE_STOPPED) { - status_ = !savestatus_.empty() ? savestatus_[0] : SCANNER_ERR_OK;//以第一个消息为? + status_ = !savestatus_.empty() ? savestatus_[0] : SCANNER_ERR_OK;//以第一个消息为准 savestatus_.clear(); if (user_cancel_) { @@ -217,7 +217,7 @@ void hg_scanner_306::thread_handle_usb_read(void) VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%s\n", hg_scanner_err_description(status_)); break; } - if (sw.elapsed_ms() > 30000 && img_conf_.resolution_dst != 600)//防止状态信息一直取不上来导致卡? + if (sw.elapsed_ms() > 30000 && img_conf_.resolution_dst != 600)//防止状态信息一直取不上来导致卡死 { if ((img_conf_.papertype == TwSS::MaxSize || img_conf_.papertype == TwSS::USStatement) && pid_ == 0x0300 && firmware_sup_dpi_600) { @@ -225,25 +225,25 @@ void hg_scanner_306::thread_handle_usb_read(void) } else { - if (!savestatus_.empty())//以第一个消息为? + if (!savestatus_.empty())//以第一个消息为准 { status_ = savestatus_[0]; } savestatus_.clear(); hg_log::log(LOG_LEVEL_WARNING, "Get Status TimeOut,get image out 30S\n"); - notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 鍙栧浘閫氫俊瓒呮? + notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 鍙栧浘閫氫俊瓒呮椂 break; } } if (sw.elapsed_s() > 130) { - if (!savestatus_.empty())//以第一个消息为? + if (!savestatus_.empty())//以第一个消息为准 { status_ = savestatus_[0]; } savestatus_.clear(); hg_log::log(LOG_LEVEL_WARNING, "MaxSize TimeOut,Get Image 130s\n"); - notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 鍙栧浘閫氫俊瓒呮? + notify_ui_working_status(hg_log::lang_load(ID_STATU_DESC_SCANNER_ERR_DEVICE_GET_IMAGE_OUTTIME), SANE_EVENT_ERROR, status_); // 閸欐牕娴橀柅姘繆鐡掑懏妞? break; } if (ret == SCANNER_ERR_OK && usb.u32_Count > 0) @@ -338,7 +338,7 @@ int hg_scanner_306::do_start(void) { return ret; } - if (is_devs_sleep_)//设备在睡眠的状态当中获取固件是失败的,所以在这个地方进行标志位设置。(总感觉不保险? + if (is_devs_sleep_)//设备在睡眠的状态当中获取固件是失败的,所以在这个地方进行标志位设置。(总感觉不保险) { is_devs_sleep_ = false; set_kernelsnap_ver(); @@ -763,7 +763,7 @@ int hg_scanner_306::initdevice() if (status_ != SCANNER_ERR_DEVICE_SLEEPING) { set_kernelsnap_ver(); - is_devs_sleep_ = false; // 睡眠唤醒 客户提前点击设置这边固件版本?还没有做判断? + is_devs_sleep_ = false; // 睡眠唤醒 客户提前点击设置这边固件版本号 还没有做判断的 } return SCANNER_ERR_OK; } @@ -795,7 +795,7 @@ void hg_scanner_306::writedown_image_configuration(void) // ic.hardwarecaps.is_autopaper = dsp_config_.params_dsp.is_autopaper; ic.hardwarecaps.capturepixtype = 0; //暂无参数 获取图像类型 - ic.hardwarecaps.lowpowermode = LowPowerMode::Min_None; //暂无参数 设置休眠时间 两个参数3399未使? + ic.hardwarecaps.lowpowermode = LowPowerMode::Min_None; //暂无参数 设置休眠时间 两个参数3399未使用 image_configuration(ic); } void hg_scanner_306::printf_devconfig(setting_hardware::HGSCANCONF_7010 *d) @@ -875,7 +875,7 @@ int hg_scanner_306::get_correction_image(int inx , int dpi, int mode) cv::Mat white_mat; cv::Mat black_mat;; - for (size_t i = 0; i < 2; i++) //黑白一起保存下? + for (size_t i = 0; i < 2; i++) //黑白一起保存下来 { vector imagedata; @@ -913,7 +913,7 @@ int hg_scanner_306::get_correction_image(int inx , int dpi, int mode) if (mat.empty()) { VLOG_MINI_1(LOG_LEVEL_WARNING, "get_correction_image image is NULL:%d\n", image_info.info.params.status); - return SCANNER_ERR_NO_DATA; //只要有一张图没有 直接退? + return SCANNER_ERR_NO_DATA; //只要有一张图没有 直接退了 } float f = 0.0; @@ -939,7 +939,7 @@ std::string hg_scanner_306::get_firmware_version() { char buf[20] = { 0 }; int ret = SCANNER_ERR_OK, - len = 10; //协议定义长度?0 100 200 =8 + len = 10; //协议定义长度为10 100 200 =8 USBCB cmd = { setting3288dsp::GET_FW_VERSION,len,0,}; { @@ -1226,13 +1226,13 @@ int hg_scanner_306::set_scan_lock_check_val(string str) } //#enum scanner_err //#{ -//# SCANNER_ERR_OK = 0, //设备正常状? +//# SCANNER_ERR_OK = 0, //设备正常状态 //# SCANNER_ERR_SLEEP, 1 //设备处于休眠当中 -//# SCANNER_ERR_UPDATE_OK, 2 //设备更新:成? +//# SCANNER_ERR_UPDATE_OK, 2 //设备更新:成功 //# SCANNER_ERR_UPDATE_UPDATAING, 3 //设备更新:进行中 -//# SCANNER_ERR_UPDATE_CHECK_VAL_ERROR, 4 //设备更新:校验检测错? -//# SCANNER_ERR_UPDATE_CHECK_FILE_LOST, 5 //设备更新:文件丢? -//# SCANNER_ERR_UPDATE_UNZIP_FAIL, 6 //设备更新:解压失? +//# SCANNER_ERR_UPDATE_CHECK_VAL_ERROR, 4 //设备更新:校验检测错误 +//# SCANNER_ERR_UPDATE_CHECK_FILE_LOST, 5 //设备更新:文件丢失 +//# SCANNER_ERR_UPDATE_UNZIP_FAIL, 6 //设备更新:解压失败 //#}; int hg_scanner_306::set_firmware_upgrade(std::string str) { diff --git a/hgdriver/hgdev/image_process.cpp b/hgdriver/hgdev/image_process.cpp index dc0b3e1..ae7f2f4 100644 --- a/hgdriver/hgdev/image_process.cpp +++ b/hgdriver/hgdev/image_process.cpp @@ -758,13 +758,13 @@ namespace hg_imgproc } return SCANNER_ERR_OK; } - int multi_out(int out_type) + int multi_out(int out_type, int bw_threshold) { std::vector mats(mats_); std::vector mat; mats_.clear(); - IMageMulti output(out_type); + IMageMulti output(out_type, bw_threshold); for(size_t i = 0;i < mats.size();i++) { @@ -1973,9 +1973,9 @@ namespace hg_imgproc { return ((imgproc*)himg)->fadeback(); } - int multi_out(HIMGPRC himg,int out_type) + int multi_out(HIMGPRC himg, int out_type, int bw_threshold) { - return ((imgproc*)himg)->multi_out(out_type); + return ((imgproc*)himg)->multi_out(out_type, bw_threshold); } int multi_out_red(HIMGPRC himg) { diff --git a/hgdriver/hgdev/image_process.h b/hgdriver/hgdev/image_process.h index 945c747..e1320fc 100644 --- a/hgdriver/hgdev/image_process.h +++ b/hgdriver/hgdev/image_process.h @@ -182,7 +182,7 @@ namespace hg_imgproc //拆分 int split(HIMGPRC himg,int split3399); int fadeback(HIMGPRC himg); - int multi_out(HIMGPRC himg,int out_type); + int multi_out(HIMGPRC himg,int out_type, int bw_threshold); int multi_out_red(HIMGPRC himg); int auto_matic_color(HIMGPRC himg,int color_type); int auto_crop(HIMGPRC himg, float dpi); diff --git a/hgdriver/hgdev/scanner_manager.cpp b/hgdriver/hgdev/scanner_manager.cpp index 3fad6fb..af8a320 100644 --- a/hgdriver/hgdev/scanner_manager.cpp +++ b/hgdriver/hgdev/scanner_manager.cpp @@ -839,6 +839,7 @@ scanner_err hg_scanner_mgr::hg_scanner_close(scanner_handle h, bool force) } } + SCAN_PTR(h)->stop(); SCAN_PTR(h)->close(force); delete SCAN_PTR(h); diff --git a/hgdriver/wrapper/hg_log.cpp b/hgdriver/wrapper/hg_log.cpp index 3cfd24c..3ba516b 100644 --- a/hgdriver/wrapper/hg_log.cpp +++ b/hgdriver/wrapper/hg_log.cpp @@ -264,6 +264,13 @@ extern "C" return true; } + static bool save_dir_files(const char* path_file, void* param) + { + ((std::vector*)param)->push_back(path_file); + + return true; + } + #if defined(WIN32) || defined(_WIN64) static std::string u2a(const wchar_t* u, UINT cp = CP_ACP) { @@ -287,25 +294,56 @@ extern "C" static int enum_files(const char* dir, bool recursive, bool(*found_file)(const char* path_file, void* param), void* param) { int ret = 0; - HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); - MODULEENTRY32W pei = { 0 }; - if (h == INVALID_HANDLE_VALUE) - ret = GetLastError(); + if (!dir || *dir == 0) + { + HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + MODULEENTRY32W pei = { 0 }; + + if (h == INVALID_HANDLE_VALUE) + ret = GetLastError(); + else + { + pei.dwSize = sizeof(pei); + if (Module32FirstW(h, &pei)) + { + do + { + std::string ansi(u2a(pei.szExePath)); + if (!found_file(ansi.c_str(), param)) + break; + pei.dwSize = sizeof(pei); + } while (Module32NextW(h, &pei)); + } + CloseHandle(h); + } + } else { - pei.dwSize = sizeof(pei); - if (Module32FirstW(h, &pei)) + WIN32_FIND_DATAA wfd = { 0 }; + HANDLE h = FindFirstFileA((std::string(dir) + "\\*").c_str(), &wfd); + if (h == INVALID_HANDLE_VALUE) + ret = GetLastError(); + else { do { - std::string ansi(u2a(pei.szExePath)); - if (!found_file(ansi.c_str(), param)) + if (strcmp(wfd.cFileName, ".") == 0 || strcmp(wfd.cFileName, "..") == 0) + continue; + if (!found_file((std::string(dir) + "\\" + wfd.cFileName).c_str(), param)) + { + ret = ECANCELED; break; - pei.dwSize = sizeof(pei); - } while (Module32NextW(h, &pei)); + } + if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && recursive) + { + ret = enum_files((std::string(dir) + "\\" + wfd.cFileName).c_str(), recursive, found_file, param); + if (ret == ECANCELED) + break; + } + } while (FindNextFileA(h, &wfd)); + FindClose(h); } - CloseHandle(h); } return ret; @@ -539,6 +577,10 @@ extern "C" { return MKDIR(fodler, S_IREAD | S_IWRITE | S_IEXEC) == 0 || errno == EEXIST; } + void get_foler_files(const char* folder, std::vector& files, bool recursive) + { + enum_files(folder, recursive, save_dir_files, &files); + } std::string ini_get(const char* app, const char* key) { return ini_.get(app, key); diff --git a/hgdriver/wrapper/hg_log.h b/hgdriver/wrapper/hg_log.h index 3813b15..2ca5f6c 100644 --- a/hgdriver/wrapper/hg_log.h +++ b/hgdriver/wrapper/hg_log.h @@ -6,6 +6,8 @@ #pragma once #include +#include + #include "../../sdk/hginclude/huagaoxxx_warraper_ex.h" #include "lang/app_language.h" #if defined(WIN32) || defined(_WIN64) @@ -64,6 +66,7 @@ extern "C" unsigned long long available_memory(void); void str_tolower(std::string& str); bool create_folder(const char* fodler); + void get_foler_files(const char* folder, std::vector& files, bool recursive = false); std::string ini_get(const char* app, const char* key); void ini_set(const char* app, const char* key, const char* val); diff --git a/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp b/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp index 357dc52..cbde3cc 100644 --- a/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp +++ b/hgdriver/wrapper/huagaoxxx_warraper_ex.cpp @@ -240,6 +240,8 @@ extern "C" RETURN_IF(err, SCANNER_ERR_CONFIGURATION_CHANGED); RETURN_IF(err, SCANNER_ERR_RELOAD_IMAGE_PARAM); RETURN_IF(err, SCANNER_ERR_RELOAD_OPT_PARAM); + RETURN_IF(err, SCANNER_ERR_IMAGE_PROC_FATAL); + RETURN_IF(err, SCANNER_ERR_NOT_OPEN); RETURN_IF(err, SCANNER_ERR_NOT_START); RETURN_IF(err, SCANNER_ERR_NOT_ANY_MORE); @@ -317,6 +319,8 @@ extern "C" RETURN_DESC_IF(err, SCANNER_ERR_CONFIGURATION_CHANGED); RETURN_DESC_IF(err, SCANNER_ERR_RELOAD_IMAGE_PARAM); RETURN_DESC_IF(err, SCANNER_ERR_RELOAD_OPT_PARAM); + RETURN_DESC_IF(err, SCANNER_ERR_IMAGE_PROC_FATAL); + RETURN_DESC_IF(err, SCANNER_ERR_NOT_OPEN); RETURN_DESC_IF(err, SCANNER_ERR_NOT_START); RETURN_DESC_IF(err, SCANNER_ERR_NOT_ANY_MORE); diff --git a/hgsane/sane_hg_mdw.cpp b/hgsane/sane_hg_mdw.cpp index 186ec86..6e3b2c9 100644 --- a/hgsane/sane_hg_mdw.cpp +++ b/hgsane/sane_hg_mdw.cpp @@ -1688,6 +1688,8 @@ SANE_Status hg_sane_middleware::start(SANE_Handle h, void* async_event) scanner_handle hs = find_openning_device(h); scanner_err err = SCANNER_ERR_INVALID_PARAMETER; + LOG_INFO(LOG_LEVEL_ALL, "sane_start ...\n"); + if(hs) err = hg_scanner_start(hs, async_event, -1); @@ -2589,8 +2591,6 @@ extern "C" { // avoid compiler exporting name in C++ style !!! } SANE_Status inner_sane_start(SANE_Handle handle) { - LOG_INFO(LOG_LEVEL_ALL, "sane_start\n"); - return hg_sane_middleware::instance()->start(handle, NULL); } SANE_Status inner_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length)