code_twain/sane/scanner.h

358 lines
13 KiB
C
Raw Normal View History

#pragma once
2022-06-15 03:04:40 +00:00
#include "scanned_img.h"
#include <vector>
#include <algorithm>
2022-06-18 08:48:41 +00:00
#include <memory>
2023-04-23 14:23:02 +00:00
#include <functional>
#include <map>
2022-06-15 03:04:40 +00:00
#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"
2022-06-18 08:48:41 +00:00
class dlg_indicator;
class dlg_setting;
2022-07-01 07:24:58 +00:00
namespace gb
{
class scanner_cfg;
2022-07-01 07:24:58 +00:00
}
2022-06-15 03:04:40 +00:00
class scanner : public ISaneInvoker, virtual public refer
{
typedef struct _simple_opt
{
value_type type;
value_limit limit;
int bytes;
}SIMPLEOPT;
2022-06-15 03:04:40 +00:00
SANE_Handle handle_;
SCANNERID id_;
int err_;
int ex_id_;
int prev_start_result_;
int dpi_;
2023-05-26 07:17:15 +00:00
int fetch_imgs_ = 0; // count for images has fetched by APP
bool is_bIndicator;
bool is_show_setting_;
unsigned int img_ind_;
std::wstring scanner_name_;
std::wstring tmp_path_;
2022-07-01 07:24:58 +00:00
std::wstring cfg_path_;
2022-06-18 08:48:41 +00:00
std::string scan_msg_;
bool scan_err_;
2022-09-19 06:16:34 +00:00
volatile bool is_ui_wait_img_;
volatile bool is_scanning_;
volatile bool user_cancel_;
2022-06-18 00:54:01 +00:00
twain_xfer xfer_;
safe_img_queue images_;
size_t max_img_mem_;
size_t wait_fetch_; // ms, wait time when image-queue is great than max_img_mem_, default 1min
safe_queue<int> events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件
int ev_cnt_;
SANE_FinalImgFormat img_fmt_;
2022-06-18 08:48:41 +00:00
std::unique_ptr<dlg_indicator> indicator_;
std::unique_ptr<dlg_setting> setting_;
gb::scanner_cfg* cfg_;
bool twain_set_;
SANEAPI sane_api_;
std::map<sane_option_id, int> sane_ids_; // <fix-id, sane-option-sn>
2023-04-23 14:23:02 +00:00
std::function<void(int, void*, int)> ui_notify;
int(__stdcall* scanner_ev_handler_)(int, void*);
void* evh_param_;
HWND app_wnd_; // for MessageBox
bool is_show_ui_;
int transfer_id(int id); // transfer fixed SANE option ID to real id, -1 is none
void transport_config_file(void);
2022-10-08 06:13:09 +00:00
void update_config(void);
2022-07-01 07:24:58 +00:00
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);
std::string choose_scanner(const std::vector<std::string>& scanners);
2022-06-15 03:04:40 +00:00
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
2023-01-10 09:30:00 +00:00
bool set_option_value_with_parent(int sn, void* data, int* err); // return true if handled sn
2022-06-15 03:04:40 +00:00
int set_option_value(int sn, SANE_Value_Type type, int size, void* data);
int set_is_multiout(bool enable);
2022-06-15 03:04:40 +00:00
int thread_start(void);
std::unique_ptr<std::thread> thread_starting_;
2022-06-15 03:04:40 +00:00
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<EXAPI> ex_opts_;
typedef std::vector<EXAPI>::iterator EXAPIPOS;
EXAPIPOS find_ex_api(int op_id);
void apply_scheme(gb::sane_config_schm* schm);
2022-06-15 03:04:40 +00:00
;
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
2022-09-12 06:45:07 +00:00
EX_OPTION_HANDLER_DECL(erase_hole);
EX_OPTION_HANDLER_DECL(search_hole_range);
2022-06-15 03:04:40 +00:00
template<class T>
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), VAL_LIMIT_NONE, param);
else if (setv(&cur, VAL_ROLE_CURRENT, VAL_LIMIT_NONE, param))
return setv(&def, VAL_ROLE_DEFAULT, VAL_LIMIT_NONE, param);
return false;
2022-06-15 03:04:40 +00:00
}
template<class S, class T>
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))
{
T v = to_t(cur);
while (setv(&v, VAL_ROLE_CURRENT, VAL_LIMIT_RANGE, param))
2022-06-15 03:04:40 +00:00
{
v = to_t(def);
if (!setv(&v, VAL_ROLE_DEFAULT, VAL_LIMIT_RANGE, param))
break;
2022-06-15 03:04:40 +00:00
v = to_t(l);
if (!setv(&v, VAL_ROLE_LOWER, VAL_LIMIT_RANGE, param))
break;
v = to_t(u);
if (!setv(&v, VAL_ROLE_UPPER, VAL_LIMIT_RANGE, param))
2022-06-15 03:04:40 +00:00
break;
v = to_t(s);
setv(&v, VAL_ROLE_STEP, VAL_LIMIT_RANGE, param);
break;
2022-06-15 03:04:40 +00:00
}
}
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);
2022-10-28 09:09:59 +00:00
static bool is_option_float(int sn, void* param);
static void __stdcall apply_scheme(gb::sane_config_schm* schm, void* param);
2022-06-15 03:04:40 +00:00
public:
scanner(SCANNERID id);
protected:
~scanner();
public:
static std::string getDeviceType();
static bool is_belong_serial(int vid, int pid, SCANNERID serial);
static void get_scanner_name(SCANNERID id, std::vector<std::string>& names);
2022-06-15 03:04:40 +00:00
static value_type from_sane_type(SANE_Value_Type type);
static value_limit from_sane_constraint(SANE_Constraint_Type type);
static int control_read_string(SANE_Handle hdev, int code, std::string& str);
2022-06-15 03:04:40 +00:00
// IRef
public:
COM_API_OVERRIDE(long, add_ref(void));
COM_API_OVERRIDE(long, release(void));
// ISaneInvoker
public:
COM_API_OVERRIDE(int, start(void));
2022-06-15 03:04:40 +00:00
COM_API_OVERRIDE(int, stop(void));
COM_API_OVERRIDE(int, get_event(void));
COM_API_OVERRIDE(void, set_event_callback(int(__stdcall* handle_ev)(int, void*) = NULL, void* para = NULL));
2022-06-15 03:04:40 +00:00
COM_API_OVERRIDE(bool, wait_image(DWORD milliseconds = -1));
COM_API_OVERRIDE(int, get_scanned_images(DWORD milliseconds = 0));
2022-06-16 09:28:46 +00:00
COM_API_OVERRIDE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz
2022-11-06 08:49:30 +00:00
COM_API_OVERRIDE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = NULL, int* dpi = NULL));
COM_API_OVERRIDE(bool, discard_first_image(void)); // call 'release' on returned value, plz
2022-06-15 03:04:40 +00:00
COM_API_OVERRIDE(bool, is_online(void));
COM_API_OVERRIDE(bool, is_paper_on(void));
COM_API_OVERRIDE(int, last_error(void));
2023-05-26 07:17:15 +00:00
COM_API_OVERRIDE(int, image_fetched(IScanImg* tx));
2022-06-15 03:04:40 +00:00
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(bool, get_value(int sn, void* data, int* len)); // get operation with in-parameter
2022-06-15 03:04:40 +00:00
COM_API_OVERRIDE(int, set_value(int sn, void* val));
COM_API_OVERRIDE(int, convert_image(SANE_ImageFormatConvert* conv));
2022-06-29 08:13:05 +00:00
COM_API_OVERRIDE(void, free_buffer(void* buf, int len));
COM_API_OVERRIDE(int, get_fixed_ids(bool(__stdcall* cb)(uint32_t id, void* param), void* param));
2022-06-15 03:04:40 +00:00
// SANE options ID ...
SANE_OPTION_ID(color_correction); // 2023-02-24 15:31:19 色偏校正
SANE_OPTION_ID(fold_type); // 2023-02-24 15:28:46 对折模式
2022-06-15 03:04:40 +00:00
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); // 二值化图像阈值
2022-09-07 07:48:41 +00:00
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); // 黑白图像反色输出
2022-09-10 02:09:37 +00:00
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); // 穿孔搜索范围 - 下
2022-10-24 08:58:09 +00:00
SANE_OPTION_ID(fold_direction); // 对折模式
2023-08-16 07:32:13 +00:00
SANE_OPTION_ID(discardblank); // 跳过空白页
2022-06-15 03:04:40 +00:00
// 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
int language_id_;
2022-06-15 03:04:40 +00:00
// ui ...
2022-06-18 00:54:01 +00:00
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, bool bIndicator));
2022-06-15 03:04:40 +00:00
COM_API_OVERRIDE(void, ui_hide(void));
COM_API_OVERRIDE(bool, ui_is_ok(void));
2022-06-18 00:54:01 +00:00
// twain
COM_API_OVERRIDE(void, twain_set_transfer(twain_xfer xfer));
2022-06-29 08:13:05 +00:00
COM_API_OVERRIDE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL));
2022-07-01 07:24:58 +00:00
COM_API_OVERRIDE(int, twain_get_config(char* buf, size_t* len));
COM_API_OVERRIDE(int, twain_set_config(char* buf, size_t len));
2022-06-18 00:54:01 +00:00
// methods:
public:
int handle_device_event(int ev_code, void* data, unsigned int* len);
};