447 lines
14 KiB
C++
447 lines
14 KiB
C++
#pragma once
|
||
#include "huagao/hgscanner_error.h"
|
||
#include <string>
|
||
#include <vector>
|
||
#include <algorithm>
|
||
#include <mutex>
|
||
#include "sane_option_trans.h"
|
||
|
||
|
||
class sane_invoker;
|
||
class scanner;
|
||
struct _dev;
|
||
|
||
|
||
class refer
|
||
{
|
||
volatile long ref_;
|
||
|
||
public:
|
||
refer() : ref_(1)
|
||
{}
|
||
protected:
|
||
virtual ~refer()
|
||
{}
|
||
|
||
public:
|
||
long add_ref(void)
|
||
{
|
||
return InterlockedIncrement(&ref_);
|
||
}
|
||
long release(void)
|
||
{
|
||
long ref = InterlockedDecrement(&ref_);
|
||
|
||
if (ref <= 0)
|
||
delete this;
|
||
|
||
return ref;
|
||
}
|
||
};
|
||
|
||
class scanned_img
|
||
{
|
||
SANE_Parameters param_;
|
||
std::vector<unsigned char> data_;
|
||
|
||
std::string file_header(SANE_FinalImgFormat* header, float resolution);
|
||
|
||
public:
|
||
scanned_img(SANE_Image* img, SANE_FinalImgFormat* header);
|
||
~scanned_img();
|
||
|
||
public:
|
||
int width(void);
|
||
int line_bytes(void);
|
||
int height(void);
|
||
int depth(void);
|
||
int channel(void);
|
||
SANE_Frame type(void);
|
||
unsigned int bytes(void);
|
||
unsigned char* bits(void);
|
||
void copy_header(SANE_Parameters* head);
|
||
};
|
||
|
||
extern HMODULE me_;
|
||
namespace local_utility
|
||
{
|
||
std::wstring reg_read(HKEY root, const wchar_t* path, const wchar_t* name);
|
||
std::wstring reg_get_app_installing_path(void);
|
||
}
|
||
|
||
class scanner : public refer
|
||
{
|
||
SANE_Handle hdev_;
|
||
sane_invoker* host_;
|
||
std::string name_;
|
||
std::string type_;
|
||
std::string vendor_;
|
||
std::string product_;
|
||
bool online_;
|
||
int option_count_;
|
||
std::mutex lock_img_;
|
||
std::vector<scanned_img*> img_;
|
||
SANE_FinalImgFormat *fmt_;
|
||
|
||
typedef struct _sane_option
|
||
{
|
||
int ind;
|
||
const SANE_Option_Descriptor* desc;
|
||
union
|
||
{
|
||
bool bv;
|
||
int iv;
|
||
double dv;
|
||
std::string* sv;
|
||
}val;
|
||
bool operator==(int id)
|
||
{
|
||
return ind == id;
|
||
}
|
||
}SANEOPTION;
|
||
std::vector<SANEOPTION> options_;
|
||
|
||
float dpi_;
|
||
HANDLE wait_img_;
|
||
volatile bool scanning_;
|
||
int err_;
|
||
std::string desc_;
|
||
|
||
void load_options(void);
|
||
void init_image_format(void);
|
||
std::string get_string(int opt, int bytes);
|
||
bool get_boolean(int opt);
|
||
int get_integer(int opt);
|
||
double get_double(int opt);
|
||
int set_string(int opt, std::string& val, int size, SANE_Int* afterdo = NULL);
|
||
|
||
enum twain_essential
|
||
{
|
||
TWAIN_RESOLUTION,
|
||
TWAIN_PAPER_SIZE,
|
||
};
|
||
|
||
int opt_ind_dpi_;
|
||
int opt_ind_color_mode_;
|
||
int opt_ind_paper_;
|
||
int opt_ind_scann_count_; // MAKELONG(count, scan_continue)
|
||
int opt_ind_text_direction_;
|
||
int opt_ind_page_;
|
||
int opt_ind_auto_descrew_;
|
||
int opt_ind_erase_black_frame_;
|
||
int opt_ind_filter_;
|
||
int opt_ind_bright_;
|
||
int opt_ind_contrast_;
|
||
int opt_ind_gamma_;
|
||
int opt_ind_ultrasonic_;
|
||
int opt_ind_flip_;
|
||
int opt_ind_rotate_bkg_;
|
||
int opt_ind_fill_blank_bkg_;
|
||
int opt_ind_edge_ident_;
|
||
int opt_ind_threshold_;
|
||
int opt_ind_bkg_filling_method_;
|
||
int opt_ind_fill_hole_;
|
||
int opt_ind_fill_hole_ratio_;
|
||
int opt_ind_noise_;
|
||
int opt_ind_noise_threshold_;
|
||
int opt_ind_rid_red_;
|
||
int opt_ind_rid_red_hsv_;
|
||
int opt_ind_sharpen_;
|
||
int opt_ind_screw_detect_;
|
||
int opt_ind_screw_detect_level_;
|
||
int opt_ind_staple_;
|
||
int opt_ind_dogear_;
|
||
int opt_ind_dark_sample_;
|
||
int opt_ind_split_;
|
||
int opt_ind_fade_bkg_;
|
||
int opt_ind_fade_bkg_val_;
|
||
int opt_ind_size_detect_;
|
||
int opt_ind_multi_out_;
|
||
|
||
SANE_ImageType img_fmt_;
|
||
int jpeg_quality_;
|
||
|
||
SANE_CompressionType compression_;
|
||
bool auto_crop_;
|
||
|
||
void(*event_cb_)(int, void*, unsigned int*, void*);
|
||
void* cb_param_;
|
||
|
||
public:
|
||
scanner(sane_invoker* host, struct _dev& dev);
|
||
|
||
static std::string type(SANE_Value_Type st);
|
||
static value_limit limit(SANE_Constraint_Type st);
|
||
|
||
protected:
|
||
~scanner();
|
||
|
||
public:
|
||
int close(void);
|
||
int start(void);
|
||
int stop(void);
|
||
void set_event_callback(void(*cb)(int, void*, unsigned int*, void*), void* param);
|
||
bool wait_image(DWORD milliseconds = -1);
|
||
int get_scanned_images(DWORD milliseconds = 0);
|
||
scanned_img* take_first_image(void); // delete returned value, plz
|
||
bool get_first_image_header(SANE_Parameters* header);
|
||
int last_error(void);
|
||
|
||
SANE_Handle handle(void);
|
||
bool is_online(void);
|
||
void set_online(bool online);
|
||
|
||
void put_image(SANE_Image* img, unsigned int* len);
|
||
void scan_finished(const char* desc, int err);
|
||
|
||
// up to sane, we set the CAP_xxx according to settings display in UI ...
|
||
bool get_value_info(int sn, std::string& type, value_limit& limit);
|
||
bool get_value(int sn, std::list<std::string>& values, std::string& now, std::string& init);
|
||
bool get_value(int sn, std::list<float>& values, float& now, float& init);
|
||
bool get_value(int sn, std::list<bool>& values, bool& now, bool& init);
|
||
bool get_value(int sn, int& now, int& init, int* lower = NULL, int* upper = NULL, int* step = NULL);
|
||
bool get_value(int sn, float& now, float& init, float* lower = NULL, float* upper = NULL, float* step = NULL);
|
||
|
||
int set_value(int sn, std::string val);
|
||
int set_value(int sn, bool val);
|
||
int set_value(int sn, int val);
|
||
int set_value(int sn, double val);
|
||
|
||
// attribute for twain ...
|
||
public:
|
||
int twain_set_resolution(float dpi);
|
||
float twain_get_resolution(float* init = NULL, std::vector<float>* values = NULL, value_limit* limit = NULL);
|
||
|
||
int twain_set_color_mode(int twain_pixel_type);
|
||
int twain_get_color_mode(int* init = NULL, std::vector<int>* values = NULL, value_limit* limit = NULL);
|
||
int twain_set_auto_color_type(int type);
|
||
|
||
int twain_get_paper_ind(void);
|
||
int twain_set_paper_lateral(bool lateral);
|
||
bool twain_is_paper_lateral(void);
|
||
int twain_set_paper_auto_match_size(bool match);
|
||
bool twain_is_paper_auto_match_size(void);
|
||
|
||
int twain_set_scan_count(int count);
|
||
int twain_get_scan_count(void);
|
||
|
||
int twain_set_final_format(SANE_ImageType type, void* param);
|
||
int twain_get_jpeg_quality(void);
|
||
SANE_ImageType get_final_format(void);
|
||
|
||
int twain_set_final_compression(int compression);
|
||
int twain_get_final_compression(int *init = NULL, std::vector<int>* values = NULL);
|
||
|
||
int twain_set_text_direction(double degree);
|
||
double twain_get_text_direction(double* init = NULL, std::list<double>* vals = NULL, value_limit* limit = NULL);
|
||
int twain_set_text_auto_matic(bool am);
|
||
bool twain_is_text_auto_matic(void);
|
||
|
||
int twain_set_page_duplex(bool dup);
|
||
bool twain_is_page_duplex(void);
|
||
int twain_set_page_discarding_blank_page(bool discard, bool receipt);
|
||
bool twain_is_page_discarding_blank_page(bool receipt);
|
||
int twain_set_page_fold(bool fold);
|
||
bool twain_is_page_fold(void);
|
||
|
||
int twain_set_auto_descrew(bool enable);
|
||
bool twain_is_auto_descrew(void);
|
||
|
||
int twain_set_erase_black_frame(bool erase);
|
||
bool twain_is_erase_black_frame(bool* init);
|
||
|
||
int twain_set_filter(int tw_filter, bool enhance);
|
||
int twain_get_filter(bool enhance);
|
||
|
||
int twain_set_bright(double bright);
|
||
double twain_get_bright(double* init = NULL, double* lower = NULL, double* upper = NULL, double* step = NULL);
|
||
|
||
int twain_set_contrast(double bright);
|
||
double twain_get_contrast(double* init = NULL, double* lower = NULL, double* upper = NULL, double* step = NULL);
|
||
|
||
int twain_set_gamma(double bright);
|
||
double twain_get_gamma(double* init = NULL, double* lower = NULL, double* upper = NULL, double* step = NULL);
|
||
|
||
int twain_set_ultrasonic_check(bool check);
|
||
bool twain_is_ultrasonic_check(bool* init = NULL);
|
||
|
||
bool twain_is_auto_crop(void);
|
||
bool twain_is_paper_on(void);
|
||
int twain_get_device_code(char* buf, unsigned int len);
|
||
|
||
int twain_set_sharpen(int sharpen);
|
||
int twain_get_sharpen(void);
|
||
|
||
int twain_get_serial_num(char buf[256]);
|
||
int twain_get_hareware_version(char buf[256]);
|
||
int twain_get_ip(char buf[256]);
|
||
|
||
int twain_get_dogear_distance(void);
|
||
int twain_set_dogear_distance(int dist);
|
||
|
||
int twain_set_power_level(int level);
|
||
int twain_get_power_level(void);
|
||
|
||
int twain_set_to_be_scan(bool yes);
|
||
bool twain_get_to_be_scan(void);
|
||
|
||
int twain_set_scan_with_hole(bool yes);
|
||
bool twain_get_scan_with_hole(void);
|
||
|
||
int twain_set_multioutput_type(int type);
|
||
int twain_get_multioutput_type(void);
|
||
|
||
int twain_get_flip_ind(void);
|
||
int twain_get_rotate_bkg_ind(void);
|
||
int twain_get_fill_black_bkg_ind(void);
|
||
int twain_get_edge_ident_ind(void);
|
||
int twain_get_threshold_ind(void);
|
||
int twain_bkg_filling_method_ind(void);
|
||
int twain_fill_hole_ind(void);
|
||
int twain_fill_hole_ratio_ind(void);
|
||
int twain_detach_noise_ind(void);
|
||
int twain_detach_noise_threshold_ind(void);
|
||
int twain_rid_red_ind(void);
|
||
int twain_rid_red_hsv_ind(void);
|
||
int twain_screw_detect_ind(void);
|
||
int twain_screw_detect_level_ind(void);
|
||
int twain_staple_detect_ind(void);
|
||
int twain_dogear_detect_ind(void);
|
||
int twain_dark_sample_ind(void);
|
||
int twain_image_split_ind(void);
|
||
int twain_fade_bkground_ind(void);
|
||
int twain_fade_bkground_val_ind(void);
|
||
int twain_size_detect_ind(void);
|
||
};
|
||
struct delete_scanner
|
||
{
|
||
void operator()(scanner* p)
|
||
{
|
||
p->release();
|
||
}
|
||
};
|
||
typedef struct _dev
|
||
{
|
||
scanner* scanner;
|
||
std::string name;
|
||
std::string type;
|
||
std::string vendor;
|
||
std::string product;
|
||
|
||
struct _dev()
|
||
{
|
||
scanner = NULL;
|
||
name = type = vendor = product = "";
|
||
}
|
||
bool operator==(const char* n)
|
||
{
|
||
return name == n;
|
||
}
|
||
bool operator==(SANE_Handle h)
|
||
{
|
||
return scanner && scanner->handle() == h;
|
||
}
|
||
}SANEDEV;
|
||
|
||
|
||
|
||
|
||
class sane_invoker
|
||
{
|
||
bool ok_;
|
||
std::wstring cfg_file_;
|
||
SANE_Int ver_;
|
||
HMODULE sane_;
|
||
HANDLE first_cb_;
|
||
SANEAPI sane_api_;
|
||
|
||
std::mutex lock_dev_;
|
||
std::vector<SANEDEV> devices_;
|
||
|
||
SANE_Status (*real_sane_init_)(SANE_Int* version_code, SANE_Auth_Callback authorize);
|
||
void (*real_sane_exit_)(void);
|
||
SANE_Status(*real_sane_get_devices_)(const SANE_Device*** device_list, SANE_Bool local_only);
|
||
SANE_Status(*real_sane_open_)(SANE_String_Const devicename, SANE_Handle* handle);
|
||
void (*real_sane_close_)(SANE_Handle handle);
|
||
const SANE_Option_Descriptor* (*real_sane_get_option_descriptor_)(SANE_Handle handle, SANE_Int option);
|
||
SANE_Status(*real_sane_control_option_)(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info);
|
||
SANE_Status(*real_sane_get_parameters_)(SANE_Handle handle, SANE_Parameters* params);
|
||
SANE_Status(*real_sane_start_)(SANE_Handle handle);
|
||
SANE_Status(*real_sane_read_)(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length);
|
||
void (*real_sane_cancel_)(SANE_Handle handle);
|
||
SANE_Status(*real_sane_set_io_mode_)(SANE_Handle handle, SANE_Bool non_blocking);
|
||
SANE_Status(*real_sane_get_select_fd_)(SANE_Handle handle, SANE_Int* fd);
|
||
SANE_String_Const(*real_sane_strstatus_)(SANE_Status status);
|
||
SANE_Status(*real_sane_init_ex_)(SANE_Int* version_code, sane_callback cb, void* param);
|
||
SANE_Status(*real_sane_io_control_)(SANE_Handle h, unsigned long code, void* data, unsigned* len);
|
||
|
||
void(*log_)(int, const char*);
|
||
|
||
bool load_sane(void);
|
||
int handle_sane_event(SANE_Handle hdev, int code, void* data, unsigned int* len);
|
||
void get_online_devices(std::vector<SANEDEV>& devs);
|
||
int get_online_device_count(void);
|
||
scanner* find_scanner(SANE_Handle hdev);
|
||
scanner* open(const char* name, int* err);
|
||
|
||
static void no_log(int, const char*);
|
||
static int sane_callback_handler( // 注册回调的对象,需要保证该回调是多线程安全的
|
||
SANE_Handle hdev // 产生事件的设备句柄
|
||
, int code // 回调事件代码
|
||
, void* data // 回调事件数据,根据事件代码有所不同,参照具体事件定义
|
||
, unsigned int* len // 数据长度(字节),或者event_data的缓冲区长度,详细请看相应的事件代码
|
||
, void* param // 用户自定义数据,与调用sane_init_ex传入时的保持一致
|
||
); // 返回值依不同的事件代码而定,通常为“0”
|
||
|
||
static sane_invoker* inst_;
|
||
|
||
protected:
|
||
sane_invoker(const wchar_t* path);
|
||
~sane_invoker();
|
||
|
||
public:
|
||
static int load_dll(const wchar_t* path_dll, HMODULE* dll);
|
||
static bool initialize(HMODULE me);
|
||
static void uninitialize(void);
|
||
static std::string u2m(const wchar_t* u, int page = CP_ACP);
|
||
static std::wstring m2u(const char* m, int page = CP_ACP);
|
||
static std::string u2ansi(const wchar_t* u);
|
||
static std::string u2utf8(const wchar_t* u);
|
||
static std::string utf82ansi(const char* utf8);
|
||
static std::string ansi2utf8(const char* ansi);
|
||
static std::wstring utf82u(const char* utf8);
|
||
static std::wstring ansi2u(const char* ansi);
|
||
static void log_debug_info(const char* info);
|
||
#ifdef VLOG_OK
|
||
static void __cdecl log_debug_info(int bytes, const char* fmt, ...);
|
||
#endif
|
||
|
||
static SANE_Status invoke_sane_init(SANE_Int* version_code, SANE_Auth_Callback authorize);
|
||
static void invoke_sane_exit(void);
|
||
static SANE_Status invoke_sane_get_devices(const SANE_Device*** device_list, SANE_Bool local_only);
|
||
static SANE_Status invoke_sane_open(SANE_String_Const devicename, SANE_Handle* handle);
|
||
static void invoke_sane_close(SANE_Handle handle);
|
||
static const SANE_Option_Descriptor* invoke_sane_get_option_descriptor(SANE_Handle handle, SANE_Int option);
|
||
static SANE_Status invoke_sane_control_option(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info);
|
||
static SANE_Status invoke_sane_get_parameters(SANE_Handle handle, SANE_Parameters* params);
|
||
static SANE_Status invoke_sane_start(SANE_Handle handle);
|
||
static SANE_Status invoke_sane_read(SANE_Handle handle, SANE_Byte* data, SANE_Int max_length, SANE_Int* length);
|
||
static void invoke_sane_cancel(SANE_Handle handle);
|
||
static SANE_Status invoke_sane_set_io_mode(SANE_Handle handle, SANE_Bool non_blocking);
|
||
static SANE_Status invoke_sane_get_select_fd(SANE_Handle handle, SANE_Int* fd);
|
||
static SANE_String_Const invoke_sane_strstatus(SANE_Status status);
|
||
static SANE_Status invoke_sane_init_ex(SANE_Int* version_code, sane_callback cb, void* param);
|
||
static SANE_Status invoke_sane_io_control(SANE_Handle h, unsigned long code, void* data, unsigned* len);
|
||
|
||
static LPSANEAPI get_api(void);
|
||
|
||
public:
|
||
static bool is_ok(void);
|
||
static std::string version(LPDWORD v = NULL);
|
||
static void get_devices(std::vector<SANEDEV>& devs);
|
||
static scanner* open_scanner(const char* name, int* err);
|
||
static int online_devices(void);
|
||
};
|
||
|
||
|