code_twain/sane/scanner.h

331 lines
11 KiB
C++

#pragma once
#include "scanned_img.h"
#include <vector>
#include <algorithm>
#include <memory>
#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<int> events_; //如果有界面,则全部保存从界面传回的消息;否则只保存开始扫描和结束扫描的事件
SANE_FinalImgFormat img_fmt_;
std::unique_ptr<dlg_indicator> indicator_;
std::unique_ptr<dlg_setting> setting_;
gb::sane_config* cfg_;
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<EXAPI> ex_opts_;
typedef std::vector<EXAPI>::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<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), param);
else if (setv(&cur, VAL_ROLE_CURRENT, param))
return setv(&def, VAL_ROLE_DEFAULT, param);
else
return false;
}
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))
{
struct
{
int role;
S val;
}vals[5];
int count = 0;
std::vector<S> 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);
};