code_device/hgdriver/hgdev/hg_scanner.cpp

3727 lines
103 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

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

#include "hg_scanner.h"
#include "../wrapper/hg_log.h"
#include "sane/sane_option_definitions.h"
#include "scanner_setting.h"
#include "scanner_manager.h"
#if defined(WIN32) || defined(_WIN64)
#include <direct.h>
#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)
, 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)
{
init_setting_func_map();
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<std::vector<char>> data, std::string* path_file, unsigned int index)
{
char head[40] = { 0 };
std::string file("");
FILE* dst = nullptr;
int ret = SCANNER_ERR_OK;
sprintf(head, "usb_%05u", index);
if(!path_file || path_file->empty())
file = hg_scanner::temporary_file((char*)".jpg", (char*)head);
dst = fopen(file.c_str(), "wb");
if (dst)
{
size_t wrote = fwrite(data->data(), 1, data->size(), dst);
if (wrote == data->size())
{
if (path_file)
*path_file = file;
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "--->Wrote %u bytes to file '%s'\n", wrote, file.c_str());
}
else
{
ret = SCANNER_ERR_WRITE_FILE_FAILED;
VLOG_MINI_3(LOG_LEVEL_FATAL, "Failed in writting file(%u/%u) '%s'\n", wrote, data->size(), file.c_str());
}
fclose(dst);
}
else
{
ret = SCANNER_ERR_CREATE_FILE_FAILED;
VLOG_MINI_1(LOG_LEVEL_FATAL, "Failed in creating file '%s'\n", file.c_str());
}
return ret;
}
void hg_scanner::thread_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<hg_scanner>(this, &hg_scanner::working_begin, &hg_scanner::working_done, NULL);
usb_img_index_ = 0;
thread_handle_usb_read();
if (scan_life_->release() == 0)
scan_life_ = NULL;
}
}
void hg_scanner::thread_image_handle(void)
{
while (run_)
{
wait_img_.wait();
if (!run_)
break;
scan_life_->add_ref();
thread_handle_image_process();
if (scan_life_->release() == 0)
scan_life_ = NULL;
}
}
void hg_scanner::dump_image_empty(hg_imgproc::HIMGPRC himg, const char* desc)
{}
void hg_scanner::dump_image_real(hg_imgproc::HIMGPRC himg, const char* desc)
{
char sn[40] = { 0 };
sprintf(sn, "_%03d.jpg", final_img_index_ + 1);
hg_imgproc::dump_2_file(himg, (dump_usb_path_ + PATH_SEPARATOR + desc + sn).c_str());
}
void hg_scanner::init_setting_func_map(void)
{
setting_map_[SANE_STD_OPT_NAME_RESTORE] = &hg_scanner::setting_restore;
setting_map_[SANE_STD_OPT_NAME_HELP] = &hg_scanner::setting_help;
setting_map_[SANE_STD_OPT_NAME_COLOR_MODE] = &hg_scanner::setting_color_mode;
setting_map_[SANE_STD_OPT_NAME_IS_MULTI_OUT] = &hg_scanner::setting_multi_out;
setting_map_[SANE_STD_OPT_NAME_MULTI_OUT_TYPE] = &hg_scanner::setting_multi_out_type;
setting_map_[SANE_STD_OPT_NAME_FILTER] = &hg_scanner::setting_rid_color;
setting_map_[SANE_STD_OPT_NAME_RID_MULTIOUT_RED] = &hg_scanner::setting_rid_multi_red;
setting_map_[SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED] = &hg_scanner::setting_rid_answer_red;
setting_map_[SANE_STD_OPT_NAME_ERASE_BACKGROUND] = &hg_scanner::setting_erase_background;
setting_map_[SANE_STD_OPT_NAME_BKG_COLOR_RANGE] = &hg_scanner::setting_erase_background_range;
setting_map_[SANE_STD_OPT_NAME_NOISE_OPTIMIZE] = &hg_scanner::setting_noise_optimize;
setting_map_[SANE_STD_OPT_NAME_NOISE_SIZE] = &hg_scanner::setting_noise_optimize_range;
setting_map_[SANE_STD_OPT_NAME_PAPER] = &hg_scanner::setting_paper;
setting_map_[SANE_STD_OPT_NAME_SIZE_CHECK] = &hg_scanner::setting_paper_check;
setting_map_[SANE_STD_OPT_NAME_PAGE] = &hg_scanner::setting_page;
setting_map_[SANE_STD_OPT_NAME_DISCARD_BLANK_SENS] = &hg_scanner::setting_page_omit_empty;
setting_map_[SANE_STD_OPT_NAME_RESOLUTION] = &hg_scanner::setting_resolution;
setting_map_[SANE_STD_OPT_NAME_EXCHANGE] = &hg_scanner::setting_exchagnge;
setting_map_[SANE_STD_OPT_NAME_SPLIT] = &hg_scanner::setting_split_image;
setting_map_[SANE_STD_OPT_NAME_ANTI_SKEW] = &hg_scanner::setting_automatic_skew;
setting_map_[SANE_STD_OPT_NAME_RID_HOLE] = &hg_scanner::setting_rid_hole;
setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE] = &hg_scanner::setting_rid_hoe_range;
setting_map_[SANE_STD_OPT_NAME_BRIGHTNESS] = &hg_scanner::setting_bright;
setting_map_[SANE_STD_OPT_NAME_CONTRAST] = &hg_scanner::setting_contrast;
setting_map_[SANE_STD_OPT_NAME_GAMMA] = &hg_scanner::setting_gamma;
setting_map_[SANE_STD_OPT_NAME_SHARPEN] = &hg_scanner::setting_sharpen;
setting_map_[SANE_STD_OPT_NAME_DARK_SAMPLE] = &hg_scanner::setting_dark_sample;
setting_map_[SANE_STD_OPT_NAME_ERASE_BLACK_FRAME] = &hg_scanner::setting_erase_black_frame;
setting_map_[SANE_STD_OPT_NAME_THRESHOLD] = &hg_scanner::setting_threshold;
setting_map_[SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL] = &hg_scanner::setting_anti_noise;
setting_map_[SANE_STD_OPT_NAME_MARGIN] = &hg_scanner::setting_margin;
setting_map_[SANE_STD_OPT_NAME_FILL_BKG_MODE] = &hg_scanner::setting_filling_background;
setting_map_[SANE_STD_OPT_NAME_IS_ANTI_PERMEATE] = &hg_scanner::setting_is_permeate;
setting_map_[SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL] = &hg_scanner::setting_is_permeate_lv;
setting_map_[SANE_STD_OPT_NAME_RID_MORR] = &hg_scanner::setting_remove_morr;
setting_map_[SANE_STD_OPT_NAME_ERROR_EXTENSION] = &hg_scanner::setting_error_extention;
setting_map_[SANE_STD_OPT_NAME_RID_GRID] = &hg_scanner::setting_remove_texture;
setting_map_[SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK] = &hg_scanner::setting_ultrasonic_check;
setting_map_[SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE] = &hg_scanner::setting_go_on_when_double_checked;
setting_map_[SANE_STD_OPT_NAME_IS_CHECK_STAPLE] = &hg_scanner::setting_staple_check;
setting_map_[SANE_STD_OPT_NAME_SCAN_MODE] = &hg_scanner::setting_scan_mode;
setting_map_[SANE_STD_OPT_NAME_SCAN_COUNT] = &hg_scanner::setting_scan_count;
setting_map_[SANE_STD_OPT_NAME_TEXT_DIRECTION] = &hg_scanner::setting_text_direction;
setting_map_[SANE_STD_OPT_NAME_IS_ROTATE_BKG_180] = &hg_scanner::setting_rotate_bkg_180;
setting_map_[SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR] = &hg_scanner::setting_fractate_check;
setting_map_[SANE_STD_OPT_NAME_DOG_EAR_SIZE] = &hg_scanner::setting_fractate_check_level;
setting_map_[SANE_STD_OPT_NAME_IS_CHECK_ASKEW] = &hg_scanner::setting_skew_check;
setting_map_[SANE_STD_OPT_NAME_ASKEW_RANGE] = &hg_scanner::setting_skew_check_level;
setting_map_[SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA] = &hg_scanner::setting_is_custom_gamma;
setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA] = &hg_scanner::setting_is_custom_area;
setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT] = &hg_scanner::setting_custom_area_left;
setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT] = &hg_scanner::setting_custom_area_right;
setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_TOP] = &hg_scanner::setting_custom_area_top;
setting_map_[SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM] = &hg_scanner::setting_custom_area_bottom;
setting_map_[SANE_STD_OPT_NAME_IMAGE_QUALITY] = &hg_scanner::setting_img_quality;
setting_map_[SANE_STD_OPT_NAME_IS_FILL_COLOR] = &hg_scanner::setting_color_fill;
setting_map_[SANE_STD_OPT_NAME_IS_PHOTO_MODE] = &hg_scanner::setting_keep_watermark;
setting_map_[SANE_STD_OPT_NAME_BINARY_THRESHOLD] = &hg_scanner::setting_black_white_threshold;
setting_map_[SANE_STD_OPT_NAME_REVERSE_01] = &hg_scanner::setting_white_pixel_0;
setting_map_[SANE_STD_OPT_NAME_FEED_STRENGTH] = &hg_scanner::setting_feedmode;
setting_map_[SANE_STD_OPT_NAME_TIME_TO_SLEEP] = &hg_scanner::setting_sleeptime;
setting_map_[SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH] = &hg_scanner::setting_auto_pick_paper;
setting_map_[SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE] = &hg_scanner::setting_auto_pick_paper_threshold;
setting_map_[SANE_STD_OPT_NAME_WAIT_TO_SCAN] = &hg_scanner::setting_auto_paper_scan;
setting_map_[SANE_STD_OPT_NAME_RID_HOLE_L] = &hg_scanner::setting_isremove_left_hole;
setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L] = &hg_scanner::setting_isremove_left_hole_threshold;
setting_map_[SANE_STD_OPT_NAME_RID_HOLE_R] = &hg_scanner::setting_isremove_right_hole;
setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R] = &hg_scanner::setting_isremove_right_hole_threshold;
setting_map_[SANE_STD_OPT_NAME_RID_HOLE_T] = &hg_scanner::setting_isremove_top_hole;
setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T] = &hg_scanner::setting_isremove_top_hole_threshold;
setting_map_[SANE_STD_OPT_NAME_RID_HOLE_B] = &hg_scanner::setting_isremove_low_hole;
setting_map_[SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B] = &hg_scanner::setting_isremove_low_hole_threshold;
setting_map_[SANE_STD_OPT_NAME_FOLD_TYPE] = &hg_scanner::setting_fold_type;
}
std::string hg_scanner::setting_name_from(const char* n_or_id)
{
if (IS_PTR_NUMBER(n_or_id))
{
if ((unsigned long)n_or_id < jsn_children_.size())
return jsn_children_[(unsigned long)n_or_id];
else
return "";
}
return n_or_id;
}
void hg_scanner::get_range(const char* name, std::vector<std::string>& range, std::string& def_val, bool& is_range/*range or list*/)
{
std::string type("");
range.clear();
if (setting_jsn_.at(name).contains("range"))
{
setting_jsn_.at(name).at("type").get_to(type);
is_range = !setting_jsn_.at(name).at("range").is_array();
if (is_range)
{
if (type == "int")
{
int l = 0, u = 0;
setting_jsn_.at(name).at("range").at("min").get_to(l);
setting_jsn_.at(name).at("range").at("max").get_to(u);
char str[20];
sprintf(str, "%d", l);
range.push_back(str);
sprintf(str, "%d", u);
range.push_back(str);
}
else
{
double l = .0f, u = .0f;
setting_jsn_.at(name).at("range").at("min").get_to(l);
setting_jsn_.at(name).at("range").at("max").get_to(u);
char str[40];
sprintf(str, "%f", l);
range.push_back(str);
sprintf(str, "%f", u);
range.push_back(str);
}
}
else
{
char str[40];
for (int i = 0; i < setting_jsn_.at(name).at("range").size(); ++i)
{
if (type == "int")
{
int v = 0;
setting_jsn_.at(name).at("range").at(i).get_to(v);
sprintf(str, "%d", v);
range.push_back(str);
}
else if(type == "float")
{
double v = 0;
setting_jsn_.at(name).at("range").at(i).get_to(v);
sprintf(str, "%f", v);
range.push_back(str);
}
else
{
std::string v("");
setting_jsn_.at(name).at("range").at(i).get_to(v);
range.push_back(v);
}
}
}
}
if (type == "int")
{
int v = 0;
char sn[20] = { 0 };
setting_jsn_.at(name).at("default").get_to(v);
sprintf(sn, "%d", v);
def_val = sn;
}
else if (type == "float")
{
double v = 0;
char sn[20] = { 0 };
setting_jsn_.at(name).at("default").get_to(v);
sprintf(sn, "%f", v);
def_val = sn;
}
else if(type == "string")
setting_jsn_.at(name).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(const char* name, bool& val)
{
std::vector<std::string> range;
std::string init(""), in(val ? "true" : "false");
bool is_range = false;;
get_range(name, range, init, is_range);
if (range.size() == 0)
return true;
for (int i = 0; i < range.size(); ++i)
{
if (in == range[i])
return true;
}
val = init == "true" ? true : false;
return false;
}
bool hg_scanner::check_range(const char* name, int& val)
{
std::vector<std::string> range;
std::string init("");
bool is_range = false;;
get_range(name, range, init, is_range);
if (range.size() == 0)
return true;
if (is_range && range.size() == 2)
{
if (val >= atoi(range[0].c_str()) && val <= atoi(range[1].c_str()))
return true;
if(val < atoi(range[0].c_str()))
val = atoi(range[0].c_str());
else
val = atoi(range[1].c_str());
return false;
}
else if (!is_range)
{
for (int i = 0; i < range.size(); ++i)
{
if (atoi(range[i].c_str()) == val)
return true;
}
}
val = atoi(init.c_str());
return false;
}
bool hg_scanner::check_range(const char* name, double& val)
{
std::vector<std::string> range;
std::string init("");
bool is_range = false;;
get_range(name, range, init, is_range);
if (range.size() == 0)
return true;
if (is_range && range.size() == 2)
{
if (val >= atof(range[0].c_str()) && val <= atof(range[1].c_str()))
return true;
if (val < atof(range[0].c_str()))
val = atof(range[0].c_str());
else
val = atof(range[1].c_str());
return false;
}
else if (!is_range)
{
for (int i = 0; i < range.size(); ++i)
{
if (fabs(atof(range[i].c_str()) - val) < .000001)
return true;
}
}
val = atof(init.c_str());
return false;
}
bool hg_scanner::check_range(const char* name, std::string& val)
{
std::vector<std::string> range;
std::string init(""), in(val);
bool is_range = false;;
get_range(name, range, init, is_range);
if (range.size() == 0)
return true;
for (int i = 0; i < range.size(); ++i)
{
if (in == range[i])
return true;
}
val = init;
return false;
}
bool hg_scanner::check_paper_and_resolution(int res, int paper)
{
if (res == 600)
{
if (paper == PAPER_MAX_SIZE ||
paper == PAPER_MAX_SIZE_CLIP ||
paper == PAPER_TRIGEMINY)
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "resolution '%d' is in-compatible with paper '%s'\n", res, paper_string(paper).c_str());
return false;
}
}
return true;
}
bool hg_scanner::check_resolution_and_quality(int res, const char* quality)
{
if (res == 600 && strcmp(quality, OPTION_VALUE_HZ_SDYX) == 0)
{
VLOG_MINI_2(LOG_LEVEL_WARNING, "resolution '%d' is in-compatible with quality '%s'\n", res, quality);
return false;
}
return true;
}
int hg_scanner::restore(const char* name)
{
std::string val("");
int ret = SCANNER_ERR_OK;
setting_jsn_.at(name).at("type").get_to(val);
if (val == "string")
{
val = "";
setting_jsn_.at(name).at("default").get_to(val);
char* buf = NULL;
int size = 0;
setting_jsn_.at(name).at("size").get_to(size);
buf = (char*)malloc(size + 4);
if (buf)
{
bzero(buf, size + 4);
strcpy(buf, val.c_str());
ret = set_setting(name, buf, val.length());
free(buf);
}
else
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
else if (val == "int")
{
int v = 0;
setting_jsn_.at(name).at("default").get_to(v);
ret = set_setting(name, (char*)&v, sizeof(v));
}
else if (val == "float")
{
double v = .0f;
setting_jsn_.at(name).at("default").get_to(v);
ret = set_setting(name, (char*)&v, sizeof(v));
}
else if (val == "bool")
{
bool v = false;
setting_jsn_.at(name).at("default").get_to(v);
ret = set_setting(name, (char*)&v, sizeof(v));
}
return ret;
}
bool hg_scanner::get_default_value(void* buf, json* jsn)
{
std::string type("");
jsn->at("type").get_to(type);
if (type == "bool")
{
bool v = false;
jsn->at("default").get_to(v);
*((SANE_Bool*)buf) = v;
}
else if (type == "int")
{
int v = 0;
jsn->at("default").get_to(v);
*((SANE_Int*)buf) = v;
}
else if (type == "float")
{
double v = 0;
jsn->at("default").get_to(v);
*((SANE_Fixed*)buf) = SANE_FIX(v);
}
else if (type == "string")
{
type = "";
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> 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;
}
// adjust custom area data ...
float v = reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT, custom_area_lt_x_, .0f, paper_size_mm_.cx, .0f, paper_size_mm_.cx);
reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT, custom_area_br_x_, .0f, paper_size_mm_.cx, v, paper_size_mm_.cx);
v = reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_TOP, custom_area_lt_y_, .0f, paper_size_mm_.cy, .0f, paper_size_mm_.cy);
reset_custom_area_jsn_value(SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM, custom_area_br_y_, .0f, paper_size_mm_.cy, v, paper_size_mm_.cy);
}
float hg_scanner::reset_custom_area_jsn_value(const char* name, double& var, float range_l, float range_u, float value_l, float value_u)
{
custom_area_br_y_;
if (setting_jsn_.contains(name))
{
float v = .0f, tmp = .0f;
setting_jsn_.at(name).at("cur").get_to(v);
tmp = v;
if (v < value_l)
v = value_l;
else if (v > value_u)
v = value_u;
if (!IS_DOUBLE_EQUAL(tmp, v))
setting_jsn_.at(name).at("cur") = v;
value_l = v;
setting_jsn_.at(name).at("default").get_to(v);
tmp = v;
if (v < range_l)
v = range_l;
else if (v > range_u)
v = range_u;
if (!IS_DOUBLE_EQUAL(tmp, v))
setting_jsn_.at(name).at("default") = v;
if (var < range_l)
var = range_l;
else if (var > range_u)
var = range_u;
if (setting_jsn_.at(name).contains("range"))
{
float lower = range_l, upper = range_u;
if (setting_jsn_.at(name).at("range").contains("min"))
{
setting_jsn_.at(name).at("range").at("min").get_to(lower);
tmp = lower;
if (lower < range_l)
lower = range_l;
else if (lower > range_u)
lower = range_u;
if (!IS_DOUBLE_EQUAL(lower, tmp))
setting_jsn_.at(name).at("range").at("min") = lower;
}
if (setting_jsn_.at(name).at("range").contains("max"))
{
setting_jsn_.at(name).at("range").at("max").get_to(upper);
tmp = upper;
if (upper < lower)
upper = lower;
else if (upper > range_u)
upper = range_u;
if (!IS_DOUBLE_EQUAL(upper, tmp))
setting_jsn_.at(name).at("range").at("max") = upper;
}
}
}
return value_l;
}
int hg_scanner::set_color_change(void)
{
// if (/* condition */)
// {
// /* code */
// }
return SCANNER_ERR_OK;
}
int hg_scanner::hgpaper_to_devspaper(Paper_Map papermap[], int len, int& paper, bool* exact, TwSS* type)
{
int ind = 0;
bool good = true, * r = exact ? exact : &good;
for (int i = 0; i < len; ++i)
{
if (paper == papermap[i].paper)
{
ind = i;
break;
}
}
if (paper == papermap[ind].paper)
*r = true;
else
*r = false;
paper = papermap[ind].paper;
if (type)
*type = papermap[ind].type;
return ind;
}
//暂时放着
int hg_scanner::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<std::mutex> 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)(void*), void* data)
{
int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
auto it = setting_map_.begin();
while (it != setting_map_.end())
{
if (it->second == func)
{
ret = set_setting(it->first.c_str(), data, 0);
break;
}
++it;
}
return ret;
}
int hg_scanner::setting_restore(void* data)
{
// restore ...
notify_setting_result_ = false;
for (auto& v : setting_map_)
{
if (setting_jsn_.contains(v.first.c_str()))
{
std::string t("");
setting_jsn_.at(v.first.c_str()).at("type").get_to(t);
if (t != "group" && t != "button")
restore(v.first.c_str());
}
}
notify_setting_result_ = true;
return SCANNER_ERR_CONFIGURATION_CHANGED;
}
int hg_scanner::setting_help(void* data)
{
int ret = SCANNER_ERR_OK;
std::string helpfile = helpfile_;
std::string com = "xdg-open ";//注意空格保留
printf("helpfile = %s\r\n",helpfile.c_str());
#if defined(WIN32) || defined(_WIN64)
com = "";
helpfile.insert(0, hg_log::get_scanner_path());
FILE* src = fopen(helpfile.c_str(), "rb");
if (src)
fclose(src);
else
#else
if (access(helpfile.c_str(),F_OK) == -1)
#endif
{
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO,"App_Help_pdf path is:%s system is:%d\r\n",helpfile.c_str());
ret = SCANNER_ERR_OPEN_FILE_FAILED;
return ret ;
}
com += helpfile;
#if defined(WIN32) || defined(_WIN64)
ShellExecuteA(NULL, "Open", com.c_str(), NULL, NULL, SW_SHOWNORMAL);
#else
system(com.c_str());
#endif
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO,"App_Help_pdf path is:%s system is:%d\r\n",helpfile.c_str());
return ret;
}
int hg_scanner::setting_color_mode(void* data)
{
std::string str((char*)data);
int old = image_prc_param_.bits.color_mode,
sub = SCANNER_ERR_OK,
val = 0,
ret = SCANNER_ERR_OK;
bool exact = check_range(SANE_STD_OPT_NAME_COLOR_MODE, str);
val = image_prc_param_.bits.color_mode = match_best_color_mode(str, NULL);
sub = on_color_mode_changed(val);
image_prc_param_.bits.color_mode = val;
if (sub == SCANNER_ERR_NOT_EXACT)
{
image_prc_param_.bits.color_mode = old;
str = color_mode_string(image_prc_param_.bits.color_mode);
ret = SCANNER_ERR_NOT_EXACT;
}
else if (sub)
{
ret = sub;
image_prc_param_.bits.color_mode = old;
}
else if (!exact)
{
ret = SCANNER_ERR_NOT_EXACT;
}
is_auto_matic_color = image_prc_param_.bits.color_mode == COLOR_MODE_AUTO_MATCH ? true :false; // 等于COLOR_MODE_AUTO_MATCH 的时候颜色模式需要变为2 彩色模式图像参数和硬件参数都如此
VLOG_MINI_4(LOG_LEVEL_DEBUG_INFO, "Change color mode from %s to %s = %s color is =%s\n", color_mode_string(old).c_str(), (char*)data, hg_scanner_err_name(ret),str.c_str());
if(ret == SCANNER_ERR_NOT_EXACT)
strcpy((char*)data, str.c_str());
return ret;
}
int hg_scanner::setting_multi_out(void* data)
{
is_multiout = *((bool*)data);
int val = image_prc_param_.bits.color_mode;
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "image_prc_param_.bits.multi_out %d\n", image_prc_param_.bits.multi_out);
if (is_multiout)
{
if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW)
val = COLOR_MODE_256_GRAY;
else
val = COLOR_MODE_24_BITS;
}
on_color_mode_changed(val);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_multi_out_type(void* data)
{
int ret = SCANNER_ERR_OK;
std::string str((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_MULTI_OUT_TYPE, str);
int color;
image_prc_param_.bits.multi_out = match_best_multi_out(str,NULL);
save_multiout = str;
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "set multi_out type from %s to %s = %s\n", multi_out_string(image_prc_param_.bits.multi_out).c_str(), (char*)data, hg_scanner_err_name(ret));
if (image_prc_param_.bits.multi_out == MULTI_GRAY_AND_BW)
color = COLOR_MODE_256_GRAY;
else
color = COLOR_MODE_24_BITS;
on_color_mode_changed(color);
return ret;
}
int hg_scanner::setting_rid_color(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(SANE_STD_OPT_NAME_FILTER, 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(void* data)
{
image_prc_param_.bits.rid_red = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_rid_answer_red(void* data)
{
image_prc_param_.bits.rid_answer_red = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_erase_background(void* data)
{
image_prc_param_.bits.erase_bakground = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_erase_background_range(void* data)
{
int ret = SCANNER_ERR_OK;
erase_bkg_range_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_BKG_COLOR_RANGE, erase_bkg_range_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = erase_bkg_range_;
}
return ret;
}
int hg_scanner::setting_noise_optimize(void* data)
{
image_prc_param_.bits.noise_optimize = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_noise_optimize_range(void* data)
{
int ret = SCANNER_ERR_OK;
noise_range_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_NOISE_SIZE, noise_range_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = noise_range_;
}
return ret;
}
int hg_scanner::setting_paper(void* data)
{
std::string paper((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_PAPER, paper);
int ret = SCANNER_ERR_OK, sub = SCANNER_ERR_OK,
val = 0,
old = image_prc_param_.bits.paper;
val = image_prc_param_.bits.paper = match_best_paper(paper, NULL);
// check 600 dpi ...
if (!check_paper_and_resolution(resolution_, val))
{
image_prc_param_.bits.paper = old;
strcpy((char*)data, paper_string(old).c_str());
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
sub = on_paper_changed(val);
image_prc_param_.bits.paper = val;
if (sub == SCANNER_ERR_NOT_EXACT)
{
ret = sub;
paper = paper_string(image_prc_param_.bits.paper);
}
else if (sub)
{
ret = sub;
image_prc_param_.bits.paper = old;
}
else if (!exact)
ret = SCANNER_ERR_NOT_EXACT;
if (save_sizecheck)
{
//setting_paper_check(0,(void*)&save_sizecheck);
invoke_setting_xxx(&hg_scanner::setting_paper_check, &save_sizecheck);
}
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change paper from %s to %s = %s\n", paper_string(old).c_str(), (char*)data, hg_scanner_err_name(ret));
if(ret == SCANNER_ERR_NOT_EXACT)
strcpy((char*)data, paper.c_str());
if(old != image_prc_param_.bits.paper)
reset_custom_area_range(image_prc_param_.bits.paper);
return ret;
}
int hg_scanner::setting_paper_check(void* data)
{
bool use = *((bool*)data);
int ret = on_paper_check_changed(use);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Change paper size-checking %s = %s\n", *((bool*)data) ? "enabled" : "disabled", hg_scanner_err_name(ret));
*((bool*)data) = use;
save_sizecheck = use;
return ret;
}
int hg_scanner::setting_page(void* data)
{
std::string val((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_PAGE, val);
int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT;
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change page from %s to %s = %s\n", page_string(image_prc_param_.bits.page).c_str(), (char*)data, hg_scanner_err_name(ret));
image_prc_param_.bits.page = match_best_page(val, NULL);
if (!exact)
strcpy((char*)data, val.c_str());
return ret;
}
int hg_scanner::setting_page_omit_empty(void* data)
{
int ret = SCANNER_ERR_OK;
omit_empty_level_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_DISCARD_BLANK_SENS, omit_empty_level_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = omit_empty_level_;
}
return ret;
}
int hg_scanner::setting_resolution(void* data)
{
int ret = SCANNER_ERR_OK,
old = resolution_,
sub = SCANNER_ERR_OK;
resolution_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_RESOLUTION, resolution_))
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(void* data)
{
image_prc_param_.bits.exchange = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_split_image(void* data)
{
image_prc_param_.bits.split = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_automatic_skew(void* data)
{
// automatic_skew_detection_ = *((bool*)data);
image_prc_param_.bits.automatic_skew = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_rid_hole(void* data)
{
image_prc_param_.bits.rid_hole = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_rid_hoe_range(void* data)
{
int ret = SCANNER_ERR_OK;
rid_hole_range_ = *((double*)data);
if (!check_range(SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE, rid_hole_range_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = rid_hole_range_;
}
rid_hole_range_*=100;
VLOG_MINI_1(LOG_LEVEL_WARNING, "rid_hole_range_ = %f\r\n", rid_hole_range_);
return ret;
}
int hg_scanner::setting_bright(void* data)
{
int ret = SCANNER_ERR_OK;
bright_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_BRIGHTNESS, bright_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = bright_;
}
return ret;
}
int hg_scanner::setting_contrast(void* data)
{
int ret = SCANNER_ERR_OK;
contrast_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_CONTRAST, contrast_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = contrast_;
}
return ret;
}
int hg_scanner::setting_gamma(void* data)
{
int ret = SCANNER_ERR_OK;
gamma_ = *((double*)data);
if (!check_range(SANE_STD_OPT_NAME_GAMMA, gamma_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((double*)data) = gamma_;
}
return ret;
}
int hg_scanner::setting_sharpen(void* data)
{
std::string str((char*)data);
int ret = SCANNER_ERR_OK;
bool exact = check_range(SANE_STD_OPT_NAME_SHARPEN, str);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Change sharpen from %s to %s = ", sharpen_string(image_prc_param_.bits.sharpen).c_str(), (char*)data);
image_prc_param_.bits.sharpen = match_best_sharpen(str, NULL);
if (!exact)
{
strcpy((char*)data, str.c_str());
ret = SCANNER_ERR_NOT_EXACT;
}
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%d\n", ret);
return ret;
}
int hg_scanner::setting_dark_sample(void* data)
{
image_prc_param_.bits.dark_sample = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_erase_black_frame(void* data)
{
image_prc_param_.bits.erase_black_frame = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_threshold(void* data)
{
int ret = SCANNER_ERR_OK;
threshold_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_THRESHOLD, threshold_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = threshold_;
}
return ret;
}
int hg_scanner::setting_anti_noise(void* data)
{
int ret = SCANNER_ERR_OK;
anti_noise_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL, anti_noise_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = anti_noise_;
}
return ret;
}
int hg_scanner::setting_margin(void* data)
{
int ret = SCANNER_ERR_OK;
margin_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_MARGIN, margin_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = margin_;
}
return ret;
}
int hg_scanner::setting_filling_background(void* data)
{
std::string str((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_FILL_BKG_MODE, str);
int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT;
image_prc_param_.bits.fill_background = match_best_fill_background(str, NULL);
if (!exact)
{
strcpy((char*)data, str.c_str());
ret = SCANNER_ERR_NOT_EXACT;
}
return ret;
}
int hg_scanner::setting_is_permeate(void* data)
{
image_prc_param_.bits.is_permeate = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_is_permeate_lv(void* data)
{
int ret = SCANNER_ERR_OK;
std::string str((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL, str);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "Change is_permeate_lv from %s to %s = ", is_permaeate_string(image_prc_param_.bits.is_permeate_lv_).c_str(), (char*)data);
image_prc_param_.bits.is_permeate_lv_ = match_best_permaeate_lv(str, NULL);
if (!exact)
{
strcpy((char*)data, str.c_str());
ret = SCANNER_ERR_NOT_EXACT;
}
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "%d\n", ret);
return ret;
}
int hg_scanner::setting_remove_morr(void* data)
{
image_prc_param_.bits.remove_morr = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_error_extention(void* data)
{
image_prc_param_.bits.error_extention = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_remove_texture(void* data)
{
image_prc_param_.bits.remove_txtture = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_ultrasonic_check(void* data)
{
bool use = *((bool*)data);
int ret = on_ultrasonic_check_changed(use);
if (ret)
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_go_on_when_double_checked(void* data)
{
bool ok = true;
std::string val((char*)data);
double_paper_handle_ = double_paper_flag_from_option_value(val, &ok);
// 此处需要通知设备双张处理方式
// OPTION_VALUE_SZTPCL_xxx 共4种选择,目前只支持出现双张后停止的两种方式
// 若要上传出现双张的图片,请确保双张信号在图片之前发出来
if(ok)
return SCANNER_ERR_OK;
else
{
strcpy((char*)data, val.c_str());
return SCANNER_ERR_NOT_EXACT;
}
}
int hg_scanner::setting_staple_check(void* data)
{
bool use = *((bool*)data);
int ret = on_staple_check_changed(use);
if (ret)
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_scan_mode(void* data)
{
std::string str((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_SCAN_MODE, str);
int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT;
if (strcmp(str.c_str(), OPTION_VALUE_SMZS_LXSM) == 0)
{
scan_count_ = -1;
}
else
{
setting_jsn_.at(SANE_STD_OPT_NAME_SCAN_COUNT).at("cur").get_to(scan_count_);
}
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "set scanning pages to %d\n", scan_count_);
return ret;
}
int hg_scanner::setting_scan_count(void* data)
{
int ret = SCANNER_ERR_OK;
std::string val("");
setting_jsn_.at(SANE_STD_OPT_NAME_SCAN_MODE).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(void* data)
{
std::string str((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_TEXT_DIRECTION, str);
int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT;
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change text direction from '%s' to '%s' = %s\n", text_direction_string(image_prc_param_.bits.text_direction).c_str()
, (char*)data, hg_scanner_err_name(ret));
image_prc_param_.bits.text_direction = match_best_text_direction(str, NULL);
if (!exact)
strcpy((char*)data, str.c_str());
if (image_prc_param_.bits.text_direction == TEXT_DIRECTION_AUTO && ImagePrc_pHandle_)
{
hg_imgproc::init_auto_txt_hanld(ImagePrc_pHandle_);
}
else if (image_prc_param_.bits.text_direction != TEXT_DIRECTION_AUTO && ImagePrc_pHandle_)
{
hg_imgproc::free_auto_txt_hanld(ImagePrc_pHandle_);
}
return ret;
}
int hg_scanner::setting_rotate_bkg_180(void* data)
{
image_prc_param_.bits.rotate_back_180 = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_fractate_check(void* data)
{
image_prc_param_.bits.fractate_check = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_fractate_check_level(void* data)
{
int ret = SCANNER_ERR_OK;
fractate_level_ = *((int*)data);
if (!check_range(SANE_STD_OPT_NAME_DOG_EAR_SIZE, fractate_level_))
{
ret = SCANNER_ERR_NOT_EXACT;
*((int*)data) = fractate_level_;
}
return ret;
}
int hg_scanner::setting_skew_check(void* data)
{
bool use = *((bool*)data);
int ret = on_skew_check_changed(use);
if (ret)
*((bool*)data) = use;
return ret;
}
int hg_scanner::setting_skew_check_level(void* data)
{
int level = *((int*)data);
bool exact = check_range(SANE_STD_OPT_NAME_ASKEW_RANGE, level);
int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT,
sub = on_skew_check_level_changed(level);
if (sub)
{
ret = sub;
}
if (ret)
*((int*)data) = level;
return ret;
}
int hg_scanner::setting_is_custom_gamma(void* data)
{
custom_gamma_ = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_custom_gamma_data(void* data)
{
SANE_Gamma* gamma = (SANE_Gamma*)data;
memcpy(custom_gamma_val_, gamma, sizeof(*custom_gamma_val_));
return SCANNER_ERR_OK;
}
int hg_scanner::setting_is_custom_area(void* data)
{
custom_area_ = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_custom_area_left(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_lt_x_ = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_custom_area_top(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_lt_y_ = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_custom_area_right(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_br_x_ = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_custom_area_bottom(void* data)
{
SANE_Fixed* v = (SANE_Fixed*)data;
custom_area_br_y_ = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_img_quality(void* data)
{
std::string str((char*)data);
bool exact = check_range(SANE_STD_OPT_NAME_IMAGE_QUALITY, str);
int ret = exact ? SCANNER_ERR_OK : SCANNER_ERR_NOT_EXACT;
int old = is_quality_;
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "Change quality from '%s' to '%s' = %s\n", is_img_quality(is_quality_).c_str()
, (char*)data, hg_scanner_err_name(ret));
is_quality_ = match_best_img_quality(str,NULL);
if (!check_resolution_and_quality(resolution_, is_img_quality(is_quality_).c_str()))
{
is_quality_ = old;
strcpy((char*)data, is_img_quality(is_quality_).c_str());
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
return SCANNER_ERR_OK;
}
int hg_scanner::setting_color_fill(void* data)
{
is_color_fill = *((bool *)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_keep_watermark(void* data)
{
keep_watermark_ = *(bool*)data;
on_pic_type(keep_watermark_);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_black_white_threshold(void* data)
{
bw_threshold_ = (unsigned char)(*(SANE_Int*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_white_pixel_0(void* data)
{
is_white_0_ = *(bool*)data;
return SCANNER_ERR_OK;
}
int hg_scanner::setting_feedmode(void* data)
{
std::string str((char *)data);
int val = match_best_paper_strength(str,NULL);
if (val == feedmode_)
return SCANNER_ERR_OK;
int ret = on_set_feedmode(val);
if (ret == SCANNER_ERR_OK)
feedmode_ = val;
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "setfeedmode from '%s' to '%s' = %s\n", is_paper_strength(feedmode_).c_str()
, (char*)data, hg_scanner_err_name(ret));
return ret;
}
int hg_scanner::setting_sleeptime(void* data)
{
std::string str((char *)data);
int val = match_best_sleep_time(str,0);
int mintosec = 0;
switch (val)
{
case SLEEP_TIME_0MIN:
val = -1; //不休眠 -1
break;
case SLEEP_TIME_5MIN:
val = 5;
break;
case SLEEP_TIME_10MIN:
val = 10;
break;
case SLEEP_TIME_30MIN:
val = 30;
break;
case SLEEP_TIME_60MIN:
val = 60;
break;
case SLEEP_TIME_120MIN:
val = 120;
break;
case SLEEP_TIME_240MIN:
val = 240;
break;
}
if (val == sleeptime_)
return SCANNER_ERR_OK;
mintosec = val ;
if (val != -1)
{
mintosec = val * 60;
}
int ret = set_sleep_time(mintosec);
if (ret == SCANNER_ERR_OK)
sleeptime_ = val;
VLOG_MINI_3(LOG_LEVEL_DEBUG_INFO, "set sleeptime from (%s)min to (%s)min = %s\n", is_sleep_time(sleeptime_).c_str()
, (char*)data, hg_scanner_err_name(ret));
return ret;
}
int hg_scanner::setting_auto_pick_paper(void* data)
{
int ret = SCANNER_ERR_OK;
bool isautopic = *((bool *)data);
ret = on_pick_paper(isautopic);
return ret;
}
int hg_scanner:: setting_auto_pick_paper_threshold(void* data)
{
int ret = SCANNER_ERR_OK;
double threshold = *((double*)data);
ret = on_pick_paper_threshold(threshold);
return ret;
}
int hg_scanner:: setting_auto_paper_scan(void* data)
{
is_auto_paper_scan = *((bool *)data);
if (!is_auto_paper_scan)
{
on_is_auto_paper(is_auto_paper_scan);
}
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_left_hole(void* data)
{
isremove_left_hole = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_right_hole(void* data)
{
isremove_right_hole = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_top_hole(void* data)
{
isremove_top_hole = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_low_hole(void* data)
{
isremove_low_hole = *((bool*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_left_hole_threshold(void* data)
{
isremove_left_hole_threshold = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_right_hole_threshold(void* data)
{
isremove_right_hole_threshold = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_top_hole_threshold(void* data)
{
isremove_top_hole_threshold = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_isremove_low_hole_threshold(void* data)
{
isremove_low_hole_threshold = *((double*)data);
return SCANNER_ERR_OK;
}
int hg_scanner::setting_fold_type(void* data)
{
string str((char*)data);
bool exact = NULL;
int val = match_best_fold_type(str, 0);
fold_type_ = val;
return SCANNER_ERR_OK;
}
int hg_scanner::on_color_mode_changed(int& color_mode)
{
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<std::mutex> lock(io_lock_);
VLOG_MINI_2(LOG_LEVEL_DEBUG_INFO, "%04x:%04x reconnected.\n", io_->get_vid(), io_->get_pid());
}
int hg_scanner::set_setting_value(const char* name, void* data, int len)
{
return SCANNER_ERR_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(&param, 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)
{
jsn_children_.clear();
setting_jsn_ = jsonconfig::load_json_from_text(json_setting_text, &jsn_children_);
VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ...\n", jsn_children_.size() - 1);
notify_setting_result_ = false;
for (size_t i = 1; i < jsn_children_.size(); ++i)
{
std::string v(jsn_children_[i]);
if (!setting_jsn_.contains(v.c_str()))
continue;
std::string val("");
setting_jsn_.at(v.c_str()).at("type").get_to(val);
if (val == "string")
{
val = "";
setting_jsn_.at(v.c_str()).at("default").get_to(val);
char* buf = NULL;
int size = 0;
setting_jsn_.at(v.c_str()).at("size").get_to(size);
buf = (char*)malloc(size + 4);
bzero(buf, size + 4);
strcpy(buf, val.c_str());
set_setting(v.c_str(), buf, val.length());
free(buf);
}
else if (val == "int")
{
int n = 0;
setting_jsn_.at(v.c_str()).at("default").get_to(n);
set_setting(v.c_str(), (char*)&n, sizeof(n));
}
else if (val == "float")
{
double d = .0f;
setting_jsn_.at(v.c_str()).at("default").get_to(d);
set_setting(v.c_str(), (char*)&d, sizeof(d));
}
else if (val == "bool")
{
bool b = false;
setting_jsn_.at(v.c_str()).at("default").get_to(b);
set_setting(v.c_str(), (char*)&b, sizeof(b));
}
}
VLOG_MINI_1(LOG_LEVEL_ALL, "Initialize %d settings ... OK\n", jsn_children_.size() - 1);
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<tiny_buffer> 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<tiny_buffer> 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<tiny_buffer> 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;
img.flag.dpi = resolution_;
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<std::mutex> 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<std::mutex> 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<std::mutex> lock(io_lock_);
return io_->get_pid();
}
int hg_scanner::get_vid(void)
{
std::lock_guard<std::mutex> lock(io_lock_);
return io_->get_vid();
}
int hg_scanner::close(bool force)
{
int ret = on_scanner_closing(force);
online_ = false;
if (ret == SCANNER_ERR_OK)
{
run_ = false;
wait_usb_.notify();
wait_img_.notify();
if(!scan_life_)
{
std::lock_guard<std::mutex> lock(io_lock_);
if (io_)
{
io_->close();
io_->release();
io_ = NULL;
}
}
else if (io_)
{
LOG_INFO(LOG_LEVEL_WARNING, "close scanner: USB thread or Image thread is still running.\n");
io_->close();
while (scan_life_)
std::this_thread::sleep_for(std::chrono::milliseconds(5));
io_->release();
io_ = NULL;
}
status_ = SCANNER_ERR_NOT_OPEN;
}
return ret;
}
int hg_scanner::set_setting(const char* name, void* data, int len)
{
int ret = SCANNER_ERR_OUT_OF_RANGE;
bool hit = false;
std::string real_n(setting_name_from(name));
if (real_n.empty())
return ret;
hit = setting_map_.count(real_n) > 0;
if (hit)
{
ret = (this->*setting_map_[real_n])(data);
}
else
{
VLOG_MINI_1(LOG_LEVEL_WARNING, "Setting '%s' is not found in base setting functions.\n", name);
ret = set_setting_value(real_n.c_str(), data, len);
}
if (ret == SCANNER_ERR_OK || ret == SCANNER_ERR_NOT_EXACT || ret == SCANNER_ERR_CONFIGURATION_CHANGED)
{
std::string type(""), name("");
setting_jsn_.at(real_n).at("type").get_to(type);
setting_jsn_.at(real_n).at("title").get_to(name);
if (type == "string")
{
setting_jsn_.at(real_n).at("cur") = (char*)data;
type = (char*)data;
}
else if (type == "int")
{
char sn[20] = { 0 };
setting_jsn_.at(real_n).at("cur") = *((int*)data);
sprintf(sn, "%d", *((int*)data));
type = sn;
}
else if (type == "float")
{
char sn[20] = { 0 };
setting_jsn_.at(real_n).at("cur") = *((double*)data);
sprintf(sn, "%f", *((double*)data));
type = sn;
}
else if (type == "bool")
{
setting_jsn_.at(real_n).at("cur") = *((bool*)data);
type = *((bool*)data) ? "true" : "false";
}
if (notify_setting_result_)
{
name.insert(0, "\350\256\276\347\275\256 \"");
name += "\" \345\200\274\344\270\272\"";
name += type + "\" \346\210\220\345\212\237\343\200\202";
notify_ui_working_status(name.c_str());
}
}
else if (notify_setting_result_)
{
std::string n("");
if (setting_jsn_.contains(real_n))
{
setting_jsn_.at(real_n).at("title").get_to(n);
}
else
n = std::string("\350\256\276\347\275\256\351\241\271") + real_n;
n.insert(0, "\350\256\276\347\275\256 \"");
n += std::string("\" \345\200\274\345\244\261\350\264\245: ") + hg_scanner_err_name(ret);
notify_ui_working_status(n.c_str());
}
return ret;
}
int hg_scanner::get_setting(const char* name, char* json_txt_buf, int* len)
{
if (!len)
return SCANNER_ERR_INVALID_PARAMETER;
std::string real_n(setting_name_from(name));
if (name == nullptr)
{
*len = setting_jsn_.size();
return SCANNER_ERR_OK;
}
else if (real_n.empty())
{
return SCANNER_ERR_OUT_OF_RANGE;
}
else if (!setting_jsn_.contains(real_n))
{
VLOG_MINI_1(LOG_LEVEL_FATAL, "!!!option(%s) is not found.\n", real_n.c_str());
return SCANNER_ERR_OUT_OF_RANGE;
}
else
{
std::string text(setting_jsn_.at(real_n).dump());
text.insert(0, "\"" + real_n + "\":");
if (*len <= text.length())
{
*len = text.length() + 8;
return SCANNER_ERR_INSUFFICIENT_MEMORY;
}
else
{
strcpy(json_txt_buf, text.c_str());
*len = text.length();
return SCANNER_ERR_OK;
}
}
}
std::string hg_scanner::name(void)
{
return name_;
}
int hg_scanner::status(void)
{
if (!wait_usb_.is_waiting() || !wait_img_.is_waiting())
return SCANNER_ERR_DEVICE_BUSY;
else
return status_;
}
bool hg_scanner::is_online(void)
{
return online_;
}
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)
{
if (*len == 0)
{
*len = setting_jsn_.size();
return SCANNER_ERR_OK;
}
else if (*len > setting_jsn_.size())
{
return SCANNER_ERR_OUT_OF_RANGE;
}
else if(*len < jsn_children_.size())
{
if (get_default_value(data, &setting_jsn_.at(jsn_children_[*len])))
return SCANNER_ERR_OK;
else
return SCANNER_ERR_DATA_DAMAGED;
}
else
{
return SCANNER_ERR_DATA_DAMAGED;
}
}
else if (code == IO_CTRL_CODE_CLEAR_ROLLER_COUNT)
{
int val = 0, ret = get_roller_num(val);
if (len)
*len = val;
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);
return SCANNER_ERR_OK;
}
else if (code == IO_CTRL_CODE_CONVERT_IMAGE_FORMAT)
{
SANE_ImageFormatConvert *conv = (SANE_ImageFormatConvert*)data;
void* threshold = conv->dst.fmt.compress.detail;
int ret = SCANNER_ERR_OK;
conv->dst.fmt.compress.detail = (void*)bw_threshold_;
ret = hg_imgproc::convert_image_file(conv);
conv->dst.fmt.compress.detail = threshold;
return ret;
}
else if (code == IO_CTRL_CODE_FREE_MEMORY)
{
free_memory(data);
return SCANNER_ERR_OK;
}
else if(code == IO_CTRL_CODE_GET_LOG_FILE && len && *len == LOG_FILE_DEVICE)
{
string str;
int ret = get_device_log(str);
VLOG_MINI_1(LOG_LEVEL_DEBUG_INFO, "str = %d\n", str.length());
*(char*)data = 0;
if (ret != SCANNER_ERR_OK)
{
return ret;
}
strcpy((char*)data, str.c_str());
return 0;
}
else if(code == IO_CTRL_CODE_SET_SCAN_LOCK_CHECK_VAL)
{
string str = (char*)data;
return set_scan_lock_check_val(str);
}
else if (code == IO_CTRL_CODE_SET_SCAN_LOCK)
{
SANE_Bool set_islock = *((SANE_Bool *)data);
return set_scan_islock(set_islock);
}
else if (code == IO_CTRL_CODE_GET_SCAN_ISLOCK)
{
SANE_Bool islock = *((SANE_Bool*)data);
int ret = get_scan_islock(&islock);
*((SANE_Bool*)data) = islock;
return ret;
}
else if (code == IO_CTRL_CODE_SET_FIRMWARE_UPGRADE)
{
string str = (char*)data;
return firmware_upgrade(str);
}
else if (code == IO_CTRL_CODE_GET_HISTORY_ROLLER_NUM)
{
int num = 0;
int ret = get_history_roller_count(num);
(*(int*)data) = num;
return ret;
}
else if (code == IO_CTRL_CODE_GET_CLEAN_PAPER_ROAD)
{
return clean_paper_road();
}
else if (code == IO_CTRL_CODE_GET_SCANN_NUM)
{
int num = 0;
int ret = get_roller_num(num);
(*(int*)data) = num;
return ret;
}
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
std::string hg_scanner::get_firmware_version(void)
{
return BRAND_DEVICE_NOT_SUPPORT;
}
std::string hg_scanner::get_serial_num(void)
{
return BRAND_DEVICE_NOT_SUPPORT;
}
std::string hg_scanner::get_ip(void)
{
return BRAND_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_roller_num(int &val)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_device_log(string &log)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_devreboot()
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_devshtudown()
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::clear_roller_num(void)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_history_roller_count(int &num)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_scan_islock(SANE_Bool set_islock)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_scan_islock(SANE_Bool* islock)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_scan_lock_check_val(string check_str)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::firmware_upgrade(std::string filename)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::clean_paper_road()
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
int hg_scanner::set_leaflet_scan(void)
{
return SCANNER_ERR_NO_DATA;
}
int hg_scanner::get_abuot_info(void)
{
return SCANNER_ERR_NO_DATA;
}
int hg_scanner::restore_default_setting(void)
{
return SCANNER_ERR_NO_DATA;
}
int hg_scanner::set_final_image_format(SANE_FinalImgFormat* fmt)
{
switch (fmt->img_format)
{
case SANE_IMAGE_TYPE_BMP:
img_type_ = ".bmp";
break;
case SANE_IMAGE_TYPE_PNG:
img_type_ = ".png";
break;
case SANE_IMAGE_TYPE_JPG:
img_type_ = ".jpg";
break;
case SANE_IMAGE_TYPE_TIFF:
return SCANNER_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_WEBP:
return SCANNER_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_PDF:
return SCANNER_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_GIF:
return SCANNER_ERR_INVALID_PARAMETER;
case SANE_IMAGE_TYPE_SVG:
return SCANNER_ERR_INVALID_PARAMETER;
default:
img_type_ = ".bmp";
break;
}
return SCANNER_ERR_OK;
}
int hg_scanner::get_compression_format(void)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_compression_format(void)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::set_auto_color_type(void)
{
is_auto_matic_color = true;
return SCANNER_ERR_OK;
}
int hg_scanner::get_device_code(void)
{
return SCANNER_ERR_DEVICE_NOT_SUPPORT;
}
int hg_scanner::get_sleep_time(int& 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<tiny_buffer>& 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_, &param);
(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_, "filter");
}
{
adjust_color(ImagePrc_pHandle_); //色调曲线 普通dsp版本需要矫正颜色
(this->*dump_img_)(ImagePrc_pHandle_, "adjust_color");
}
if ((img_conf_.pixtype == COLOR_MODE_24_BITS && img_conf_.hsvcorrect) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::answerSheetFilterRed(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "answerSheetFilterRed");
}
if ((img_conf_.refuseInflow) && (pid_ != 0x239 && pid_ != 0x439))
{
int lv = 5;
if (image_prc_param_.bits.is_permeate_lv_ == 0)
lv = 5;
else if (image_prc_param_.bits.is_permeate_lv_ == 1)
lv = 15;
else if (image_prc_param_.bits.is_permeate_lv_ == 2)
lv = 25;
else if (image_prc_param_.bits.is_permeate_lv_ == 3)
lv = 35;
else if (image_prc_param_.bits.is_permeate_lv_ == 4)
lv = 45;
hg_imgproc::antiInflow(ImagePrc_pHandle_, lv);
(this->*dump_img_)(ImagePrc_pHandle_, "antiInflow");
}
if ((img_conf_.colorCorrection && img_conf_.pixtype != COLOR_MODE_BLACK_WHITE) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::colorCorrection(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "colorCorrection");
}
if (((img_conf_.imageRotateDegree != TEXT_DIRECTION_0 || img_conf_.is_backrotate180) && (!img_conf_.is_autotext)) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::orentation(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "orentation");
}
if ((img_conf_.removeMorr) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::textureRemove(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "textureRemove");
}
if ((img_conf_.detachnoise.is_detachnoise) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::nosieDetach(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "nosieDetach");
}
if ((img_conf_.pixtype == COLOR_MODE_BLACK_WHITE) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::errorextention(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "errorextention");
}
if ((img_conf_.en_fold && pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::fold(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "fold");
}
if (img_conf_.multi_output_red && img_conf_.pixtype == COLOR_MODE_24_BITS)//239
{
err = hg_imgproc::multi_out_red(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "multi_out_red");
}
if ((img_conf_.sharpen) && (pid_ != 0x239 && pid_ != 0x439))
{
hg_imgproc::sharpenType(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "sharpenType");
}
if (image_prc_param_.bits.split) //239
{
split3399_++;
err = hg_imgproc::split(ImagePrc_pHandle_,split3399_);
(this->*dump_img_)(ImagePrc_pHandle_, "split");
}
if (!img_conf_.splitImage || !img_conf_.multi_output_red || !is_multiout) //239
{
if (img_conf_.automaticcolor)
{
hg_imgproc::auto_matic_color(ImagePrc_pHandle_, img_conf_.automaticcolortype);
(this->*dump_img_)(ImagePrc_pHandle_, "auto_matic_color");
}
}
if (img_conf_.is_autotext)//239
{
//hg_imgproc::ocr_auto_txtdirect(ImagePrc_pHandle_);
hg_imgproc::tesseract_auto_txtdirect(ImagePrc_pHandle_);
(this->*dump_img_)(ImagePrc_pHandle_, "ocr_auto_txtdirect");
}
if ((is_quality_ == IMG_SPEED && (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::vector<unsigned char>bmpdata;
//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);
}
}