From 12ba0f89793f228eab9dade821558850718baad0 Mon Sep 17 00:00:00 2001
From: gb <741021719@qq.com>
Date: Wed, 15 Jun 2022 11:04:40 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84TWAIN=E6=9E=B6=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
device/device.def | 2 +-
device/{hgscanner.vcxproj => scanner.vcxproj} | 2 +-
...cxproj.filters => scanner.vcxproj.filters} | 0
huagaotwain/huagaotwain.h | 446 -----
huagaotwain/sane_option_trans.cpp | 630 ------
huagaotwain/sane_option_trans.h | 230 ---
protocol/sane.def | 18 -
{huagaotwain => sane}/huagaotwain.cpp | 14 +-
sane/huagaotwain.h | 12 +
sane/s2t_api.h | 393 ++++
sane/sane.def | 6 +
protocol/hgsane.vcxproj => sane/sane.vcxproj | 15 +-
.../sane.vcxproj.filters | 24 +
sane/sane.vcxproj.user | 4 +
sane/sane_option_trans.cpp | 294 +++
sane/sane_option_trans.h | 41 +
sane/scanned_img.cpp | 143 ++
sane/scanned_img.h | 51 +
sane/scanner.cpp | 1767 +++++++++++++++++
sane/scanner.h | 270 +++
{huagaotwain => sane}/ui.cpp | 0
{huagaotwain => sane}/ui.h | 0
sln/hgscanner.sln | 25 +-
{huagaotwain => twain}/dllmain.cpp | 1 -
{huagaotwain => twain}/huagaotwain.rc | 0
twain/load_sane.cpp | 176 ++
twain/load_sane.h | 19 +
{huagaotwain => twain}/pch.cpp | 0
{huagaotwain => twain}/pch.h | 0
{huagaotwain => twain}/resource.h | 0
{huagaotwain => twain}/targetver.h | 0
{huagaotwain => twain}/twain.def | 0
.../twain.vcxproj | 17 +-
.../twain.vcxproj.filters | 50 +-
twain/twain.vcxproj.user | 4 +
{huagaotwain => twain}/twain/huagaods.cpp | 1276 ++++++++----
{huagaotwain => twain}/twain/huagaods.hpp | 5 +-
{huagaotwain => twain}/twain/twain_2.4.h | 0
{huagaotwain => twain}/twain/twpp.hpp | 0
.../twain/twpp/application.hpp | 0
{huagaotwain => twain}/twain/twpp/audio.hpp | 0
.../twain/twpp/capability.hpp | 21 +
{huagaotwain => twain}/twain/twpp/cie.hpp | 0
.../twain/twpp/curveresponse.hpp | 0
.../twain/twpp/customdata.hpp | 0
.../twain/twpp/datasource.hpp | 0
.../twain/twpp/deviceevent.hpp | 0
.../twain/twpp/element8.hpp | 0
{huagaotwain => twain}/twain/twpp/enums.hpp | 0
{huagaotwain => twain}/twain/twpp/env.hpp | 0
{huagaotwain => twain}/twain/twpp/event.hpp | 0
.../twain/twpp/exception.hpp | 0
.../twain/twpp/extimageinfo.hpp | 0
.../twain/twpp/filesystem.hpp | 0
{huagaotwain => twain}/twain/twpp/fix32.hpp | 0
{huagaotwain => twain}/twain/twpp/frame.hpp | 0
.../twain/twpp/identity.hpp | 0
.../twain/twpp/imageinfo.hpp | 0
.../twain/twpp/imagelayout.hpp | 0
.../twain/twpp/imagememxfer.hpp | 0
.../twain/twpp/imagenativexfer.hpp | 0
.../twain/twpp/internal.hpp | 0
.../twain/twpp/jpegcompression.hpp | 0
{huagaotwain => twain}/twain/twpp/memory.hpp | 0
.../twain/twpp/memoryops.hpp | 0
.../twain/twpp/palette8.hpp | 0
.../twain/twpp/passthrough.hpp | 0
.../twain/twpp/pendingxfers.hpp | 0
.../twain/twpp/setupfilexfer.hpp | 0
.../twain/twpp/setupmemxfer.hpp | 0
{huagaotwain => twain}/twain/twpp/status.hpp | 0
{huagaotwain => twain}/twain/twpp/strings.hpp | 0
{huagaotwain => twain}/twain/twpp/twglue.hpp | 0
{huagaotwain => twain}/twain/twpp/types.hpp | 0
.../twain/twpp/typesops.hpp | 0
.../twain/twpp/userinterface.hpp | 0
{huagaotwain => twain}/twain/twpp/utils.hpp | 0
77 files changed, 4159 insertions(+), 1797 deletions(-)
rename device/{hgscanner.vcxproj => scanner.vcxproj} (99%)
rename device/{hgscanner.vcxproj.filters => scanner.vcxproj.filters} (100%)
delete mode 100644 huagaotwain/huagaotwain.h
delete mode 100644 huagaotwain/sane_option_trans.cpp
delete mode 100644 huagaotwain/sane_option_trans.h
delete mode 100644 protocol/sane.def
rename {huagaotwain => sane}/huagaotwain.cpp (99%)
create mode 100644 sane/huagaotwain.h
create mode 100644 sane/s2t_api.h
create mode 100644 sane/sane.def
rename protocol/hgsane.vcxproj => sane/sane.vcxproj (94%)
rename protocol/hgsane.vcxproj.filters => sane/sane.vcxproj.filters (79%)
create mode 100644 sane/sane.vcxproj.user
create mode 100644 sane/sane_option_trans.cpp
create mode 100644 sane/sane_option_trans.h
create mode 100644 sane/scanned_img.cpp
create mode 100644 sane/scanned_img.h
create mode 100644 sane/scanner.cpp
create mode 100644 sane/scanner.h
rename {huagaotwain => sane}/ui.cpp (100%)
rename {huagaotwain => sane}/ui.h (100%)
rename {huagaotwain => twain}/dllmain.cpp (94%)
rename {huagaotwain => twain}/huagaotwain.rc (100%)
create mode 100644 twain/load_sane.cpp
create mode 100644 twain/load_sane.h
rename {huagaotwain => twain}/pch.cpp (100%)
rename {huagaotwain => twain}/pch.h (100%)
rename {huagaotwain => twain}/resource.h (100%)
rename {huagaotwain => twain}/targetver.h (100%)
rename {huagaotwain => twain}/twain.def (100%)
rename huagaotwain/huagaotwain.vcxproj => twain/twain.vcxproj (93%)
rename huagaotwain/huagaotwain.vcxproj.filters => twain/twain.vcxproj.filters (83%)
create mode 100644 twain/twain.vcxproj.user
rename {huagaotwain => twain}/twain/huagaods.cpp (61%)
rename {huagaotwain => twain}/twain/huagaods.hpp (97%)
rename {huagaotwain => twain}/twain/twain_2.4.h (100%)
rename {huagaotwain => twain}/twain/twpp.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/application.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/audio.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/capability.hpp (98%)
rename {huagaotwain => twain}/twain/twpp/cie.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/curveresponse.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/customdata.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/datasource.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/deviceevent.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/element8.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/enums.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/env.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/event.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/exception.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/extimageinfo.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/filesystem.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/fix32.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/frame.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/identity.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/imageinfo.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/imagelayout.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/imagememxfer.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/imagenativexfer.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/internal.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/jpegcompression.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/memory.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/memoryops.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/palette8.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/passthrough.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/pendingxfers.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/setupfilexfer.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/setupmemxfer.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/status.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/strings.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/twglue.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/types.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/typesops.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/userinterface.hpp (100%)
rename {huagaotwain => twain}/twain/twpp/utils.hpp (100%)
diff --git a/device/device.def b/device/device.def
index 5dc1d1e..d4f5f41 100644
--- a/device/device.def
+++ b/device/device.def
@@ -1,4 +1,4 @@
-LIBRARY hgscanner
+LIBRARY scanner
EXPORTS
hg_scanner_initialize
hg_scanner_uninitialize
diff --git a/device/hgscanner.vcxproj b/device/scanner.vcxproj
similarity index 99%
rename from device/hgscanner.vcxproj
rename to device/scanner.vcxproj
index 0743560..217a3cb 100644
--- a/device/hgscanner.vcxproj
+++ b/device/scanner.vcxproj
@@ -22,7 +22,7 @@
16.0
Win32Proj
{9ed4b425-73e0-423e-9712-455e777481b4}
- hgscanner
+ scanner
10.0
diff --git a/device/hgscanner.vcxproj.filters b/device/scanner.vcxproj.filters
similarity index 100%
rename from device/hgscanner.vcxproj.filters
rename to device/scanner.vcxproj.filters
diff --git a/huagaotwain/huagaotwain.h b/huagaotwain/huagaotwain.h
deleted file mode 100644
index 0e25600..0000000
--- a/huagaotwain/huagaotwain.h
+++ /dev/null
@@ -1,446 +0,0 @@
-#pragma once
-#include "huagao/hgscanner_error.h"
-#include
-#include
-#include
-#include
-#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 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 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 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& values, std::string& now, std::string& init);
- bool get_value(int sn, std::list& values, float& now, float& init);
- bool get_value(int sn, std::list& 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* 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* 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* values = NULL);
-
- int twain_set_text_direction(double degree);
- double twain_get_text_direction(double* init = NULL, std::list* 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 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& 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& devs);
- static scanner* open_scanner(const char* name, int* err);
- static int online_devices(void);
-};
-
-
diff --git a/huagaotwain/sane_option_trans.cpp b/huagaotwain/sane_option_trans.cpp
deleted file mode 100644
index 1216bff..0000000
--- a/huagaotwain/sane_option_trans.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-#include "sane_option_trans.h"
-#include
-#include "./twain/twain_2.4.h"
-
-
-namespace sane_trans
-{
- bool get_value_list(const SANE_Option_Descriptor* desc, std::list* values)
- {
- if (desc->type != SANE_TYPE_STRING)
- return false;
- if (desc->constraint_type != SANE_CONSTRAINT_STRING_LIST)
- return false;
-
- const SANE_String_Const* str = desc->constraint.string_list;
- int ind = 0;
- while (str[ind])
- values->push_back(str[ind++]);
-
- return true;
- }
- bool get_value_list(const SANE_Option_Descriptor* desc, std::list* values)
- {
- if (desc->type != SANE_TYPE_INT && desc->type != SANE_TYPE_FIXED)
- return false;
- if (desc->constraint_type != SANE_CONSTRAINT_WORD_LIST)
- return false;
-
- const SANE_Word* val = desc->constraint.word_list;
- if (desc->type == SANE_TYPE_FIXED)
- {
- for (int i = 0; i < val[0]; ++i)
- values->push_back(SANE_UNFIX(val[i + 1]));
- }
- else
- {
- for (int i = 0; i < val[0]; ++i)
- values->push_back(val[i + 1]);
- }
-
- return true;
- }
- bool get_value_range(const SANE_Option_Descriptor* desc, double* lower, double* upper)
- {
- if (desc->type != SANE_TYPE_INT && desc->type != SANE_TYPE_FIXED)
- return false;
- if (desc->constraint_type != SANE_CONSTRAINT_RANGE)
- return false;
-
- if (desc->type == SANE_TYPE_FIXED)
- {
- *lower = SANE_UNFIX(desc->constraint.range->min);
- *upper = SANE_UNFIX(desc->constraint.range->max);
- }
- else
- {
- *lower = desc->constraint.range->min;
- *upper = desc->constraint.range->max;
- }
-
- return true;
- }
-}
-
-
-namespace color_mode
-{
- static char g_name[] = { "\351\242\234\350\211\262\346\250\241\345\274\217" }; // 颜色模式
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- struct
- {
- int tw_pixel;
- char op_val[80];
- }g_ops[] = { {TWPT_BW, { "\351\273\221\347\231\275" }}, // 黑白
- {TWPT_GRAY, { "256\347\272\247\347\201\260\345\272\246" }}, // 256级灰度
- {TWPT_RGB, { "24\344\275\215\345\275\251\350\211\262" }}, // 24位彩色
- {TWPT_AUTOMATIC_COLOR, {"\351\242\234\350\211\262\350\207\252\345\212\250\350\257\206\345\210\253"}} // 颜色自动识别
- };
- int to_twain_pixel_type(const char* op_val)
- {
- for (size_t i = 0; i < _countof(g_ops); ++i)
- {
- if (strcmp(g_ops[i].op_val, op_val) == 0)
- return g_ops[i].tw_pixel;
- }
-
- return TWPT_RGB;
- }
- std::string from_twain_pixel_type(int twpt)
- {
- for (size_t i = 0; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].tw_pixel == twpt)
- return g_ops[i].op_val;
- }
-
- return g_ops[_countof(g_ops) - 1].op_val;
- }
-}
-
-namespace dpi
-{
- static char g_name[] = { "\345\210\206\350\276\250\347\216\207" }; // 分辨率
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace paper
-{
- static char g_name[] = { "\347\272\270\345\274\240\345\260\272\345\257\270" }; // 纸张尺寸
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_lateral[] = { "\346\250\252\345\220\221" };
- bool is_lateral(const char* paper_val)
- {
- return strstr(paper_val, g_lateral) != NULL;
- }
- std::string lateral_title(void)
- {
- return g_lateral;
- }
-
- static char g_auto_size[] = { "\345\214\271\351\205\215\345\216\237\345\247\213\345\260\272\345\257\270" }; // 匹配原始尺寸
- bool is_auto_size(const char* paper_val)
- {
- return strstr(paper_val, g_auto_size) != NULL;
- }
- std::string auto_size_title(void)
- {
- return g_auto_size;
- }
-
- static char g_auto_crop[] = { "\346\234\200\345\244\247\346\211\253\346\217\217\345\260\272\345\257\270\350\207\252\345\212\250\350\243\201\345\210\207" }; // 最大扫描尺寸自动裁切
- bool is_auto_crop(const char* paper_val)
- {
- return strstr(paper_val, g_auto_crop) != NULL;
- }
-}
-
-namespace scan_count
-{
- static char g_parent[] = { "\346\211\253\346\217\217\345\274\240\346\225\260" };// 扫描张数
- bool is_parent(const char* desc_title)
- {
- return strcmp(g_parent, desc_title) == 0;
- }
- static char g_name[] = { "\346\211\253\346\217\217\346\225\260\351\207\217" }; // 扫描数量
- bool is_me(const char* desc_title)
- {
- return strstr(desc_title, g_name);
- }
- std::string scan_continous_val(void)
- {
- return "\350\277\236\347\273\255\346\211\253\346\217\217"; // 连续扫描
- }
-}
-
-namespace text_direction
-{
- static char g_direction[] = { "\346\226\207\347\250\277\346\226\271\345\220\221" }; // 文稿方向
- bool is_me(const char* desc_title)
- {
- return strcmp(desc_title, g_direction) == 0;
- }
- struct
- {
- double angle;
- std::string op_val;
- }g_ops[] = { {.0f, "0\302\260"}
- , {90.0f, "90\302\260"}
- , {180.0f, "180\302\260"}
- , {270.0f, "270\302\260"}
- };
- static char g_auto_dir[] = { "\350\207\252\345\212\250\346\226\207\346\234\254\346\226\271\345\220\221\350\257\206\345\210\253\302\260" }; // 自动文本方向识别°
- double to_twain_angle(const char* opt_val)
- {
- for (size_t i = 0; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].op_val == opt_val)
- return g_ops[i].angle;
- }
-
- return g_ops[0].angle;
- }
- std::string from_twain_angle(double angle)
- {
- for (size_t i = 0; i < _countof(g_ops); ++i)
- {
- if (IS_DOUBLE_EQUAL(g_ops[i].angle, angle))
- return g_ops[i].op_val;
- }
-
- return g_ops[0].op_val;
- }
- bool is_auto(const char* opt_val)
- {
- return strcmp(opt_val, g_auto_dir) == 0;
- }
- std::string auto_val(void)
- {
- return g_auto_dir;
- }
-}
-
-namespace page
-{
- static char g_name[] = { "\346\211\253\346\217\217\351\241\265\351\235\242" }; // 扫描页面
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_not_duplex[] = { "\345\215\225\351\235\242" }; // 单面
- static char g_duplex[] = { "\345\217\214\351\235\242" }; // 双面
- bool is_duplex(const char* opval)
- {
- return strcmp(opval, g_duplex) == 0;
- }
- std::string from_duplex(bool duplex)
- {
- return duplex ? g_duplex : g_not_duplex;
- }
-
- static char g_discard_blank[] = { "\350\267\263\350\277\207\347\251\272\347\231\275\351\241\265\357\274\210\351\200\232\347\224\250\357\274\211" }; // 跳过空白页(通用)
- static char g_discard_blank_receipt[] = { "\350\267\263\350\277\207\347\251\272\347\231\275\351\241\265\357\274\210\345\217\221\347\245\250\347\272\270\357\274\211" }; // 跳过空白页(发票纸)
- bool is_discard_blank_page(const char* opval, bool receipt)
- {
- return receipt ? strcmp(g_discard_blank_receipt, opval) == 0 :
- strcmp(g_discard_blank, opval) == 0;
- }
- std::string discard_blank_page_title(bool receipt)
- {
- return receipt ? g_discard_blank_receipt : g_discard_blank;
- }
-
- static char g_fold[] = { "\345\257\271\346\212\230" }; // 对折
- bool is_fold(const char* opval)
- {
- return strcmp(g_fold, opval) == 0;
- }
- std::string fold_page_title(void)
- {
- return g_fold;
- }
-
-}
-
-namespace auto_descrew
-{
- static char g_name[] = { "\350\207\252\345\212\250\347\272\240\345\201\217" }; // 自动纠偏
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace erase_black_frame
-{
- static char g_name[] = { "\346\266\210\351\231\244\351\273\221\346\241\206" }; // 消除黑框
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace filter
-{
- static char g_name[] = { "\347\201\260\345\272\246\346\210\226\351\273\221\347\231\275\345\233\276\345\203\217 - \351\231\244\350\211\262" }; // 灰度或黑白图像 - 除色
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- struct
- {
- int twfilter;
- std::string opt_val;
- }g_ops[] = { {TWFT_RED, "\351\231\244\347\272\242\350\211\262"} // 除红色
- , {TWFT_GREEN, "\351\231\244\347\273\277\350\211\262"} // 除绿色
- , {TWFT_BLUE, "\351\231\244\350\223\235\350\211\262"} // 除蓝色
- , {TWFT_NONE, "\344\270\215\351\231\244\350\211\262"} // 不除色
-
- // 颜色增强
- // , {ENHANCE_COLOR_NONE, "\351\231\244\347\273\277\350\211\262"} // 不增强
- , {ENHANCE_COLOR_RED, "\347\272\242\350\211\262\345\242\236\345\274\272"} // 红色增强
- , {ENHANCE_COLOR_GREEN,"\347\273\277\350\211\262\345\242\236\345\274\272"} // 绿色增强
- , {ENHANCE_COLOR_BLUE, "\350\223\235\350\211\262\345\242\236\345\274\272"} // 蓝色增强
- };
- static int g_enhance_base = 4;
- int to_filter_type(const char* opt_val, bool enhance)
- {
- if (enhance)
- {
- for (size_t i = g_enhance_base; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].opt_val == opt_val)
- return g_ops[i].twfilter;
- }
-
- return ENHANCE_COLOR_NONE;
- }
-
- for (size_t i = 0; i < g_enhance_base; ++i)
- {
- if (g_ops[i].opt_val == opt_val)
- return g_ops[i].twfilter;
- }
-
- return TWFT_NONE;
- }
- std::string from_filter_type(int filter, bool enhance)
- {
- if (enhance)
- {
- for (size_t i = g_enhance_base; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].twfilter == filter)
- return g_ops[i].opt_val;
- }
- }
- else
- {
- for (size_t i = 0; i < g_enhance_base; ++i)
- {
- if (g_ops[i].twfilter == filter)
- return g_ops[i].opt_val;
- }
- }
-
- return g_ops[g_enhance_base - 1].opt_val;
- }
-}
-
-namespace bright
-{
- static char g_name[] = { "\344\272\256\345\272\246" }; // 亮度
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-namespace contrast
-{
- static char g_name[] = { "\345\257\271\346\257\224\345\272\246" }; // 对比度
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-namespace gamma
-{
- static char g_name[] = { "\344\274\275\347\216\233" }; // 伽玛
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace ultrasonic
-{
- static char g_name[] = { "\350\266\205\345\243\260\346\263\242\346\243\200\346\265\213" }; // 超声波检测
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace flip
-{
- static char g_name[] = { "\344\272\244\346\215\242\346\255\243\345\217\215\351\235\242" }; // 交换正反面
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace rotate_bg
-{
- static char g_name[] = { "\350\203\214\351\235\242\346\227\213\350\275\254180\302\260" }; // 背面旋转180°
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace fill_black_border
-{
- static char g_name[] = { "\346\266\210\351\231\244\351\273\221\346\241\206" }; // 消除黑框
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace edge_ident
-{
- static char g_name[] = { "\350\276\271\347\274\230\347\274\251\350\277\233" }; // 边缘缩进
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace threshold
-{
- static char g_name[] = { "\351\230\210\345\200\274" }; // 阈值
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace bkg_filling_method
-{
- static char g_name[] = { "\350\203\214\346\231\257\345\241\253\345\205\205\346\226\271\345\274\217" }; // 背景填充方式
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_convex[] = { "\345\207\270\345\244\232\350\276\271\345\275\242" };// 凸多边形
- bool is_convex(const char* opval)
- {
- return strcmp(opval, g_convex) == 0;
- }
-}
-
-namespace fill_hole
-{
- static char g_name[] = { "\347\251\277\345\255\224\347\247\273\351\231\244" }; // 穿孔移除
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_ratio[] = { "\347\251\277\345\255\224\346\220\234\347\264\242\350\214\203\345\233\264\345\215\240\345\271\205\351\235\242\346\257\224\344\276\213" }; // 穿孔搜索范围占幅面比例
- bool is_ratio(const char* desc_title)
- {
- return strstr(desc_title, g_ratio) != NULL;
- }
-}
-
-namespace noise
-{
- static char g_name[] = { "\351\273\221\347\231\275\345\233\276\345\203\217\345\231\252\347\202\271\344\274\230\345\214\226" }; // 黑白图像噪点优化
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_threshold[] = { "\345\231\252\347\202\271\344\274\230\345\214\226\345\260\272\345\257\270" }; // 噪点优化尺寸
- bool is_threshold(const char* desc_title)
- {
- return strstr(desc_title, g_threshold) != NULL;
- }
-}
-
-namespace rid_red
-{
- static char g_name[] = { "24\344\275\215\345\275\251\350\211\262\345\233\276\345\203\217 - \345\244\232\346\265\201\350\276\223\345\207\272\351\231\244\347\272\242" }; // 24位彩色图像 - 多流输出除红
- static char g_hsv[] = { "24\344\275\215\345\275\251\350\211\262\345\233\276\345\203\217 - \347\255\224\351\242\230\345\215\241\351\231\244\347\272\242" }; // 24位彩色图像 - 答题卡除红
- bool is_me(const char* desc_title, bool hsv)
- {
- return strcmp(hsv ? g_hsv : g_name, desc_title) == 0;
- }
-}
-
-namespace sharpen
-{
- static char g_name[] = { "\351\224\220\345\214\226\344\270\216\346\250\241\347\263\212" }; // 锐化与模糊
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- struct
- {
- int type;
- std::string op_val;
- }g_ops[] = { {SHARPEN_NONE, "\346\227\240"} // 无
- , {SHARPEN_NORMAL, "\351\224\220\345\214\226"} // 锐化
- , {SHARPEN_MORE, "\350\277\233\344\270\200\346\255\245\351\224\220\345\214\226"} // 进一步锐化
- , {SHARPEN_BLUR, "\346\250\241\347\263\212"} // 模糊
- , {SHARPEN_BLUR_MORE, "\350\277\233\344\270\200\346\255\245\346\250\241\347\263\212"} // 进一步模糊
- };
- int to_type(const char* opval)
- {
- for (size_t i = 0; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].op_val == opval)
- return g_ops[i].type;
- }
-
- return SHARPEN_NONE;
- }
- std::string from_type(int type)
- {
- for (size_t i = 0; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].type == type)
- return g_ops[i].op_val;
- }
-
- return g_ops[0].op_val;
- }
-}
-
-namespace screw
-{
- static char g_name[] = { "\346\255\252\346\226\234\346\243\200\346\265\213" }; // 歪斜检测
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_level[] = { "\346\255\252\346\226\234\346\243\200\346\265\213\345\244\215\346\235\202\345\272\246" }; // 歪斜检测复杂度
- bool is_level(const char* desc_title)
- {
- return strstr(desc_title, g_level) != NULL;
- }
-}
-
-namespace staple
-{
- static char g_name[] = { "\350\243\205\350\256\242\346\243\200\346\265\213" }; // 装订检测
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace dogear
-{
- static char g_name[] = { "\346\212\230\350\247\222\346\243\200\346\265\213" }; // 折角检测
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace sample
-{
- static char g_name[] = { "\346\267\261\350\211\262\346\240\267\345\274\240" }; // 深色样张
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace split
-{
- static char g_name[] = { "\345\233\276\345\203\217\346\213\206\345\210\206" }; // 图像拆分
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace fade_bkg
-{
- static char g_name[] = { "\350\203\214\346\231\257\347\247\273\351\231\244" }; // 背景移除
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- static char g_val[] = { "\350\203\214\346\231\257\350\211\262\345\275\251\346\265\256\345\212\250\350\214\203\345\233\264" }; // 背景色彩浮动范围
- bool is_value(const char* desc_title)
- {
- return strstr(desc_title, g_val) != NULL;
- }
-}
-
-namespace size_detect
-{
- static char g_name[] = { "\345\260\272\345\257\270\346\243\200\346\265\213" }; // 尺寸检测
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-}
-
-namespace multi_out
-{
- static char g_name[] = { "24\344\275\215\345\275\251\350\211\262\345\233\276\345\203\217-\345\244\232\346\265\201\350\276\223\345\207\272" }; // 24位彩色图像-多流输出
- bool is_me(const char* desc_title)
- {
- return strcmp(g_name, desc_title) == 0;
- }
-
- struct
- {
- int type;
- std::string op_val;
- }g_ops[] = { {MULTI_OUT_NONE, "\344\270\215\351\200\211\346\213\251\350\276\223\345\207\272\346\250\241\345\274\217"} // 不选择输出模式
- , {MULTI_OUT_ALL, "\345\275\251\350\211\262+\347\201\260\345\272\246+\351\273\221\347\231\275"} // 彩色+灰度+黑白
- , {MULTI_OUT_COLOR_GRAY, "\345\275\251\350\211\262+\347\201\260\345\272\246"} // 彩色+灰度
- , {MULTI_OUT_COLOR_BW, "\345\275\251\350\211\262+\351\273\221\347\231\275"} // 彩色+黑白
- , {MULTI_OUT_GRAY_BW, "\347\201\260\345\272\246+\351\273\221\347\231\275"} // 灰度+黑白
- };
- int to_twain_type(const char* opval)
- {
- for (int i = 0; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].op_val == opval)
- return g_ops[i].type;
- }
-
- return MULTI_OUT_NONE;
- }
- std::string from_twain_type(int type)
- {
- for (int i = 0; i < _countof(g_ops); ++i)
- {
- if (g_ops[i].type == type)
- return g_ops[i].op_val;
- }
-
- return g_ops[0].op_val;
- }
-}
diff --git a/huagaotwain/sane_option_trans.h b/huagaotwain/sane_option_trans.h
deleted file mode 100644
index e551fa2..0000000
--- a/huagaotwain/sane_option_trans.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// utilities for transfroming options between TWAIN and sane ...
-//
-// Date: 2022-04-14
-//
-
-#pragma once
-
-#include "sane/sane_ex.h"
-#include
-#include
-#include
-
-#define TWPT_AUTOMATIC_COLOR 0x0a0c
-#define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .000001
-
-#define ENHANCE_COLOR_NONE 0
-#define ENHANCE_COLOR_RED 1
-#define ENHANCE_COLOR_GREEN 2
-#define ENHANCE_COLOR_BLUE 3
-
-#define SHARPEN_NONE 0
-#define SHARPEN_NORMAL 1
-#define SHARPEN_MORE 2
-#define SHARPEN_BLUR 3
-#define SHARPEN_BLUR_MORE 4
-
-#define MULTI_OUT_NONE -1
-#define MULTI_OUT_ALL 0
-#define MULTI_OUT_COLOR_GRAY 1
-#define MULTI_OUT_COLOR_BW 2
-#define MULTI_OUT_GRAY_BW 3
-
-enum value_limit
-{
- VAL_LIMIT_NONE = 0, //
- VAL_LIMIT_ENUM, //
- VAL_LIMIT_RANGE, //
-};
-
-namespace sane_trans
-{
- bool get_value_list(const SANE_Option_Descriptor* desc, std::list* values);
- bool get_value_list(const SANE_Option_Descriptor* desc, std::list* values);
- bool get_value_range(const SANE_Option_Descriptor* desc, double* lower, double* upper);
-}
-
-
-namespace color_mode
-{
- bool is_me(const char* desc_title);
- int to_twain_pixel_type(const char* op_val);
- std::string from_twain_pixel_type(int twpt);
-}
-
-namespace dpi
-{
- bool is_me(const char* desc_title);
-}
-
-namespace paper
-{
- bool is_me(const char* desc_title);
- bool is_lateral(const char* paper_val);
- std::string lateral_title(void);
- bool is_auto_size(const char* paper_val);
- std::string auto_size_title(void);
- bool is_auto_crop(const char* paper_val);
-}
-
-namespace scan_count
-{
- bool is_parent(const char* desc_title);
- bool is_me(const char* desc_title);
- std::string scan_continous_val(void);
-}
-
-namespace text_direction
-{
- bool is_me(const char* desc_title);
- double to_twain_angle(const char* opt_val);
- std::string from_twain_angle(double angle);
-
- bool is_auto(const char* opt_val);
- std::string auto_val(void);
-}
-
-namespace page
-{
- bool is_me(const char* desc_title);
- bool is_duplex(const char* opval);
- std::string from_duplex(bool duplex);
- bool is_discard_blank_page(const char* opval, bool receipt);
- std::string discard_blank_page_title(bool receipt);
- bool is_fold(const char* opval);
- std::string fold_page_title(void);
-}
-
-namespace auto_descrew
-{
- bool is_me(const char* desc_title);
-}
-
-namespace erase_black_frame
-{
- bool is_me(const char* desc_title);
-}
-
-namespace filter
-{
- bool is_me(const char* desc_title);
- int to_filter_type(const char* opt_val, bool enhance);
- std::string from_filter_type(int filter, bool enhance);
-}
-
-namespace bright
-{
- bool is_me(const char* desc_title);
-}
-namespace contrast
-{
- bool is_me(const char* desc_title);
-}
-namespace gamma
-{
- bool is_me(const char* desc_title);
-}
-
-namespace ultrasonic
-{
- bool is_me(const char* desc_title);
-}
-
-namespace flip
-{
- bool is_me(const char* desc_title);
-}
-
-namespace rotate_bg
-{
- bool is_me(const char* desc_title);
-}
-
-namespace fill_black_border
-{
- bool is_me(const char* desc_title);
-}
-
-namespace edge_ident
-{
- bool is_me(const char* desc_title);
-}
-
-namespace threshold
-{
- bool is_me(const char* desc_title);
-}
-
-namespace bkg_filling_method
-{
- bool is_me(const char* desc_title);
- bool is_convex(const char* opval);
-}
-
-namespace fill_hole
-{
- bool is_me(const char* desc_title);
- bool is_ratio(const char* desc_title);
-}
-
-namespace noise
-{
- bool is_me(const char* desc_title);
- bool is_threshold(const char* desc_title);
-}
-
-namespace rid_red
-{
- bool is_me(const char* desc_title, bool hsv/*是否为答题卡除红*/);
-}
-
-namespace sharpen
-{
- bool is_me(const char* desc_title);
- int to_type(const char* opval);
- std::string from_type(int type);
-}
-
-namespace screw
-{
- bool is_me(const char* desc_title);
- bool is_level(const char* desc_title);
-}
-
-namespace staple
-{
- bool is_me(const char* desc_title);
-}
-
-namespace dogear
-{
- bool is_me(const char* desc_title);
-}
-
-namespace sample
-{
- bool is_me(const char* desc_title);
-}
-
-namespace split
-{
- bool is_me(const char* desc_title);
-}
-
-namespace fade_bkg
-{
- bool is_me(const char* desc_title);
- bool is_value(const char* desc_title);
-}
-
-namespace size_detect
-{
- bool is_me(const char* desc_title);
-}
-
-namespace multi_out
-{
- bool is_me(const char* desc_title);
- int to_twain_type(const char* opval);
- std::string from_twain_type(int type);
-}
diff --git a/protocol/sane.def b/protocol/sane.def
deleted file mode 100644
index 669ddba..0000000
--- a/protocol/sane.def
+++ /dev/null
@@ -1,18 +0,0 @@
-LIBRARY hgsane
-EXPORTS
- sane_hgsane_init
- sane_hgsane_exit
- sane_hgsane_get_devices
- sane_hgsane_open
- sane_hgsane_close
- sane_hgsane_get_option_descriptor
- sane_hgsane_control_option
- sane_hgsane_get_parameters
- sane_hgsane_start
- sane_hgsane_read
- sane_hgsane_cancel
- sane_hgsane_set_io_mode
- sane_hgsane_get_select_fd
- sane_hgsane_strstatus
- sane_hgsane_init_ex
- sane_hgsane_io_control
\ No newline at end of file
diff --git a/huagaotwain/huagaotwain.cpp b/sane/huagaotwain.cpp
similarity index 99%
rename from huagaotwain/huagaotwain.cpp
rename to sane/huagaotwain.cpp
index 2be9a65..7dda641 100644
--- a/huagaotwain/huagaotwain.cpp
+++ b/sane/huagaotwain.cpp
@@ -1,8 +1,6 @@
#include "pch.h"
#include "huagaotwain.h"
#include "huagao/hgscanner_error.h"
-#include "./twain/twain_2.4.h"
-#include "../../code_device/sdk/hginclude/hg_log.h"
#define STR(s) #s
#define PASTE_STR(a, b) STR(a##b)
@@ -46,7 +44,15 @@ namespace local_utility
}
std::wstring reg_get_app_installing_path(void)
{
- return reg_read(HKEY_LOCAL_MACHINE, L"SOFTWARE\\HuaGoScan", L"AppDirectory");
+#ifdef OEM_HANWANG
+ std::wstring path(L"SOFTWARE\\HwScanner");
+#elif defined(OEM_LISICHENG)
+ std::wstring path(L"SOFTWARE\\LscScanner");
+#else
+ std::wstring path(L"SOFTWARE\\HuaGoScan");
+#endif
+
+ return reg_read(HKEY_LOCAL_MACHINE, path.c_str(), L"AppDirectory");
}
}
@@ -498,7 +504,7 @@ std::wstring sane_invoker::ansi2u(const char* ansi)
void sane_invoker::log_debug_info(const char* info)
{
if (sane_invoker::inst_)
- sane_invoker::inst_->log_(LOG_LEVEL_DEBUG_INFO, info);
+ sane_invoker::inst_->log_(/*LOG_LEVEL_DEBUG_INFO*/1, info);
else
OutputDebugStringA(info);
}
diff --git a/sane/huagaotwain.h b/sane/huagaotwain.h
new file mode 100644
index 0000000..cfb5d21
--- /dev/null
+++ b/sane/huagaotwain.h
@@ -0,0 +1,12 @@
+#pragma once
+#include "huagao/hgscanner_error.h"
+#include
+#include
+#include
+#include
+#include "sane_option_trans.h"
+#include "s2t_api.h"
+
+
+
+
diff --git a/sane/s2t_api.h b/sane/s2t_api.h
new file mode 100644
index 0000000..995d4b4
--- /dev/null
+++ b/sane/s2t_api.h
@@ -0,0 +1,393 @@
+#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,
+};
+
+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 char*, bits(void));
+ 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(void)); // call 'release' on returned value, plz
+ COM_API_DECLARE(bool, get_first_image_header(SANE_Parameters* header));
+ 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));
+
+ // 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);
+ SANE_OPTION_ID_API(bright);
+ SANE_OPTION_ID_API(contrast);
+ SANE_OPTION_ID_API(gamma);
+ SANE_OPTION_ID_API(is_erase_black_frame); // bool
+ 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);
+ 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-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(void, ui_show_main(void));
+ COM_API_DECLARE(void, ui_show_setting(bool with_scan));
+ COM_API_DECLARE(void, ui_show_progress(void));
+ COM_API_DECLARE(void, ui_hide(void));
+ COM_API_DECLARE(void, ui_handle_sane_event(int sane_ev, void* data, unsigned int* len));
+ COM_API_DECLARE(bool, ui_is_ok(void));
+ COM_API_DECLARE(bool, ui_is_progress_ui_showing(void));
+};
+
+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);
+
+
diff --git a/sane/sane.def b/sane/sane.def
new file mode 100644
index 0000000..deda82a
--- /dev/null
+++ b/sane/sane.def
@@ -0,0 +1,6 @@
+LIBRARY sane
+EXPORTS
+ initialize
+ open_scanner
+ is_scanner_online
+ uninitialize
diff --git a/protocol/hgsane.vcxproj b/sane/sane.vcxproj
similarity index 94%
rename from protocol/hgsane.vcxproj
rename to sane/sane.vcxproj
index 6c8578a..cea4c71 100644
--- a/protocol/hgsane.vcxproj
+++ b/sane/sane.vcxproj
@@ -22,9 +22,9 @@
16.0
Win32Proj
{6eec8a02-7f98-4422-8ed6-2434d43bd1e1}
- hgsane
+ sane
10.0
- hgsane
+ sane
@@ -103,7 +103,7 @@
Level3
true
- BACKEND_NAME=hgsane;TWPP_IS_DS;EXPORT_SANE_API;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ BACKEND_NAME=sane;TWPP_IS_DS;EXPORT_SANE_API;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
stdcpp17
4996
@@ -128,7 +128,7 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
true
true
true
- BACKEND_NAME=hgsane;TWPP_IS_DS;EXPORT_SANE_API;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ BACKEND_NAME=sane;TWPP_IS_DS;EXPORT_SANE_API;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
stdcpp17
4996
@@ -197,6 +197,9 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
+
+
+
@@ -211,6 +214,10 @@ move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$
+
+
+
+
diff --git a/protocol/hgsane.vcxproj.filters b/sane/sane.vcxproj.filters
similarity index 79%
rename from protocol/hgsane.vcxproj.filters
rename to sane/sane.vcxproj.filters
index 9800114..87f970f 100644
--- a/protocol/hgsane.vcxproj.filters
+++ b/sane/sane.vcxproj.filters
@@ -13,6 +13,9 @@
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+ {8ae15a45-410d-4611-b852-f82b64bb1fcc}
+
@@ -30,6 +33,15 @@
源文件
+
+ sane2twain
+
+
+ sane2twain
+
+
+ sane2twain
+
@@ -68,6 +80,18 @@
头文件
+
+ sane2twain
+
+
+ sane2twain
+
+
+ sane2twain
+
+
+ sane2twain
+
diff --git a/sane/sane.vcxproj.user b/sane/sane.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/sane/sane.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/sane/sane_option_trans.cpp b/sane/sane_option_trans.cpp
new file mode 100644
index 0000000..bf5f82d
--- /dev/null
+++ b/sane/sane_option_trans.cpp
@@ -0,0 +1,294 @@
+#include "sane_option_trans.h"
+#include
+#include
+
+namespace sane_opt_trans
+{
+ static struct
+ {
+ int twain_id;
+ const char* opt_val;
+ }
+ g_color_mode_map[] = {{COLOR_BW, OPTION_VALUE_YSMS_HB}
+ , {COLOR_GRAY, OPTION_VALUE_YSMS_256JHD}
+ , {COLOR_RGB, OPTION_VALUE_YSMS_24WCS}
+ , {COLOR_AUTO_MATCH, OPTION_VALUE_YSMS_YSZDSB}
+ },
+ g_multiout_map[] = { {MULTI_OUT_NONE, "\346\227\240"}
+ , {MULTI_OUT_ALL, OPTION_VALUE_DLSC_CS_HD_HB}
+ , {MULTI_OUT_COLOR_GRAY, OPTION_VALUE_DLSC_CS_HD}
+ , {MULTI_OUT_COLOR_BW, OPTION_VALUE_DLSC_CS_HB}
+ , {MULTI_OUT_GRAY_BW, OPTION_VALUE_DLSC_HD_HB}
+ },
+ g_enhance_map[] = { {ENHANCE_NONE, OPTION_VALUE_HDHHBTX_CS_BCS}
+ , {ENHANCE_RED, OPTION_VALUE_HDHHBTX_CS_HSZQ}
+ , {ENHANCE_GREEN, OPTION_VALUE_HDHHBTX_CS_LSZQ}
+ , {ENHANCE_BLUE, OPTION_VALUE_HDHHBTX_CS_LANSEZENGQIANG}
+ },
+ g_filter_map[] = { {FILTER_NONE, OPTION_VALUE_HDHHBTX_CS_BCS}
+ , {FILTER_RED, OPTION_VALUE_HDHHBTX_CS_CHS}
+ , {FILTER_GREEN, OPTION_VALUE_HDHHBTX_CS_CLS}
+ , {FILTER_BLUE, OPTION_VALUE_HDHHBTX_CS_CHULANSE}
+ },
+ g_auto_color_map[] = { {0, OPTION_VALUE_YSMS_HB}
+ , {1, OPTION_VALUE_YSMS_256JHD}
+ },
+ g_sharpen_map[] = { {SHARPEN_NONE, OPTION_VALUE_RHYMH_W}
+ , {SHARPEN_SHARPEN, OPTION_VALUE_RHYMH_RH}
+ , {SHARPEN_SHARPEN_MORE, OPTION_VALUE_RHYMH_JYBRH}
+ , {SHARPEN_BLUR, OPTION_VALUE_RHYMH_MH}
+ , {SHARPEN_BLUR_MORE, OPTION_VALUE_RHYMH_JYBMH}
+ },
+ g_paper_map[] = { {PAPER_LETTER, OPTION_VALUE_ZZCC_Letter}
+ , {PAPER_LEGAL, OPTION_VALUE_ZZCC_LEGAL}
+ //, {PAPER_8K, OPTION_VALUE_ZZCC_8K}
+ //, {PAPER_16K, OPTION_VALUE_ZZCC_16K}
+ , {PAPER_A3, OPTION_VALUE_ZZCC_A3}
+ , {PAPER_A4, OPTION_VALUE_ZZCC_A4}
+ , {PAPER_A5, OPTION_VALUE_ZZCC_A5}
+ , {PAPER_A6, OPTION_VALUE_ZZCC_A6}
+ , {PAPER_B4, OPTION_VALUE_ZZCC_B4}
+ , {PAPER_B5, OPTION_VALUE_ZZCC_B5}
+ , {PAPER_B6, OPTION_VALUE_ZZCC_B6}
+ , {PAPER_STATEMENT, OPTION_VALUE_ZZCC_PPYSCC}
+ , {PAPER_MAXSIZE, OPTION_VALUE_ZZCC_ZDSMCC}
+ , {PAPER_MAXSIZE_CROP, OPTION_VALUE_ZZCC_ZDSMCCZDCQ}
+ , {PAPER_DOUBLE_LETTER, OPTION_VALUE_ZZCC_DoubleLetter}
+ , {PAPER_TRIPPLE, OPTION_VALUE_ZZCC_SLSJ}
+ }
+ ;
+#define VALUE_FROM_TWAIN(arr, val) \
+ for (int i = 0; i < _countof(arr); ++i) \
+ { \
+ if (arr[i].twain_id == val) \
+ return arr[i].opt_val; \
+ }
+#define VALUE_TO_TWAIN(arr, val) \
+ for (int i = 0; i < _countof(arr); ++i) \
+ { \
+ if (strcmp(arr[i].opt_val, val) == 0) \
+ return arr[i].twain_id; \
+ }
+
+ const char* color_mode_from_twain(int val)
+ {
+ VALUE_FROM_TWAIN(g_color_mode_map, val);
+
+ return OPTION_VALUE_YSMS_YSZDSB;
+ }
+ int color_mode_to_twain(const char* val)
+ {
+ VALUE_TO_TWAIN(g_color_mode_map, val);
+
+ return COLOR_AUTO_MATCH;
+ }
+
+ const char* multiout_value_from_twain(int val)
+ {
+ VALUE_FROM_TWAIN(g_multiout_map, val);
+
+ return NULL;
+ }
+ int multiout_value_to_twain(const char* val)
+ {
+ VALUE_TO_TWAIN(g_multiout_map, val);
+
+ return -1;
+ }
+
+ const char* filter_enhance_value_from_twain(int val, bool filter)
+ {
+ if (filter)
+ {
+ for (int i = 0; i < _countof(g_filter_map); ++i)
+ {
+ if (g_filter_map[i].twain_id == val)
+ return g_filter_map[i].opt_val;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < _countof(g_enhance_map); ++i)
+ {
+ if (g_enhance_map[i].twain_id == val)
+ return g_enhance_map[i].opt_val;
+ }
+ }
+
+ return OPTION_VALUE_HDHHBTX_CS_BCS;
+ }
+ int filter_enhance_value_to_twain(const char* val, bool* is_filter)
+ {
+ bool type = false;
+
+ if (!is_filter)
+ is_filter = &type;
+
+ *is_filter = true;
+ for (int i = 0; i < _countof(g_filter_map); ++i)
+ {
+ if (strcmp(g_filter_map[i].opt_val, val) == 0)
+ return g_filter_map[i].twain_id;
+ }
+ *is_filter = false;
+ for (int i = 0; i < _countof(g_enhance_map); ++i)
+ {
+ if (strcmp(g_enhance_map[i].opt_val, val) == 0)
+ return g_enhance_map[i].twain_id;
+ }
+
+ return ENHANCE_NONE;
+ }
+
+ const char* text_direction_from_twain(float val)
+ {
+ while (val < .0f)
+ val += 360.0f;
+ while (val > 360.0f)
+ val -= 360.0f;
+
+ if (60.0f < val && val < 120.0f)
+ return OPTION_VALUE_WGFX_90;
+ else if (150.0f < val && val < 210.0f)
+ return OPTION_VALUE_WGFX_180;
+ else if (240.0f < val && val < 300.0f)
+ return OPTION_VALUE_WGFX__90;
+ else if (330.0f < val || val < 30.0f)
+ return OPTION_VALUE_WGFX_0;
+ else
+ return OPTION_VALUE_WGFX_ZDWBFXSB;
+ }
+ float text_direction_to_twain(const char* val)
+ {
+ if (strcmp(val, OPTION_VALUE_WGFX_90) == 0)
+ return 90.0f;
+ else if (strcmp(val, OPTION_VALUE_WGFX_180) == 0)
+ return 180.0f;
+ else if (strcmp(val, OPTION_VALUE_WGFX__90) == 0)
+ return 270.0f;
+ else if (strcmp(val, OPTION_VALUE_WGFX_0) == 0)
+ return .0f;
+ else
+ return AUTO_MATIC_ROTATE;
+ }
+
+ struct
+ {
+ const char* normal;
+ const char* lateral;
+ }g_lateral_map[] =
+ { {OPTION_VALUE_ZZCC_A4, OPTION_VALUE_ZZCC_A4HX}
+ , {OPTION_VALUE_ZZCC_16K, OPTION_VALUE_ZZCC_16KHX}
+ , {OPTION_VALUE_ZZCC_A5, OPTION_VALUE_ZZCC_A5HX}
+ , {OPTION_VALUE_ZZCC_A6, OPTION_VALUE_ZZCC_A6HX}
+ , {OPTION_VALUE_ZZCC_B5, OPTION_VALUE_ZZCC_B5HX}
+ , {OPTION_VALUE_ZZCC_B6, OPTION_VALUE_ZZCC_B6HX}
+ , {OPTION_VALUE_ZZCC_Letter, OPTION_VALUE_ZZCC_LetterHX}
+ };
+
+ const char* paper_from_twain(int val)
+ {
+ VALUE_FROM_TWAIN(g_paper_map, val);
+
+ return NULL;
+ }
+ int paper_to_twain(const char* val)
+ {
+ VALUE_TO_TWAIN(g_paper_map, val);
+
+ return -1;
+ }
+ const char* switch_paper_lateral(const char* val)
+ {
+ for (int i = 0; i < _countof(g_lateral_map); ++i)
+ {
+ if (strcmp(g_lateral_map[i].normal, val) == 0)
+ return g_lateral_map[i].lateral;
+ else if (strcmp(g_lateral_map[i].lateral, val) == 0)
+ return g_lateral_map[i].normal;
+ }
+
+ return NULL;
+ }
+ bool is_paper_lateral(const char* val)
+ {
+ for (int i = 0; i < _countof(g_lateral_map); ++i)
+ {
+ if (strcmp(g_lateral_map[i].lateral, val) == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ const char* auto_color_type_from_twain(int val)
+ {
+ VALUE_FROM_TWAIN(g_auto_color_map, val);
+
+ return OPTION_VALUE_YSMS_24WCS;
+ }
+ int auto_color_type_to_twain(const char* val)
+ {
+ VALUE_TO_TWAIN(g_auto_color_map, val);
+
+ return -1;
+ }
+
+ const char* sharpen_from_twain(int val)
+ {
+ VALUE_FROM_TWAIN(g_sharpen_map, val);
+
+ return OPTION_VALUE_RHYMH_W;
+ }
+ int sharpen_to_twain(const char* val)
+ {
+ VALUE_TO_TWAIN(g_sharpen_map, val);
+
+ return SHARPEN_NONE;
+ }
+
+ struct {
+ int twain;
+ int sane;
+ }
+ g_compression_map[] = { {0, SANE_COMPRESSION_NONE}
+ , {5, SANE_COMPRESSION_GROUP4}
+ }
+ ;
+#define INT_FROM_TWAIN(arr, val) \
+ for (int i = 0; i < _countof(arr); ++i) \
+ { \
+ if (arr[i].twain == val) \
+ return arr[i].sane; \
+ }
+#define INT_TO_TWAIN(arr, val) \
+ for (int i = 0; i < _countof(arr); ++i) \
+ { \
+ if (arr[i].sane == val) \
+ return arr[i].twain; \
+ }
+
+ int compression_from_twain(int val)
+ {
+ INT_FROM_TWAIN(g_compression_map, val);
+
+ return SANE_COMPRESSION_NONE;
+ }
+ int compression_to_twain(int val)
+ {
+ INT_TO_TWAIN(g_compression_map, val);
+
+ return 0;
+ }
+ std::vector support_image_types(void)
+ {
+ std::vector it;
+
+ it.push_back(SANE_IMAGE_TYPE_BMP);
+ it.push_back(SANE_IMAGE_TYPE_TIFF);
+ it.push_back(SANE_IMAGE_TYPE_JFIF);
+
+ return it;
+ }
+}
+
diff --git a/sane/sane_option_trans.h b/sane/sane_option_trans.h
new file mode 100644
index 0000000..72dbac2
--- /dev/null
+++ b/sane/sane_option_trans.h
@@ -0,0 +1,41 @@
+// utilities for transfroming options between TWAIN and sane ...
+//
+// Date: 2022-04-14
+//
+
+#pragma once
+
+#include "s2t_api.h"
+
+namespace sane_opt_trans
+{
+ const char* color_mode_from_twain(int val);
+ int color_mode_to_twain(const char* val);
+
+ const char* multiout_value_from_twain(int val);
+ int multiout_value_to_twain(const char* val);
+
+ const char* filter_enhance_value_from_twain(int val, bool filter);
+ int filter_enhance_value_to_twain(const char* val, bool* is_filter);
+
+ const char* text_direction_from_twain(float val);
+ float text_direction_to_twain(const char* val);
+
+ const char* paper_from_twain(int val);
+ int paper_to_twain(const char* val);
+
+ const char* switch_paper_lateral(const char* val);
+ bool is_paper_lateral(const char* val);
+
+ const char* auto_color_type_from_twain(int val);
+ int auto_color_type_to_twain(const char* val);
+
+ const char* sharpen_from_twain(int val);
+ int sharpen_to_twain(const char* val);
+
+ int compression_from_twain(int val);
+ int compression_to_twain(int val);
+
+ std::vector support_image_types(void);
+}
+
diff --git a/sane/scanned_img.cpp b/sane/scanned_img.cpp
new file mode 100644
index 0000000..bdf2f17
--- /dev/null
+++ b/sane/scanned_img.cpp
@@ -0,0 +1,143 @@
+#include "scanned_img.h"
+
+#include
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// class refer
+refer::refer() : ref_(1)
+{}
+refer::~refer()
+{}
+
+COM_API_IMPLEMENT(refer, long, add_ref(void))
+{
+ return InterlockedIncrement(&ref_);
+}
+COM_API_IMPLEMENT(refer, long, release(void))
+{
+ long ref = InterlockedDecrement(&ref_);
+
+ if (ref == 0)
+ delete this;
+
+ return ref;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// class scanned_img
+scanned_img::scanned_img(SANE_Parameters head, unsigned char* data) : head_(head)
+{
+ size_t bytes = line_bytes() * height();
+ std::string h(file_header(SANE_IMAGE_TYPE_BMP, 200.0f));
+ unsigned char* src = data + head.bytes_per_line * head.lines - head.bytes_per_line,
+ * dst = NULL;
+
+ bytes_ = bytes + h.length();
+ data_ = new unsigned char[bytes_];
+ memcpy(data_, h.c_str(), h.length());
+ dst = data_ + h.length();
+
+ if (head.format == SANE_FRAME_RGB)
+ {
+ for (int i = 0; i < height(); ++i)
+ {
+ for (int j = 0; j < head.pixels_per_line; ++j)
+ {
+ dst[j * 3 + 0] = src[j * 3 + 2];
+ dst[j * 3 + 1] = src[j * 3 + 1];
+ dst[j * 3 + 2] = src[j * 3 + 0];
+ }
+ src -= head.bytes_per_line;
+ dst += line_bytes();
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height(); ++i, dst += line_bytes(), src -= head.bytes_per_line)
+ memcpy(dst, src, head.bytes_per_line);
+ }
+}
+scanned_img::~scanned_img()
+{
+ if (data_)
+ delete[] data_;
+}
+
+std::string scanned_img::file_header(SANE_ImageType type, float resolution)
+{
+ std::string h("");
+
+ if (type == SANE_IMAGE_TYPE_BMP)
+ {
+ BITMAPINFOHEADER bih = { 0 };
+
+ bih.biSize = sizeof(bih);
+ bih.biWidth = width();
+ bih.biBitCount = depth();
+ bih.biSizeImage = line_bytes() * height();
+ bih.biPlanes = 1;
+ bih.biHeight = height();
+ bih.biCompression = BI_RGB;
+ bih.biXPelsPerMeter = bih.biYPelsPerMeter = resolution * 39.37f + .5f;
+
+ h = std::string((char*)&bih, sizeof(bih));
+ }
+
+ return h;
+}
+
+// IRef
+COM_API_IMPLEMENT(scanned_img, long, add_ref(void))
+{
+ return refer::add_ref();
+}
+COM_API_IMPLEMENT(scanned_img, long, release(void))
+{
+ return refer::release();
+}
+
+// IScanImg
+COM_API_IMPLEMENT(scanned_img, int, width(void))
+{
+ return head_.pixels_per_line;
+}
+COM_API_IMPLEMENT(scanned_img, int, line_bytes(void))
+{
+ return (head_.bytes_per_line + 3) / 4 * 4;
+}
+COM_API_IMPLEMENT(scanned_img, int, height(void))
+{
+ return head_.lines;
+}
+COM_API_IMPLEMENT(scanned_img, int, depth(void))
+{
+ if (head_.format == SANE_FRAME_RGB)
+ return head_.depth * 3;
+ else
+ return head_.depth;
+
+}
+COM_API_IMPLEMENT(scanned_img, int, channel(void))
+{
+ return head_.format == SANE_FRAME_RGB ? 3 : 1;
+}
+COM_API_IMPLEMENT(scanned_img, SANE_Frame, type(void))
+{
+ return head_.format;
+}
+COM_API_IMPLEMENT(scanned_img, unsigned int, bytes(void))
+{
+ return bytes_;
+}
+COM_API_IMPLEMENT(scanned_img, unsigned char*, bits(void))
+{
+ return data_;
+}
+COM_API_IMPLEMENT(scanned_img, void, copy_header(SANE_Parameters* head))
+{
+ *head = head_;
+}
diff --git a/sane/scanned_img.h b/sane/scanned_img.h
new file mode 100644
index 0000000..af45c83
--- /dev/null
+++ b/sane/scanned_img.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "s2t_api.h"
+
+
+class refer : public IRef
+{
+ volatile long ref_;
+
+protected:
+ refer();
+ virtual ~refer();
+
+ // IRef
+public:
+ COM_API_OVERRIDE(long, add_ref(void));
+ COM_API_OVERRIDE(long, release(void));
+};
+
+class scanned_img : public IScanImg, virtual public refer
+{
+ SANE_Parameters head_;
+ unsigned char* data_;
+ unsigned int bytes_;
+
+ std::string file_header(SANE_ImageType type, float resolution);
+
+public:
+ scanned_img(SANE_Parameters head, unsigned char* data);
+
+
+protected:
+ ~scanned_img();
+
+ // IRef
+public:
+ COM_API_OVERRIDE(long, add_ref(void));
+ COM_API_OVERRIDE(long, release(void));
+
+ // IScanImg
+public:
+ COM_API_OVERRIDE(int, width(void));
+ COM_API_OVERRIDE(int, line_bytes(void));
+ COM_API_OVERRIDE(int, height(void));
+ COM_API_OVERRIDE(int, depth(void));
+ COM_API_OVERRIDE(int, channel(void));
+ COM_API_OVERRIDE(SANE_Frame, type(void));
+ COM_API_OVERRIDE(unsigned int, bytes(void));
+ COM_API_OVERRIDE(unsigned char*, bits(void));
+ COM_API_OVERRIDE(void, copy_header(SANE_Parameters* head));
+};
+
diff --git a/sane/scanner.cpp b/sane/scanner.cpp
new file mode 100644
index 0000000..13fe82d
--- /dev/null
+++ b/sane/scanner.cpp
@@ -0,0 +1,1767 @@
+#include "scanner.h"
+
+#include
+#include "../sdk/hginclude/huagaoxxx_warraper_ex.h"
+#include
+#include "../../code_device/hgsane/sane_hg_mdw.h"
+#include "sane_option_trans.h"
+#include
+
+
+static IMPLEMENT_OPTION_STRING_COMPARE(compare_sane_opt);
+
+#define SET_SANE_OPT_ID(id, id_name, title, val, extension) \
+ if(compare_sane_opt(OPTION_TITLE_##title, val)) \
+ { \
+ id_name##_id_ = id; \
+ extension(id); \
+ }
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// class scanner
+scanner::scanner(SCANNERID id) : handle_(NULL), id_(id), ex_id_(EXTENSION_ID_BASE), prev_start_result_(SCANNER_ERR_NOT_START)
+{
+ err_ = open();
+}
+scanner::~scanner()
+{}
+
+std::string scanner::get_scanner_name(SCANNERID id)
+{
+ ScannerInfo* devs = NULL;
+ long count = 0;
+ std::string name("");
+
+ if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_INSUFFICIENT_MEMORY)
+ {
+ count++;
+ devs = new ScannerInfo[count];
+ if (hg_scanner_enum(devs, &count, true) == SCANNER_ERR_OK)
+ {
+ for (int i = 0; i < count; ++i)
+ {
+ if (devs[i].vid == GET_SCANNER_VID(id) &&
+ devs[i].pid == GET_SCANNER_PID(id))
+ {
+ name = devs[i].name;
+ break;
+ }
+ }
+ }
+ delete[] devs;
+ }
+
+ return name;
+}
+value_type scanner::from_sane_type(SANE_Value_Type type)
+{
+ if (type == SANE_TYPE_BOOL)
+ return VAL_TYPE_BOOL;
+ else if (type == SANE_TYPE_INT)
+ return VAL_TYPE_INT;
+ else if (type == SANE_TYPE_FIXED)
+ return VAL_TYPE_FLOAT;
+ else if (type == SANE_TYPE_STRING)
+ return VAL_TYPE_STR;
+ else
+ return VAL_TYPE_NONE;
+}
+value_limit scanner::from_sane_constraint(SANE_Constraint_Type type)
+{
+ if (type == SANE_CONSTRAINT_RANGE)
+ return VAL_LIMIT_RANGE;
+ else if (type == SANE_CONSTRAINT_STRING_LIST || type == SANE_CONSTRAINT_WORD_LIST)
+ return VAL_LIMIT_ENUM;
+ else
+ return VAL_LIMIT_NONE;
+}
+
+int __stdcall scanner::to_int(SANE_Int v)
+{
+ return v;
+}
+float __stdcall scanner::to_float(SANE_Fixed v)
+{
+ return SANE_UNFIX(v);
+}
+
+// IRef
+COM_API_IMPLEMENT(scanner, long, add_ref(void))
+{
+ return refer::add_ref();
+}
+COM_API_IMPLEMENT(scanner, long, release(void))
+{
+ return refer::release();
+}
+
+int scanner::open(void)
+{
+ int ret = close();
+ std::string name(scanner::get_scanner_name(id_));
+
+ if (name.empty())
+ return SCANNER_ERR_DEVICE_NOT_FOUND;
+
+ ret = hg_sane_middleware::instance()->open_device(name.c_str(), &handle_);
+ if (ret == SANE_STATUS_GOOD)
+ {
+ ret = init_options_id();
+ }
+
+ return ret;
+}
+int scanner::close(void)
+{
+ if (handle_)
+ hg_sane_middleware::instance()->close_device(handle_);
+ handle_ = NULL;
+ ex_id_ = EXTENSION_ID_BASE;
+
+ return SCANNER_ERR_OK;
+}
+int scanner::init_options_id(void)
+{
+ SANE_Int op_id = 1;
+ const SANE_Option_Descriptor* desc = NULL;
+ int ret = SCANNER_ERR_OK;
+
+#define SET_OPT_ID(var, predef, func) \
+ SET_SANE_OPT_ID(op_id, var, predef, desc->title, func)
+
+ while ((desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, op_id)))
+ {
+ SET_OPT_ID(is_multiout, DLSC, extension_none)
+ else SET_OPT_ID(multiout_type, DLSCLX, extension_multiout_type)
+ else SET_OPT_ID(color_mode, YSMS, extension_color_mode)
+ else SET_OPT_ID(erase_color, HDHHBTX_CS, extension_erase_color)
+ else SET_OPT_ID(erase_multiout_red, 24WCSTX_DLSCCH, extension_none)
+ else SET_OPT_ID(erase_paper_red, 24WCSTX_DTKCH, extension_none)
+ else SET_OPT_ID(is_erase_background, BJYC, extension_none)
+ else SET_OPT_ID(background_color_range, BJSCFDFW, extension_none)
+ else SET_OPT_ID(sharpen, RHYMH, extension_sharpen)
+ else SET_OPT_ID(erase_morr, QCMW, extension_none)
+ else SET_OPT_ID(erase_grids, CWW, extension_none)
+ else SET_OPT_ID(error_extend, CWKS, extension_none)
+ else SET_OPT_ID(is_noise_modify, HBTXZDYH, extension_none)
+ else SET_OPT_ID(noise_threshold, ZDYHCC, extension_none)
+ else SET_OPT_ID(paper, ZZCC, extension_paper)
+ else SET_OPT_ID(is_custom_area, ZDYSMQY, extension_none)
+ else SET_OPT_ID(curstom_area_l, SMQYZCmm, extension_none)
+ else SET_OPT_ID(curstom_area_r, SMQYYCmm, extension_none)
+ else SET_OPT_ID(curstom_area_t, SMQYSCmm, extension_none)
+ else SET_OPT_ID(curstom_area_b, SMQYXCmm, extension_none)
+ else SET_OPT_ID(is_size_check, CCJC, extension_none)
+ else SET_OPT_ID(page, SMYM, extension_page)
+ else SET_OPT_ID(blank_page_threshold, TGKBYLMD, extension_none)
+ else SET_OPT_ID(resolution, FBL, extension_none)
+ else SET_OPT_ID(image_quality, HZ, extension_none)
+ else SET_OPT_ID(is_swap, JHZFM, extension_none)
+ else SET_OPT_ID(is_split, TXCF, extension_none)
+ else SET_OPT_ID(is_auto_deskew, ZDJP, extension_none)
+ else SET_OPT_ID(is_custom_gamma, QYSDQX, extension_none)
+ else SET_OPT_ID(bright, LDZ, extension_none)
+ else SET_OPT_ID(contrast, DBD, extension_none)
+ else SET_OPT_ID(gamma, JMZ, extension_none)
+ else SET_OPT_ID(is_erase_black_frame, XCHK, extension_none)
+ else SET_OPT_ID(deep_sample, SSYZ, extension_none)
+ else SET_OPT_ID(threshold, YZ, extension_none)
+ else SET_OPT_ID(anti_noise, BJKZDJ, extension_none)
+ else SET_OPT_ID(margin, BYSJ, extension_none)
+ else SET_OPT_ID(fill_background, BJTCFS, extension_fill_bkg_method)
+ else SET_OPT_ID(is_anti_permeate, FZST, extension_none)
+ else SET_OPT_ID(anti_permeate_level, FZSTDJ, extension_none)
+ else SET_OPT_ID(is_erase_hole, CKYC, extension_none)
+ else SET_OPT_ID(search_hole_range, CKSSFWZFMBL, extension_none)
+ else SET_OPT_ID(is_filling_color, SCTC, extension_none)
+ else SET_OPT_ID(is_ultrasonic_check, CSBJC, extension_none)
+ else SET_OPT_ID(is_check_staple, ZDJC, extension_none)
+ else SET_OPT_ID(scan_mode, SMZS, extension_none)
+ else SET_OPT_ID(scan_count, SMSL, extension_none)
+ else SET_OPT_ID(text_direction, WGFX, extension_text_direction)
+ else SET_OPT_ID(is_rotate_bkg180, BMXZ180, extension_none)
+ else SET_OPT_ID(is_check_dogear, ZJJC, extension_none)
+ else SET_OPT_ID(dogear_size, ZJDX, extension_none)
+ else SET_OPT_ID(is_check_skew, WXJC, extension_none)
+ else SET_OPT_ID(skew_range, WXRRD, extension_none)
+ op_id++;
+ }
+
+#define EX_APPENDIX_API(name) \
+ { \
+ EXAPI ea; \
+ ea.ind = ex_##name##_id_ = ex_id_++; \
+ ea.ex_api = &scanner::handle_ex_##name; \
+ ex_opts_.push_back(ea); \
+ }
+ EX_APPENDIX_API(final_compression);
+ EX_APPENDIX_API(final_format);
+ EX_APPENDIX_API(serial);
+ EX_APPENDIX_API(to_be_scan);
+ EX_APPENDIX_API(scan_with_hole);
+ EX_APPENDIX_API(device_code);
+ EX_APPENDIX_API(power);
+ EX_APPENDIX_API(hardware_version);
+ EX_APPENDIX_API(ip);
+
+ return ret;
+}
+int scanner::control_read_string(int code, std::string& ret)
+{
+ char* buf = NULL;
+ unsigned len = 0;
+ int err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
+
+ ret = "";
+ if (err == SANE_STATUS_NO_MEM)
+ {
+ len += 4;
+ buf = new char[len];
+ memset(buf, 0, len);
+ err = hg_sane_middleware::instance()->io_control(handle_, code, buf, &len);
+ if (err == SANE_STATUS_GOOD)
+ ret = buf;
+ delete[] buf;
+ }
+
+ return err;
+}
+
+void scanner::extension_none(int id)
+{
+}
+void scanner::extension_multiout_type(int id)
+{
+ EXAPI ea;
+
+ ex_multiout_type_id_ = ex_id_++;
+ ea.ind = ex_multiout_type_id_;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_multiout;
+
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_color_mode(int id)
+{
+ EXAPI ea;
+
+ ea.ind = ex_color_mode_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_color_mode;
+ ex_opts_.push_back(ea);
+
+ ex_auto_color_type_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ind = ex_auto_color_type_id_;
+ ea.ex_api = &scanner::handle_ex_auto_color_type;
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_sharpen(int id)
+{
+ EXAPI ea;
+
+ ex_sharpen_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ind = ex_sharpen_id_;
+ ea.ex_api = &scanner::handle_ex_sharpen;
+
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_paper(int id)
+{
+ EXAPI ea;
+
+ ea.ind = ex_paper_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_paper;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_paper_lateral_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_paper_lateral;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_auto_paper_size_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_auto_paper_size;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_is_paper_auto_crop_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_auto_paper_crop;
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_fill_bkg_method(int id)
+{
+ EXAPI ea;
+
+ ea.ind = ex_fill_background_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_fill_background;
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_text_direction(int id)
+{
+ EXAPI ea;
+
+ ea.ind = ex_text_direction_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_text_direction;
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_page(int id)
+{
+ EXAPI ea;
+
+ ea.ind = ex_duplex_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_duplex;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_discard_blank_page_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_discard_blank_page;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_discard_blank_receipt_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_discard_blank_receipt;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_is_page_fold_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_page_fold;
+ ex_opts_.push_back(ea);
+}
+void scanner::extension_erase_color(int id)
+{
+ EXAPI ea;
+
+ ea.ind = ex_color_filter_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_color_filter;
+ ex_opts_.push_back(ea);
+
+ ea.ind = ex_color_enhance_id_ = ex_id_++;
+ ea.base_ind = id;
+ ea.ex_api = &scanner::handle_ex_color_enhance;
+ ex_opts_.push_back(ea);
+}
+bool scanner::get_option_value_with_parent(int sn, set_opt_value setv, void* param) // return true if handled
+{
+ bool handled = true;
+
+ if (sn == scan_count_id_)
+ {
+ SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, scan_mode_id_);
+ char* buf = new char[parent->size + 4];
+
+ memset(buf, 0, parent->size);
+ hg_sane_middleware::instance()->get_cur_value(handle_, scan_mode_id_, buf);
+ handled = compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf);
+ delete[] buf;
+ if (handled)
+ {
+ int count = -1;
+ value_role role = VAL_ROLE_CURRENT;
+ buf = (char*)hg_sane_middleware::instance()->get_def_value(handle_, scan_mode_id_);
+ if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, buf))
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ local_utility::free_memory(buf);
+
+ setv(&count, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), param);
+ }
+ }
+ else
+ handled = false;
+
+ return handled;
+}
+bool scanner::set_option_value_with_parent(int sn, void* data, int* err) // return true if handled
+{
+ bool handled = true;
+
+ if (sn == scan_count_id_)
+ {
+ SANE_Option_Descriptor* parent = hg_sane_middleware::instance()->get_option_descriptor(handle_, scan_mode_id_);
+ char* val = new char[parent->size + 4];
+ SANE_Int after = 0;
+
+ memset(val, 0, parent->size + 4);
+ hg_sane_middleware::instance()->get_cur_value(handle_, scan_mode_id_, val);
+ if (compare_sane_opt(OPTION_VALUE_SMZS_LXSM, val))
+ {
+ if (*(int*)data != -1)
+ {
+ strcpy(val, OPTION_VALUE_SMZS_SMZDZS);
+ *err = hg_sane_middleware::instance()->set_option(handle_, scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
+ }
+ }
+ else if (*(int*)data == -1)
+ {
+ strcpy(val, OPTION_VALUE_SMZS_LXSM);
+ *err = hg_sane_middleware::instance()->set_option(handle_, scan_mode_id_, SANE_ACTION_SET_VALUE, val, &after);
+ }
+ handled = false;
+ }
+ else
+ {
+ handled = false;
+ }
+
+ return handled;
+}
+int scanner::set_option_value(int sn, SANE_Value_Type type, int size, void* data)
+{
+ char* buf = NULL;
+ SANE_Bool sb = SANE_FALSE;
+ SANE_Int si = 0, after = 0;
+ SANE_Fixed sf = 0;
+ int ret = SCANNER_ERR_OK;
+
+ if (type == SANE_TYPE_BOOL)
+ {
+ sb = *(bool*)data ? SANE_TRUE : SANE_FALSE;
+ data = &sb;
+ }
+ else if (type == SANE_TYPE_INT)
+ {
+ si = *(int*)data;
+ data = &si;
+ }
+ else if (type == SANE_TYPE_FIXED)
+ {
+ sf = SANE_FIX(*(float*)data);
+ data = &sf;
+ }
+ else
+ {
+ buf = new char[size + 4];
+ memset(buf, 0, size + 4);
+ strcpy(buf, (char*)data);
+ data = buf;
+ }
+ ret = hg_sane_middleware::instance()->set_option(handle_, sn, SANE_ACTION_SET_VALUE, data, &after);
+ if (buf)
+ delete[] buf;
+
+ return ret;
+}
+
+scanner::EXAPIPOS scanner::find_ex_api(int op_id)
+{
+ return std::find(ex_opts_.begin(), ex_opts_.end(), op_id);
+}
+
+EX_OPTION_HANDLER_IMPL(multiout)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+
+ if (setv)
+ {
+ char* cur = new char[desc->size],
+ * def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
+ init = sane_opt_trans::multiout_value_to_twain(def),
+ val = 0;
+
+ local_utility::free_memory(def);
+ memset(cur, 0, desc->size);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
+ now = sane_opt_trans::multiout_value_to_twain(cur);
+ delete[] cur;
+
+ {
+ // parent item ...
+ SANE_Bool enable = SANE_TRUE;
+ if (hg_sane_middleware::instance()->get_cur_value(handle_, is_multiout_id_, &enable))
+ {
+ if (!enable)
+ now = MULTI_OUT_NONE;
+ }
+ }
+
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ // we have no 'MULTI_OUT_NONE' item in this option, this is used as is_multiout_id_
+ val = MULTI_OUT_NONE;
+ value_role role = val == now ? VAL_ROLE_CURRENT : VAL_ROLE_NONE;
+ if (!setv(&val, role, data))
+ break;
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ val = sane_opt_trans::multiout_value_to_twain(desc->constraint.string_list[i]);
+ if (val == now)
+ role = VAL_ROLE_CURRENT;
+ if (val == init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&val, role, data))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(now, init, setv, data);
+ } while (0);
+ }
+ else
+ {
+ char* val = new char[desc->size];
+ const char* in = sane_opt_trans::multiout_value_from_twain(*(int*)data);
+ SANE_Int after = 0;
+
+ if (in && strcmp(in, "\346\227\240"))
+ {
+ // enable multi-out ...
+ *((SANE_Bool*)val) = SANE_TRUE;
+ ret = hg_sane_middleware::instance()->set_option(handle_, is_multiout_id_, SANE_ACTION_SET_VALUE, val, &after);
+ strcpy(val, in);
+ }
+ else
+ {
+ // disable multi-out, let multiout type side
+ base_id = is_multiout_id_;
+ *((SANE_Bool*)val) = SANE_FALSE;
+ }
+ if (ret == SANE_STATUS_GOOD)
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
+ delete[] val;
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(auto_color_type)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ int len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ if (setv)
+ {
+ len = sane_opt_trans::auto_color_type_to_twain(buf);
+ setv(&len, VAL_ROLE_CURRENT, data);
+ }
+ else
+ {
+ SANE_Int after = 0;
+
+ strcpy(buf, sane_opt_trans::auto_color_type_from_twain(*(int*)data));
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(color_mode)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+
+ if (setv)
+ {
+ char* cur = new char[desc->size],
+ * def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
+ init = sane_opt_trans::color_mode_to_twain(def),
+ val = 0;
+
+ local_utility::free_memory(def);
+ memset(cur, 0, desc->size);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
+ now = sane_opt_trans::color_mode_to_twain(cur);
+ delete[] cur;
+
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ val = sane_opt_trans::color_mode_to_twain(desc->constraint.string_list[i]);
+ if (val == now)
+ role = VAL_ROLE_CURRENT;
+ if (val == init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&val, role, data))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(now, init, setv, data);
+ } while (0);
+ }
+ else
+ {
+ char* val = new char[desc->size];
+ const char* in = sane_opt_trans::color_mode_from_twain(*(int*)data);
+ SANE_Int after = 0;
+
+ strcpy(val, in);
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
+ delete[] val;
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(sharpen)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+
+ if (setv)
+ {
+ char* cur = new char[desc->size],
+ * def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ int now = 0, // sane_opt_trans::multiout_value_to_twain(cur)
+ init = sane_opt_trans::sharpen_to_twain(def),
+ val = 0;
+
+ local_utility::free_memory(def);
+ memset(cur, 0, desc->size);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, cur);
+ now = sane_opt_trans::sharpen_to_twain(cur);
+ delete[] cur;
+
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ val = sane_opt_trans::sharpen_to_twain(desc->constraint.string_list[i]);
+ if (val == now)
+ role = VAL_ROLE_CURRENT;
+ if (val == init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&val, role, data))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(now, init, setv, data);
+ } while (0);
+ }
+ else
+ {
+ char* val = new char[desc->size];
+ const char* in = sane_opt_trans::sharpen_from_twain(*(int*)data);
+ SANE_Int after = 0;
+
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, val, &after);
+ delete[] val;
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(paper)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ int len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ int now = sane_opt_trans::paper_to_twain(buf),
+ init = sane_opt_trans::paper_to_twain(def),
+ val = 0;
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ val = sane_opt_trans::paper_to_twain(desc->constraint.string_list[i]);
+ if (val == -1)
+ continue;
+ if (val == now)
+ role = VAL_ROLE_CURRENT;
+ if (val == init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&val, role, data))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(now, init, setv, data);
+ } while (0);
+ }
+ else if (sane_opt_trans::paper_from_twain(*(int*)data))
+ {
+ SANE_Int after = 0;
+ strcpy(buf, sane_opt_trans::paper_from_twain(*(int*)data));
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ }
+ else
+ ret = SCANNER_ERR_INVALID_PARAMETER;
+
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(paper_lateral)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ int len = desc->size + 4;
+ char* buf = new char[len];
+ const char* lateral_swap = NULL;
+ bool lateral = false;
+
+ memset(buf, 0, len);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ lateral_swap = sane_opt_trans::switch_paper_lateral(buf);
+ lateral = sane_opt_trans::is_paper_lateral(buf);
+ if (setv)
+ {
+ setv(&lateral, VAL_ROLE_CURRENT, data);
+ }
+ else if (lateral_swap)
+ {
+ SANE_Int after = 0;
+ if (lateral != *(bool*)data)
+ {
+ strcpy(buf, lateral_swap);
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ }
+ else
+ ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
+
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(auto_paper_size)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ int len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ if (setv)
+ {
+ bool yes = strcmp(buf, OPTION_VALUE_ZZCC_PPYSCC) == 0;
+ setv(&yes, VAL_ROLE_CURRENT, data);
+ }
+ else
+ {
+ SANE_Int after = 0;
+ strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_PPYSCC : OPTION_VALUE_ZZCC_A4);
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(auto_paper_crop)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ int len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ if (setv)
+ {
+ bool yes = strcmp(buf, OPTION_VALUE_ZZCC_ZDSMCCZDCQ) == 0;
+ setv(&yes, VAL_ROLE_CURRENT, data);
+ }
+ else
+ {
+ SANE_Int after = 0;
+ strcpy(buf, *(bool*)data ? OPTION_VALUE_ZZCC_ZDSMCCZDCQ : OPTION_VALUE_ZZCC_ZDSMCC);
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(text_direction)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ int len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ char* def = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ float now = .0f, init = sane_opt_trans::text_direction_to_twain(def), val = .0f;
+
+ local_utility::free_memory(def);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ now = sane_opt_trans::text_direction_to_twain(buf);
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ val = sane_opt_trans::text_direction_to_twain(desc->constraint.string_list[i]);
+ if (IS_DOUBLE_EQUAL(val, now))
+ role = VAL_ROLE_CURRENT;
+ if (IS_DOUBLE_EQUAL(val, init))
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&val, role, data))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(now, init, setv, data);
+ } while (0);
+ }
+ else
+ {
+ SANE_Int after = 0;
+
+ strcpy(buf, sane_opt_trans::text_direction_from_twain(*(float*)data));
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(duplex)
+{
+ int ret = SCANNER_ERR_OK;
+ bool val = *(bool*)data;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ unsigned len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ void* init = hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0;
+ if (val && strcmp((char*)init, OPTION_VALUE_SMYM_SM) == 0 ||
+ !val && strcmp((char*)init, OPTION_VALUE_SMYM_DM) == 0)
+ setv(&val, value_role(VAL_ROLE_CURRENT | VAL_ROLE_DEFAULT), data);
+ else if (setv(&val, VAL_ROLE_CURRENT, data))
+ {
+ if (strcmp((char*)init, OPTION_VALUE_SMYM_SM) == 0)
+ {
+ val = true;
+ setv(&val, VAL_ROLE_DEFAULT, data);
+ }
+ if (strcmp((char*)init, OPTION_VALUE_SMYM_DM) == 0)
+ {
+ val = false;
+ setv(&val, VAL_ROLE_DEFAULT, data);
+ }
+ }
+ }
+ else
+ {
+ strcpy(buf, val ? OPTION_VALUE_SMYM_SM : OPTION_VALUE_SMYM_DM);
+ SANE_Int after = 0;
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(fill_background)
+{
+ int ret = SCANNER_ERR_OK;
+ bool val = *(bool*)data;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ unsigned len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ val = strcmp(buf, OPTION_VALUE_SMYM_SM) == 0;
+ set_cur_and_def_value(strcmp(buf, OPTION_VALUE_BJTCFS_TDBX) == 0, strcmp(init, OPTION_VALUE_BJTCFS_TDBX) == 0, setv, data);
+ local_utility::free_memory(init);
+ }
+ else
+ {
+ strcpy(buf, val ? OPTION_VALUE_BJTCFS_TDBX : OPTION_VALUE_BJTCFS_ADBX);
+ SANE_Int after = 0;
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(discard_blank_page)
+{
+ int ret = SCANNER_ERR_OK;
+ bool val = *(bool*)data;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ unsigned len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYTY) == 0;
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+ else
+ {
+ if (val)
+ strcpy(buf, OPTION_VALUE_SMYM_TGKBYTY);
+ else
+ {
+ char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ strcpy(buf, init);
+ local_utility::free_memory(init);
+ }
+ SANE_Int after = 0;
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(discard_blank_receipt)
+{
+ int ret = SCANNER_ERR_OK;
+ bool val = *(bool*)data;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ unsigned len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ val = strcmp(buf, OPTION_VALUE_SMYM_TGKBYFPZ) == 0;
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+ else
+ {
+ if (val)
+ strcpy(buf, OPTION_VALUE_SMYM_TGKBYFPZ);
+ else
+ {
+ char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ strcpy(buf, init);
+ local_utility::free_memory(init);
+ }
+ SANE_Int after = 0;
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(page_fold)
+{
+ int ret = SCANNER_ERR_OK;
+ bool val = *(bool*)data;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ unsigned len = desc->size + 4;
+ char* buf = new char[len];
+
+ memset(buf, 0, len);
+ if (setv)
+ {
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ val = strcmp(buf, OPTION_VALUE_SMYM_DZ) == 0;
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+ else
+ {
+ if (val)
+ strcpy(buf, OPTION_VALUE_SMYM_DZ);
+ else
+ {
+ char* init = (char*)hg_sane_middleware::instance()->get_def_value(handle_, base_id);
+ strcpy(buf, init);
+ local_utility::free_memory(init);
+ }
+ SANE_Int after = 0;
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(color_filter) // int (filter_value)
+{
+ int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ char* buf = NULL;
+ unsigned int len = 0;
+
+ if (desc)
+ {
+ len = desc->size + 4;
+ buf = new char[len];
+ memset(buf, 0, len);
+ if (setv)
+ {
+ bool filter = false;
+ int val = FILTER_NONE, now = FILTER_NONE;
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ now = sane_opt_trans::filter_enhance_value_to_twain(buf, &filter);
+ if (!filter)
+ now = val;
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ int v = sane_opt_trans::filter_enhance_value_to_twain(desc->constraint.string_list[i], &filter);
+ if (!filter && v != FILTER_NONE)
+ continue;
+ if (v == now)
+ role = VAL_ROLE_CURRENT;
+ if (v == val)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&v, role, data))
+ break;
+ }
+ }
+ }while (0);
+ }
+ else
+ {
+ const char* val = sane_opt_trans::filter_enhance_value_from_twain(*((int*)data), true);
+ SANE_Int after = 0;
+
+ strcpy(buf, val);
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(color_enhance) // int (enhance_value)
+{
+ int ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, base_id);
+ char* buf = NULL;
+ unsigned int len = 0;
+
+ if (desc)
+ {
+ len = desc->size + 4;
+ buf = new char[len];
+ memset(buf, 0, len);
+ if (setv)
+ {
+ bool filter = false;
+ int val = ENHANCE_NONE, now = ENHANCE_NONE;
+ hg_sane_middleware::instance()->get_cur_value(handle_, base_id, buf);
+ now = sane_opt_trans::filter_enhance_value_to_twain(buf, &filter);
+ if (filter)
+ now = val;
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ int v = sane_opt_trans::filter_enhance_value_to_twain(desc->constraint.string_list[i], &filter);
+ if (filter && v != ENHANCE_NONE)
+ continue;
+ if (v == now)
+ role = VAL_ROLE_CURRENT;
+ if (v == val)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&v, role, data))
+ break;
+ }
+ }
+ } while (0);
+ }
+ else
+ {
+ const char* val = sane_opt_trans::filter_enhance_value_from_twain(*((int*)data), false);
+ SANE_Int after = 0;
+
+ strcpy(buf, val);
+ ret = hg_sane_middleware::instance()->set_option(handle_, base_id, SANE_ACTION_SET_VALUE, buf, &after);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ delete[] buf;
+ }
+
+ return ret;
+}
+
+EX_OPTION_HANDLER_IMPL(final_compression)
+{
+ int ret = SCANNER_ERR_OK;
+ int* compression = (int*)data;
+ unsigned int len = sizeof(*compression);
+
+ if (setv)
+ {
+ int val = 0;
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_COMPRESSION, &val, &len);
+ if (ret == SANE_STATUS_GOOD)
+ {
+ int i = SANE_COMPRESSION_FIRST;
+ for (; i < SANE_COMPRESSION_LAST; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ if (i == val)
+ role = VAL_ROLE_CURRENT;
+ if (i == SANE_COMPRESSION_NONE)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ int v = sane_opt_trans::compression_to_twain(i);
+ if (!setv(&v, role, data))
+ break;
+ }
+ }
+ }
+ else
+ {
+ int val = sane_opt_trans::compression_from_twain(*(int*)data);
+ len = sizeof(val);
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_FINAL_COMPRESSION, &val, &len);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(final_format)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_FinalImgFormat ff;
+ unsigned int len = sizeof(ff);
+
+ if (setv)
+ {
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_FINAL_IMAGE_FORMAT, &ff, &len);
+ if (ret == SANE_STATUS_GOOD)
+ {
+ int now = ff.img_format, init = SANE_IMAGE_TYPE_BMP;
+ std::vector all(sane_opt_trans::support_image_types());
+ for (int i = 0; i < all.size(); ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ ff.img_format = (SANE_ImageType)all[i];
+ if (ff.img_format == now)
+ role = VAL_ROLE_CURRENT;
+ if (ff.img_format == init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ if (!setv(&ff, role, data))
+ break;
+ }
+ }
+ }
+ else
+ {
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_FINAL_IMAGE_FORMAT, data, &len);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(serial)
+{
+ int ret = SCANNER_ERR_INVALID_PARAMETER;
+ if (setv)
+ {
+ std::string val("");
+
+ ret = control_read_string(IO_CTRL_CODE_GET_SERIAL, val);
+ if (ret == SANE_STATUS_GOOD)
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(to_be_scan)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Bool wait_paper = SANE_FALSE;
+ unsigned int len = sizeof(wait_paper);
+
+ if (setv)
+ {
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_SCAN_WHEN_PAPER_ON, &wait_paper, &len);
+ if (ret == SANE_STATUS_GOOD)
+ {
+ bool val = wait_paper == SANE_TRUE;
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+ }
+ else
+ {
+ wait_paper = *((bool*)data) ? SANE_TRUE : SANE_FALSE;
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_SCAN_WHEN_PAPER_ON, &wait_paper, &len);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(scan_with_hole)
+{
+ int ret = SCANNER_ERR_OK;
+ SANE_Bool with_hole = SANE_FALSE;
+ unsigned int len = sizeof(with_hole);
+
+ if (setv)
+ {
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_SCAN_WITH_HOLE, &with_hole, &len);
+ if (ret == SANE_STATUS_GOOD)
+ {
+ bool val = with_hole == SANE_TRUE;
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+ }
+ else
+ {
+ with_hole = *((bool*)data) ? SANE_TRUE : SANE_FALSE;
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_SCAN_WITH_HOLE, &with_hole, &len);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(device_code)
+{
+ int ret = SCANNER_ERR_INVALID_PARAMETER;
+ if (setv)
+ {
+ std::string val("");
+
+ ret = control_read_string(IO_CTRL_CODE_GET_DEVICE_CODE, val);
+ if (ret == SANE_STATUS_GOOD)
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(power)
+{
+ int ret = SCANNER_ERR_OK;
+
+ if (setv)
+ {
+ SANE_Power now = SANE_POWER_MINUTES_30, init = SANE_POWER_MINUTES_30;
+ unsigned int len = sizeof(now);
+
+ hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_POWER_LEVEL, &now, &len);
+ for (int i = SANE_POWER_FIRST; i < SANE_POWER_LAST; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ if (i == now)
+ role = VAL_ROLE_CURRENT;
+ if (i == init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+
+ SANE_Power power = (SANE_Power)i;
+ if (!setv(&power, role, data))
+ break;
+ }
+ }
+ else
+ {
+ SANE_Power power = *((SANE_Power*)data);
+ unsigned int len = sizeof(power);
+ ret = hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_SET_POWER_LEVEL, &power, &len);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(hardware_version)
+{
+ int ret = SCANNER_ERR_INVALID_PARAMETER;
+ if (setv)
+ {
+ std::string val("");
+
+ ret = control_read_string(IO_CTRL_CODE_GET_HARDWARE_VERSION, val);
+ if (ret == SANE_STATUS_GOOD)
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+
+ return ret;
+}
+EX_OPTION_HANDLER_IMPL(ip)
+{
+ int ret = SCANNER_ERR_INVALID_PARAMETER;
+ if (setv)
+ {
+ std::string val("");
+
+ ret = control_read_string(IO_CTRL_CODE_GET_IP, val);
+ if (ret == SANE_STATUS_GOOD)
+ setv(&val, VAL_ROLE_CURRENT, data);
+ }
+
+ return ret;
+}
+
+// ISaneInvoker
+COM_API_IMPLEMENT(scanner, int, start(void))
+{
+ int ret = hg_sane_middleware::instance()->start(handle_, NULL);
+
+ // the third-APPs in linux will call 'stop' after every start, but it not happens in windows-apps, so we handle this as following ...
+ if(ret == SANE_STATUS_NO_DOCS && prev_start_result_ == SANE_STATUS_GOOD)
+ ret = hg_sane_middleware::instance()->start(handle_, NULL);
+
+ prev_start_result_ = ret;
+
+ return ret;
+}
+COM_API_IMPLEMENT(scanner, int, stop(void))
+{
+ return hg_sane_middleware::instance()->stop(handle_);
+}
+COM_API_IMPLEMENT(scanner, void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param))
+{
+}
+COM_API_IMPLEMENT(scanner, bool, wait_image(DWORD milliseconds))
+{
+ int count = get_scanned_images(milliseconds);
+
+ return count > 0;
+}
+COM_API_IMPLEMENT(scanner, int, get_scanned_images(DWORD milliseconds))
+{
+ unsigned int count = 0;
+
+ hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_IMAGE_QUEUE_COUNT, NULL, &count);
+ if (count == 0 && milliseconds)
+ {
+ while (count == 0)
+ {
+ Sleep(10);
+ if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_IMAGE_QUEUE_COUNT, NULL, &count)
+ != SCANNER_ERR_OK)
+ break;
+ if (milliseconds != -1)
+ {
+ if (milliseconds <= 10)
+ break;
+
+ milliseconds -= 10;
+ }
+ }
+ }
+
+ return count;
+}
+COM_API_IMPLEMENT(scanner, IScanImg*, take_first_image(void))
+{
+ scanned_img* img = NULL;
+ SANE_Parameters head;
+
+ if (hg_sane_middleware::instance()->get_image_parameters(handle_, &head) == SANE_STATUS_GOOD)
+ {
+ int off = 0, size = head.bytes_per_line * head.lines, rcv = size;
+ unsigned char* buf = new unsigned char[size];
+
+ while (hg_sane_middleware::instance()->read(handle_, buf + off, &rcv) == SANE_STATUS_GOOD)
+ {
+ off += rcv;
+ if (off >= size)
+ break;
+ rcv = size - off;
+ }
+
+ img = new scanned_img(head, buf);
+ delete[] buf;
+ }
+
+ return dynamic_cast(img);
+}
+COM_API_IMPLEMENT(scanner, bool, get_first_image_header(SANE_Parameters* header))
+{
+ return hg_sane_middleware::instance()->get_image_parameters(handle_, header) == SANE_STATUS_GOOD;
+}
+COM_API_IMPLEMENT(scanner, bool, is_online(void))
+{
+ return !scanner::get_scanner_name(id_).empty();
+}
+COM_API_IMPLEMENT(scanner, bool, is_paper_on(void))
+{
+ SANE_Bool on = SANE_FALSE;
+ unsigned int len = sizeof(on);
+
+ if (hg_sane_middleware::instance()->io_control(handle_, IO_CTRL_CODE_GET_PAPER_ON, &on, &len) == SANE_STATUS_GOOD)
+ return on == SANE_TRUE;
+ else
+ return false;
+}
+COM_API_IMPLEMENT(scanner, bool, get_option_info(int sn, value_type* type, value_limit* limit, int* bytes))
+{
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
+ bool ret = false;
+
+ if (desc)
+ {
+ if (type)
+ *type = scanner::from_sane_type(desc->type);
+ if (limit)
+ *limit = scanner::from_sane_constraint(desc->constraint_type);
+ if (bytes)
+ *bytes = desc->size;
+
+ ret = true;
+ }
+
+ return ret;
+}
+COM_API_IMPLEMENT(scanner, bool, get_value(int sn, set_opt_value setval, void* param))
+{
+ EXAPIPOS ex = find_ex_api(sn);
+ int ret = SANE_STATUS_INVAL;
+ SANE_Int after = 0;
+
+ if (ex == ex_opts_.end())
+ {
+ if (get_option_value_with_parent(sn, setval, param))
+ return true;
+
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
+ void* init = hg_sane_middleware::instance()->get_def_value(handle_, sn);
+ ret = SANE_STATUS_GOOD;
+ if (desc->type == SANE_TYPE_BOOL)
+ {
+ SANE_Bool v = SANE_FALSE;
+ bool val = false;
+
+ hg_sane_middleware::instance()->get_cur_value(handle_, sn, &v);
+ val = v == SANE_TRUE;
+ set_cur_and_def_value(val, *(SANE_Bool*)init == SANE_TRUE, setval, param);
+ }
+ else if (desc->type == SANE_TYPE_INT)
+ {
+ SANE_Int cur = 0, def = *(SANE_Int*)init;
+ int val = 0;
+
+ hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
+ val = cur;
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
+ {
+ set_value_range(cur, def, desc->constraint.range->min, desc->constraint.range->max, desc->constraint.range->quant, setval, param, scanner::to_int);
+ }
+ else if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
+ {
+ const SANE_Word* v = desc->constraint.word_list;
+ for (int i = 0; i < v[0]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ if (v[i + 1] == cur)
+ role = value_role(role | VAL_ROLE_CURRENT);
+ if (v[i + 1] == *(SANE_Int*)init)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ val = v[i + 1];
+ if (!setval(&val, role, param))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(val, *(SANE_Int*)init, setval, param);
+
+ }while (0);
+ }
+ else if (desc->type == SANE_TYPE_FIXED)
+ {
+ SANE_Fixed cur = 0, def = *(SANE_Fixed*)init;
+ float val = .0f;
+
+ hg_sane_middleware::instance()->get_cur_value(handle_, sn, &cur);
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_RANGE)
+ {
+ set_value_range(cur, def, desc->constraint.range->min, desc->constraint.range->max, desc->constraint.range->quant, setval, param, scanner::to_float);
+ }
+ else if (desc->constraint_type == SANE_CONSTRAINT_WORD_LIST)
+ {
+ const SANE_Word* v = desc->constraint.word_list;
+ for (int i = 0; i < v[0]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ if (v[i + 1] == cur)
+ role = value_role(role | VAL_ROLE_CURRENT);
+ if (v[i + 1] == def)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+ val = SANE_UNFIX(v[i + 1]);
+ if (!setval(&val, role, param))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(val, SANE_UNFIX(*(SANE_Fixed*)init), setval, param);
+ } while (0);
+ }
+ else if (desc->type == SANE_TYPE_STRING)
+ {
+ char* buf = new char[desc->size + 4];
+ std::string val(""), def((char*)init);
+
+ memset(buf, 0, desc->size + 4);
+ hg_sane_middleware::instance()->get_cur_value(handle_, sn, buf);
+ val = buf;
+ do
+ {
+ if (desc->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ for (int i = 0; desc->constraint.string_list[i]; ++i)
+ {
+ value_role role = VAL_ROLE_NONE;
+ if (strcmp(desc->constraint.string_list[i], buf) == 0)
+ role = value_role(role | VAL_ROLE_CURRENT);
+ if (strcmp(desc->constraint.string_list[i], (char*)init) == 0)
+ role = value_role(role | VAL_ROLE_DEFAULT);
+
+ val = desc->constraint.string_list[i];
+ if (!setval(&val, role, param))
+ break;
+ }
+ }
+ else
+ set_cur_and_def_value(val, def, setval, param);
+ } while (0);
+ delete[] buf;
+ }
+ else
+ {
+ ret = SANE_STATUS_INVAL;
+ }
+ local_utility::free_memory(init);
+ }
+ else
+ {
+ ret = (this->*ex->ex_api)(ex->base_ind, param, setval);
+ }
+
+ return ret == SANE_STATUS_GOOD;
+}
+COM_API_IMPLEMENT(scanner, int, set_value(int sn, void* val))
+{
+ EXAPIPOS ex = find_ex_api(sn);
+ int ret = SANE_STATUS_INVAL;
+ SANE_Int after = 0;
+ SANE_Option_Descriptor* desc = hg_sane_middleware::instance()->get_option_descriptor(handle_, sn);
+
+ if (ex == ex_opts_.end())
+ {
+ if (!set_option_value_with_parent(sn, val, &ret))
+ ret = set_option_value(sn, desc->type, desc->size, val);
+ ret = local_utility::sane_statu_2_scanner_err(ret);
+ }
+ else
+ {
+ ret = (this->*ex->ex_api)(ex->base_ind, val, NULL);
+ }
+
+ return ret;
+}
+
+// SANE options ID ...
+SANE_OPTION_ID_IMPLEMENT(is_multiout)
+SANE_OPTION_ID_IMPLEMENT(multiout_type)
+SANE_OPTION_ID_IMPLEMENT(color_mode)
+SANE_OPTION_ID_IMPLEMENT(erase_color)
+SANE_OPTION_ID_IMPLEMENT(erase_multiout_red)
+SANE_OPTION_ID_IMPLEMENT(erase_paper_red)
+SANE_OPTION_ID_IMPLEMENT(is_erase_background)
+SANE_OPTION_ID_IMPLEMENT(background_color_range)
+SANE_OPTION_ID_IMPLEMENT(sharpen)
+SANE_OPTION_ID_IMPLEMENT(erase_morr)
+SANE_OPTION_ID_IMPLEMENT(erase_grids)
+SANE_OPTION_ID_IMPLEMENT(error_extend)
+SANE_OPTION_ID_IMPLEMENT(is_noise_modify)
+SANE_OPTION_ID_IMPLEMENT(noise_threshold)
+SANE_OPTION_ID_IMPLEMENT(paper)
+SANE_OPTION_ID_IMPLEMENT(is_custom_area)
+SANE_OPTION_ID_IMPLEMENT(curstom_area_l)
+SANE_OPTION_ID_IMPLEMENT(curstom_area_r)
+SANE_OPTION_ID_IMPLEMENT(curstom_area_t)
+SANE_OPTION_ID_IMPLEMENT(curstom_area_b)
+SANE_OPTION_ID_IMPLEMENT(is_size_check)
+SANE_OPTION_ID_IMPLEMENT(page)
+SANE_OPTION_ID_IMPLEMENT(blank_page_threshold)
+SANE_OPTION_ID_IMPLEMENT(resolution)
+SANE_OPTION_ID_IMPLEMENT(image_quality)
+SANE_OPTION_ID_IMPLEMENT(is_swap)
+SANE_OPTION_ID_IMPLEMENT(is_split)
+SANE_OPTION_ID_IMPLEMENT(is_auto_deskew)
+SANE_OPTION_ID_IMPLEMENT(is_custom_gamma)
+SANE_OPTION_ID_IMPLEMENT(bright)
+SANE_OPTION_ID_IMPLEMENT(contrast)
+SANE_OPTION_ID_IMPLEMENT(gamma)
+SANE_OPTION_ID_IMPLEMENT(is_erase_black_frame)
+SANE_OPTION_ID_IMPLEMENT(deep_sample)
+SANE_OPTION_ID_IMPLEMENT(threshold)
+SANE_OPTION_ID_IMPLEMENT(anti_noise)
+SANE_OPTION_ID_IMPLEMENT(margin)
+SANE_OPTION_ID_IMPLEMENT(fill_background)
+SANE_OPTION_ID_IMPLEMENT(is_anti_permeate)
+SANE_OPTION_ID_IMPLEMENT(anti_permeate_level)
+SANE_OPTION_ID_IMPLEMENT(is_erase_hole)
+SANE_OPTION_ID_IMPLEMENT(search_hole_range)
+SANE_OPTION_ID_IMPLEMENT(is_filling_color)
+SANE_OPTION_ID_IMPLEMENT(is_ultrasonic_check)
+SANE_OPTION_ID_IMPLEMENT(is_check_staple)
+SANE_OPTION_ID_IMPLEMENT(scan_mode)
+SANE_OPTION_ID_IMPLEMENT(scan_count)
+SANE_OPTION_ID_IMPLEMENT(text_direction)
+SANE_OPTION_ID_IMPLEMENT(is_rotate_bkg180)
+SANE_OPTION_ID_IMPLEMENT(is_check_dogear)
+SANE_OPTION_ID_IMPLEMENT(dogear_size)
+SANE_OPTION_ID_IMPLEMENT(is_check_skew)
+SANE_OPTION_ID_IMPLEMENT(skew_range)
+
+// SANE-ex option ID:
+SANE_OPTION_ID_IMPLEMENT(ex_multiout_type)
+SANE_OPTION_ID_IMPLEMENT(ex_auto_color_type)
+SANE_OPTION_ID_IMPLEMENT(ex_color_mode)
+SANE_OPTION_ID_IMPLEMENT(ex_sharpen)
+SANE_OPTION_ID_IMPLEMENT(ex_paper)
+SANE_OPTION_ID_IMPLEMENT(ex_paper_lateral)
+SANE_OPTION_ID_IMPLEMENT(ex_auto_paper_size)
+SANE_OPTION_ID_IMPLEMENT(ex_is_paper_auto_crop)
+SANE_OPTION_ID_IMPLEMENT(ex_text_direction)
+SANE_OPTION_ID_IMPLEMENT(ex_duplex)
+SANE_OPTION_ID_IMPLEMENT(ex_fill_background)
+SANE_OPTION_ID_IMPLEMENT(ex_discard_blank_page)
+SANE_OPTION_ID_IMPLEMENT(ex_discard_blank_receipt)
+SANE_OPTION_ID_IMPLEMENT(ex_is_page_fold)
+SANE_OPTION_ID_IMPLEMENT(ex_color_filter)
+SANE_OPTION_ID_IMPLEMENT(ex_color_enhance)
+SANE_OPTION_ID_IMPLEMENT(ex_final_compression)
+SANE_OPTION_ID_IMPLEMENT(ex_final_format)
+SANE_OPTION_ID_IMPLEMENT(ex_serial)
+SANE_OPTION_ID_IMPLEMENT(ex_to_be_scan)
+SANE_OPTION_ID_IMPLEMENT(ex_scan_with_hole)
+SANE_OPTION_ID_IMPLEMENT(ex_device_code)
+SANE_OPTION_ID_IMPLEMENT(ex_power)
+SANE_OPTION_ID_IMPLEMENT(ex_hardware_version)
+SANE_OPTION_ID_IMPLEMENT(ex_ip)
+
+// ui ...
+COM_API_IMPLEMENT(scanner, void, ui_show_main(void))
+{
+}
+COM_API_IMPLEMENT(scanner, void, ui_show_setting(bool with_scan))
+{
+}
+COM_API_IMPLEMENT(scanner, void, ui_show_progress(void))
+{
+}
+COM_API_IMPLEMENT(scanner, void, ui_hide(void))
+{
+}
+COM_API_IMPLEMENT(scanner, void, ui_handle_sane_event(int sane_ev, void* data, unsigned int* len))
+{
+}
+COM_API_IMPLEMENT(scanner, bool, ui_is_ok(void))
+{
+ return false;
+}
+COM_API_IMPLEMENT(scanner, bool, ui_is_progress_ui_showing(void))
+{
+ return false;
+}
+
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// exports
+#ifdef EXPORT_SANE_API
+__declspec(dllexport)
+#else
+__declspec(dllimport)
+#endif
+int __stdcall initialize(void* reserve)
+{
+ hg_sane_middleware::instance();
+
+ return SANE_STATUS_GOOD;
+}
+#ifdef EXPORT_SANE_API
+__declspec(dllexport)
+#else
+__declspec(dllimport)
+#endif
+int __stdcall open_scanner(SCANNERID scanner_id, ISaneInvoker** invoker)
+{
+ if (!invoker)
+ return SCANNER_ERR_INVALID_PARAMETER;
+
+ if (!is_scanner_online(scanner_id))
+ return SCANNER_ERR_DEVICE_NOT_FOUND;
+
+ scanner* scn = new scanner(scanner_id);
+ *invoker = dynamic_cast(scn);
+
+ return 0;
+}
+#ifdef EXPORT_SANE_API
+__declspec(dllexport)
+#else
+__declspec(dllimport)
+#endif
+bool __stdcall is_scanner_online(SCANNERID scanner_id)
+{
+ return !scanner::get_scanner_name(scanner_id).empty();
+}
+#ifdef EXPORT_SANE_API
+__declspec(dllexport)
+#else
+__declspec(dllimport)
+#endif
+int __stdcall uninitialize(void* reserve)
+{
+ hg_sane_middleware::clear();
+
+ return 0;
+}
+
+
diff --git a/sane/scanner.h b/sane/scanner.h
new file mode 100644
index 0000000..47f783d
--- /dev/null
+++ b/sane/scanner.h
@@ -0,0 +1,270 @@
+#pragma once
+
+#include "scanned_img.h"
+#include
+#include
+
+
+#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
+
+class scanner : public ISaneInvoker, virtual public refer
+{
+ SANE_Handle handle_;
+ SCANNERID id_;
+ int err_;
+ int ex_id_;
+ int prev_start_result_;
+
+ 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 ex_opts_;
+ typedef std::vector::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
+
+
+ template
+ 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
+ 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 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 < 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);
+
+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(void, set_event_callback(void(*cb)(int ev_type, void* data, unsigned int* len, void* param), void* param));
+ 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(void)); // call 'release' on returned value, plz
+ COM_API_OVERRIDE(bool, get_first_image_header(SANE_Parameters* header));
+ 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));
+
+ // 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-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(void, ui_show_main(void));
+ COM_API_OVERRIDE(void, ui_show_setting(bool with_scan));
+ COM_API_OVERRIDE(void, ui_show_progress(void));
+ COM_API_OVERRIDE(void, ui_hide(void));
+ COM_API_OVERRIDE(void, ui_handle_sane_event(int sane_ev, void* data, unsigned int* len));
+ COM_API_OVERRIDE(bool, ui_is_ok(void));
+ COM_API_OVERRIDE(bool, ui_is_progress_ui_showing(void));
+};
\ No newline at end of file
diff --git a/huagaotwain/ui.cpp b/sane/ui.cpp
similarity index 100%
rename from huagaotwain/ui.cpp
rename to sane/ui.cpp
diff --git a/huagaotwain/ui.h b/sane/ui.h
similarity index 100%
rename from huagaotwain/ui.h
rename to sane/ui.h
diff --git a/sln/hgscanner.sln b/sln/hgscanner.sln
index 139bbc3..fec2f9f 100644
--- a/sln/hgscanner.sln
+++ b/sln/hgscanner.sln
@@ -3,14 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.32106.194
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hgscanner", "..\device\hgscanner.vcxproj", "{9ED4B425-73E0-423E-9712-455E777481B4}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sane", "..\sane\sane.vcxproj", "{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hgsane", "..\protocol\hgsane.vcxproj", "{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}"
- ProjectSection(ProjectDependencies) = postProject
- {9ED4B425-73E0-423E-9712-455E777481B4} = {9ED4B425-73E0-423E-9712-455E777481B4}
- EndProjectSection
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scanner", "..\device\scanner.vcxproj", "{9ED4B425-73E0-423E-9712-455E777481B4}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "huagaotwain", "..\huagaotwain\huagaotwain.vcxproj", "{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "twain", "..\twain\twain.vcxproj", "{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -20,14 +17,6 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x64.ActiveCfg = Debug|x64
- {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x64.Build.0 = Debug|x64
- {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x86.ActiveCfg = Debug|Win32
- {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x86.Build.0 = Debug|Win32
- {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x64.ActiveCfg = Release|x64
- {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x64.Build.0 = Release|x64
- {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x86.ActiveCfg = Release|Win32
- {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x86.Build.0 = Release|Win32
{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}.Debug|x64.ActiveCfg = Debug|x64
{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}.Debug|x64.Build.0 = Debug|x64
{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}.Debug|x86.ActiveCfg = Debug|Win32
@@ -36,6 +25,14 @@ Global
{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}.Release|x64.Build.0 = Release|x64
{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}.Release|x86.ActiveCfg = Release|Win32
{6EEC8A02-7F98-4422-8ED6-2434D43BD1E1}.Release|x86.Build.0 = Release|Win32
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x64.ActiveCfg = Debug|x64
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x64.Build.0 = Debug|x64
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x86.ActiveCfg = Debug|Win32
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Debug|x86.Build.0 = Debug|Win32
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x64.ActiveCfg = Release|x64
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x64.Build.0 = Release|x64
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x86.ActiveCfg = Release|Win32
+ {9ED4B425-73E0-423E-9712-455E777481B4}.Release|x86.Build.0 = Release|Win32
{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}.Debug|x64.ActiveCfg = Debug|Win32
{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}.Debug|x86.ActiveCfg = Debug|Win32
{C3B47CE2-27CE-4509-AB59-3C0F194F0FCE}.Debug|x86.Build.0 = Debug|Win32
diff --git a/huagaotwain/dllmain.cpp b/twain/dllmain.cpp
similarity index 94%
rename from huagaotwain/dllmain.cpp
rename to twain/dllmain.cpp
index ae98183..2ca3ead 100644
--- a/huagaotwain/dllmain.cpp
+++ b/twain/dllmain.cpp
@@ -1,5 +1,4 @@
#include "pch.h"
-#include "huagaotwain.h"
HMODULE me_ = NULL;
diff --git a/huagaotwain/huagaotwain.rc b/twain/huagaotwain.rc
similarity index 100%
rename from huagaotwain/huagaotwain.rc
rename to twain/huagaotwain.rc
diff --git a/twain/load_sane.cpp b/twain/load_sane.cpp
new file mode 100644
index 0000000..8140a3c
--- /dev/null
+++ b/twain/load_sane.cpp
@@ -0,0 +1,176 @@
+#include "pch.h"
+#include "load_sane.h"
+#include
+
+namespace load_sane_util
+{
+ static std::wstring sane_path(L"");
+ static HMODULE sane_module(NULL);
+ static int (__stdcall* sane_inst)(SCANNERID, ISaneInvoker**) = NULL;
+ static int(__stdcall* is_on)(SCANNERID) = NULL;
+ static int(__stdcall* init)(void*) = NULL;
+ static int(__stdcall* uninit)(void*) = NULL;
+
+ static std::wstring reg_read(HKEY root, const wchar_t* path, const wchar_t* name)
+ {
+ HKEY key = NULL;
+
+ RegOpenKeyW(root, path, &key);
+ if (!key)
+ return L"";
+
+ wchar_t* buf = NULL;
+ DWORD len = 0;
+ DWORD type = REG_SZ;
+ std::wstring ret(L"");
+
+ RegQueryValueExW(key, name, NULL, &type, (LPBYTE)buf, &len);
+ if (len)
+ {
+ buf = new wchar_t[len + 4];
+ memset(buf, 0, (len + 4) * sizeof(*buf));
+ RegQueryValueExW(key, name, NULL, &type, (LPBYTE)buf, &len);
+ ret = buf;
+ delete[] buf;
+ }
+ RegCloseKey(key);
+
+ return ret;
+ }
+ static std::wstring reg_get_app_installing_path(void)
+ {
+#ifdef OEM_HANWANG
+ std::wstring path(L"SOFTWARE\\HanvonScan");
+#elif defined(OEM_LISICHENG)
+ std::wstring path(L"SOFTWARE\\LanxumScan");
+#else
+ std::wstring path(L"SOFTWARE\\HuaGoScan");
+#endif
+
+ return reg_read(HKEY_LOCAL_MACHINE, path.c_str(), L"AppDirectory");
+ }
+ static int load_dll(const wchar_t* path_dll, HMODULE* dll)
+ {
+ HMODULE h = LoadLibraryW(path_dll);
+ int ret = GetLastError();
+
+ if (!h && ret == ERROR_MOD_NOT_FOUND)
+ {
+ std::wstring dir(path_dll);
+ size_t pos = dir.rfind(L'\\');
+ wchar_t path[MAX_PATH] = { 0 };
+
+ GetCurrentDirectoryW(_countof(path) - 1, path);
+ if (pos != std::wstring::npos)
+ dir.erase(pos);
+ SetCurrentDirectoryW(dir.c_str());
+ h = LoadLibraryW(path_dll);
+ ret = GetLastError();
+ SetCurrentDirectoryW(path);
+ }
+
+ if (dll)
+ *dll = h;
+
+ return ret;
+ }
+ static std::string u2m(const wchar_t* u, int page)
+ {
+ char* ansi = NULL;
+ int len = 0;
+ std::string mb("");
+
+ len = WideCharToMultiByte(page, 0, u, lstrlenW(u), NULL, 0, NULL, NULL);
+ ansi = new char[len + 2];
+ len = WideCharToMultiByte(page, 0, u, lstrlenW(u), ansi, len, NULL, NULL);
+ ansi[len--] = 0;
+ mb = ansi;
+ delete[] ansi;
+
+ return mb;
+ }
+ static std::wstring m2u(const char* m, int page)
+ {
+ wchar_t* unic = NULL;
+ int len = 0;
+ std::wstring u(L"");
+
+ len = MultiByteToWideChar(page, 0, m, lstrlenA(m), NULL, 0);
+ unic = new wchar_t[len + 2];
+ len = MultiByteToWideChar(page, 0, m, lstrlenA(m), unic, len);
+ unic[len--] = 0;
+ u = unic;
+ delete[] unic;
+
+ return u;
+ }
+
+ bool initialize(HMODULE me)
+ {
+ bool ret = false;
+ sane_path = reg_get_app_installing_path();
+ if (!sane_path.empty())
+ {
+ sane_path += L"\\sane.dll";
+ load_dll(sane_path.c_str(), &sane_module);
+ if (sane_module)
+ {
+ *((FARPROC*)&init) = GetProcAddress(sane_module, "initialize");
+ *((FARPROC*)&sane_inst) = GetProcAddress(sane_module, "open_scanner");
+ *((FARPROC*)&is_on) = GetProcAddress(sane_module, "is_scanner_online");
+ *((FARPROC*)&uninit) = GetProcAddress(sane_module, "uninitialize");
+ ret = is_ok();
+ if (ret)
+ ret = init(NULL) == 0;
+ }
+ }
+
+ return ret;
+ }
+ bool is_ok(void)
+ {
+ return sane_inst != NULL && is_on != NULL && init != NULL && uninit != NULL;
+ }
+ bool is_online(SCANNERID guid)
+ {
+ if (is_on)
+ return is_on(guid);
+ else
+ return false;
+ }
+ ISaneInvoker* open(SCANNERID guid, int* err)
+ {
+ ISaneInvoker* ret = NULL;
+ int code = 0;
+
+ if (!err)
+ err = &code;
+
+ if (sane_inst)
+ *err = sane_inst(guid, &ret);
+
+ return ret;
+ }
+ void uninitialize(void)
+ {
+ if (uninit)
+ uninit(NULL);
+
+ if (sane_module)
+ {
+ FreeLibrary(sane_module);
+ sane_module = NULL;
+ }
+ sane_path = L"";
+ sane_inst = NULL;
+ }
+
+ std::string utf82ansi(const char* utf8)
+ {
+ return u2m(m2u(utf8, CP_UTF8).c_str(), CP_ACP);
+ }
+ std::string ansi2utf8(const char* ansi)
+ {
+ return u2m(m2u(ansi, CP_ACP).c_str(), CP_UTF8);
+ }
+};
diff --git a/twain/load_sane.h b/twain/load_sane.h
new file mode 100644
index 0000000..8f4486a
--- /dev/null
+++ b/twain/load_sane.h
@@ -0,0 +1,19 @@
+#pragma once
+
+// utility for loading sane component ...
+
+#include "../sane/s2t_api.h"
+#include
+
+namespace load_sane_util
+{
+ bool initialize(HMODULE me);
+ bool is_ok(void);
+ bool is_online(SCANNERID guid);
+ ISaneInvoker* open(SCANNERID guid, int* err);
+ void uninitialize(void);
+
+ std::string utf82ansi(const char* utf8);
+ std::string ansi2utf8(const char* ansi);
+};
+
diff --git a/huagaotwain/pch.cpp b/twain/pch.cpp
similarity index 100%
rename from huagaotwain/pch.cpp
rename to twain/pch.cpp
diff --git a/huagaotwain/pch.h b/twain/pch.h
similarity index 100%
rename from huagaotwain/pch.h
rename to twain/pch.h
diff --git a/huagaotwain/resource.h b/twain/resource.h
similarity index 100%
rename from huagaotwain/resource.h
rename to twain/resource.h
diff --git a/huagaotwain/targetver.h b/twain/targetver.h
similarity index 100%
rename from huagaotwain/targetver.h
rename to twain/targetver.h
diff --git a/huagaotwain/twain.def b/twain/twain.def
similarity index 100%
rename from huagaotwain/twain.def
rename to twain/twain.def
diff --git a/huagaotwain/huagaotwain.vcxproj b/twain/twain.vcxproj
similarity index 93%
rename from huagaotwain/huagaotwain.vcxproj
rename to twain/twain.vcxproj
index 67b80f6..3a27b11 100644
--- a/huagaotwain/huagaotwain.vcxproj
+++ b/twain/twain.vcxproj
@@ -13,7 +13,7 @@
{c3b47ce2-27ce-4509-ab59-3c0f194f0fce}
DynamicLibrary
- huagaotwain
+ twain
Win32Proj
10.0
@@ -75,7 +75,7 @@
move /Y "$(OutDirFullPath)$(ProjectName).exp" "$(SolutionDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration)"
move /Y "$(OutDirFullPath)$(ProjectName).lib" "$(SolutionDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration)"
move /Y "$(OutDirFullPath)$(ProjectName).pdb" "$(SolutionDir)..\..\sdk\lib\win\$(PlatformTarget)\$(Configuration)"
-copy $(TargetPath) $(WinDir)\twain_32\HuaGoScan\$(ProjectName).ds /y
+copy $(TargetPath) $(WinDir)\twain_32\HuaGoScan\huagaotwain.ds /y
@@ -106,11 +106,10 @@ copy $(TargetPath) $(WinDir)\twain_32\HuaGoScan\$(ProjectName).ds /y
-
-
+
+
-
@@ -153,24 +152,18 @@ copy $(TargetPath) $(WinDir)\twain_32\HuaGoScan\$(ProjectName).ds /y
-
-
+
Create
Create
-
- NotUsing
- NotUsing
-
NotUsing
NotUsing
-
diff --git a/huagaotwain/huagaotwain.vcxproj.filters b/twain/twain.vcxproj.filters
similarity index 83%
rename from huagaotwain/huagaotwain.vcxproj.filters
rename to twain/twain.vcxproj.filters
index e82d13b..bf07ba3 100644
--- a/huagaotwain/huagaotwain.vcxproj.filters
+++ b/twain/twain.vcxproj.filters
@@ -11,21 +11,28 @@
{df21031b-938a-4a08-ae64-e869e2586201}
+
+ {89716198-13ed-4593-819e-97f4426c7baa}
+
+
+ {6d97172d-832d-4c93-ad0e-92fdf76af26b}
+
-
-
-
twain
-
-
+
+ Sources
+
+
+ Sources
+
+
+ Sources
+
-
-
-
twain
@@ -149,17 +156,30 @@
twain
-
-
-
-
-
-
-
+
+ Headers
+
+
+ Headers
+
+
+ Headers
+
+
+ Headers
+
+
+ Headers
+
Resource Files
+
+
+ Sources
+
+
\ No newline at end of file
diff --git a/twain/twain.vcxproj.user b/twain/twain.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/twain/twain.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/huagaotwain/twain/huagaods.cpp b/twain/twain/huagaods.cpp
similarity index 61%
rename from huagaotwain/twain/huagaods.cpp
rename to twain/twain/huagaods.cpp
index 9d8e038..9fe5a0d 100644
--- a/huagaotwain/twain/huagaods.cpp
+++ b/twain/twain/huagaods.cpp
@@ -18,15 +18,13 @@
#endif // WIN32
using namespace std;
-#include "../huagaotwain.h"
-#include "../ui.h"
-
#define enum2str(R) #R
using namespace Twpp;
using namespace std::placeholders;
+extern HMODULE me_;
//custom define caps enum
enum CapTypeEx : unsigned short {
@@ -48,14 +46,15 @@ enum CapTypeEx : unsigned short {
CAP_TYPE_EX_DOGEAR_DETECT = 0x8096,
CAP_TYPE_EX_BKG_FILLING_METHOD = 0x8097,
CAP_TYPE_EX_EDGE_IDENT = 0x8098,
- CAP_TYPE_EX_THRESHOLD = 0x8099,
- CAP_TYPE_EX_THRESHOLD_1 = 0x8100,
+ CAP_TYPE_EX_ANTI_NOISE = 0x8099,
+ CAP_TYPE_EX_THRESHOLD = 0x8100,
CAP_TYPE_EX_DETACH_NOISE = 0x8101,
CAP_TYPE_EX_DETACH_NOISE_THRESHOLD = 0x8102,
CAP_TYPE_EX_SIZE_DETECT = 0x8103,
CAP_TYPE_EX_POWER_LEVEL = 0x8104,
CAP_TYPE_EX_ENCODE = 0x8105,
CAP_TYPE_EX_DARK_SAMPLE = 0x8016,
+ CAP_TYPE_EX_CROP_MODEL = 0x8106,
CAP_TYPE_EX_DOGEAR_DIST = 0x8107,
CAP_TYPE_EX_IMAGE_SPLIT = 0x8108,
CAP_TYPE_EX_FADE_BKG = 0x8109,
@@ -147,6 +146,26 @@ enum CapTypeEx : unsigned short {
CAP_TYPE_EX_78,
CAP_TYPE_EX_79,
CAP_TYPE_EX_80,
+ CAP_TYPE_EX_81,
+ CAP_TYPE_EX_82,
+ CAP_TYPE_EX_83,
+ CAP_TYPE_EX_84,
+ CAP_TYPE_EX_85,
+ CAP_TYPE_EX_86,
+ CAP_TYPE_EX_87,
+ CAP_TYPE_EX_88,
+ CAP_TYPE_EX_89,
+ CAP_TYPE_EX_90,
+ CAP_TYPE_EX_91,
+ CAP_TYPE_EX_92,
+ CAP_TYPE_EX_93,
+ CAP_TYPE_EX_94,
+ CAP_TYPE_EX_95,
+ CAP_TYPE_EX_96,
+ CAP_TYPE_EX_97,
+ CAP_TYPE_EX_98,
+ CAP_TYPE_EX_99,
+ CAP_TYPE_EX_100,
};
@@ -277,6 +296,24 @@ Result CapSupGetAllReset(Msg msg, Capability& data, std::initializer_list va
}
}
template
+Result CapSupGetAllReset(Msg msg, Capability& data, std::list values, T1& currvalue, T2 defaultvalue, UInt32 currindex, UInt32 defaultindex) {
+ switch (msg) {
+ case Msg::Get:
+ data = Capability::createEnumeration(values, currindex, defaultindex);
+ return { ReturnCode::Success, ConditionCode::Success };
+ case Msg::GetCurrent:
+ data = Capability::createOneValue((T2)currvalue);
+ return { ReturnCode::Success, ConditionCode::Success };
+ case Msg::Reset:
+ case Msg::GetDefault:
+ currvalue = (T1)defaultvalue;
+ data = Capability::createOneValue(defaultvalue);
+ return { ReturnCode::Success, ConditionCode::Success };
+ default:
+ return { ReturnCode::Failure, ConditionCode::CapBadOperation };
+ }
+}
+template
Result CapSupGetAllResetEx(Msg msg, Capability& data, std::initializer_list values, T1& currvalue, T2 defaultvalue, UInt32 currindex, UInt32 defaultindex) {
switch (msg) {
case Msg::Get:
@@ -294,6 +331,24 @@ Result CapSupGetAllResetEx(Msg msg, Capability& data, std::initializer_list
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
+template
+Result CapSupGetAllResetEx(Msg msg, Capability& data, std::list values, T1& currvalue, T2 defaultvalue, UInt32 currindex, UInt32 defaultindex) {
+ switch (msg) {
+ case Msg::Get:
+ data = Capability::createEnumeration(cap, values, currindex, defaultindex);
+ return { ReturnCode::Success, ConditionCode::Success };
+ case Msg::GetCurrent:
+ data = Capability::createOneValue(cap, (T2)currvalue);
+ return { ReturnCode::Success, ConditionCode::Success };
+ case Msg::Reset:
+ case Msg::GetDefault:
+ currvalue = (T1)defaultvalue;
+ data = Capability::createOneValue(cap, defaultvalue);
+ return { ReturnCode::Success, ConditionCode::Success };
+ default:
+ return { ReturnCode::Failure, ConditionCode::CapBadOperation };
+ }
+}
template
Result CapSupGetAllReset(Msg msg, Capability& data, T1& currvalue, T2 defaultvalue) {
@@ -414,6 +469,10 @@ static void copy_type(UInt32& to, int from)
{
to = from;
}
+static void copy_type(int& to, UInt32 from)
+{
+ to = from;
+}
static void copy_type(Fix32& to, double from)
{
to = from;
@@ -422,28 +481,156 @@ static void copy_type(Fix32& to, float from)
{
to = from;
}
+static void copy_type(float& to, Fix32 from)
+{
+ to = from.toFloat();
+}
static void copy_type(Str255& to, std::string from)
{
- to.setData(sane_invoker::utf82ansi(from.c_str()).c_str());
+ to.setData(load_sane_util::utf82ansi(from.c_str()).c_str());
}
static void copy_type(std::string& to, Str255 from)
{
- to = sane_invoker::ansi2utf8(from.data());
+ to = load_sane_util::ansi2utf8(from.data());
}
static void copy_type(Str64& to, std::string from)
{
- to.setData(sane_invoker::utf82ansi(from.c_str()).c_str());
+ to.setData(load_sane_util::utf82ansi(from.c_str()).c_str());
}
static void copy_type(std::string& to, Str64 from)
{
- to = sane_invoker::ansi2utf8(from.data());
+ to = load_sane_util::ansi2utf8(from.data());
}
+UINT16 bit_depth_from_sane(int sane)
+{
+ if (sane == COLOR_BW)
+ return 1;
+ else if (sane == COLOR_GRAY)
+ return 8;
+ else if (sane == COLOR_RGB)
+ return 24;
+ else
+ return sane;
+}
+static ImageFileFormat from_sane_image_type(int sane_img_type)
+{
+ ImageFileFormat fmt = ImageFileFormat::Bmp;
+ switch (sane_img_type)
+ {
+ case SANE_IMAGE_TYPE_PNG:
+ fmt = ImageFileFormat::Png;
+ break;
+ case SANE_IMAGE_TYPE_JPG:
+ fmt = ImageFileFormat::Jpx;
+ break;
+ case SANE_IMAGE_TYPE_TIFF:
+ fmt = ImageFileFormat::Tiff;
+ break;
+ case SANE_IMAGE_TYPE_JFIF:
+ fmt = ImageFileFormat::Jfif;
+ break;
+ case SANE_IMAGE_TYPE_WEBP:
+ break;
+ case SANE_IMAGE_TYPE_PDF:
+ fmt = ImageFileFormat::Pdf;
+ break;
+ case SANE_IMAGE_TYPE_GIF:
+ break;
+ case SANE_IMAGE_TYPE_SVG:
+ break;
+ default:
+ break;
+ }
+
+ return fmt;
+}
+
+struct
+{
+ Filter twain;
+ int sane;
+}g_filter[] = { {Filter::Red, FILTER_RED}, {Filter::Green, FILTER_GREEN}, {Filter::Blue, FILTER_BLUE}, {Filter::None, FILTER_NONE} };
+Filter from_sane_filter(int sane)
+{
+ for (int i = 0; i < _countof(g_filter); ++i)
+ {
+ if (g_filter[i].sane == sane)
+ return g_filter[i].twain;
+ }
+
+ return Filter::None;
+}
+int to_sane_filter(Filter twain)
+{
+ for (int i = 0; i < _countof(g_filter); ++i)
+ {
+ if (g_filter[i].twain == twain)
+ return g_filter[i].sane;
+ }
+
+ return FILTER_NONE;
+}
+
+struct
+{
+ Filter twain;
+ int sane;
+}g_enhance[] = { {Filter::Red, ENHANCE_RED}, {Filter::Green, ENHANCE_GREEN}, {Filter::Blue, ENHANCE_BLUE}, {Filter::None, ENHANCE_NONE} };
+Filter from_sane_enhance(int sane)
+{
+ for (int i = 0; i < _countof(g_filter); ++i)
+ {
+ if (g_filter[i].sane == sane)
+ return g_filter[i].twain;
+ }
+
+ return Filter::None;
+}
+int to_sane_enhance(Filter twain)
+{
+ for (int i = 0; i < _countof(g_filter); ++i)
+ {
+ if (g_filter[i].twain == twain)
+ return g_filter[i].sane;
+ }
+
+ return FILTER_NONE;
+}
+
+float trans_range(float val, float min_from, float max_from, float min_to, float max_to)
+{
+ // transfer val in range [min_from, max_from] to value in range [min_to, max_to]
+ val -= min_from;
+ val /= max_from - min_from;
+ val *= max_to - min_to;
+ val += min_to;
+
+ return val;
+}
+
+
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// huagao_ds ...
+#define PRODUCT_PID 0x0100
+#define PRODUCT_VID 0x3072
+#define PRODUCT_VENDOR "HUAGO"
+#define PRODUCT_FAMILY "HG100"
+#define PRODUCT_NAME "HG0100"
+
+#define TO_STR(a) #a
+#define VERSION_MAIN 4
+#define VERSION_SUB 1007
+#define VERSION_BUILD 2022
+#define VERSION_PATCH 6131
+#define TO_VER_STR(vs) TO_STR(v##vs)
+#define VERSION_STR(a, b, c, d) TO_VER_STR(a.b.c.d)
+
static Identity* srcIdent = new Identity(
- Version(3, 3, Language::English, Country::China, "v3.3.5.6"),
- DataGroup::Image, "HUAGO", "HUAGAO Series", "Huagao scanner series");
+ Version(VERSION_MAIN, VERSION_SUB, Language::English, Country::China, VERSION_STR(VERSION_MAIN, VERSION_SUB, VERSION_BUILD, VERSION_PATCH)),
+ DataGroup::Image, PRODUCT_VENDOR, PRODUCT_FAMILY, PRODUCT_NAME);
+static const SCANNERID scanner_guid = MAKE_SCANNER_ID(PRODUCT_PID, PRODUCT_VID);
static std::once_flag oc;
@@ -489,71 +676,13 @@ void huagao_ds::scan_event(int sane_event, void* data, unsigned int* len, void*
const Identity& huagao_ds::defaultIdentity() noexcept {
// remember, we return a reference, therefore the identity must not be placed on the stack of this method
- if (sane_invoker::is_ok())
- {
- DWORD ver = 0;
- std::string v(sane_invoker::version(&ver)),
- n("HUAGO"), t("Huagao scanner series"), m("HUAGAO Series");
- std::vector devs;
- char v32[32] = { 0 }, n32[32] = { 0 }, t32[32] = { 0 }, m32[32] = { 0 };
-
- sane_invoker::get_devices(devs);
- if (devs.size())
- {
- n = devs[0].vendor;
- t = devs[0].name;
- m = devs[0].product;
- }
- if (ver == 0)
- {
- ver = MAKELPARAM(56, 0x303);
- v = "v3.3.56";
- }
- else
- v.insert(0, "v");
-
- delete srcIdent;
-#define COPY_32(a) strcpy_s(v##32, _countof(v##32), v##.c_str())
- COPY_32(v);
- COPY_32(n);
- COPY_32(t);
- COPY_32(m);
- srcIdent = new Twpp::Identity(Twpp::Version((ver >> 24) & 0x0ff, (ver >> 16) & 0x0ff, Language::English, Country::China, v32),
- DataGroup::Image, n32, m32, t32);
- }
-
return *srcIdent;
}
Result huagao_ds::selectIdentity(Twpp::Identity& ident) noexcept {
// remember, we return a reference, therefore the identity must not be placed on the stack of this method
- if (sane_invoker::is_ok())
- {
- DWORD ver = 0;
- std::vector devs;
- Version twver;
- char v32[32] = { 0 }, n32[32] = { 0 }, t32[32] = { 0 }, m32[32] = { 0 };
+ ident = *srcIdent;
- sane_invoker::get_devices(devs);
- if (devs.size())
- {
- strcpy(m32, devs[0].type.c_str());
- strcpy(n32, devs[0].product.c_str());
- strcpy(t32, devs[0].name.c_str());
- ident = Identity(twver, DataGroup::Image, n32, m32, t32);
-
- return success();
- }
- // show dialog to select the devices listed in devs here ...
- //if (dlg.DoModal() == IDOK)
- //{
- // ident = Identity(twver, DataGroup::Image, n32, m32, t32);
- // return success();
- //}
- //else
- {
- return { ReturnCode::Failure, ConditionCode::Bummer };
- }
- }
+ return success();
return { ReturnCode::Failure, ConditionCode::NoDs };
}
@@ -633,7 +762,7 @@ Result huagao_ds::eventProcess(const Identity&, Event& event)
}
Twpp::Result huagao_ds::deviceEventGet(const Twpp::Identity& origin, Twpp::DeviceEvent& data)
{
- // data = DeviceEvent::simple(sane_invoker::take_event(), "HUAGAO");
+ // data = DeviceEvent::simple(load_sane_util::take_event(), "HUAGAO");
// return success();
return seqError();
@@ -648,9 +777,9 @@ Result huagao_ds::identityOpenDs(const Identity& id)
//
// return { ReturnCode::Failure, ConditionCode::CapBadOperation };
//}
- if (!sane_invoker::is_ok())
- sane_invoker::initialize(me_);
- if (!sane_invoker::is_ok())
+ if (!load_sane_util::is_ok())
+ load_sane_util::initialize(me_);
+ if (!load_sane_util::is_ok())
{
CloseHandle(singleton_);
singleton_ = NULL;
@@ -666,21 +795,22 @@ Result huagao_ds::identityOpenDs(const Identity& id)
{
CloseHandle(singleton_);
singleton_ = NULL;
- sane_invoker::uninitialize();
+ load_sane_util::uninitialize();
return result;
}
int err = 0;
- scanner_.reset(sane_invoker::open_scanner(target.productName().begin(), &err));
+ Sleep(100);
+ scanner_.reset(load_sane_util::open(scanner_guid, &err));
if (!scanner_.get())
{
//CloseHandle(singleton_);
//singleton_ = NULL;
- sane_invoker::uninitialize();
+ load_sane_util::uninitialize();
return { ReturnCode::Failure, huagao_ds::condition_code_from_hg_error(err) };
}
- ui_.reset(new twain_ui(local_utility::reg_get_app_installing_path().c_str()));
+ // ui_.reset(new twain_ui(local_utility::reg_get_app_installing_path().c_str()));
scanner_->set_event_callback(&huagao_ds::scan_event, this);
init_support_caps();
@@ -688,7 +818,7 @@ Result huagao_ds::identityOpenDs(const Identity& id)
}
Result huagao_ds::identityCloseDs(const Identity&)
{
- ui_.reset();
+ // ui_.reset();
if (scanner_.get())
{
scanner_.reset();
@@ -698,7 +828,7 @@ Result huagao_ds::identityCloseDs(const Identity&)
CloseHandle(singleton_);
singleton_ = NULL;
}
- sane_invoker::uninitialize();
+ load_sane_util::uninitialize();
return success();
}
@@ -749,7 +879,7 @@ Result huagao_ds::setupMemXferGet(const Identity&, SetupMemXfer& data)
}
Result huagao_ds::userInterfaceDisable(const Identity&, UserInterface& ui)
{
- ui_->hide_ui();
+ scanner_->ui_hide();
return success();
}
@@ -758,7 +888,7 @@ Result huagao_ds::userInterfaceEnable(const Identity&, UserInterface& ui)
if (!ui.showUi())
{
if (m_bIndicator)
- ui_->show_main_ui(sane_invoker::get_api());
+ scanner_->ui_show_main();
return scanner_->start() == SCANNER_ERR_OK ? success() : seqError();
}
@@ -780,13 +910,19 @@ Result huagao_ds::imageInfoGet(const Identity&, ImageInfo& data)
if (scanner_->get_first_image_header(&head))
{
- data.setBitsPerPixel(head.depth);
+ if(head.format == SANE_FRAME_RGB)
+ data.setBitsPerPixel(head.depth * 3);
+ else
+ data.setBitsPerPixel(head.depth);
data.setHeight(head.lines);
- data.setPixelType(head.depth == 24 ? PixelType::Rgb : PixelType::Gray);
+ data.setPixelType(head.format == SANE_FRAME_RGB ? PixelType::Rgb : PixelType::Gray);
data.setPlanar(false);
data.setWidth(head.pixels_per_line);
- data.setXResolution(scanner_->twain_get_resolution());
- data.setYResolution(scanner_->twain_get_resolution());
+
+ int res = 200;
+ GET_SANE_OPT(int, scanner_, resolution, &res, NULL, NULL, NULL, NULL);
+ data.setXResolution(res);
+ data.setYResolution(res);
data.compression(Compression::None);
}
@@ -799,11 +935,14 @@ Result huagao_ds::imageLayoutGet(const Identity&, ImageLayout& data)
if (!scanner_.get() || scanner_->get_scanned_images() == 0)
return seqError();
+ int res = 200;
+ GET_SANE_OPT(int, scanner_, resolution, &res, NULL, NULL, NULL, NULL);
+
scanner_->get_first_image_header(&head);
data.setDocumentNumber(1);
data.setFrameNumber(1);
data.setPageNumber(1);
- data.setFrame(Frame(0, 0, static_cast(head.pixels_per_line) / scanner_->twain_get_resolution(), static_cast(head.lines) / scanner_->twain_get_resolution()));
+ data.setFrame(Frame(0, 0, static_cast(head.pixels_per_line) / res, static_cast(head.lines) / res));
return success();
}
@@ -829,7 +968,7 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
if (!scanner_.get() || scanner_->get_scanned_images() == 0)
return seqError();
- scanned_img *img = scanner_->take_first_image();
+ IScanImg *img = scanner_->take_first_image();
unsigned char *src = img->bits() + img->bytes() - img->line_bytes(),
*dst = NULL;
@@ -843,7 +982,7 @@ Result huagao_ds::imageMemXferGet(const Identity& origin, ImageMemXfer& data)
dst = (unsigned char*)data.memory().data().data();
for (int i = 0; i < img->height(); ++i, src -= img->line_bytes(), dst += img->line_bytes())
std::copy(src, src + img->line_bytes(), dst);
- delete img;
+ img->release();
return success();
}
@@ -852,7 +991,7 @@ Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
if (!scanner_.get() || scanner_->get_scanned_images() == 0)
return seqError();
- scanned_img* img = scanner_->take_first_image();
+ IScanImg* img = scanner_->take_first_image();
if (!img)
return seqError();
@@ -860,13 +999,13 @@ Result huagao_ds::imageNativeXferGet(const Identity& id, ImageNativeXfer& data)
data.release();
data = ImageNativeXfer(img->bytes());
std::copy(img->bits(), img->bits() + img->bytes(), data.data().data());
- delete img;
+ img->release();
return { ReturnCode::XferDone, ConditionCode::Success };
}
Twpp::Result huagao_ds::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data)
{
- // sane_invoker::invoke_sane_cancel();
+ // load_sane_util::invoke_sane_cancel();
return success();
}
@@ -876,7 +1015,7 @@ Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin)
if (!scanner_.get() || scanner_->get_scanned_images() == 0)
return seqError();
- scanned_img *img = scanner_->take_first_image();
+ IScanImg *img = scanner_->take_first_image();
Twpp::Result ret = seqError();
FILE* dst = NULL;
@@ -892,7 +1031,7 @@ Twpp::Result huagao_ds::imageFileXferGet(const Twpp::Identity& origin)
fclose(dst);
}
- delete img;
+ img->release();
}
return ret;
@@ -969,12 +1108,10 @@ Result huagao_ds::capCommon(const Identity&, Msg msg, Capability& data) {
Twpp::Result huagao_ds::showTwainUI(Twpp::UserInterface& data, bool bUiOnly)
{
// display user UI ... (setting UI, can we show my own main window here ?)
- LPSANEAPI api = sane_invoker::get_api();
-
if (bUiOnly)
- ui_->show_setting_ui(api, false);
+ scanner_->ui_show_setting(false);
else
- ui_->show_main_ui(api);
+ scanner_->ui_show_main();
return success();
}
@@ -1006,13 +1143,19 @@ void huagao_ds::init_support_caps(void)
if (item > 65535 || item < -1 || item == 0) {
return badValue();
}
- return scanner_->twain_set_scan_count(item) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK;
+ int count = item;
+ SET_SANE_OPT(ret, scanner_, scan_count, &count);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- Int16 tmp_count = scanner_->twain_get_scan_count();
+ int count = -1;
+ Int16 tmp_count = 0;
+ GET_SANE_OPT(int, scanner_, scan_count, &count, NULL, NULL, NULL);
+ tmp_count = count;
return oneValGetSet(msg, data, tmp_count, -1);
};
- if (ui_->is_ok())
+ if (scanner_->ui_is_ok())
{
m_query[CapType::UiControllable] = msgSupportGetAll;
m_caps[CapType::UiControllable] = std::bind(oneValGet, _1, _2, Bool(true));
@@ -1028,7 +1171,7 @@ void huagao_ds::init_support_caps(void)
if(scanner_.get())
data = Capability::createOneValue((Twpp::Bool)scanner_->is_online());
else
- data = Capability::createOneValue((Twpp::Bool)(sane_invoker::online_devices() > 0));
+ data = Capability::createOneValue((Twpp::Bool)(load_sane_util::is_online(scanner_guid)));
return success();
default:
@@ -1044,14 +1187,19 @@ void huagao_ds::init_support_caps(void)
{
int mech = (int)data.currentItem();
if (msg == Msg::Reset)
- scanner_->twain_get_final_compression(&mech);
- return scanner_->twain_set_final_compression(mech) == SCANNER_ERR_OK ? success() : badValue();
+ GET_SANE_OPT(int, scanner_, ex_final_compression, NULL, &mech, NULL, NULL);
+
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_final_compression, (int*)&mech);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
std::vector values;
+ int init = 0, now = 0;
std::list vals;
Compression Now, Init;
UInt32 ni = 0, ii = 0;
- int init = 0, now = scanner_->twain_get_final_compression(&init, &values);
+
+ GET_SANE_OPT(int, scanner_, ex_final_compression, &now, &init, &values, NULL);
Now = (Compression)now;
Init = (Compression)init;
for (const auto& v : values)
@@ -1066,26 +1214,33 @@ void huagao_ds::init_support_caps(void)
m_query[CapType::IBitDepth] = msgSupportGetAllSetReset;
m_caps[CapType::IBitDepth] = [this](Msg msg, Capability& data) -> Result {
- if (Msg::Set == msg) {
+ int now = 0, init = 0;
+ std::vector all;
+ GET_SANE_OPT(int, scanner_, ex_color_mode, &now, &init, &all, NULL);
+ if (Msg::Set == msg || Msg::Reset == msg) {
auto mech = data.currentItem();
int ret = SCANNER_ERR_INVALID_PARAMETER;
- if (mech == 1)
- ret = scanner_->twain_set_color_mode((int)PixelType::BlackWhite);
- else if(mech == 8)
- ret = scanner_->twain_set_color_mode((int)PixelType::Gray);
- else if(mech == 24)
- ret = scanner_->twain_set_color_mode((int)PixelType::Rgb);
+ if (Msg::Set == msg)
+ {
+ if (mech == 1)
+ init = COLOR_BW;
+ else if (mech == 8)
+ init = COLOR_GRAY;
+ else if (mech == 24)
+ init = COLOR_RGB;
+ else
+ init = mech;
+ }
+ SET_SANE_OPT(ret, scanner_, ex_color_mode, &init);
return ret == SCANNER_ERR_OK ? success() : badValue();
}
- UINT16 twpt = scanner_->twain_get_color_mode();
- if (twpt == (int)PixelType::BlackWhite)
- twpt = 1;
- else if (twpt == (int)PixelType::Gray)
- twpt = 8;
- else
- twpt = 24;
-
- return CapSupGetAllReset(msg, data, twpt, 24);
+ UINT16 Now = bit_depth_from_sane(now), Init = bit_depth_from_sane(init);
+ std::list vals;
+ UInt32 ni = std::distance(all.begin(), std::find(all.begin(), all.end(), now)),
+ ii = std::distance(all.begin(), std::find(all.begin(), all.end(), init));
+ for (auto& v : all)
+ vals.push_back(bit_depth_from_sane(v));
+ return cap_get_enum_values(msg, data, vals, Now, Init, ni, ii);
};
m_query[CapType::IBitOrder] = msgSupportGetAllSetReset;
@@ -1098,12 +1253,12 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::IXResolution] = [this](Msg msg, Capability& data) {
if (!scanner_.get())
return seqError();
- std::vector values;
- value_limit limit = VAL_LIMIT_NONE;
- float init = .0f, now = .0f;
+ std::vector values;
+ value_limit limit = VAL_LIMIT_ENUM;
+ int init = 0, now = 0;
+ GET_SANE_OPT(int, scanner_, resolution, &now, &init, &values, NULL);
switch (msg) {
case Msg::Get:
- now = scanner_->twain_get_resolution(&init, &values, &limit);
if (limit == VAL_LIMIT_RANGE)
{
data = Capability::createRange(Fix32(values[0]), Fix32(values[1]), Fix32(50.0f), Fix32(now), Fix32(init));
@@ -1117,29 +1272,32 @@ void huagao_ds::init_support_caps(void)
for (const auto& v : values)
{
Fix32 f;
- copy_type(f, v);
+ float vf = v;
+ copy_type(f, vf);
vals.push_back(f);
}
- copy_type(Now, now);
- copy_type(Init, init);
+ float nowf = now, initf = init;
+ copy_type(Now, nowf);
+ copy_type(Init, initf);
ni = std::distance(vals.begin(), std::find(vals.begin(), vals.end(), Now));
ii = std::distance(vals.begin(), std::find(vals.begin(), vals.end(), Init));
return cap_get_enum_values(msg, data, vals, Now, Init, ni, ii);
}
case Msg::GetCurrent:
- now = scanner_->twain_get_resolution();
data = Capability::createOneValue(Fix32(now));
return success();
case Msg::GetDefault:
- now = scanner_->twain_get_resolution(&init);
data = Capability::createOneValue(Fix32(init));
return success();
case Msg::Reset:
- now = scanner_->twain_get_resolution(&init);
data = Capability::createOneValue(Fix32(init));
case Msg::Set: {
auto mech = data.currentItem();
- return scanner_->twain_set_resolution((float)mech) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK;
+ float resl = (float)mech;
+ int resli = resl;
+ SET_SANE_OPT(ret, scanner_, resolution, &resli);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
default:
return capBadOperation();
@@ -1155,6 +1313,32 @@ void huagao_ds::init_support_caps(void)
m_query[CapType::IYNativeResolution] = msgSupportGetAll;
m_caps[CapType::IYNativeResolution] = m_caps[CapType::IXNativeResolution];
+ m_query[CapType::ISupportedSizes] = msgSupportGetAllSetReset;
+ m_caps[CapType::ISupportedSizes] = [this](Msg msg, Capability& data) {
+ int now = 0,
+ init = 0;
+ std::vector all;
+ GET_SANE_OPT(int, scanner_, ex_paper, &now, &init, &all, NULL);
+ if (msg == Msg::Set || msg == Msg::Reset)
+ {
+ if(msg == Msg::Set)
+ init = (int)data.currentItem();
+
+ SET_SANE_OPT(now, scanner_, ex_paper, &init);
+ return now == SCANNER_ERR_OK ? success() : badValue();
+ }
+
+ std::list vals;
+ Twpp::PaperSize Now = (PaperSize)now,
+ Init = (PaperSize)init;
+ UInt32 ni = std::distance(all.begin(), std::find(all.begin(), all.end(), now)),
+ ii = std::distance(all.begin(), std::find(all.begin(), all.end(), init));
+ for (auto& v : all)
+ vals.push_back((PaperSize)v);
+
+ return cap_get_enum_values(msg, data, vals, Now, Init, ni, ii);
+ };
+
m_query[CapType::IPhysicalWidth] = msgSupportGetAll;
m_caps[CapType::IPhysicalWidth] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
@@ -1163,9 +1347,11 @@ void huagao_ds::init_support_caps(void)
case Msg::GetDefault:
{
float init = 10.0f;
+ int cur = 200;
SANE_Parameters param = { 0 };
+ GET_SANE_OPT(int, scanner_, resolution, &cur, NULL, NULL, NULL);
if (scanner_.get() && scanner_->get_first_image_header(¶m))
- init = param.bytes_per_line / scanner_->twain_get_resolution();
+ init = param.bytes_per_line * 1.0f / cur;
data = Capability::createOneValue(data.type(), Fix32(init));
return success();
}
@@ -1182,9 +1368,11 @@ void huagao_ds::init_support_caps(void)
case Msg::GetDefault:
{
float init = 10.0f;
+ int cur = 200;
SANE_Parameters param = { 0 };
+ GET_SANE_OPT(int, scanner_, resolution, &cur, NULL, NULL, NULL);
if (scanner_.get() && scanner_->get_first_image_header(¶m))
- init = param.lines / scanner_->twain_get_resolution();
+ init = param.lines * 1.0f / cur;
data = Capability::createOneValue(data.type(), Fix32(init));
return success();
}
@@ -1210,34 +1398,26 @@ void huagao_ds::init_support_caps(void)
}
return CapSupGetAllReset(msg, data, { XferMech::Native, XferMech::File, XferMech::Memory }, m_capXferMech, XferMech::Native, (int)m_capXferMech, 0);
};
-
+
m_query[CapType::IPixelType] = msgSupportGetAllSetReset;
m_caps[CapType::IPixelType] = [this](Msg msg, Capability& data) -> Result {
if (!scanner_.get())
return seqError();
- if (Msg::Reset == msg)
- {
- int init = 0;
- scanner_->twain_get_color_mode(&init);
- data = Capability::createOneValue((Twpp::PixelType)init);
- msg = Msg::Set;
- }
- if (Msg::Set == msg) {
- auto mech = data.currentItem();
- return scanner_->twain_set_color_mode((int)mech) == SCANNER_ERR_OK ? success() : badValue();
- }
std::vector values;
- value_limit limit = VAL_LIMIT_NONE;
int init = 0, now = 0;
+
+ GET_SANE_OPT(int, scanner_, ex_color_mode, &now, &init, &values, NULL);
+ if (Msg::Reset == msg || Msg::Set == msg)
+ {
+ if(Msg::Set == msg)
+ init = (int)data.currentItem();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_color_mode, &init);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
+ }
switch (msg) {
case Msg::Get:
- now = scanner_->twain_get_color_mode(&init, &values, &limit);
- //if (limit == VAL_LIMIT_RANGE)
- //{
- // data = Capability::createRange((Twpp::PixelType)(values[0]), (Twpp::PixelType)(values[1]), (Twpp::PixelType)(1), (Twpp::PixelType)(now), (Twpp::PixelType)(init));
- // return success();
- //}
- if (limit == VAL_LIMIT_ENUM)
+ if (1)
{
std::list vals;
UInt32 ni, ii;
@@ -1249,11 +1429,9 @@ void huagao_ds::init_support_caps(void)
return cap_get_enum_values(msg, data, vals, Now, Init, ni, ii);
}
case Msg::GetCurrent:
- now = scanner_->twain_get_color_mode();
data = Capability::createOneValue((Twpp::PixelType)now);
return success();
case Msg::GetDefault:
- now = scanner_->twain_get_color_mode(&init);
data = Capability::createOneValue((Twpp::PixelType)init);
return success();
}
@@ -1264,20 +1442,30 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::IAutomaticColorEnabled] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem();
- scanner_->twain_set_color_mode(mech ? TWPT_AUTOMATIC_COLOR : (int)PixelType::Rgb);
+ int ret = SCANNER_ERR_OK, val = mech ? COLOR_AUTO_MATCH : COLOR_RGB;
+ SET_SANE_OPT(ret, scanner_, color_mode, &val);
+
return success();
}
- int twpt = scanner_->twain_get_color_mode() == TWPT_AUTOMATIC_COLOR ? 1 : 0;
+ int cur = 0;
+ GET_SANE_OPT(int, scanner_, color_mode, &cur, NULL, NULL, NULL);
+ int twpt = cur == COLOR_AUTO_MATCH ? 1 : 0;
return CapSupGetAllReset(msg, data, { FALSE,TRUE }, twpt, false, twpt ? 1 : 0, 0);
};
m_query[CapType::IAutomaticColorNonColorPixelType] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticColorNonColorPixelType] = [this](Msg msg, Capability& data)->Result {
if (msg == Msg::Set) {
- auto mech = data.currentItem();
- if (scanner_->twain_get_color_mode() == TWPT_AUTOMATIC_COLOR) {
+ int mech = (int)data.currentItem();
+ //int now = 0;
+ //GET_SANE_OPT(int, scanner_, color_mode, &now, NULL, NULL, NULL);
+ //if (now == TWPT_AUTOMATIC_COLOR)
+ {
if ((UInt16)mech == 0 || (UInt16)mech == 1) {
- if (scanner_->twain_set_auto_color_type((int)mech) == SCANNER_ERR_OK)
+ int ret = SCANNER_ERR_OK,
+ val = mech;
+ SET_SANE_OPT(ret, scanner_, ex_auto_color_type, &val);
+ if (ret == SCANNER_ERR_OK)
{
automaticcolortype_ = (UInt16)mech;
return success();
@@ -1291,13 +1479,23 @@ void huagao_ds::init_support_caps(void)
m_query[CapType::IJpegQuality] = msgSupportGetAllSetReset;
m_caps[CapType::IJpegQuality] = [this](Msg msg, Capability& data)->Result {
+ SANE_FinalImgFormat fif;
+ fif.img_format = SANE_IMAGE_TYPE_JPG;
if (Msg::Set == msg) {
auto mech = data.currentItem();
if ((int)mech <= 0 || (int)mech > 100)
return badValue();
- return scanner_->twain_set_final_format(SANE_IMAGE_TYPE_JPG, (void*)mech) == SCANNER_ERR_OK ? success() : badValue();
+
+ int ret = SCANNER_ERR_OK;
+ fif.detail = (void*)mech;
+ SET_SANE_OPT(ret, scanner_, ex_final_format, &fif);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- unsigned short q = scanner_->twain_get_jpeg_quality();
+ unsigned short q = 80;
+ fif.detail = (void*)q;
+ GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &fif, NULL, NULL, NULL);
+ if(fif.img_format == SANE_IMAGE_TYPE_JPG)
+ q = (unsigned short)fif.detail;
return CapSupGetAllResetEx(msg, data, q, 80);
};
@@ -1306,9 +1504,14 @@ void huagao_ds::init_support_caps(void)
CapabilityPrintf(msg, enum2str(CapTypeEx::IOrientation), msg == Msg::Set ? to_string((int)data.currentItem()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem();
- return scanner_->twain_set_paper_lateral(mech == Orientation::Landscape) ? success() : badValue();
+ bool lateral = mech == Orientation::Landscape;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_paper_lateral, &lateral);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- int lateral = scanner_->twain_is_paper_lateral() ? (int)Orientation::Landscape : (int)Orientation::Portrait;
+ bool is_lateral = false;
+ GET_SANE_OPT(bool, scanner_, ex_paper_lateral, &is_lateral, NULL, NULL, NULL);
+ int lateral = is_lateral ? (int)Orientation::Landscape : (int)Orientation::Portrait;
return CapSupGetAllReset(msg, data, { Orientation::Portrait, Orientation::Landscape }, lateral, Orientation::Portrait, lateral == 0 ? 0 : 1, 0);
};
@@ -1316,12 +1519,15 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::IRotation] = [this](Msg msg, Capability& data) -> Result {
if (Msg::Set == msg) {
auto res = data.currentItem();
- return scanner_->twain_set_text_direction(res.toFloat()) == SCANNER_ERR_OK ? success() : badValue();
+ float angle = res.toFloat();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_text_direction, &angle);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- double init = .0f, now = .0f;
- std::list values;
- value_limit limit = VAL_LIMIT_NONE;
- now = scanner_->twain_get_text_direction(&init, &values, &limit);
+ float init = .0f, now = .0f;
+ std::list values;
+
+ GET_SANE_OPT(float, scanner_, ex_text_direction, &now, &init, NULL, &values);
Fix32 Init = Fix32(init), Now = Fix32(now);
std::list vls;
@@ -1358,9 +1564,12 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::DuplexEnabled] = [this](Msg msg, Capability& data) -> Result {
if (Msg::Set == msg) {
bool mech = data.currentItem();
- return scanner_->twain_set_page_duplex(mech) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_duplex, &mech);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- BYTE dup = scanner_->twain_is_page_duplex();
+ BYTE dup = 1;
+ GET_SANE_OPT(bool, scanner_, ex_duplex, (bool*)&dup, NULL, NULL, NULL);
return CapSupGetAllReset(msg, data, dup, Bool(true));
};
@@ -1376,37 +1585,37 @@ void huagao_ds::init_support_caps(void)
m_query[CapType::IImageFileFormat] = msgSupportGetAllSetReset;
m_caps[CapType::IImageFileFormat] = [this](Msg msg, Capability& data) -> Result {
- CapabilityPrintf(msg, enum2str(CapType::IImageFileFormat), msg == Msg::Set ? to_string((int)data.currentItem()) : "");
- if (Msg::Set == msg) {
- auto mech = data.currentItem();
- SANE_ImageType type = SANE_IMAGE_TYPE_BMP;
- if (mech == ImageFileFormat::Bmp)
- type = SANE_IMAGE_TYPE_BMP;
- else if(mech == ImageFileFormat::Tiff)
- type = SANE_IMAGE_TYPE_TIFF;
- else if(mech == ImageFileFormat::Jfif)
- type = SANE_IMAGE_TYPE_JFIF;
- else
- return badValue();
- return scanner_->twain_set_final_format(type, NULL) == SCANNER_ERR_OK ? success() : badValue();
+ SANE_FinalImgFormat now, init;
+ std::vector all;
+ GET_SANE_OPT(SANE_FinalImgFormat, scanner_, ex_final_format, &now, &init, &all, NULL);
+ if (Msg::Set == msg || Msg::Reset == msg) {
+ if(Msg::Set == msg)
+ init.img_format = (SANE_ImageType)(int)data.currentItem();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_final_format, &init);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- ImageFileFormat fmt = ImageFileFormat::Bmp;
- SANE_ImageType type = scanner_->get_final_format();
- if (type == SANE_IMAGE_TYPE_TIFF)
- fmt = ImageFileFormat::Tiff;
- else if(type == SANE_IMAGE_TYPE_JFIF)
- fmt = ImageFileFormat::Jfif;
- return CapSupGetAllReset < ImageFileFormat, ImageFileFormat, CapType::IImageFileFormat>(msg, data, { ImageFileFormat::Bmp, ImageFileFormat::Tiff,ImageFileFormat::Jfif },
- fmt, ImageFileFormat::Bmp, fmt == ImageFileFormat::Bmp ? 0 : (fmt == ImageFileFormat::Tiff ? 1 : 2), 0);
+ ImageFileFormat Now = (ImageFileFormat)(int)now.img_format, Init = (ImageFileFormat)(int)init.img_format;
+ std::list vals;
+ UInt32 i = 0, n = 0;
+ for (const auto& v : all)
+ vals.push_back((ImageFileFormat)(int)v.img_format);
+ i = std::distance(vals.begin(), std::find(vals.begin(), vals.end(), Init));
+ n = std::distance(vals.begin(), std::find(vals.begin(), vals.end(), Now));
+
+ return cap_get_enum_values(msg, data, vals, Now, Init, n, i);
};
m_query[CapType::IAutomaticDeskew] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticDeskew] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto atuodsw = data.currentItem();
- return scanner_->twain_set_auto_descrew((bool)atuodsw) == SCANNER_ERR_OK ? success() : seqError();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, is_auto_deskew, (bool*)&atuodsw);
+ return ret == SCANNER_ERR_OK ? success() : seqError();
}
- BYTE ato = scanner_->twain_is_auto_descrew();
+ BYTE ato = 1;
+ GET_SANE_OPT(bool, scanner_, is_auto_deskew, (bool*)&ato, NULL, NULL, NULL);
return CapSupGetAllReset(msg, data, ato, true);
};
@@ -1414,16 +1623,24 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem();
- return scanner_->twain_set_text_auto_matic(mech) == SCANNER_ERR_OK ? success() : badValue();
+ float direction = mech ? AUTO_MATIC_ROTATE : .0f;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_text_direction, &direction);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- BYTE am = scanner_->twain_is_text_auto_matic();
+ float direction = .0f;
+ BYTE am = 0;
+ GET_SANE_OPT(float, scanner_, ex_text_direction, &direction, NULL, NULL, NULL);
+ am = IS_DOUBLE_EQUAL(direction, AUTO_MATIC_ROTATE);
return CapSupGetAllReset(msg, data, am, false);
};
m_query[CapType::SerialNumber] = msgSupportGetAll;
m_caps[CapType::SerialNumber] = [this](Msg msg, Capability& data)->Result {
Str255 str;
- scanner_->twain_get_serial_num(str.data());
+ std::string v("");
+ GET_SANE_OPT(std::string, scanner_, ex_serial, &v, NULL, NULL, NULL);
+ strcpy(str.data(), v.c_str());
return CapSupGetAll(msg, data, str, str);
};
@@ -1442,9 +1659,14 @@ void huagao_ds::init_support_caps(void)
CapabilityPrintf(msg, enum2str(CapType::IAutoSize), msg == Msg::Set ? to_string((int)data.currentItem()) : "");
if (Msg::Set == msg) {
auto autosize = data.currentItem();
- return scanner_->twain_set_paper_auto_match_size(autosize == AutoSize::Auto) == SCANNER_ERR_OK ? success() : badValue();
+ bool match = autosize == AutoSize::Auto;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_auto_paper_size, &match);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- UInt16 size = scanner_->twain_is_paper_auto_match_size() ? (UInt16)AutoSize::Auto : (UInt16)AutoSize::None;
+ bool match = true;
+ GET_SANE_OPT(bool, scanner_, ex_auto_paper_size, &match, NULL, NULL, NULL);
+ UInt16 size = match ? (UInt16)AutoSize::Auto : (UInt16)AutoSize::None;
return CapSupGetAllReset(msg, data, { AutoSize::None, AutoSize::Auto }, size, AutoSize::None, (size == (UInt16)AutoSize::Auto) ? 1 : 0, 0);
};
@@ -1452,12 +1674,16 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::IAutomaticBorderDetection] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto autodetectborder = data.currentItem();
- return scanner_->twain_set_erase_black_frame((bool)autodetectborder) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, is_erase_black_frame, (bool*)&autodetectborder);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- bool val = false;
+ bool val = false, cur = false;
Bool init = false,
- erase = scanner_->twain_is_erase_black_frame(&val);
+ erase = false;
+ GET_SANE_OPT(bool, scanner_, is_erase_black_frame, &cur, &val, NULL, NULL);
init = val;
+ erase = cur;
return CapSupGetAllReset(msg, data, { false,true }, erase, init, erase ? 1 : 0, 0);
};
@@ -1465,10 +1691,14 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem();
- return scanner_->twain_set_page_discarding_blank_page(mech == DiscardBlankPages::Auto, false) == SCANNER_ERR_OK ? success() : badValue();
+ bool discard = mech == DiscardBlankPages::Auto;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_discard_blank_page, &discard);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- DiscardBlankPages autodiscradblank = scanner_->twain_is_page_discarding_blank_page(false) ?
- DiscardBlankPages::Auto : DiscardBlankPages::Disabled;
+ bool discard = false;
+ GET_SANE_OPT(bool, scanner_, ex_discard_blank_page, &discard, NULL, NULL, NULL);
+ DiscardBlankPages autodiscradblank = discard ? DiscardBlankPages::Auto : DiscardBlankPages::Disabled;
return CapSupGetAllReset(msg, data, autodiscradblank, DiscardBlankPages::Disabled);
};
@@ -1476,67 +1706,81 @@ void huagao_ds::init_support_caps(void)
m_caps[(CapType)CAP_TYPE_EX_DISCARD_BLANK_RECEIPT] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem();
- return scanner_->twain_set_page_discarding_blank_page(mech == DiscardBlankPages::Auto, true) == SCANNER_ERR_OK ? success() : badValue();
+ bool discard = mech == DiscardBlankPages::Auto;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_discard_blank_receipt, &discard);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- DiscardBlankPages autodiscradblank = scanner_->twain_is_page_discarding_blank_page(true) ?
- DiscardBlankPages::Auto : DiscardBlankPages::Disabled;
+ bool discard = false;
+ GET_SANE_OPT(bool, scanner_, ex_discard_blank_receipt, &discard, NULL, NULL, NULL);
+ DiscardBlankPages autodiscradblank = discard ? DiscardBlankPages::Auto : DiscardBlankPages::Disabled;
return CapSupGetAllResetEx(msg, data, autodiscradblank, DiscardBlankPages::Disabled);
+ // return success();
};
m_query[CapType::IFilter] = msgSupportGetAllSetReset;
m_caps[CapType::IFilter] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem();
- return scanner_->twain_set_filter((int)mech, false) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK, val = to_sane_filter((Filter)mech);
+ SET_SANE_OPT(ret, scanner_, ex_color_filter, &val);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- BYTE f = (BYTE)scanner_->twain_get_filter(false);
- UInt32 ind = 3;
- if (f == (BYTE)Filter::Red)
- ind = 0;
- else if (f == (BYTE)Filter::Green)
- ind = 1;
- else if (f == (BYTE)Filter::Blue)
- ind = 2;
- return CapSupGetAllReset(msg, data, { Filter::Red, Filter::Green,Filter::Blue,Filter::None }, f, Filter::None, ind, 3);
- };
+ int cur = FILTER_NONE, def = FILTER_NONE;
+ std::vector vals;
+ GET_SANE_OPT(int, scanner_, ex_color_filter, &cur, &def, &vals, NULL);
- m_query[(CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR] = msgSupportGetAllSetReset;
- m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR] = [this](Msg msg, Capability& data)->Result {
- if (Msg::Set == msg) {
- auto mech = data.currentItem();
- return scanner_->twain_set_filter((int)mech, true) == SCANNER_ERR_OK ? success() : badValue();
+ std::list vs;
+ Filter now = Filter::None, init = Filter::None;
+ UInt32 curInd = 0, defInd = 0, ind = 0;
+
+ for (auto& v : vals)
+ {
+ vs.push_back(from_sane_filter(v));
+ if (v == cur)
+ {
+ curInd = ind;
+ now = from_sane_filter(v);
+ }
+ else if (v == def)
+ {
+ defInd = ind;
+ init = from_sane_filter(v);
+ }
+ ind++;
}
- BYTE f = (BYTE)scanner_->twain_get_filter(true);
- UInt32 ind = 3;
- if (f == ENHANCE_COLOR_RED)
- ind = 0;
- else if (f == ENHANCE_COLOR_GREEN)
- ind = 1;
- else if (f == ENHANCE_COLOR_BLUE)
- ind = 2;
- return CapSupGetAllResetEx(msg, data, { Filter::Red, Filter::Green,Filter::Blue,Filter::None }, f, Filter::None, ind, 3);
+ BYTE f = (BYTE)now;
+ return CapSupGetAllReset(msg, data, vs, f, init, curInd, defInd);
};
m_query[CapType::IBrightness] = msgSupportGetAllSetReset;
m_caps[CapType::IBrightness] = [this](Msg msg, Capability& data)->Result {
- double init = .0f, l = .0f, u = .0f, step = .0f,
- now = scanner_->twain_get_bright(&init, &l, &u, &step);
+ int init = 128, l = 1, u = 255, step = 1, now = 128;
+ int ret = SCANNER_ERR_OK;
+ GET_SANE_OPT_RANGE(int, scanner_, bright, &now, &init, &l, &u, &step);
+ float sf = trans_range(step, l, u, -1000.0f, 1000.0f),
+ nf = trans_range(now, l, u, -1000.0f, 1000.0f),
+ initf = trans_range(init, l, u, -1000.0f, 1000.0f);
switch (msg) {
case Msg::Get:
- data = Capability::createRange(Fix32(l), Fix32(u), Fix32(step), Fix32(now), Fix32(init));
+ data = Capability::createRange(Fix32(-1000.0f), Fix32(1000.0f), Fix32(sf), Fix32(nf), Fix32(initf));
return success();
case Msg::GetCurrent:
- data = Capability::createOneValue(Fix32(now));
+ data = Capability::createOneValue(Fix32(nf));
return success();
case Msg::GetDefault:
- case Msg::Reset:
- data = Capability::createOneValue(Fix32(init));
+ data = Capability::createOneValue(Fix32(initf));
return success();
+ case Msg::Reset:
+ data = Capability::createOneValue(Fix32(initf));
case Msg::Set: {
auto mech = data.currentItem();
- if (mech > u || mech < -l)
+ if (mech > 1000.0f || mech < -1000.0f)
return badValue();
- return scanner_->twain_set_bright(mech.toFloat()) == SCANNER_ERR_OK ? success() : badValue();
+ sf = mech.toFloat();
+ now = trans_range(sf, -1000.0f, 1000.0f, l, u) + .5f;
+ SET_SANE_OPT(ret, scanner_, bright, &now);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
default:
return capBadOperation();
@@ -1545,24 +1789,68 @@ void huagao_ds::init_support_caps(void)
m_query[CapType::IContrast] = msgSupportGetAllSetReset;
m_caps[CapType::IContrast] = [this](Msg msg, Capability& data)->Result {
- double init = .0f, l = .0f, u = .0f, step = .0f,
- now = scanner_->twain_get_contrast(&init, &l, &u, &step);
+ int init = 4, l = 1, u = 7, step = 1, now = 4;
+ int ret = SCANNER_ERR_OK;
+ GET_SANE_OPT_RANGE(int, scanner_, contrast, &now, &init, &l, &u, &step);
+ float sf = trans_range(step, l, u, -1000.0f, 1000.0f),
+ nf = trans_range(now, l, u, -1000.0f, 1000.0f),
+ initf = trans_range(init, l, u, -1000.0f, 1000.0f);
switch (msg) {
case Msg::Get:
- data = Capability::createRange(Fix32(l), Fix32(u), Fix32(step), Fix32(now), Fix32(init));
+ data = Capability::createRange(Fix32(-1000.0f), Fix32(1000.0f), Fix32(sf), Fix32(nf), Fix32(initf));
return success();
case Msg::GetCurrent:
- data = Capability::createOneValue(Fix32(now));
+ data = Capability::createOneValue(Fix32(nf));
return success();
case Msg::GetDefault:
- case Msg::Reset:
- data = Capability::createOneValue(Fix32(init));
+ data = Capability::createOneValue(Fix32(initf));
return success();
+ case Msg::Reset:
+ data = Capability::createOneValue(Fix32(initf));
case Msg::Set: {
auto mech = data.currentItem();
- if (mech > u || mech < -l)
+ if (mech > 1000.0f || mech < -1000.0f)
return badValue();
- return scanner_->twain_set_contrast(mech.toFloat()) == SCANNER_ERR_OK ? success() : badValue();
+ sf = mech.toFloat();
+ now = trans_range(sf, -1000.0f, 1000.0f, l, u) + .5f;
+ SET_SANE_OPT(ret, scanner_, contrast, &now);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
+ }
+ default:
+ return capBadOperation();
+ }
+ };
+
+ m_query[(CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO] = msgSupportGetAllSetReset;
+ m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO] = [this](Msg msg, Capability& data)->Result {
+ float init = .0f, l = .0f, u = .0f, step = .0f, now = .0f;
+ int ret = SCANNER_ERR_OK;
+ GET_SANE_OPT_RANGE(float, scanner_, search_hole_range, &now, &init, &l, &u, &step);
+ init *= 100; init += .5f;
+ l *= 100; l += .5f;
+ u *= 100; u += .5f;
+ step *= 100; step += .5f;
+ now *= 100; now += .5f;
+ switch (msg) {
+ case Msg::Get:
+ data = Capability::createRange((CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO, UInt32(l), UInt32(u), UInt32(step), UInt32(now), UInt32(init));
+ return success();
+ case Msg::GetCurrent:
+ data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO, UInt32(now));
+ return success();
+ case Msg::GetDefault:
+ data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO, UInt32(init));
+ return success();
+ case Msg::Reset:
+ data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO, UInt32(init));
+ case Msg::Set: {
+ auto mech = data.currentItem();
+ if (mech > u || mech < l)
+ return badValue();
+ float v = mech;
+ v /= 100.0f;
+ SET_SANE_OPT(ret, scanner_, search_hole_range, &v);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
default:
return capBadOperation();
@@ -1571,8 +1859,9 @@ void huagao_ds::init_support_caps(void)
m_query[CapType::IGamma] = msgSupportGetAllSetReset;
m_caps[CapType::IGamma] = [this](Msg msg, Capability& data)->Result {
- double init = .0f, l = .0f, u = .0f, step = .0f,
- now = scanner_->twain_get_gamma(&init, &l, &u, &step);
+ float init = .0f, l = .0f, u = .0f, step = .0f, now = .0f;
+ int ret = SCANNER_ERR_OK;
+ GET_SANE_OPT_RANGE(float, scanner_, gamma, &now, &init, &l, &u, &step);
switch (msg) {
case Msg::Get:
data = Capability::createRange(Fix32(l), Fix32(u), Fix32(step), Fix32(now), Fix32(init));
@@ -1588,7 +1877,9 @@ void huagao_ds::init_support_caps(void)
auto mech = data.currentItem();
if (mech > u || mech < l)
return badValue();
- return scanner_->twain_set_gamma(mech.toFloat()) == SCANNER_ERR_OK ? success() : badValue();
+ now = mech.toFloat();
+ SET_SANE_OPT(ret, scanner_, gamma, &now);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
default:
return capBadOperation();
@@ -1604,22 +1895,30 @@ void huagao_ds::init_support_caps(void)
m_caps[CapType::DoubleFeedDetection] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto atuodsw = data.currentItem();
- return scanner_->twain_set_ultrasonic_check((bool)atuodsw) == SCANNER_ERR_OK ? success() : seqError();
+ int ret = SCANNER_ERR_OK;
+ bool enable = atuodsw == DoubleFeedDetection::Ultrasonic;
+ SET_SANE_OPT(ret, scanner_, is_ultrasonic_check, &enable);
+ return ret == SCANNER_ERR_OK ? success() : seqError();
}
DoubleFeedDetection init = DoubleFeedDetection::Ultrasonic;
- BYTE ato = scanner_->twain_is_ultrasonic_check();
+ bool enable = true, def = true;
+ GET_SANE_OPT(bool, scanner_, is_ultrasonic_check, &enable, &def, NULL, NULL);
+ BYTE ato = !enable;
+ init = def ? DoubleFeedDetection::Ultrasonic : DoubleFeedDetection::ByLength;
return CapSupGetAllReset(msg, data, ato, init);
};
m_query[CapType::IAutomaticCropUsesFrame] = msgSupportGetAll;
m_caps[CapType::IAutomaticCropUsesFrame] = [this](Msg msg, Capability& data)->Result {
- BYTE crop = scanner_->twain_is_auto_crop();
+ bool yes = false;
+ GET_SANE_OPT(bool, scanner_, ex_is_paper_auto_crop, &yes, NULL, NULL, NULL);
+ BYTE crop = yes;
return CapSupGetAll(msg, data, crop, false);
};
m_query[CapType::FeederLoaded] = msgSupportGetAll;
m_caps[CapType::FeederLoaded] = [this](Msg msg, Capability& data) -> Result {
- Bool paperon = scanner_->twain_is_paper_on();
+ Bool paperon = scanner_->is_paper_on();
return CapSupGetAll(msg, data, paperon, paperon);
};
@@ -1639,59 +1938,76 @@ void huagao_ds::init_support_caps(void)
auto fold = data.currentItem();
if (msg == Msg::Reset)
fold = false;
- return scanner_->twain_set_page_fold(fold) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_is_page_fold, &fold);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- BYTE fold = scanner_->twain_is_page_fold();
+ bool yes = false;
+ GET_SANE_OPT(bool, scanner_, ex_is_page_fold, &yes, NULL, NULL, NULL);
+ BYTE fold = yes;
return CapSupGetAllResetEx(msg, data, fold, 0);
};
- m_query[(CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN] = msgSupportGetAllSetReset;
- m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN] = [this](Msg msg, Capability& data)->Result {
- if (Msg::Set == msg) {
- auto mech = data.currentItem();
- return scanner_->twain_set_sharpen((int)mech) == SCANNER_ERR_OK ? success() : badValue();
- }
- BYTE f = (BYTE)scanner_->twain_get_sharpen();
- return CapSupGetAllResetEx(msg, data, { 0, 1, 2, 3, 4}, f, 0, f, 0);
- };
-
m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_DOGEAR_DIST)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_DOGEAR_DIST)] = [this](Msg msg, Capability& data)->Result {
- if (Msg::Set == msg) {
+ int now = 10, init = 10, l = 0, u = 100, s = 10;
+ GET_SANE_OPT_RANGE(int, scanner_, dogear_size, &now, &init, &l, &u, &s);
+ if (Msg::Set == msg || Msg::Reset == msg) {
auto mech = data.currentItem();
if (mech < 10 || mech > 300)
return badValue();
- return scanner_->twain_set_dogear_distance(mech) == SCANNER_ERR_OK ? success() : badValue();
+ int ret = SCANNER_ERR_OK;
+ int val = trans_range(mech, 10, 300, l, u) + .5f;
+ SET_SANE_OPT(ret, scanner_, dogear_size, &val);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- UInt32 init = 50,
- now = scanner_->twain_get_dogear_distance();
+ UInt32 Now = trans_range(now, l, u, 10, 300) + .5f,
+ Init = trans_range(init, l, u, 10, 300) + .5f;
- return CapSupGetAllResetEx(msg, data, now, init);
+ return CapSupGetAllResetEx(msg, data, Now, Init);
};
- m_query[CapType(CapTypeEx::CAP_TYPE_EX_MULTI_OUT)] = msgSupportGetAllSetReset;
- m_caps[CapType(CapTypeEx::CAP_TYPE_EX_MULTI_OUT)] = [this](Msg msg, Capability& data)->Result {
- if (Msg::Set == msg || Msg::Reset == msg) {
- auto multi = data.currentItem();
- if (msg == Msg::Reset)
- multi = false;
- multi_out_ = multi;
- return success();
+ m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_CROP_MODEL)] = msgSupportGetAllSetReset;
+ m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_CROP_MODEL)] = [this](Msg msg, Capability& data)->Result {
+ bool cur = false, def = false;
+ GET_SANE_OPT(bool, scanner_, ex_is_paper_auto_crop, &cur, &def, NULL, NULL);
+ if (Msg::Set == msg || Msg::Reset == msg)
+ {
+ if (Msg::Set == msg)
+ def = data.currentItem() == 1;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_is_paper_auto_crop, &def);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- BYTE multi = multi_out_;
- return CapSupGetAllResetEx(msg, data, multi, 0);
+ BYTE crop = cur;
+ return CapSupGetAll(msg, data, crop, def);
};
m_query[(CapType)CapTypeEx::CAP_TYPE_EX_MULTI_OUT_TYPE] = msgSupportGetAllSetReset;
m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_MULTI_OUT_TYPE] = [this](Msg msg, Capability& data)->Result {
+ int cur = MULTI_OUT_NONE, def = MULTI_OUT_NONE;
+ std::vector all;
+ GET_SANE_OPT(int, scanner_, ex_multiout_type, &cur, &def, &all, NULL);
if (Msg::Set == msg || Msg::Reset == msg) {
auto mech = data.currentItem();
if (msg == Msg::Reset)
- mech = -1;
- return scanner_->twain_set_multioutput_type((int)mech) == SCANNER_ERR_OK ? success() : badValue();
+ mech = def;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_multiout_type, &mech);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- UInt32 f = (UInt32)scanner_->twain_get_multioutput_type();
- return CapSupGetAllResetEx(msg, data, { (UInt32)-1, 0, 1, 2, 3 }, f, -1, 0, 0);
+ Int32 now = cur, init = def, ind = 0, curInd = 0, defInd = 0;
+ std::list vals;
+ for (auto& v : all)
+ {
+ vals.push_back(v);
+ if (v == cur)
+ curInd = ind;
+ else if (v == def)
+ defInd = ind;
+ ind++;
+ }
+ return CapSupGetAllResetEx(msg, data, vals, now, init, curInd, defInd);
};
m_query[CapType(CapTypeEx::CAP_TYPE_EX_TO_BE_SCAN)] = msgSupportGetAllSetReset;
@@ -1700,9 +2016,13 @@ void huagao_ds::init_support_caps(void)
auto tobe = data.currentItem();
if (msg == Msg::Reset)
tobe = false;
- return scanner_->twain_set_to_be_scan(tobe) == SCANNER_ERR_OK ? success() : seqError();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_to_be_scan, &tobe);
+ return ret == SCANNER_ERR_OK ? success() : seqError();
}
- BYTE tobe = scanner_->twain_get_to_be_scan();
+ bool val = false;
+ GET_SANE_OPT(bool, scanner_, ex_to_be_scan, &val, NULL, NULL, NULL);
+ BYTE tobe = val;
return CapSupGetAllResetEx(msg, data, tobe, 0);
};
@@ -1712,61 +2032,155 @@ void huagao_ds::init_support_caps(void)
auto tobe = data.currentItem();
if (msg == Msg::Reset)
tobe = false;
- return scanner_->twain_set_scan_with_hole(tobe) == SCANNER_ERR_OK ? success() : seqError();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_scan_with_hole, &tobe);
+ return ret == SCANNER_ERR_OK ? success() : seqError();
}
- BYTE tobe = scanner_->twain_get_scan_with_hole();
+ bool val = false;
+ GET_SANE_OPT(bool, scanner_, ex_scan_with_hole, &val, NULL, NULL, NULL);
+ BYTE tobe = val;
return CapSupGetAllResetEx(msg, data, tobe, 0);
};
- char code[256] = { 0 };
- unsigned int len = _countof(code);
- if (scanner_->twain_get_device_code(code, len) == SCANNER_ERR_OK)
- {
- m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_ENCODE)] = msgSupportGetAll;
- m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_ENCODE)] = [this](Msg msg, Capability& data)->Result {
- char code[256] = { 0 };
- unsigned int len = _countof(code);
- Str255 str;
- scanner_->twain_get_device_code(code, len);
- str.setData(code, 32);
- data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_ENCODE, str);
- return success();
- };
- }
+ m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_ENCODE)] = msgSupportGetAll;
+ m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_ENCODE)] = [this](Msg msg, Capability& data)->Result {
+ std::string code("");
+ GET_SANE_OPT(std::string, scanner_, ex_device_code, &code, NULL, NULL, NULL);
+ Str255 str;
+ str.setData(code.c_str(), 32);
+ data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_ENCODE, str);
+ return success();
+ };
m_query[(CapType)(CapTypeEx::CAP_TYPE_EX_POWER_LEVEL)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::CAP_TYPE_EX_POWER_LEVEL)] = [this](Msg msg, Capability& data)->Result {
- UInt32 init = 4;
+ int cur = SANE_POWER_MINUTES_30, def = SANE_POWER_MINUTES_30;
+ std::vector all;
+ GET_SANE_OPT(int, scanner_, ex_power, &cur, &def, &all, NULL);
if (Msg::Set == msg || Msg::Reset == msg) {
if(msg == Msg::Set)
- init = data.currentItem();
- scanner_->twain_set_power_level(init);
- return success();
+ def = data.currentItem();
+
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_power, &def);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
}
- UInt32 level = scanner_->twain_get_power_level();
- return CapSupGetAllResetEx(msg, data, level, init);
+ UInt32 now = cur, init = def, ind = 0, curInd = 0, defInd = 0;
+ std::list vals;
+ for (auto& v : all)
+ {
+ vals.push_back(v);
+ if (v == cur)
+ curInd = ind;
+ else if (v == def)
+ defInd = ind;
+ ind++;
+ }
+ return CapSupGetAllResetEx(msg, data, vals, now, init, curInd, defInd);
+ };
+
+ m_query[(CapType)CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD] = msgSupportGetAllSetReset;
+ m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD] = [this](Msg msg, Capability& data)->Result {
+ if (Msg::Set == msg) {
+ auto convex = data.currentItem();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_fill_background, (bool*)&convex);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
+ }
+ bool val = false, cur = false;
+ Bool init = false,
+ erase = false;
+ GET_SANE_OPT(bool, scanner_, ex_fill_background, &cur, &val, NULL, NULL);
+ init = val;
+ erase = cur;
+ return CapSupGetAllResetEx(msg, data, { false,true }, erase, init, erase ? 1 : 0, 0);
+ };
+
+ m_query[(CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN] = msgSupportGetAllSetReset;
+ m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN] = [this](Msg msg, Capability& data)->Result {
+ int cur = MULTI_OUT_NONE, def = MULTI_OUT_NONE;
+ std::vector all;
+ GET_SANE_OPT(int, scanner_, ex_sharpen, &cur, &def, &all, NULL);
+ if (Msg::Set == msg || Msg::Reset == msg) {
+ auto mech = data.currentItem();
+ if (msg == Msg::Reset)
+ mech = def;
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_sharpen, &mech);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
+ }
+ Int32 now = cur, init = def, ind = 0, curInd = 0, defInd = 0;
+ std::list vals;
+ for (auto& v : all)
+ {
+ vals.push_back(v);
+ if (v == cur)
+ curInd = ind;
+ else if (v == def)
+ defInd = ind;
+ ind++;
+ }
+ return CapSupGetAllResetEx(msg, data, vals, now, init, curInd, defInd);
+ };
+ //SET_EXISTING_EXTENSION(ex_color_enhance, (CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR);
+ m_query[(CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR] = msgSupportGetAllSetReset;
+ m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR] = [this](Msg msg, Capability& data)->Result {
+ int cur = FILTER_NONE, def = FILTER_NONE;
+ std::vector vals;
+ GET_SANE_OPT(int, scanner_, ex_color_enhance, &cur, &def, &vals, NULL);
+ if (Msg::Set == msg || Msg::Reset == msg) {
+ if(Msg::Set == msg)
+ def = data.currentItem();
+ int ret = SCANNER_ERR_OK;
+ SET_SANE_OPT(ret, scanner_, ex_color_filter, &def);
+ return ret == SCANNER_ERR_OK ? success() : badValue();
+ }
+
+ std::list vs;
+ Filter now = from_sane_filter(cur), init = from_sane_filter(def);
+ UInt32 curInd = 0, defInd = 0, ind = 0;
+
+ for (auto& v : vals)
+ {
+ vs.push_back(from_sane_filter(v));
+ if (v == cur)
+ {
+ curInd = ind;
+ }
+ else if (v == def)
+ {
+ defInd = ind;
+ }
+ ind++;
+ }
+ UInt32 val = (UInt32)now;
+ return CapSupGetAllResetEx(msg, data, vs, val, init, curInd, defInd);
};
init_support_caps_ex();
m_query[(CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION] = msgSupportGetAll;
m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION] = [this](Msg msg, Capability& data)->Result {
+ std::string ver("");
+ GET_SANE_OPT(std::string, scanner_, ex_hardware_version, &ver, NULL, NULL, NULL);
Str255 str;
- scanner_->twain_get_hareware_version(str.data());
+ strcpy(str.data(), ver.c_str());
data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_HARDWARE_VERSION, str);
- return success(); // CapSupGetAllEx(msg, data, str, str);
+ return success();
};
m_query[(CapType)CapTypeEx::CAP_TYPE_EX_IP] = msgSupportGetAll;
m_caps[(CapType)CapTypeEx::CAP_TYPE_EX_IP] = [this](Msg msg, Capability& data)->Result {
+ std::string ip("");
+ GET_SANE_OPT(std::string, scanner_, ex_ip, &ip, NULL, NULL, NULL);
Str255 str;
- scanner_->twain_get_ip(str.data());
+ strcpy(str.data(), ip.c_str());
data = Capability::createOneValue((CapType)CapTypeEx::CAP_TYPE_EX_IP, str);
return success(); // CapSupGetAll(msg, data, str, str);
};
#define SET_EXISTING_EXTENSION(scan_ind, cap) \
- op_ind = scanner_->##scan_ind(); \
+ op_ind = scanner_->sane_opt_id_##scan_ind();\
if(op_ind != -1) \
{ \
m_query[(CapType)cap] = msgSupportGetAllSetReset; \
@@ -1774,29 +2188,32 @@ void huagao_ds::init_support_caps(void)
}
int op_ind = -1;
- SET_EXISTING_EXTENSION(twain_get_paper_ind, CapType::ISupportedSizes);
- SET_EXISTING_EXTENSION(twain_get_flip_ind, CapTypeEx::CAP_TYPE_EX_FLIP);
- SET_EXISTING_EXTENSION(twain_get_rotate_bkg_ind, CapTypeEx::CAP_TYPE_EX_ROTATE_BKG_180);
- SET_EXISTING_EXTENSION(twain_get_fill_black_bkg_ind, CapTypeEx::CAP_TYPE_EX_FILL_BLACK_BKG);
- SET_EXISTING_EXTENSION(twain_get_edge_ident_ind, CapTypeEx::CAP_TYPE_EX_EDGE_IDENT);
- SET_EXISTING_EXTENSION(twain_get_threshold_ind, CapTypeEx::CAP_TYPE_EX_THRESHOLD);
- SET_EXISTING_EXTENSION(twain_get_threshold_ind, CapTypeEx::CAP_TYPE_EX_THRESHOLD_1);
- SET_EXISTING_EXTENSION(twain_bkg_filling_method_ind, CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD);
- SET_EXISTING_EXTENSION(twain_fill_hole_ind, CapTypeEx::CAP_TYPE_EX_FILL_HOLE);
- SET_EXISTING_EXTENSION(twain_fill_hole_ratio_ind, CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO);
- SET_EXISTING_EXTENSION(twain_detach_noise_ind, CapTypeEx::CAP_TYPE_EX_DETACH_NOISE);
- SET_EXISTING_EXTENSION(twain_detach_noise_threshold_ind, CapTypeEx::CAP_TYPE_EX_DETACH_NOISE_THRESHOLD);
- SET_EXISTING_EXTENSION(twain_rid_red_ind, CapTypeEx::CAP_TYPE_EX_RID_RED);
- SET_EXISTING_EXTENSION(twain_rid_red_hsv_ind, CapTypeEx::CAP_TYPE_EX_RID_RED_HSV);
- SET_EXISTING_EXTENSION(twain_screw_detect_ind, CapTypeEx::CAP_TYPE_EX_SCREW_DETECT);
- SET_EXISTING_EXTENSION(twain_screw_detect_level_ind, CapTypeEx::CAP_TYPE_EX_SCREW_DETECT_LEVEL);
- SET_EXISTING_EXTENSION(twain_staple_detect_ind, CapTypeEx::CAP_TYPE_EX_STAPLE_DETECT);
- SET_EXISTING_EXTENSION(twain_dogear_detect_ind, CapTypeEx::CAP_TYPE_EX_DOGEAR_DETECT);
- SET_EXISTING_EXTENSION(twain_dark_sample_ind, CapTypeEx::CAP_TYPE_EX_DARK_SAMPLE);
- SET_EXISTING_EXTENSION(twain_image_split_ind, CapTypeEx::CAP_TYPE_EX_IMAGE_SPLIT);
- SET_EXISTING_EXTENSION(twain_fade_bkground_ind, CapTypeEx::CAP_TYPE_EX_FADE_BKG);
- SET_EXISTING_EXTENSION(twain_fade_bkground_val_ind, CapTypeEx::CAP_TYPE_EX_FADE_BKG_VALUE);
- SET_EXISTING_EXTENSION(twain_size_detect_ind, CapTypeEx::CAP_TYPE_EX_SIZE_DETECT);
+ // SET_EXISTING_EXTENSION(paper, CapType::ISupportedSizes);
+ SET_EXISTING_EXTENSION(is_swap, CapTypeEx::CAP_TYPE_EX_FLIP);
+ SET_EXISTING_EXTENSION(is_rotate_bkg180, CapTypeEx::CAP_TYPE_EX_ROTATE_BKG_180);
+ SET_EXISTING_EXTENSION(is_filling_color, CapTypeEx::CAP_TYPE_EX_FILL_BLACK_BKG);
+ SET_EXISTING_EXTENSION(margin, CapTypeEx::CAP_TYPE_EX_EDGE_IDENT);
+ SET_EXISTING_EXTENSION(anti_noise, CapTypeEx::CAP_TYPE_EX_ANTI_NOISE);
+ SET_EXISTING_EXTENSION(threshold, CapTypeEx::CAP_TYPE_EX_THRESHOLD);
+ SET_EXISTING_EXTENSION(is_erase_hole, CapTypeEx::CAP_TYPE_EX_FILL_HOLE);
+ //SET_EXISTING_EXTENSION(ex_fill_background, CapTypeEx::CAP_TYPE_EX_BKG_FILLING_METHOD);
+ //SET_EXISTING_EXTENSION(ex_sharpen, (CapType)CapTypeEx::CAP_TYPE_EX_SHARPEN);
+ //SET_EXISTING_EXTENSION(ex_color_enhance, (CapType)CapTypeEx::CAP_TYPE_EX_ENHANCE_COLOR);
+ //SET_EXISTING_EXTENSION(search_hole_range, CapTypeEx::CAP_TYPE_EX_FILL_HOLE_RATIO);
+ SET_EXISTING_EXTENSION(is_noise_modify, CapTypeEx::CAP_TYPE_EX_DETACH_NOISE);
+ SET_EXISTING_EXTENSION(noise_threshold, CapTypeEx::CAP_TYPE_EX_DETACH_NOISE_THRESHOLD);
+ SET_EXISTING_EXTENSION(erase_multiout_red, CapTypeEx::CAP_TYPE_EX_RID_RED);
+ SET_EXISTING_EXTENSION(erase_paper_red, CapTypeEx::CAP_TYPE_EX_RID_RED_HSV);
+ SET_EXISTING_EXTENSION(is_check_skew, CapTypeEx::CAP_TYPE_EX_SCREW_DETECT);
+ SET_EXISTING_EXTENSION(skew_range, CapTypeEx::CAP_TYPE_EX_SCREW_DETECT_LEVEL);
+ SET_EXISTING_EXTENSION(is_check_staple, CapTypeEx::CAP_TYPE_EX_STAPLE_DETECT);
+ SET_EXISTING_EXTENSION(is_check_dogear, CapTypeEx::CAP_TYPE_EX_DOGEAR_DETECT);
+ SET_EXISTING_EXTENSION(deep_sample, CapTypeEx::CAP_TYPE_EX_DARK_SAMPLE);
+ SET_EXISTING_EXTENSION(is_split, CapTypeEx::CAP_TYPE_EX_IMAGE_SPLIT);
+ SET_EXISTING_EXTENSION(is_erase_background, CapTypeEx::CAP_TYPE_EX_FADE_BKG);
+ SET_EXISTING_EXTENSION(background_color_range, CapTypeEx::CAP_TYPE_EX_FADE_BKG_VALUE);
+ SET_EXISTING_EXTENSION(is_size_check, CapTypeEx::CAP_TYPE_EX_SIZE_DETECT);
+ SET_EXISTING_EXTENSION(is_multiout, CapTypeEx::CAP_TYPE_EX_MULTI_OUT);
}
void huagao_ds::init_support_caps_ex(void)
{
@@ -1805,17 +2222,21 @@ void huagao_ds::init_support_caps_ex(void)
m_caps[(CapType)cap] = [this](Msg msg, Capability& data) -> Result { \
if (!scanner_.get()) \
return seqError(); \
- if(msg == Msg::Set) { \
- ctype item; \
- copy_type(item, data.currentItem