#pragma once #include "scanned_img.h" #include #include #include #define SANE_OPTION_ID(name) \ SANE_OPTION_ID_OVERRIDE(name); \ int name##_id_ = -1; #define SANE_OPTION_ID_IMPLEMENT(name) \ SANE_OPTION_IMPLEMENT(scanner, name) \ { \ return name##_id_; \ } #define EX_HANDLER_PROTO(name) \ int name(int base_id, void* data, set_opt_value setv) #define EX_OPTION_HANDLER_DECL(name) EX_HANDLER_PROTO(handle_ex_##name) #define EX_OPTION_HANDLER_IMPL(name) EX_HANDLER_PROTO(scanner::handle_ex_##name) #define EXTENSION_ID_BASE 0x300 #include "DlgPage.h" class dlg_indicator; class dlg_setting; namespace gb { class sane_config; } class scanner : public ISaneInvoker, virtual public refer { SANE_Handle handle_; SCANNERID id_; int err_; int ex_id_; int prev_start_result_; int dpi_; unsigned int img_ind_; std::wstring scanner_name_; std::wstring tmp_path_; std::wstring cfg_path_; std::string scan_msg_; bool scan_err_; volatile bool is_ui_wait_img_; volatile bool is_scanning_; twain_xfer xfer_; safe_img_queue images_; safe_queue events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件 SANE_FinalImgFormat img_fmt_; std::unique_ptr indicator_; std::unique_ptr setting_; gb::sane_config* cfg_; void transport_config_file(void); void update_config(void); void load_config(const wchar_t* file); void save_config(const wchar_t* file); void apply_config(void); void on_ui_event(int uev, void* sender); int open(void); int close(void); int init_options_id(void); int control_read_string(int code, std::string& ret); void extension_none(int id); void extension_multiout_type(int id); void extension_color_mode(int id); void extension_sharpen(int id); void extension_paper(int id); void extension_fill_bkg_method(int id); void extension_text_direction(int id); void extension_page(int id); void extension_erase_color(int id); bool get_option_value_with_parent(int sn, set_opt_value setv, void* param); // return true if handled bool set_option_value_with_parent(int sn, void* data, int* err); // return true if handled int set_option_value(int sn, SANE_Value_Type type, int size, void* data); typedef struct _ex_api { unsigned int ind; unsigned int base_ind; int(scanner::* ex_api)(int, void*, set_opt_value); bool operator==(const int& id) { return ind == id; } }EXAPI; std::vector ex_opts_; typedef std::vector::iterator EXAPIPOS; EXAPIPOS find_ex_api(int op_id); ; EX_OPTION_HANDLER_DECL(multiout); EX_OPTION_HANDLER_DECL(auto_color_type); EX_OPTION_HANDLER_DECL(color_mode); EX_OPTION_HANDLER_DECL(sharpen); // int EX_OPTION_HANDLER_DECL(paper); EX_OPTION_HANDLER_DECL(paper_lateral); EX_OPTION_HANDLER_DECL(auto_paper_size); EX_OPTION_HANDLER_DECL(auto_paper_crop); EX_OPTION_HANDLER_DECL(text_direction); EX_OPTION_HANDLER_DECL(duplex); EX_OPTION_HANDLER_DECL(fill_background); // bool true - 凸多边形 EX_OPTION_HANDLER_DECL(discard_blank_page); EX_OPTION_HANDLER_DECL(discard_blank_receipt); EX_OPTION_HANDLER_DECL(page_fold); EX_OPTION_HANDLER_DECL(color_filter); EX_OPTION_HANDLER_DECL(color_enhance); EX_OPTION_HANDLER_DECL(final_compression); // int EX_OPTION_HANDLER_DECL(final_format); // SANE_FinalImgFormat EX_OPTION_HANDLER_DECL(serial); // std::string EX_OPTION_HANDLER_DECL(to_be_scan); // bool EX_OPTION_HANDLER_DECL(scan_with_hole); // bool EX_OPTION_HANDLER_DECL(device_code); // std::string EX_OPTION_HANDLER_DECL(power); // int EX_OPTION_HANDLER_DECL(hardware_version); // std::string EX_OPTION_HANDLER_DECL(ip); // std::string EX_OPTION_HANDLER_DECL(erase_hole); EX_OPTION_HANDLER_DECL(search_hole_range); template bool set_cur_and_def_value(T cur, T def, set_opt_value setv, void* param) { if (cur == def) return setv(&cur, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), param); else if (setv(&cur, VAL_ROLE_CURRENT, param)) return setv(&def, VAL_ROLE_DEFAULT, param); else return false; } template void set_value_range(S cur, S def, S l, S u, S s, set_opt_value setv, void* param, T(__stdcall* to_t)(S)) { struct { int role; S val; }vals[5]; int count = 0; std::vector sv; sv.push_back(cur); sv.push_back(def); sv.push_back(l); sv.push_back(u); std::sort(sv.begin(), sv.end()); for (int i = 0; i < (int)sv.size(); ++i) { if (i && sv[i] == sv[i - 1]) continue; vals[count].val = sv[i]; vals[count].role = 0; if (sv[i] == cur) vals[count].role |= VAL_ROLE_CURRENT; if (sv[i] == def) vals[count].role |= VAL_ROLE_DEFAULT; if (sv[i] == l) vals[count].role |= VAL_ROLE_LOWER; if (sv[i] == u) vals[count].role |= VAL_ROLE_UPPER; count++; } vals[count].val = s; vals[count++].role = VAL_ROLE_STEP; for (int i = 0; i < count; ++i) { T v = to_t(vals[i].val); if (!setv(&v, (value_role)vals[i].role, param)) break; } } static int __stdcall to_int(SANE_Int v); static float __stdcall to_float(SANE_Fixed v); static void __stdcall ui_callback(int uev, void* sender, void* param); static bool __stdcall is_option_float(int sn, void* param); public: scanner(SCANNERID id); protected: ~scanner(); public: static std::string get_scanner_name(SCANNERID id); static value_type from_sane_type(SANE_Value_Type type); static value_limit from_sane_constraint(SANE_Constraint_Type type); // IRef public: COM_API_OVERRIDE(long, add_ref(void)); COM_API_OVERRIDE(long, release(void)); // ISaneInvoker public: COM_API_OVERRIDE(int, start(void)); COM_API_OVERRIDE(int, stop(void)); COM_API_OVERRIDE(int, get_event(void)); COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1)); COM_API_OVERRIDE(int, get_scanned_images(DWORD milliseconds = 0)); COM_API_OVERRIDE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz COM_API_OVERRIDE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = NULL)); COM_API_OVERRIDE(bool, is_online(void)); COM_API_OVERRIDE(bool, is_paper_on(void)); COM_API_OVERRIDE(bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes)); COM_API_OVERRIDE(bool, get_value(int sn, set_opt_value, void* param)); COM_API_OVERRIDE(int, set_value(int sn, void* val)); COM_API_OVERRIDE(int, convert_image(SANE_ImageFormatConvert* conv)); COM_API_OVERRIDE(void, free_buffer(void* buf, int len)); // SANE options ID ... SANE_OPTION_ID(is_multiout); SANE_OPTION_ID(multiout_type); SANE_OPTION_ID(color_mode); SANE_OPTION_ID(erase_color); SANE_OPTION_ID(erase_multiout_red); SANE_OPTION_ID(erase_paper_red); SANE_OPTION_ID(is_erase_background); SANE_OPTION_ID(background_color_range); SANE_OPTION_ID(sharpen); SANE_OPTION_ID(erase_morr); SANE_OPTION_ID(erase_grids); // 除网纹 SANE_OPTION_ID(error_extend); SANE_OPTION_ID(is_noise_modify); SANE_OPTION_ID(noise_threshold); SANE_OPTION_ID(paper); SANE_OPTION_ID(is_custom_area); SANE_OPTION_ID(curstom_area_l); SANE_OPTION_ID(curstom_area_r); SANE_OPTION_ID(curstom_area_t); SANE_OPTION_ID(curstom_area_b); SANE_OPTION_ID(is_size_check); SANE_OPTION_ID(page); SANE_OPTION_ID(blank_page_threshold); // 跳过空白页灵敏度 SANE_OPTION_ID(resolution); SANE_OPTION_ID(image_quality); SANE_OPTION_ID(is_swap); // 交换正反面 SANE_OPTION_ID(is_split); // 图像拆分 SANE_OPTION_ID(is_auto_deskew); // 自动纠偏 SANE_OPTION_ID(is_custom_gamma); SANE_OPTION_ID(bright); SANE_OPTION_ID(contrast); SANE_OPTION_ID(gamma); SANE_OPTION_ID(is_erase_black_frame); // bool SANE_OPTION_ID(deep_sample); SANE_OPTION_ID(threshold); SANE_OPTION_ID(anti_noise); // 抗噪等级 SANE_OPTION_ID(margin); SANE_OPTION_ID(fill_background); SANE_OPTION_ID(is_anti_permeate); SANE_OPTION_ID(anti_permeate_level); SANE_OPTION_ID(is_erase_hole); SANE_OPTION_ID(search_hole_range); SANE_OPTION_ID(is_filling_color); // 色彩填充 SANE_OPTION_ID(is_ultrasonic_check); SANE_OPTION_ID(is_check_staple); SANE_OPTION_ID(scan_mode); // 扫描张数 SANE_OPTION_ID(scan_count); // 扫描数量 SANE_OPTION_ID(text_direction); SANE_OPTION_ID(is_rotate_bkg180); SANE_OPTION_ID(is_check_dogear); SANE_OPTION_ID(dogear_size); SANE_OPTION_ID(is_check_skew); SANE_OPTION_ID(skew_range); SANE_OPTION_ID(black_white_threshold); // 二值化图像阈值 SANE_OPTION_ID(is_photo_mode); // 照片模式 SANE_OPTION_ID(double_feed_handle); // 双张图片处理 SANE_OPTION_ID(scan_when_paper_on); // 待纸扫描 SANE_OPTION_ID(feed_strength); // 分纸强度 SANE_OPTION_ID(power_scheme); // 休眠时间 SANE_OPTION_ID(is_auto_strength); // 自动搓纸强度 SANE_OPTION_ID(feed_strength_value); // 自动搓纸强度设定值 SANE_OPTION_ID(is_reverse_bw); // 黑白图像反色输出 SANE_OPTION_ID(is_erase_hole_l); // 穿孔移除 - 左 SANE_OPTION_ID(search_hole_range_l); // 穿孔搜索范围 - 左 SANE_OPTION_ID(is_erase_hole_r); // 穿孔移除 - 右 SANE_OPTION_ID(search_hole_range_r); // 穿孔搜索范围 - 右 SANE_OPTION_ID(is_erase_hole_t); // 穿孔移除 - 上 SANE_OPTION_ID(search_hole_range_t); // 穿孔搜索范围 - 上 SANE_OPTION_ID(is_erase_hole_b); // 穿孔移除 - 下 SANE_OPTION_ID(search_hole_range_b); // 穿孔搜索范围 - 下 // SANE-ex option ID: SANE_OPTION_ID(ex_multiout_type); // int SANE_OPTION_ID(ex_auto_color_type); // int SANE_OPTION_ID(ex_color_mode); // int SANE_OPTION_ID(ex_sharpen); // int SANE_OPTION_ID(ex_paper); // paper_value SANE_OPTION_ID(ex_paper_lateral); // bool SANE_OPTION_ID(ex_auto_paper_size); // bool SANE_OPTION_ID(ex_is_paper_auto_crop); // bool SANE_OPTION_ID(ex_text_direction); // float 90, 180, ..., -1 is auto-text-direction SANE_OPTION_ID(ex_duplex); // bool SANE_OPTION_ID(ex_fill_background); // bool true - 凸多边形 SANE_OPTION_ID(ex_discard_blank_page); // bool SANE_OPTION_ID(ex_discard_blank_receipt); // bool SANE_OPTION_ID(ex_is_page_fold); // bool SANE_OPTION_ID(ex_color_filter); // int (filter_value) SANE_OPTION_ID(ex_color_enhance); // int (enhance_value) SANE_OPTION_ID(ex_final_compression); // int SANE_OPTION_ID(ex_final_format); // SANE_FinalImgFormat SANE_OPTION_ID(ex_serial); // std::string SANE_OPTION_ID(ex_to_be_scan); // bool SANE_OPTION_ID(ex_scan_with_hole); // bool SANE_OPTION_ID(ex_device_code); // std::string SANE_OPTION_ID(ex_power); // int SANE_OPTION_ID(ex_hardware_version); // std::string SANE_OPTION_ID(ex_ip); // std::string // ui ... COM_API_OVERRIDE(bool, ui_show_main(HWND parent)); COM_API_OVERRIDE(bool, ui_show_setting(HWND parent, bool with_scan, bool indicator = true)); COM_API_OVERRIDE(bool, ui_show_progress(HWND parent)); COM_API_OVERRIDE(void, ui_hide(void)); COM_API_OVERRIDE(bool, ui_is_ok(void)); // twain COM_API_OVERRIDE(void, twain_set_transfer(twain_xfer xfer)); COM_API_OVERRIDE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL)); COM_API_OVERRIDE(int, twain_get_config(char* buf, size_t* len)); COM_API_OVERRIDE(int, twain_set_config(char* buf, size_t len)); // methods: public: int handle_device_event(int ev_code, void* data, unsigned int* len); int last_error(void); };