#pragma once // // For: interface definition for SANE to TWAIN // // Date: 2022-06-08 // #include #include #include #include #define COM_API_DECLARE(ret, decl) virtual ret __stdcall decl = 0 #define COM_API_DECLARE_NON_PURE(ret, decl) virtual ret __stdcall decl #define COM_API_OVERRIDE(ret, decl) virtual ret __stdcall decl override #define COM_API_IMPLEMENT(cls, ret, decl) ret __stdcall cls##::decl #define SANE_OPTION_ID_API(opt) COM_API_DECLARE(int, sane_opt_id_##opt(void)) // -1 is none #define SANE_OPTION_ID_OVERRIDE(opt) COM_API_OVERRIDE(int, sane_opt_id_##opt(void)) #define SANE_OPTION_IMPLEMENT(cls, opt) int __stdcall cls##::sane_opt_id_##opt(void) #define SANE_OPTION_ID_API_EX(opt) COM_API_DECLARE(int, sane_opt_id_ex_##opt(void)) // -1 is none #define SANE_OPTION_ID_OVERRIDE_EX(opt) COM_API_OVERRIDE(int, sane_opt_id_ex_##opt(void)) #define SANE_OPTION_IMPLEMENT_EX(cls, opt) int __stdcall cls##::sane_opt_id_ex_##opt(void) #define ALIGN_MEMORY(n, align) ((n + align - 1) / (align) * (align)) #define _TO_UNICODE_(str) L##str #define UNICODE_STR(str) _TO_UNICODE_(str) #define TWPT_AUTOMATIC_COLOR 0x0a0c #define AUTO_MATIC_ROTATE 123.456f #define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .000001 enum value_limit { VAL_LIMIT_NONE = 0, // VAL_LIMIT_ENUM, // VAL_LIMIT_RANGE, // }; enum value_role { VAL_ROLE_NONE = 0, // this value is no role but an item of the option only VAL_ROLE_DEFAULT = 0x01, // this value is the default value of the option VAL_ROLE_CURRENT = 0x02, // this value is the current value of the option VAL_ROLE_LOWER = 0x04, // the lower value of a VAL_LIMIT_RANGE VAL_ROLE_UPPER = 0x08, // the upper value of a VAL_LIMIT_RANGE VAL_ROLE_STEP = 0x10, // the step value of a VAL_LIMIT_RANGE }; enum value_type { VAL_TYPE_NONE = 0, VAL_TYPE_BOOL, // bool VAL_TYPE_INT, // int VAL_TYPE_FLOAT, // float VAL_TYPE_STR, // char* VAL_TYPE_BUTTON, // a button }; enum color_value // 除最后一项外,其余与Twpp::PixelType值保持一致 { COLOR_BW = 0, COLOR_GRAY, COLOR_RGB, COLOR_AUTO_MATCH = TWPT_AUTOMATIC_COLOR, }; enum paper_value // 与Twpp::PaperSize保持一致 { PAPER_A4 = 1, PAPER_16K = 1, PAPER_LETTER = 3, PAPER_LEGAL = 4, PAPER_A5 = 5, PAPER_B4 = 6, PAPER_B6 = 7, PAPER_A3 = 11, PAPER_8K = 11, PAPER_A6 = 13, PAPER_B5 = 29, PAPER_STATEMENT = 52, // 匹配原始尺寸 PAPER_MAXSIZE = 54, // 最大扫描尺寸 // 以下为未匹配选项 PAPER_DOUBLE_LETTER = 103, PAPER_MAXSIZE_CROP = 154, // 最大扫描尺寸自动裁切 PAPER_TRIPPLE = 111, // 三联试卷 }; enum filter_value // 除色选项 { FILTER_NONE = 0, FILTER_RED, FILTER_GREEN, FILTER_BLUE, }; enum enhance_value // 颜色增强选项 { ENHANCE_NONE = 0, ENHANCE_RED, ENHANCE_GREEN, ENHANCE_BLUE, }; enum sharpen_value { SHARPEN_NONE = 0, SHARPEN_SHARPEN, SHARPEN_SHARPEN_MORE, SHARPEN_BLUR, SHARPEN_BLUR_MORE, }; enum multiout_value { MULTI_OUT_NONE = -1, MULTI_OUT_ALL, MULTI_OUT_COLOR_GRAY, MULTI_OUT_COLOR_BW, MULTI_OUT_GRAY_BW, }; enum twain_xfer { TWAIN_XFER_Native = 0, // BITMAPINFOHEADER + bits TWAIN_XFER_File = 1, // BITMAPFILEHEADER + TWAIN_XFER_Native TWAIN_XFER_Memory = 2, // to be implementing ... }; typedef bool(__stdcall* set_opt_value)(void* val, value_role role, void* param); // return false to stop the callback __declspec(novtable) struct IRef { COM_API_DECLARE(long, add_ref(void)); COM_API_DECLARE(long, release(void)); }; __declspec(novtable) struct IScanImg : public IRef { COM_API_DECLARE(int, width(void)); COM_API_DECLARE(int, line_bytes(void)); COM_API_DECLARE(int, height(void)); COM_API_DECLARE(int, depth(void)); COM_API_DECLARE(int, channel(void)); COM_API_DECLARE(SANE_Frame, type(void)); COM_API_DECLARE(unsigned int, bytes(void)); COM_API_DECLARE(unsigned int, header_size(void)); COM_API_DECLARE(unsigned char*, data(unsigned long long off, unsigned int *bytes)); COM_API_DECLARE(int, read(void* buf, size_t* bytes, unsigned long long off = 0)); COM_API_DECLARE(const char*, file(void)); COM_API_DECLARE(void, keep_file(bool keep)); COM_API_DECLARE(void, copy_header(SANE_Parameters* head)); }; __declspec(novtable) struct ISaneInvoker : public IRef { COM_API_DECLARE(int, start(void)); COM_API_DECLARE(int, stop(void)); COM_API_DECLARE(void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param)); COM_API_DECLARE(bool, wait_image(DWORD milliseconds = -1)); COM_API_DECLARE(int, get_scanned_images(DWORD milliseconds = 0)); COM_API_DECLARE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz COM_API_DECLARE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = NULL)); COM_API_DECLARE(bool, is_online(void)); COM_API_DECLARE(bool, is_paper_on(void)); // Function: 获取配置项信息 // // Parameter: sn - 配置项索引 // // type - 配置项数据类型 // // limit - 配置项限制类型 // // bytes - *type 为 VAL_TYPE_STR时,需要的最小空间字节数 COM_API_DECLARE(bool, get_option_info(int sn, value_type* type, value_limit* limit, int *bytes)); COM_API_DECLARE(bool, get_value(int sn, set_opt_value, void* param)); COM_API_DECLARE(int, set_value(int sn, void* val)); COM_API_DECLARE(int, convert_image(SANE_ImageFormatConvert* conv)); COM_API_DECLARE(void, free_buffer(void* buf, int len)); // SANE options ID ... SANE_OPTION_ID_API(is_multiout); // 多流输出 SANE_OPTION_ID_API(multiout_type); // 多流输出类型 SANE_OPTION_ID_API(color_mode); // 颜色模式 SANE_OPTION_ID_API(erase_color); // 除色或增强 SANE_OPTION_ID_API(erase_multiout_red); // 多流输出除红 SANE_OPTION_ID_API(erase_paper_red); // 试卷除红 SANE_OPTION_ID_API(is_erase_background); // 背景移除 SANE_OPTION_ID_API(background_color_range); // 背景色彩范围 SANE_OPTION_ID_API(sharpen); // 锐化与模糊 SANE_OPTION_ID_API(erase_morr); // 除摩尔纹 SANE_OPTION_ID_API(erase_grids); // 除网纹 SANE_OPTION_ID_API(error_extend); // 错误扩散 SANE_OPTION_ID_API(is_noise_modify); // 噪点优化 SANE_OPTION_ID_API(noise_threshold); // 噪点优化尺寸 SANE_OPTION_ID_API(paper); // 纸张尺寸 SANE_OPTION_ID_API(is_custom_area); // 自定义扫描区域 SANE_OPTION_ID_API(curstom_area_l); // 自定义扫描区域 左 SANE_OPTION_ID_API(curstom_area_r); // 自定义扫描区域 右 SANE_OPTION_ID_API(curstom_area_t); // 自定义扫描区域 上 SANE_OPTION_ID_API(curstom_area_b); // 自定义扫描区域 下 SANE_OPTION_ID_API(is_size_check); // 尺寸检测 SANE_OPTION_ID_API(page); // 扫描页面 SANE_OPTION_ID_API(blank_page_threshold); // 跳过空白页灵敏度 SANE_OPTION_ID_API(resolution); // 分辨率 SANE_OPTION_ID_API(image_quality); // 图像质量 SANE_OPTION_ID_API(is_swap); // 交换正反面 SANE_OPTION_ID_API(is_split); // 图像拆分 SANE_OPTION_ID_API(is_auto_deskew); // 自动纠偏 SANE_OPTION_ID_API(is_custom_gamma); // 自定义gamma SANE_OPTION_ID_API(bright); // 亮度 SANE_OPTION_ID_API(contrast); // 对比度 SANE_OPTION_ID_API(gamma); // gamma SANE_OPTION_ID_API(is_erase_black_frame); // 消除黑框 SANE_OPTION_ID_API(deep_sample); // 深色样张 SANE_OPTION_ID_API(threshold); // 阈值 SANE_OPTION_ID_API(anti_noise); // 背景抗噪等级 SANE_OPTION_ID_API(margin); // 边缘缩进 SANE_OPTION_ID_API(fill_background); // 背景填充方式 SANE_OPTION_ID_API(is_anti_permeate); // 防止渗透 SANE_OPTION_ID_API(anti_permeate_level); // 防止渗透等级 SANE_OPTION_ID_API(is_erase_hole); // 穿孔移除 SANE_OPTION_ID_API(search_hole_range); // 穿孔搜索范围 SANE_OPTION_ID_API(is_filling_color); // 色彩填充 SANE_OPTION_ID_API(is_ultrasonic_check); // 超声波检测 SANE_OPTION_ID_API(is_check_staple); // 装订检测 SANE_OPTION_ID_API(scan_mode); // 扫描张数 SANE_OPTION_ID_API(scan_count); // 扫描数量 SANE_OPTION_ID_API(text_direction); // 文稿方向 SANE_OPTION_ID_API(is_rotate_bkg180); // 背面旋转180度 SANE_OPTION_ID_API(is_check_dogear); // 折角检测 SANE_OPTION_ID_API(dogear_size); // 折角检测大小 SANE_OPTION_ID_API(is_check_skew); // 歪斜检测 SANE_OPTION_ID_API(skew_range); // 歪斜容忍度 SANE_OPTION_ID_API(black_white_threshold); // 二值化图像阈值 // SANE-ex option ID: SANE_OPTION_ID_API_EX(multiout_type); // int SANE_OPTION_ID_API_EX(auto_color_type); // int SANE_OPTION_ID_API_EX(color_mode); // int SANE_OPTION_ID_API_EX(sharpen); // int SANE_OPTION_ID_API_EX(paper); // paper_value SANE_OPTION_ID_API_EX(paper_lateral); // bool SANE_OPTION_ID_API_EX(auto_paper_size); // bool SANE_OPTION_ID_API_EX(is_paper_auto_crop); // bool SANE_OPTION_ID_API_EX(text_direction); // float 90, 180, ..., -1 is auto-text-direction SANE_OPTION_ID_API_EX(duplex); // bool SANE_OPTION_ID_API_EX(fill_background); // bool true - 凸多边形 SANE_OPTION_ID_API_EX(discard_blank_page); // bool SANE_OPTION_ID_API_EX(discard_blank_receipt); // bool SANE_OPTION_ID_API_EX(is_page_fold); // bool SANE_OPTION_ID_API_EX(color_filter); // int (filter_value) SANE_OPTION_ID_API_EX(color_enhance); // int (enhance_value) SANE_OPTION_ID_API_EX(final_compression); // int SANE_OPTION_ID_API_EX(final_format); // SANE_FinalImgFormat SANE_OPTION_ID_API_EX(serial); // std::string SANE_OPTION_ID_API_EX(to_be_scan); // bool SANE_OPTION_ID_API_EX(scan_with_hole); // bool SANE_OPTION_ID_API_EX(device_code); // std::string SANE_OPTION_ID_API_EX(power); // int SANE_OPTION_ID_API_EX(hardware_version); // std::string SANE_OPTION_ID_API_EX(ip); // std::string // ui ... COM_API_DECLARE(bool, ui_show_main(HWND parent)); COM_API_DECLARE(bool, ui_show_setting(HWND parent, bool with_scan)); COM_API_DECLARE(bool, ui_show_progress(HWND parent)); COM_API_DECLARE(void, ui_hide(void)); COM_API_DECLARE(bool, ui_is_ok(void)); // twain COM_API_DECLARE(void, twain_set_transfer(twain_xfer xfer)); COM_API_DECLARE(void, twain_set_compression(SANE_CompressionType compression, void* detail = NULL)); COM_API_DECLARE(int, twain_get_config(char* buf, size_t* len)); COM_API_DECLARE(int, twain_set_config(char* buf, size_t len)); }; struct delete_scanner { void operator()(ISaneInvoker* p) { p->release(); } }; #include #include namespace sane_opts { template class get_opts { public: T* init_; T* cur_; T* lower_; T* upper_; T* step_; std::vector* vvs_; std::list* lvs_; public: get_opts(T* cur = NULL, T* init = NULL, std::vector* vs = NULL, std::list* ls = NULL, T* lower = NULL, T* upper = NULL, T* step = NULL) : init_(init), cur_(cur), vvs_(vs), lvs_(ls) , lower_(lower), upper_(upper), step_(step) {} ~get_opts() {} }; template bool __stdcall set_opt_value(void* val, value_role role, void* param) { get_opts* v = (get_opts*)param; bool go = true; if (role & VAL_ROLE_CURRENT) { if (v->cur_) { *v->cur_ = *(T*)val; } } if (role & VAL_ROLE_DEFAULT) { if (v->init_) { *v->init_ = *(T*)val; } } if (role & VAL_ROLE_LOWER) { if (v->lower_) *v->lower_ = *(T*)val; } if (role & VAL_ROLE_UPPER) { if (v->upper_) *v->upper_ = *(T*)val; } if (role & VAL_ROLE_STEP) { if (v->step_) *v->step_ = *(T*)val; return go; } if (v->vvs_) v->vvs_->push_back(*(T*)val); else if (v->lvs_) v->lvs_->push_back(*(T*)val); return go; } } #define GET_SANE_OPT(type, object, id_name, cur, init, vec, lst) \ { \ int ind = object->sane_opt_id_##id_name##(); \ if(ind > 0) \ { \ sane_opts::get_opts op(cur, init, vec, lst); \ object->get_value(ind, sane_opts::set_opt_value, &op);\ } \ } #define GET_SANE_OPT_RANGE(type, object, id_name, cur, init, low, up, step) \ { \ int ind = object->sane_opt_id_##id_name##(); \ if(ind > 0) \ { \ sane_opts::get_opts op(cur, init, NULL, NULL, low, up, step); \ object->get_value(ind, sane_opts::set_opt_value, &op);\ } \ } #define SET_SANE_OPT(ret, object, id_name, val) \ { \ int ind = object->sane_opt_id_##id_name##(); \ if(ind > 0) \ ret = object->set_value(ind, val); \ else \ ret = SCANNER_ERR_INVALID_PARAMETER; \ } typedef unsigned int SCANNERID; #define MAKE_SCANNER_ID(pid, vid) MAKELONG(pid, vid) #define GET_SCANNER_PID(sid) LOWORD(sid) #define GET_SCANNER_VID(sid) HIWORD(sid) #ifdef EXPORT_SANE_API __declspec(dllexport) #else __declspec(dllimport) #endif int __stdcall initialize(void* reserve); #ifdef EXPORT_SANE_API __declspec(dllexport) #else __declspec(dllimport) #endif int __stdcall open_scanner(SCANNERID scanner_id, ISaneInvoker** invoker); #ifdef EXPORT_SANE_API __declspec(dllexport) #else __declspec(dllimport) #endif bool __stdcall is_scanner_online(SCANNERID scanner_id); #ifdef EXPORT_SANE_API __declspec(dllexport) #else __declspec(dllimport) #endif int __stdcall uninitialize(void* reserve);