432 lines
14 KiB
C++
432 lines
14 KiB
C++
#pragma once
|
||
|
||
//
|
||
// For: interface definition for SANE to TWAIN
|
||
//
|
||
// Date: 2022-06-08
|
||
//
|
||
|
||
#include <Windows.h>
|
||
#include <sane/sane_ex.h>
|
||
#include <huagao/hgscanner_error.h>
|
||
#include <string>
|
||
|
||
#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
|
||
struct __declspec(novtable) IRef
|
||
{
|
||
COM_API_DECLARE(long, add_ref(void));
|
||
COM_API_DECLARE(long, release(void));
|
||
};
|
||
struct __declspec(novtable) 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));
|
||
COM_API_DECLARE(int, image_status(void));
|
||
};
|
||
struct __declspec(novtable) ISaneInvoker : public IRef
|
||
{
|
||
COM_API_DECLARE(int, start(void));
|
||
COM_API_DECLARE(int, stop(void));
|
||
COM_API_DECLARE(int, get_event(void));
|
||
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_OPTION_ID_API(is_photo_mode); // 照片模式
|
||
SANE_OPTION_ID_API(double_feed_handle); // 双张图片处理
|
||
SANE_OPTION_ID_API(scan_when_paper_on); // 待纸扫描
|
||
SANE_OPTION_ID_API(feed_strength); // 分纸强度
|
||
SANE_OPTION_ID_API(power_scheme); // 休眠时间
|
||
SANE_OPTION_ID_API(is_auto_strength); // 自动搓纸强度
|
||
SANE_OPTION_ID_API(feed_strength_value); // 自动搓纸强度设定值
|
||
SANE_OPTION_ID_API(is_reverse_bw); // 黑白图像反色输出
|
||
SANE_OPTION_ID_API(is_erase_hole_l); // 穿孔移除 - 左
|
||
SANE_OPTION_ID_API(search_hole_range_l); // 穿孔搜索范围 - 左
|
||
SANE_OPTION_ID_API(is_erase_hole_r); // 穿孔移除 - 右
|
||
SANE_OPTION_ID_API(search_hole_range_r); // 穿孔搜索范围 - 右
|
||
SANE_OPTION_ID_API(is_erase_hole_t); // 穿孔移除 - 上
|
||
SANE_OPTION_ID_API(search_hole_range_t); // 穿孔搜索范围 - 上
|
||
SANE_OPTION_ID_API(is_erase_hole_b); // 穿孔移除 - 下
|
||
SANE_OPTION_ID_API(search_hole_range_b); // 穿孔搜索范围 - 下
|
||
|
||
// 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, bool indicator = true));
|
||
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 <vector>
|
||
#include <list>
|
||
namespace sane_opts
|
||
{
|
||
template<class T>
|
||
class get_opts
|
||
{
|
||
public:
|
||
T* init_;
|
||
T* cur_;
|
||
T* lower_;
|
||
T* upper_;
|
||
T* step_;
|
||
std::vector<T>* vvs_;
|
||
std::list<T>* lvs_;
|
||
|
||
public:
|
||
get_opts(T* cur = NULL, T* init = NULL, std::vector<T>* vs = NULL, std::list<T>* 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<class T>
|
||
bool __stdcall set_opt_value(void* val, value_role role, void* param)
|
||
{
|
||
get_opts<T>* v = (get_opts<T>*)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<type> op(cur, init, vec, lst); \
|
||
object->get_value(ind, sane_opts::set_opt_value<type>, &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<type> op(cur, init, NULL, NULL, low, up, step); \
|
||
object->get_value(ind, sane_opts::set_opt_value<type>, &op);\
|
||
if(step && fabs(*step) < .000001) *step = 1; \
|
||
} \
|
||
}
|
||
#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; \
|
||
load_sane_util::log_info((std::wstring(L"Fatal: property '") + L###id_name + L"' not found !!!\r\n").c_str(), 0); \
|
||
} \
|
||
}
|
||
|
||
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);
|
||
|
||
|