2023-07-10 07:28:45 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// For: interface definition for SANE to TWAIN
|
|
|
|
|
//
|
|
|
|
|
// Date: 2022-06-08
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include <sane/sane_ex.h>
|
|
|
|
|
#include <huagao/hgscanner_error.h>
|
|
|
|
|
#include <string>
|
2023-09-21 03:23:38 +00:00
|
|
|
|
#include <vector>
|
|
|
|
|
#include <list>
|
2023-07-10 07:28:45 +00:00
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define COM_API_DECLARE(ret, decl) virtual ret decl = 0
|
|
|
|
|
#define COM_API_DECLARE_NON_PURE(ret, decl) virtual ret decl
|
|
|
|
|
#define COM_API_OVERRIDE(ret, decl) virtual ret decl override
|
|
|
|
|
#define COM_API_IMPLEMENT(cls, ret, decl) ret 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 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 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, //
|
|
|
|
|
|
|
|
|
|
VAL_LIMIT_MASK = 0x0ff,
|
|
|
|
|
VAL_LIMIT_READONLY = 0x100,
|
|
|
|
|
};
|
|
|
|
|
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_STREAM, // uint8_t[], must give array length
|
|
|
|
|
VAL_TYPE_BUTTON, // a button
|
|
|
|
|
};
|
|
|
|
|
enum color_value // 除最后一项外,其余与Twpp::PixelType值保持一致
|
|
|
|
|
{
|
|
|
|
|
COLOR_BW = 0,
|
|
|
|
|
COLOR_GRAY,
|
|
|
|
|
COLOR_RGB,
|
|
|
|
|
COLOR_AUTO_MATCH = TWPT_AUTOMATIC_COLOR,
|
|
|
|
|
};
|
|
|
|
|
enum paper_value // 与Twpp::PaperSize保持一致
|
|
|
|
|
{
|
|
|
|
|
PAPER_A4 = 1,
|
|
|
|
|
PAPER_16K = 1,
|
|
|
|
|
PAPER_LETTER = 3,
|
|
|
|
|
PAPER_LEGAL = 4,
|
|
|
|
|
PAPER_A5 = 5,
|
|
|
|
|
PAPER_B4 = 6,
|
|
|
|
|
PAPER_B6 = 7,
|
|
|
|
|
PAPER_A3 = 11,
|
|
|
|
|
PAPER_8K = 11,
|
|
|
|
|
PAPER_A6 = 13,
|
|
|
|
|
PAPER_B5 = 29,
|
|
|
|
|
PAPER_STATEMENT = 52, // 匹配原始尺寸
|
|
|
|
|
PAPER_MAXSIZE = 54, // 最大扫描尺寸
|
|
|
|
|
|
|
|
|
|
// 以下为未匹配选项
|
|
|
|
|
PAPER_DOUBLE_LETTER = 103,
|
|
|
|
|
PAPER_MAXSIZE_CROP = 154, // 最大扫描尺寸自动裁切
|
|
|
|
|
PAPER_TRIPPLE = 111, // 三联试卷
|
|
|
|
|
};
|
|
|
|
|
enum filter_value // 除色选项
|
|
|
|
|
{
|
|
|
|
|
FILTER_NONE = 0,
|
|
|
|
|
FILTER_RED,
|
|
|
|
|
FILTER_GREEN,
|
|
|
|
|
FILTER_BLUE,
|
|
|
|
|
};
|
|
|
|
|
enum enhance_value // 颜色增强选项
|
|
|
|
|
{
|
|
|
|
|
ENHANCE_NONE = 0,
|
|
|
|
|
ENHANCE_RED,
|
|
|
|
|
ENHANCE_GREEN,
|
|
|
|
|
ENHANCE_BLUE,
|
|
|
|
|
};
|
|
|
|
|
enum sharpen_value
|
|
|
|
|
{
|
|
|
|
|
SHARPEN_NONE = 0,
|
|
|
|
|
SHARPEN_SHARPEN,
|
|
|
|
|
SHARPEN_SHARPEN_MORE,
|
|
|
|
|
SHARPEN_BLUR,
|
|
|
|
|
SHARPEN_BLUR_MORE,
|
|
|
|
|
};
|
|
|
|
|
enum multiout_value
|
|
|
|
|
{
|
|
|
|
|
MULTI_OUT_NONE = -1,
|
|
|
|
|
MULTI_OUT_ALL,
|
|
|
|
|
MULTI_OUT_COLOR_GRAY,
|
|
|
|
|
MULTI_OUT_COLOR_BW,
|
|
|
|
|
MULTI_OUT_GRAY_BW,
|
|
|
|
|
};
|
|
|
|
|
enum twain_xfer
|
|
|
|
|
{
|
|
|
|
|
TWAIN_XFER_Native = 0, // BITMAPINFOHEADER + bits
|
|
|
|
|
TWAIN_XFER_File = 1, // BITMAPFILEHEADER + TWAIN_XFER_Native
|
|
|
|
|
TWAIN_XFER_Memory = 2, // to be implementing ...
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-21 03:23:38 +00:00
|
|
|
|
typedef bool(*set_opt_value)(void* val, value_role role, value_limit limit, void* param);
|
2023-07-10 07:28:45 +00:00
|
|
|
|
class IRef
|
|
|
|
|
{
|
|
|
|
|
public:
|
2023-10-20 07:21:17 +00:00
|
|
|
|
COM_API_DECLARE(int32_t, add_ref(void));
|
|
|
|
|
COM_API_DECLARE(int32_t, release(void));
|
2023-07-10 07:28:45 +00:00
|
|
|
|
};
|
|
|
|
|
class IScanImg : public IRef // 为兼容TWAIN传输方式,位图全部转换为完整的位图文件内容,TWAIN协议层在获取数据时,根据不同传输方式跳过对应的文件头即可 - 2023-07-03
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
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(int, dpi(void));
|
|
|
|
|
COM_API_DECLARE(SANE_Frame, type(void));
|
|
|
|
|
COM_API_DECLARE(unsigned int, bytes(void));
|
|
|
|
|
COM_API_DECLARE(unsigned int, header_size(void));
|
|
|
|
|
COM_API_DECLARE(unsigned char*, data(unsigned long long off, unsigned int *bytes));
|
|
|
|
|
COM_API_DECLARE(int, read(void* buf, size_t* bytes, unsigned long long off = 0));
|
|
|
|
|
COM_API_DECLARE(const char*, file(void));
|
|
|
|
|
COM_API_DECLARE(void, keep_file(bool keep));
|
|
|
|
|
COM_API_DECLARE(void, copy_header(SANE_Parameters* head));
|
|
|
|
|
COM_API_DECLARE(int, image_status(void));
|
|
|
|
|
COM_API_DECLARE(size_t, get_bits_offset(void));
|
|
|
|
|
};
|
|
|
|
|
class ISaneInvoker : public IRef
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
COM_API_DECLARE(int, start(void));
|
|
|
|
|
COM_API_DECLARE(int, stop(void));
|
|
|
|
|
COM_API_DECLARE(int, get_event(void));
|
|
|
|
|
COM_API_DECLARE(void, set_event_callback(int(* handle_ev)(int, void*) = nullptr, void* para = nullptr));
|
|
|
|
|
COM_API_DECLARE(bool, wait_image(DWORD milliseconds = -1));
|
|
|
|
|
COM_API_DECLARE(int, get_scanned_images(DWORD milliseconds = 0));
|
|
|
|
|
COM_API_DECLARE(IScanImg*, take_first_image(twain_xfer xfer = TWAIN_XFER_Native)); // call 'release' on returned value, plz
|
|
|
|
|
COM_API_DECLARE(bool, get_first_image_header(SANE_Parameters* header, size_t* bytes = nullptr, int *dpi = nullptr));
|
2023-08-04 05:13:36 +00:00
|
|
|
|
COM_API_DECLARE(bool, discard_first_image(void));
|
2023-09-21 03:23:38 +00:00
|
|
|
|
COM_API_DECLARE(int, convert_image(SANE_ImageFormatConvert* conv));
|
2023-07-10 07:28:45 +00:00
|
|
|
|
COM_API_DECLARE(bool, is_online(void));
|
|
|
|
|
COM_API_DECLARE(bool, is_paper_on(void));
|
|
|
|
|
COM_API_DECLARE(int, last_error(void));
|
|
|
|
|
COM_API_DECLARE(int, image_fetched(IScanImg* tx)); // notify the image 'tx' has fetched by APP
|
|
|
|
|
|
2023-09-21 03:23:38 +00:00
|
|
|
|
// ui ...
|
|
|
|
|
COM_API_DECLARE(bool, ui_is_ok(void));
|
|
|
|
|
COM_API_DECLARE(bool, ui_show_setting(HWND parent, bool with_scan, bool indicator = true));
|
|
|
|
|
COM_API_DECLARE(bool, ui_show_progress(HWND parent, bool bIndicator));
|
|
|
|
|
COM_API_DECLARE(void, ui_hide(void));
|
|
|
|
|
|
|
|
|
|
// twain
|
|
|
|
|
COM_API_DECLARE(void, twain_set_transfer(twain_xfer xfer));
|
|
|
|
|
COM_API_DECLARE(void, twain_set_compression(SANE_CompressionType compression, void* detail = nullptr));
|
|
|
|
|
COM_API_DECLARE(int, twain_get_config(char* buf, size_t* len));
|
|
|
|
|
COM_API_DECLARE(int, twain_set_config(char* buf, size_t len));
|
|
|
|
|
|
2023-07-10 07:28:45 +00:00
|
|
|
|
// Function: 获取配置项信息
|
|
|
|
|
//
|
|
|
|
|
// Parameter: sn - 配置项索引 - sane_option_id
|
|
|
|
|
//
|
|
|
|
|
// type - 配置项数据类型
|
|
|
|
|
//
|
|
|
|
|
// limit - 配置项限制类型
|
|
|
|
|
//
|
|
|
|
|
// bytes - *type 为 VAL_TYPE_STR时,需要的最小空间字节数
|
2023-09-21 03:23:38 +00:00
|
|
|
|
COM_API_DECLARE(bool, get_option_info(int sn, value_type* type, value_limit* limit, int *bytes, bool* readonly));
|
2023-09-23 08:07:23 +00:00
|
|
|
|
COM_API_DECLARE(int, get_fixed_ids(SANE_Bool(* cb)(int id, void* param), void* param));
|
2023-07-10 07:28:45 +00:00
|
|
|
|
|
2023-09-21 03:23:38 +00:00
|
|
|
|
COM_API_DECLARE(bool, get_value(int sn, set_opt_value func, void* param));
|
2023-07-10 07:28:45 +00:00
|
|
|
|
COM_API_DECLARE(bool, get_value(int sn, void* data, int* len)); // get operation with in-parameter
|
|
|
|
|
COM_API_DECLARE(int, set_value(int sn, void* val));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct delete_scanner
|
|
|
|
|
{
|
|
|
|
|
void operator()(ISaneInvoker* p)
|
|
|
|
|
{
|
|
|
|
|
p->release();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace sane_opts
|
|
|
|
|
{
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
RANGE_POS_CURRENT = 0,
|
|
|
|
|
RANGE_POS_DEFAULT,
|
|
|
|
|
RANGE_POS_ENUM_BEGIN,
|
|
|
|
|
RANGE_POS_LOWER = RANGE_POS_ENUM_BEGIN,
|
|
|
|
|
RANGE_POS_UPPER,
|
|
|
|
|
RANGE_POS_STEP,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
class get_opts
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// 0 - cur val; 1 - def val;
|
|
|
|
|
//
|
|
|
|
|
// LIST: 2 - elements ...
|
|
|
|
|
//
|
|
|
|
|
// RANGE: 2 - lower; 3 - upper; 4 - step
|
|
|
|
|
T range[5];
|
|
|
|
|
value_limit lmt_;
|
|
|
|
|
|
|
|
|
|
std::vector<T>* lvs_;
|
|
|
|
|
value_limit* limit_;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
get_opts(value_limit* limit, std::vector<T>* ls) : limit_(limit), lvs_(ls)
|
|
|
|
|
{}
|
|
|
|
|
~get_opts()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void re_order(void)
|
|
|
|
|
{
|
|
|
|
|
if (limit_)
|
|
|
|
|
*limit_ = lmt_;
|
|
|
|
|
|
|
|
|
|
if (lmt_ == VAL_LIMIT_RANGE || lmt_ == VAL_LIMIT_NONE)
|
|
|
|
|
{
|
|
|
|
|
if (lvs_)
|
|
|
|
|
{
|
|
|
|
|
lvs_->clear();
|
|
|
|
|
for (size_t i = 0; i < _countof(range); ++i)
|
|
|
|
|
lvs_->push_back(range[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(lvs_)
|
|
|
|
|
{
|
|
|
|
|
lvs_->insert(lvs_->begin(), range[RANGE_POS_DEFAULT]);
|
|
|
|
|
lvs_->insert(lvs_->begin(), range[RANGE_POS_CURRENT]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
|
bool set_opt_value(void* val, value_role role, value_limit limit, void* param)
|
|
|
|
|
{
|
|
|
|
|
get_opts<T>* v = (get_opts<T>*)param;
|
|
|
|
|
bool go = true;
|
|
|
|
|
|
|
|
|
|
v->lmt_ = limit;
|
|
|
|
|
if (role & VAL_ROLE_CURRENT)
|
|
|
|
|
{
|
|
|
|
|
v->range[RANGE_POS_CURRENT] = *(T*)val;
|
|
|
|
|
}
|
|
|
|
|
if (role & VAL_ROLE_DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
v->range[RANGE_POS_DEFAULT] = *(T*)val;
|
|
|
|
|
}
|
|
|
|
|
if (role & VAL_ROLE_LOWER)
|
|
|
|
|
{
|
|
|
|
|
v->range[RANGE_POS_LOWER] = *(T*)val;
|
|
|
|
|
}
|
|
|
|
|
if (role & VAL_ROLE_UPPER)
|
|
|
|
|
{
|
|
|
|
|
v->range[RANGE_POS_UPPER] = *(T*)val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (role & VAL_ROLE_STEP)
|
|
|
|
|
{
|
|
|
|
|
v->range[RANGE_POS_STEP] = *(T*)val;
|
|
|
|
|
}
|
|
|
|
|
else if (v->lvs_)
|
|
|
|
|
v->lvs_->push_back(*(T*)val);
|
|
|
|
|
|
|
|
|
|
return go;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define GET_SANE_OPT(type, object, id_name, limit, vct) \
|
|
|
|
|
{ \
|
|
|
|
|
sane_opts::get_opts<type> op(limit, vct); \
|
|
|
|
|
object->get_value(SANE_OPT_ID_##id_name, sane_opts::set_opt_value<type>, &op); \
|
|
|
|
|
op.re_order(); \
|
|
|
|
|
}
|
|
|
|
|
#define SET_SANE_OPT(ret, object, id_name, val) \
|
|
|
|
|
{ \
|
|
|
|
|
ret = object->set_value(SANE_OPT_ID_##id_name, val); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
|
{
|
2023-09-21 03:23:38 +00:00
|
|
|
|
bool is_scanner_online(const char* model);
|
2023-09-22 08:26:22 +00:00
|
|
|
|
ISaneInvoker* open_scanner(const char* model, int* err);
|
2023-07-10 07:28:45 +00:00
|
|
|
|
int uninitialize_sane(void* reserve);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-21 03:23:38 +00:00
|
|
|
|
|
|
|
|
|
// 标准TWAIN属性值与SANE属性值之间的转换
|
|
|
|
|
namespace s2t
|
|
|
|
|
{
|
|
|
|
|
// 页面 与 双面转换
|
|
|
|
|
bool page_is_duplex(const char* sane_val);
|
|
|
|
|
std::string page_from_duplex(bool duplex);
|
|
|
|
|
|
|
|
|
|
// 页面 与 丢弃空白页
|
|
|
|
|
bool discard_blank_from_sane(const char* sane_val);
|
|
|
|
|
std::string discard_blank_to_sane(bool discard);
|
|
|
|
|
|
|
|
|
|
// 页面 与 丢弃空白发票
|
|
|
|
|
bool discard_blank_receipt_from_sane(const char* sane_val);
|
|
|
|
|
std::string discard_blank_receipt_to_sane(bool discard);
|
|
|
|
|
|
|
|
|
|
// 页面 与 对折
|
|
|
|
|
bool fold_from_sane(const char* sane_val);
|
|
|
|
|
std::string fold_to_sane(bool fold);
|
|
|
|
|
|
|
|
|
|
// 语言
|
|
|
|
|
int language_to_twain(const char* sane_val);
|
|
|
|
|
std::string language_from_twain(int twain);
|
|
|
|
|
|
|
|
|
|
// 位深 与 颜色模式
|
|
|
|
|
int bits_from_sane(const char* color_mode);
|
|
|
|
|
std::string bits_to_sane(int bits);
|
|
|
|
|
|
|
|
|
|
// PixelType 与 颜色模式
|
|
|
|
|
int pixel_type_from_sane(const char* color_mode);
|
|
|
|
|
std::string pixel_type_to_sane(int pixel);
|
|
|
|
|
|
|
|
|
|
// 自动颜色匹配 与 颜色模式
|
|
|
|
|
bool color_mode_is_auto(const char* color_mode);
|
|
|
|
|
std::string color_mode_from_auto(bool auto_mode);
|
|
|
|
|
|
|
|
|
|
// 支持的尺寸 与 纸张
|
|
|
|
|
int paper_size_from_sane(const char* sane_val);
|
|
|
|
|
std::string paper_size_to_sane(int paper);
|
|
|
|
|
|
|
|
|
|
// 横向 与 纸张
|
|
|
|
|
bool lateral_from_sane(const char* sane_val, bool* support_lateral);
|
|
|
|
|
std::string lateral_to_sane(const char* sane_val, bool lateral); // 如果sane_val不支持横向则返回sane_val,确定是否支持横向请调用lateral_from_sane
|
|
|
|
|
|
|
|
|
|
// 自动尺寸 与 纸张
|
|
|
|
|
bool auto_size_from_sane(const char* sane_val);
|
|
|
|
|
std::string auto_size_to_sane(bool autos);
|
|
|
|
|
|
|
|
|
|
// 自动裁切 与 纸张
|
|
|
|
|
bool auto_crop_from_sane(const char* sane_val);
|
|
|
|
|
std::string auto_crop_to_sane(bool autos);
|
|
|
|
|
|
|
|
|
|
// 旋转角度 与 送纸方向
|
|
|
|
|
double rotation_from_sane(const char* sane_val);
|
|
|
|
|
std::string rotation_to_sane(double rot);
|
|
|
|
|
bool auto_rotation_from_sane(const char* sane_val);
|
|
|
|
|
std::string auto_rotation_to_sane(bool autor);
|
|
|
|
|
|
|
|
|
|
// 滤波 与 除色与增强
|
|
|
|
|
void filter_from_sane(const std::vector<std::string>& sane/*sane_opts::RANGE_POS*/, std::vector<int>& twain, bool filter/*true - filter; false - enhance*/);
|
|
|
|
|
std::string filter_to_sane(int filter);
|
|
|
|
|
std::string enhance_to_sane(int enhance);
|
|
|
|
|
|
|
|
|
|
// 多流输出
|
|
|
|
|
int multi_out_from_sane(const char* sane_val);
|
|
|
|
|
std::string multi_out_to_sane(int mo);
|
|
|
|
|
|
|
|
|
|
// 休眠时间兼容老版本协议
|
|
|
|
|
int power_from_sane(const char* sane_val);
|
|
|
|
|
std::string power_to_sane(int power);
|
|
|
|
|
|
|
|
|
|
// 背景填充方式 设置凸多边形
|
|
|
|
|
bool convex_from_sane(const char* sane_val);
|
|
|
|
|
std::string convex_to_sane(bool convex);
|
|
|
|
|
|
|
|
|
|
// 锐化
|
|
|
|
|
int sharpen_from_sane(const char* sane_val);
|
|
|
|
|
std::string sharpen_to_sane(int sharpen);
|
|
|
|
|
};
|