twain3.0/huagao/huagaods.cpp

2846 lines
105 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#include <memory>
#include "huagaods.hpp"
#include "twglue.hpp"
#include "resource.h"
#include "CTwainUI.h"
#include "CIndicatorDlg.h"
//#include "Cmsgbox.h"
#include "Device/PublicFunc.h"
#include "Device/GScanO200.h"
#include "Device/GScanO400.h"
#include "Device/GScanO400Android.h"
#include "Device/GScanO1003399.h"
#include "Device/filetools.h"
#include "Device/GScanVirtual.h"
#include <list>
#include <map>
#include "GscanJsonConfig.h"
#include "G4Tiff.h"
#include "Device/UsbScanEx.h"
#ifdef WIN32
#include <Psapi.h>
#endif // WIN32
using namespace std;
//custom define caps enum
enum class CapTypeEx : unsigned short {
Base = 0x8000,//custom caps enum value must bigger than CapTypeEx::Base value,otherwise might make conflict
TwEx_IMultiOutputRed = 0x8026,
TwEx_IFillHole = 0x8018,
TwEx_IFillHoleRatio = 0x8092,
TwEx_IFillBackground = 0x8004,
TwEx_IBackRotate180 = 0x8005,
TwEx_IAutoDiscardBlankVince = 0x8091,
TwEx_IEnhanceColor = 0x8007,
TwEx_HardwareVersion = 0x8025,
TwEx_ScrewDetectEnable = 0x8006,
TwEx_ScrewLevel = 0x8021,
TwEx_Sharpen = 0x8022,
TwEx_EnFold = 0x8037,
TwEx_StableDetectEnable = 0x8090,
TwEx_UVModel = 0x8093,
TwEx_SwitchFrontBack = 0x8094,
TwEx_HsvCorrect = 0x8095,
TwEx_DogEarDelection = 0x8096,
TwEx_FillBackgroundMode = 0x8097,
TwEx_CroporDesaskewIndent = 0x8098,
TwEx_CropNoise = 0x8099,
TwEx_CroporDesaskewThreshold = 0x8100,
TwEx_IDetachNoise = 0x8101,
TwEx_IDetachNoiseValue = 0x8102,
TwEx_SizeDetect = 0x8103,
TwEx_LowPowerMode = 0x8104,
TwEx_ENCODE = 0x8105,
TwEx_CropModel=0x8106,
TwEx_DogEarDistance = 0x8107,
TwEx_ImageSplit = 0x8108,
TwEx_IFadeBack = 0x8109,
TwEx_IFadeBackValue = 0x8110,
};
enum class PaperSizeEx : unsigned short {
K8 = 0x81,
K16 = 0x82,
Trigeminy = 0x83,
};
using namespace Twpp;
using namespace std::placeholders;
#define TWPP_ENTRY_MFC(SourceClass)\
extern "C" TWPP_DETAIL_EXPORT Twpp::ReturnCode TWPP_DETAIL_CALLSTYLE \
DS_Entry(Twpp::Identity* origin, Twpp::DataGroup dg, Twpp::Dat dat, Twpp::Msg msg, void* data){\
AFX_MANAGE_STATE(AfxGetStaticModuleState()); \
static_assert(\
std::is_base_of<Twpp::SourceFromThis<SourceClass, false>, SourceClass>::value ||\
std::is_base_of<Twpp::SourceFromThis<SourceClass, true>, SourceClass>::value,\
"Class " #SourceClass " is not derived from SourceFromThis."\
);\
return SourceClass::entry(origin, dg, dat, msg, data);\
}
TWPP_ENTRY_MFC(HuagaoDs)
static constexpr const Identity srcIdent(
Version(3, 3, Language::English, Country::China, "v3.3.5.6"),
DataGroup::Image,
#ifdef MAKEHUAGAO
"HUAGO",
#elif defined HANVON
"HANVON",
#elif defined AUGE
"AUGE",
#elif defined LANXUM
"LANXUM",
#elif defined MAKERIGHTWAY
"RIGHTWAY",
#else // MAKEHUAGAO
"ZHIBEN",
#endif
#ifdef G200
#ifdef ISG100
#ifdef LANXUM
"G62S Series",
#elif defined HANVON
"HW-8190F Series",
#else // ISG100
"G100 Series",
#endif
#else // ISG100
#ifdef LANXUM
"G73S Series",
#elif defined HANVON
"HW-9110M Series",
#else // ISG100
"G200 Series",
#endif
#endif
#elif defined(G300) // G200
#ifdef LANXUM
"G42S Series",
#elif defined HANVON
"HW-7000W Series",
#else // ISG100
"G300 Series",//<2F><><EFBFBD>ݾɼ<DDBE><C9BC><EFBFBD> pm changed <20><>G300 Series
#endif
#elif defined(G400) // G200
#ifdef LANXUM
"G52S Series",
#elif defined HANVON
"HW-7000W Series",
#else // ISG100
"G400 Series",
#endif
#endif
#ifdef G200
#ifdef ISG100
#ifdef MAKEHUAGAO
"HUAGOSCAN G100 TWAIN"
#elif defined AUGE
"AUGESCAN G100 TWAIN"
#elif defined HANVON
"HANVONSCAN HW-8190F TAWIN"
#elif defined LANXUM //!LANXUM
"LANXUMSCAN G62S TWAIN"
#else // !MAKEHUAGAO
"ZhibenScan G100 TWAIN"
#endif
#else // ISG100
#ifdef MAKEHUAGAO
"HUAGOSCAN G200 TWAIN"
#elif defined HANVON
"HANVONSCAN HW-9110M TAWIN"
#elif defined LANXUM //!LANXUM
"LANXUMSCAN G73S TWAIN"
#else // !MAKEHUAGAO
"ZhibenScan G200 TWAIN"
#endif
#endif
#elif defined G300 // G200
#ifdef MAKEHUAGAO
#ifdef UV
"HUAGOSCAN G300UV TWAIN"
#else
"HUAGOSCAN G300 TWAIN"// <20><><EFBFBD>ݾɼ<DDBE><C9BC><EFBFBD> pm changed "HUAGOSCAN G300 TWAIN"
#endif
#elif defined UV && defined MAKERIGHTWAY
"RIGHTWAYSCAN G300 TWAIN"
#elif defined HANVON
"HANVONSCAN HW-7000W TAWIN"
#elif defined LANXUM //!LANXUM
"LANXUMSCAN G42S TWAIN"
#else // !MAKEHUAGAO
"ZhibenScan G300 TWAIN"
#endif
#elif defined(G400) // G200
#ifdef MAKEHUAGAO
"HUAGOSCAN G400 TWAIN"
#elif defined HANVON
"HANVONSCAN HW-7000W TAWIN"
#elif defined LANXUM //!LANXUM
"LANXUMSCAN G52S TWAIN"
#else // !MAKEHUAGAO
"ZhibenScan G400 TWAIN"
#endif
#endif
#if defined(_MSC_VER)
""
#elif defined(__GNUC__)
" GCC"
#elif defined(__clang__)
" CLang"
#endif
);
// lets just simulate uniform resolution for both axes
static constexpr UInt32 RESOLUTIONX = 85;
//static std::unique_ptr<CWinApp> application(new CWinApp());
#ifdef LANXUM
static list<float> resList = { 100.0,150.0,200.0,240.0,300.0 };
#else
static list<float> resList = { 100.0,150.0,200.0,240.0,300.0,600.0 };
#endif // LANXUM
//<2F><><EFBFBD><EFBFBD>G200 G300<30><30>G400ֽ<30>ŷ<EFBFBD><C5B7><EFBFBD>
#ifdef G200
static list<UInt16> paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6,
(UInt16)PaperSize::IsoB4,(UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6,
(UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::UsLedger,
(UInt16)PaperSize::MaxSize,(UInt16)PaperSize::None,(UInt16)PaperSize::UsStatement,
(UInt16)PaperSizeEx::K8,(UInt16)PaperSizeEx::K16,(UInt16)PaperSizeEx::Trigeminy };
#elif defined G300
static list<UInt16> paperSizeList = { (UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6, (UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6,
(UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::None,(UInt16)PaperSizeEx::K16 };
#elif defined G400
static list<UInt16> paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6,
(UInt16)PaperSize::IsoB4,(UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6,
(UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::UsLedger,
(UInt16)PaperSize::MaxSize,(UInt16)PaperSize::None,(UInt16)PaperSize::UsStatement ,
(UInt16)PaperSizeEx::K8,(UInt16)PaperSizeEx::K16,(UInt16)PaperSizeEx::Trigeminy };
#endif // G200
static list<float> imageRotateList = { 0.0,90.0,180.0,270.0 };
enum class DeviceEventType : UInt16
{
CustomEvents = 0x8000,
Dev_OPENCOVER,
Dev_NOFEED,
Dev_FEEDERROR,
Dev_STABLE,
Dev_SKREW,
Dev_COUNTMOE,
Dev_HARDWAREERROR,
Dev_FPGAERROR,
Dev_UserStop,
Dev_DogEar
};
static map<unsigned int, DeviceEvent::Type> mapDeviceEvent = {
{OPEN_COVER,(DeviceEvent::Type)(DeviceEventType::Dev_OPENCOVER)},
{NO_FEED,(DeviceEvent::Type)(DeviceEventType::Dev_NOFEED)},
{FEED_IN_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_FEEDERROR)},
{PAPER_JAM,DeviceEvent::Type::PaperJam},
{DETECT_DOUBLE_FEED,DeviceEvent::Type::PaperDoubleFeed},
{DETECT_STAPLE,(DeviceEvent::Type)(DeviceEventType::Dev_STABLE)},
{PAPER_SKEW,(DeviceEvent::Type)(DeviceEventType::Dev_SKREW)},
{COUNT_MODE,(DeviceEvent::Type)(DeviceEventType::Dev_COUNTMOE)},
{HARDWARE_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_HARDWAREERROR)},
{FPGA_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_FPGAERROR)},
{USB_DISCONNECTED,DeviceEvent::Type::CheckDeviceOnline},
{USER_STOP,(DeviceEvent::Type)(DeviceEventType::Dev_UserStop)},
{DOG_EAR,(DeviceEvent::Type)(DeviceEventType::Dev_DogEar)}
};
struct Vid_pid
{
WORD vid;
WORD pid;
};
#ifdef LANXUM
static std::vector<Vid_pid> DeviceID{
{0x31c9,0x8200},
#ifdef G200
#ifdef ISG100
{0x31c9,0x8629},
{0x31c9,0x8620},
#else
{0x31c9,0x8739},
{0x31c9,0x8730},
#endif // ISG100
#elif defined G300
{0x31c9,0x8420},
#elif defined G400
{0x31c9,0x8520},
#endif // ISG100
};
#elif defined AUGE
static std::vector<Vid_pid> DeviceID{
{0x3072,0x0130},
};
#elif defined HANVON
static std::vector<Vid_pid> DeviceID{
#ifdef G200
#ifdef ISG100
{0x2903,0x8000},
#else
{0x2903,0x9000},
#endif // ISG100
#elif defined G400
{0x2903,0x7000},
#endif // G200
};
#else
static std::vector<Vid_pid> DeviceID{
{0x64B,0x7823},
#ifdef G200
#ifdef ISG100
{0x3072,0x100},
{0x3072,0x139},
#else
{0x3072,0x239},
{0x3072,0x200},
#endif // ISG100
#elif defined G300
{0x3072,0x0300},
#elif defined G400
{0x3072,0x400},
#endif // ISG100
};
#endif
static void DeleteWnd(CDialog* pWnd) {
if (pWnd && pWnd->GetSafeHwnd()) {
if (pWnd->m_hWnd)
DestroyWindow(pWnd->m_hWnd);
}
}
static std::unique_ptr<CTwainUI, void(*)(CDialog*)> guiTwain(nullptr, DeleteWnd);
//static std::unique_ptr<Cmsgbox> msgbox;
#if TWPP_DETAIL_OS_WIN
static std::unique_ptr<CDialog, void(*)(CDialog*)> guiBridge(nullptr, DeleteWnd);
#endif
//static std::unique_ptr<CIndicatorDlg, void(*)(CDialog*)> guiIndicator(nullptr, DeleteWnd);
static CIndicatorDlg* guiIndicator = NULL;
//#define HG_VIRTUAL
#ifndef HG_VIRTUAL
static std::unique_ptr<IScanner> scanner; //(new GScanO200());
#else
static std::unique_ptr<IScanner> scanner(new GScanVirtual());
#endif
//long __stdcall callback(_EXCEPTION_POINTERS* excp)
//{
// MessageBox(0, L"Error", L"error", MB_OK);
// return EXCEPTION_CONTINUE_SEARCH;
//}
static std::once_flag oc;
HuagaoDs::HuagaoDs()
: m_scanparam(new GScanCap)
, bmpData(new std::vector<unsigned char>)
, hMutex(NULL)
{
std::call_once(oc, [&]() { log4cplus::Initializer(); });
//log4cplus::Initializer();
//log4cplus::deinitialize();
/*string ss1= getOSInfo();
string ss2=getManufactureID();
string ss3=getCpuType();
string ss4= getMemoryInfo();
DWORD dwNum;
CString aas[10];
GetDiskInfo(dwNum,aas);*/
//SetUnhandledExceptionFilter(callback);
//memoryinfo.reset(new std::thread([this]() {
// PROCESS_MEMORY_COUNTERS pmc;
// GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
// while (pmc.PeakPagefileUsage < 0x40000000&&m_memoryfalg){
// GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
// std::this_thread::sleep_for(std::chrono::milliseconds(10));
// }
// if (scanner.get()){
// scanner->Stop_scan();
// scanner->reset();
// scanner->ResetScanner();
// }
// //guiIndicator.reset();
// if (!m_memoryfalg)
// return;
// MessageBox(NULL, L"<22>ڴ治<DAB4><E6B2BB>", L"<22><>ʾ", MB_OK| MB_SYSTEMMODAL);
//}));
}
void HuagaoDs::showmsg(std::string caption, std::string text, int retcode)
{
if (scanner.get()) {
int num = scanner->get_imgnReaded() * (m_scanparam->is_duplex ? 2 : 1) * (m_scanparam->multi_output_red ? 2 : 1) / (m_scanparam->en_fold ? 2 : 1) * (m_scanparam->is_split ? 2 : 1);
int imgread = scanner->get_imgnReaded();
IScanner* ptr = scanner.get();
if (typeid(*ptr) == typeid(GScanO1003399))
{
//readnum = readnum / 2 * (m_scanparam->en_fold ? 2 : 1);
num = scanner->get_imgnReaded() * (m_scanparam->multi_output_red ? 2 : 1) * (m_scanparam->is_split ? 2 : 1);
if(!m_scanparam->en_fold)
imgread /= 2;
}
if (retcode == 200)
{
if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince))
{
text += "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>ʹ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\nɨ<EFBFBD><EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>\n<EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>--\nɨ<EFBFBD><EFBFBD>ţ<EFBFBD>" + to_string(imgread) + "\nɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>--\n<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>"
+ to_string(scanner->get_imgTransfered()) + "\n<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>" + to_string(num - scanner->get_imgTransfered());
scanner->set_lose_image_num(0);
}
}
else
{
if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince))
{
text += "\nɨ<EFBFBD><EFBFBD>ͳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>\n<EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>" + to_string(scanner->get_scannum()) +
"\nɨ<EFBFBD><EFBFBD>ţ<EFBFBD>" + to_string(imgread) + "\nɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>" + to_string(scanner->get_scannum() - imgread) +
"\n<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>" + to_string(scanner->get_imgTransfered()) + "\n<EFBFBD>ϴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҳ<EFBFBD><EFBFBD>" + to_string(num - scanner->get_imgTransfered());
scanner->set_lose_image_num(0);
}
}
}
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString((text + " " + caption).c_str()), NULL, SW_HIDE);
}
void HuagaoDs::hgmsg(CString str)
{
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), str, NULL, SW_HIDE);
}
HuagaoDs::~HuagaoDs()
{
if (memoryinfo.get()) {
m_memoryfalg = false;
if (memoryinfo->joinable())
memoryinfo->join();
}
if (scanner.get())
scanner.reset();
}
const Identity& HuagaoDs::defaultIdentity() noexcept {
// remember, we return a reference, therefore the identity must not be placed on the stack of this method
return srcIdent;
}
Result HuagaoDs::call(const Identity& origin, DataGroup dg, Dat dat, Msg msg, void* data) {
try {
// we can override almost anything from SourceFromThis, even the top-most source instance call
//FileTools::write_log("D:\\1.txt", "call:datagroup-"+to_string((int)dg)+"dat-"+to_string(int(dat))+"msg-"+to_string(int(msg)));
return Base::call(origin, dg, dat, msg, data);
}
catch (const CapabilityException& e) {
FileTools::writelog(log_ERROR, e.what());
return badValue();
}
}
Result HuagaoDs::customDataGet(const Twpp::Identity& origin, Twpp::CustomData& data)
{
//<2F>ӱ<EFBFBD><D3B1><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5>ļ<EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>ȡ<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ϴ<EFBFBD>
TCHAR szIniFile[MAX_PATH] = { 0 };
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_LOCAL_APPDATA, TRUE);
_tcscat(szIniFile, HUAGAO_SCAN);
_tcscat(szIniFile, TWAIN_INIPATH);
_tcscat(szIniFile, TEXT("\\"));
_tcscat(szIniFile, TWAIN_JSON_NAME);
string path = TCHAR2STRING(szIniFile);
int t;
FILE* file = fopen(path.c_str(), "rb");
fseek(file, 0, SEEK_END);
t = ftell(file);
//data = CustomData(t);
std::string buf(t, 0);
fseek(file, 0, SEEK_SET);
fread((void*)buf.c_str(), t, 1, file);
fclose(file);
data = CustomData(t);
auto pdata = data.lock<unsigned char>();
memcpy(pdata.data(), buf.c_str(), t);
return success();
}
Result HuagaoDs::customDataSet(const Twpp::Identity& origin, Twpp::CustomData& data)
{
GScanCap sc;
//<2F><><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>תGscanCaps
GscanJsonConfig js;
std::string str;
str.resize(data.size());
auto pdata = data.lock<unsigned char>();
memcpy((void*)str.c_str(), pdata, data.size());
//vector<GScanCap> vc = js.parseJsonFromString(str);
//m_scanparam.reset(new GScanCap(vc[0]));
//std::unique_ptr<GScanCap> cap(new GScanCap(js.JsonToGscancap(json::parse(str))));
m_scanparam.reset(new GScanCap(js.JsonToGscancap(json::parse(str))));
return success();
}
// some helper functions to handle capability stuff
template<typename T>
static Result oneValGet(Msg msg, Capability& data, const T& value) {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue(data.type(), value);
return {};
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
static Result oneValGetString(Msg msg, Capability& data, std::string value) {
Str255 str;
str.setData(value.c_str(), value.size());
return oneValGet(msg, data, str);
}
template<typename T>
static Result enmGet(Msg msg, Capability& data, const T& value) {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration(data.type(), { value });
return {};
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue(data.type(), value);
return {};
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T>
static Result oneValGetSet(Msg msg, Capability& data, T& value, const T& def) {
switch (msg) {
case Msg::Reset:
value = def;
// fallthrough
case Msg::Get:
case Msg::GetCurrent:
data = Capability::createOneValue(data.type(), value);
return {};
case Msg::GetDefault:
data = Capability::createOneValue(data.type(), def);
return {};
case Msg::Set:
value = data.currentItem<T>();
return {};
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T>
static Result oneValGetSetConst(Msg msg, Capability& data, const T& def) {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
case Msg::Reset:
data = Capability::createOneValue(data.type(), def);
return {};
case Msg::Set:
return data.currentItem<T>() == def ?
Result() : Result(ReturnCode::Failure, ConditionCode::BadValue);
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T>
static Result enmGetSetConst(Msg msg, Capability& data, const T& def) {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration(data.type(), { def });
return {};
case Msg::GetCurrent:
case Msg::GetDefault:
case Msg::Reset:
data = Capability::createOneValue(data.type(), def);
return {};
case Msg::Set:
return data.currentItem<T>() == def ?
Result() : Result(ReturnCode::Failure, ConditionCode::BadValue);
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
/// Shortcut for Result(RC::Failure, CC::CheckDeviceOnline).
static constexpr Result checkDeviceOnline() noexcept {
return { ReturnCode::Failure,ConditionCode::CheckDeviceOnline };
}
Result HuagaoDs::capCommon(const Identity&, Msg msg, Capability& data) {
auto it = m_caps.find(data.type());
if (it != m_caps.end()) {
return (it->second)(msg, data);
}
return capUnsupported();
}
Result HuagaoDs::capabilityGet(const Identity& origin, Capability& data) {
return capCommon(origin, Msg::Get, data);
}
Result HuagaoDs::capabilityGetCurrent(const Identity& origin, Capability& data) {
return capCommon(origin, Msg::GetCurrent, data);
}
Result HuagaoDs::capabilityGetDefault(const Identity& origin, Capability& data) {
return capCommon(origin, Msg::GetDefault, data);
}
Result HuagaoDs::capabilityQuerySupport(const Identity&, Capability& data) {
auto it = m_query.find(data.type());
MsgSupport sup = it != m_query.end() ? it->second : msgSupportEmpty;
data = Capability::createOneValue(data.type(), sup);
return success();
}
template<typename T, Twpp::CapType cap>
Result CapSupGetAll(Msg msg, Capability& data, std::initializer_list<T> values, T& currvalue, T defaultvalue, UInt32 currindex, UInt32 defaultindex) {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<cap>((T2)values, currindex, defaultindex);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue(values[defaultindex]);
return { ReturnCode::Success, ConditionCode::Success };
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T1, typename T2, Twpp::CapType cap>
Result CapSupGetAll(Msg msg, Capability& data, T1& currvalue, T2 defaultvalue) {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue<cap>((T2)defaultvalue);
return { ReturnCode::Success, ConditionCode::Success };
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T, Twpp::CapType cap>
Result CapSupGetAllEx(Msg msg, Capability& data, T& currvalue, T defaultvalue) {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue<T>(cap, defaultvalue);
return { ReturnCode::Success, ConditionCode::Success };
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T1, typename T2, Twpp::CapType cap>
Result CapSupGetAllReset(Msg msg, Capability& data, std::initializer_list<T2> 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<typename T1, typename T2, Twpp::CapType cap>
Result CapSupGetAllReset(Msg msg, Capability& data, T1& currvalue, T2 defaultvalue) {
switch (msg) {
case Msg::Get:
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<typename T1, typename T2, Twpp::CapType cap>
Result CapSupGetAllResetEx(Msg msg, Capability& data, std::initializer_list<T2> values, T1& currvalue, T2 defaultvalue, UInt32 currindex, UInt32 defaultindex) {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<T2>(cap, values, currindex, defaultindex);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::GetCurrent:
data = Capability::createOneValue<T2>(cap, (T2)currvalue);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::Reset:
case Msg::GetDefault:
currvalue = (T1)defaultvalue;
data = Capability::createOneValue<T2>(cap, defaultvalue);
return { ReturnCode::Success, ConditionCode::Success };
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
template<typename T1, typename T2, Twpp::CapType cap>
Result CapSupGetAllResetEx(Msg msg, Capability& data, T1& currvalue, T2 defaultvalue) {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
data = Capability::createOneValue<T2>(cap, (T2)currvalue);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::Reset:
case Msg::GetDefault:
currvalue = (T1)defaultvalue;
data = Capability::createOneValue<T2>(cap, defaultvalue);
return { ReturnCode::Success, ConditionCode::Success };
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
}
Result HuagaoDs::capabilityReset(const Identity& origin, Capability& data) {
return capCommon(origin, Msg::Reset, data);
}
Result HuagaoDs::capabilityResetAll(const Identity& origin) {
for (auto& pair : m_query) {
if ((pair.second & MsgSupport::Reset) != msgSupportEmpty) {
Capability dummyCap(pair.first);
capCommon(origin, Msg::Reset, dummyCap);
}
}
return success();
}
Result HuagaoDs::capabilitySet(const Identity& origin, Capability& data) {
return capCommon(origin, Msg::Set, data);
}
Result HuagaoDs::eventProcess(const Identity&, Event& event) {
// Qt needs to process its events, otherwise the GUI will appear frozen
// this is Windows-only method, Linux and macOS behave differently
if (guiTwain) {
// // QApplication::processEvents(); - TODO: needs more investigation; results in freeze when attempting to scan using old DSM
// QApplication::sendPostedEvents();
//guiTwain->PostMessageW((UINT)(event.message()));
guiTwain->SendMessage((UINT)(event.message()));
}
//if (inState(DsState::XferReady))
// event.setMessage(Msg::XferReady);
//else
event.setMessage(Msg::Null);
return { ReturnCode::NotDsEvent, ConditionCode::Success };
}
Twpp::Result HuagaoDs::deviceEventGet(const Twpp::Identity& origin, Twpp::DeviceEvent& data)
{
if (devEvent.size() > 0)
{
data = devEvent.front();
devEvent.pop();
return success();
}
return seqError();
}
//add------------------<2D><><EFBFBD><EFBFBD>jpgͼ<67><CDBC>dpi---------------------------
void HuagaoDs::SetResoluton(const char* path, int resolution)
{
FILE* file = fopen(path, "rb+");
if (!file)
return;
//<2F><>ȡ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>С
int len = _filelength(_fileno(file));
char* buf = new char[len];
fread(buf, sizeof(char), len, file);
char* pResolution = (char*)&resolution;
//<2F><><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9>ͼƬ<CDBC>ܶȵ<DCB6>λ
buf[0x0D] = 1;
//ˮƽ<CBAE>ܶȣ<DCB6>ˮƽ<CBAE>ֱ<EFBFBD><D6B1><EFBFBD>
buf[0x0E] = pResolution[1];
buf[0x0F] = pResolution[0];
//<2F><>ֱ<EFBFBD>ܶȣ<DCB6><C8A3><EFBFBD>ֱ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>
buf[0x10] = pResolution[1];
buf[0x11] = pResolution[0];
fseek(file, 0, SEEK_SET);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭʼ<D4AD><CABC><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD>޸<EFBFBD><DEB8><EFBFBD>Ч
fwrite(buf, sizeof(char), len, file);
fclose(file);
delete[]buf;
}
void HuagaoDs::dogear_callback(int indexpaper)
{
CString text;
text.Format(_T("74 %d"), indexpaper);
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE);
showmsg("<EFBFBD><EFBFBD>ʾ","<EFBFBD><EFBFBD>"+to_string(indexpaper)+"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۽ǣ<EFBFBD>");
scanner->Stop_scan();
//scanner->reset();
scanner->ResetScanner();
onDeviceEvent(DOG_EAR);
}
Result HuagaoDs::identityOpenDs(const Identity&) {
hMutex = CreateMutex(NULL, FALSE, _T("LookitApp"));
if (GetLastError() == ERROR_ALREADY_EXISTS) { //<2F><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD>Mutex<65><78><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
CloseHandle(hMutex);
hMutex = NULL;
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("202"), NULL, SW_HIDE);
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[(UsbSupported)202]);
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
Twain_config().GetOrSetPintfCapability(is_printfcapability, true);
auto usblist = UsbScan_List::find_all_usb();
if (!usblist.empty())
{
for each (auto & usb in usblist)
{
for(int x=0;x<DeviceID.size();x++)
{
if (DeviceID[x].vid ==usb.vid && DeviceID[x].pid ==usb.pid)
{
vid = usb.vid;
pid = usb.pid;
if (!scanner.get()) {
#ifdef G200
if (pid == 0x139 || pid == 0x239 || pid == 0x8739 || pid == 0x8629 || pid == 0x130 ||pid == 0x8000 || pid == 0x9000)
scanner.reset(new GScanO1003399());
else
scanner.reset(new GScanO200());
#else
#ifdef ANDROIDSERIAL
scanner.reset(new GScanO400Android());
#else
scanner.reset(new GScanO400());
#endif
#endif // G400
break;
}
}
}
}
}
FileTools::writelog(log_INFO, "open ds find device vid=" + to_string(vid) + "\tpid=" + to_string(pid));
if (vid == 0 || pid == 0)
{
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
//showmsg("<22><>ʾ", msgs[(UsbSupported)201]);
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("δ<EFBFBD>ҵ<EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>!<21><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>USB<53><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ͨ! <20><>ʾ"), NULL, SW_HIDE);
if (hMutex) {
CloseHandle(hMutex);
hMutex = NULL;
}
return checkDeviceOnline();
}
scanner->open(vid, pid);
if (scanner->get_ErrorCode() == SLEEPING) {
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
hMutex = NULL;
}
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[(UsbSupported)81]);
return seqError();
}
if (!scanner->IsConnected()) {
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[(UsbSupported)201]);
if (hMutex) {
CloseHandle(hMutex);
hMutex = NULL;
}
return checkDeviceOnline();
}
else
{
scanner->regist_deviceevent_callback(DeviceEvent_callback, this);
auto dgcall = [&](int pagenum)
{
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE);
showmsg("<EFBFBD><EFBFBD>ʾ", "<EFBFBD><EFBFBD>" + to_string(pagenum) + "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۽ǣ<EFBFBD>");
scanner->Stop_scan();
//scanner->reset();
scanner->ResetScanner();
onDeviceEvent(DOG_EAR);
};
scanner->DogEar_callback(dgcall);
}
m_haveError = false;
updataGscanCap();
bmpData->resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header());
bmInfo.biHeight = 2000;
bmInfo.biWidth = 2000;
bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1);
m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1);
//MessageBox(NULL, L"2", L"", 0);
// init caps
// there are caps a minimal source must support
// query -> says which operations a cap supports
// caps -> has handler for each specific cap
m_query[CapType::SupportedCaps] = msgSupportGetAll;
m_caps[CapType::SupportedCaps] = [this](Msg msg, Capability& data) {
if ((msg == Msg::Get) || (Msg::GetCurrent == msg) || (Msg::GetDefault == msg)) {
data = Capability::createArray<CapType::SupportedCaps>(m_caps.size());
auto arr = data.array<CapType::SupportedCaps>();
UInt32 i = 0;
for (const auto& kv : m_caps) {
arr[i] = kv.first;
i++;
}
return success();
}
else
return capBadOperation();
};
m_query[CapType::UiControllable] = msgSupportGetAll;
m_caps[CapType::UiControllable] = std::bind(oneValGet<Bool>, _1, _2, Bool(true));
m_query[CapType::DeviceOnline] = msgSupportGetAll;
//m_caps[CapType::DeviceOnline] = std::bind(enmGet<Bool>, _1, _2, Bool(scanner->IsConnected()));
m_caps[CapType::DeviceOnline] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::DeviceOnline));
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue<CapType::DeviceOnline>((Twpp::Bool)scanner->IsConnected());
return {};
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
};
m_query[CapType::XferCount] = msgSupportGetAllSetReset;
m_caps[CapType::XferCount] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::XferCount),msg==Msg::Set?to_string((int)data.currentItem<Int16>()):"");
if (msg == Msg::Set) {
auto item = data.currentItem<Int16>();
if (item > 65535 || item < -1 || item == 0) {
return badValue();
}
m_scanparam->scannum = item;
return success();
}
Int16 tmp_count = m_scanparam->scannum;
auto ret = oneValGetSet<Int16>(msg, data, tmp_count, -1);
if (!Twpp::success(ret) && m_scanparam->scannum == 0) {
m_scanparam->scannum = -1;
return { ReturnCode::CheckStatus, ConditionCode::BadValue };
}
return ret;
};
m_query[CapType::ICompression] = msgSupportGetAllSetReset;
//m_caps[CapType::ICompression] = std::bind(enmGetSetConst<Compression>, _1, _2, Compression::None);
m_caps[CapType::ICompression] = [this](Msg msg, Capability& data)->Result{
CapabilityPrintf(msg, enum2str(CapType::ICompression), msg == Msg::Set ? to_string((int)data.currentItem<CapType::ICompression>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::ICompression>();
if (Compression::None == mech || mech == Compression::Group4) {
m_compression = mech;
return success();
}
else
return badValue();
}
return CapSupGetAllReset<Compression, Compression, CapType::ICompression>(msg, data, { Compression::None, Compression::Group4 }, m_compression, Compression::None, m_compression == Compression::None ? 0 : 1, 0);
};
m_query[CapType::IBitDepth] = msgSupportGetAllSetReset;
m_caps[CapType::IBitDepth] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::IBitDepth), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IBitDepth>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IBitDepth>();
if (((mech == 1) && (m_scanparam->pixtype == 0)) || ((mech == 8) && (m_scanparam->pixtype == 1)) || ((mech == 24) && (m_scanparam->pixtype == 2))) {
m_iBitdepth = (UINT16)mech;
return success();
}
return badValue();
}
return CapSupGetAllReset<UINT16, UINT16, CapType::IBitDepth>(msg, data, m_iBitdepth, 24);
};
m_query[CapType::IBitOrder] = msgSupportGetAllSetReset;
m_caps[CapType::IBitOrder] = std::bind(oneValGetSetConst<BitOrder>, _1, _2, BitOrder::MsbFirst);
m_query[CapType::IPlanarChunky] = msgSupportGetAllSetReset;
m_caps[CapType::IPlanarChunky] = std::bind(enmGetSetConst<PlanarChunky>, _1, _2, PlanarChunky::Chunky);
m_query[CapType::IPhysicalWidth] = msgSupportGetAll;
m_caps[CapType::IPhysicalWidth] = std::bind(oneValGet<Fix32>, _1, _2, Fix32(static_cast<float>(header()->biWidth) / m_scanparam->resolution_dst));
m_query[CapType::IPhysicalHeight] = msgSupportGetAll;
m_caps[CapType::IPhysicalHeight] = std::bind(oneValGet<Fix32>, _1, _2, Fix32(static_cast<float>(header()->biHeight) / m_scanparam->resolution_dst));
m_query[CapType::IPixelFlavor] = msgSupportGetAllSetReset;
m_caps[CapType::IPixelFlavor] = std::bind(enmGetSetConst<PixelFlavor>, _1, _2, PixelFlavor::Chocolate);
m_query[CapType::IPixelType] = msgSupportGetAllSetReset;
m_caps[CapType::IPixelType] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::IPixelType), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IPixelType>()) : "");
if( Msg::Set==msg) {
auto mech = data.currentItem<CapType::IPixelType>();
if (mech == PixelType::Rgb || mech == PixelType::Gray || mech == PixelType::BlackWhite)
{
m_scanparam->automaticcolor = FALSE;
m_scanparam->pixtype = (int)mech;
if (m_scanparam->pixtype == (int)PixelType::Rgb){
m_scanparam->filter = (BYTE)Filter::None;
m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None;
}
else{
m_scanparam->multi_output_red = 0;//<2F>Dz<EFBFBD>ɫģʽ<C4A3><EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_scanparam->detachnoise.is_detachnoise = false;
m_scanparam->fadeback = false;
}
m_iBitdepth = mech == PixelType::Rgb ? 24 : (mech == PixelType::Gray ? 8 : 1);
return success();
}
return badValue();
}
return CapSupGetAllReset<int, PixelType, CapType::IPixelType>(msg, data, { PixelType::BlackWhite,PixelType::Gray,PixelType::Rgb }, m_scanparam->pixtype, PixelType::Rgb,
m_scanparam->pixtype == (int)PixelType::Rgb ? 2 : (m_scanparam->pixtype == (int)PixelType::Gray ? 1 : 0), 2);
};
m_query[CapType::IAutomaticColorEnabled] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticColorEnabled] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutomaticColorEnabled), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutomaticColorEnabled>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IAutomaticColorEnabled>();
if (mech) {
m_scanparam->automaticcolor = TRUE;
m_scanparam->filter = (BYTE)Filter::None;
m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None;
m_scanparam->pixtype = (int)PixelType::Rgb;
}
else
m_scanparam->automaticcolor = FALSE;
m_iBitdepth = m_scanparam->pixtype == int(PixelType::Rgb) ? 24 : (m_scanparam->pixtype == int(PixelType::Gray) ? 8 : 1);
return success();
}
return CapSupGetAllReset<int, Bool, CapType::IAutomaticColorEnabled>(msg, data, { FALSE,TRUE }, m_scanparam->automaticcolor, false, m_scanparam->automaticcolor ? 1 : 0, 0);
};
m_query[CapType::IAutomaticColorNonColorPixelType] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticColorNonColorPixelType] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutomaticColorNonColorPixelType), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutomaticColorNonColorPixelType>()) : "");
if (msg == Msg::Set) {
auto mech = data.currentItem<CapType::IAutomaticColorNonColorPixelType>();
if (m_scanparam->automaticcolor == TRUE) {
if ((UInt16)mech == 0 || (UInt16)mech == 1) {
m_scanparam->automaticcolortype = (UInt16)mech;
return success();
}
}
return seqError();
}
return CapSupGetAllReset<int, PixelType, CapType::IAutomaticColorNonColorPixelType>(msg, data, { PixelType::BlackWhite, PixelType::Gray }, m_scanparam->automaticcolortype, PixelType::Gray, m_scanparam->automaticcolortype, 1);
};
//add------------------jpeg<65><67><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>---------------------
m_query[CapType::IJpegQuality] = msgSupportGetAllSetReset;
m_caps[CapType::IJpegQuality] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IJpegQuality), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IJpegQuality>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IJpegQuality>();
if ((int)mech <= 0 || (int)mech > 100)
return badValue();
m_jpegQuality = (int)mech;
return success();
}
return CapSupGetAllResetEx<unsigned short, UInt16, CapType::IJpegQuality>(msg, data, m_jpegQuality, 80);
};
m_query[CapType::IUnits] = msgSupportGetAllSetReset;
m_caps[CapType::IUnits] = std::bind(enmGetSetConst<Unit>, _1, _2, Unit::Inches);
m_query[CapType::IXferMech] = msgSupportGetAllSetReset;
m_caps[CapType::IXferMech] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::IXferMech), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IXferMech>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IXferMech>();
if (mech == XferMech::Native || mech == XferMech::Memory || mech == XferMech::File) {
m_capXferMech = mech;
return success();
}
else {
return badValue();
}
}
return CapSupGetAllReset<XferMech, XferMech, CapType::IXferMech>(msg, data, { XferMech::Native, XferMech::File, XferMech::Memory }, m_capXferMech, XferMech::Native, (int)m_capXferMech, 0);
};
m_query[CapType::IXResolution] = msgSupportGetAllSetReset;
m_caps[CapType::IXResolution] = [this](Msg msg, Capability& data) {
CapabilityPrintf(msg, enum2str(CapType::IXResolution), msg == Msg::Set ? to_string((float)data.currentItem<CapType::IXResolution>()) : "");
switch (msg) {
case Msg::Get:
data = Capability::createRange<CapType::IXResolution>(Fix32(100.0f), Fix32(600.0f), Fix32(1.0f), Fix32(m_scanparam->resolution_dst), Fix32(200.0));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IXResolution>(Fix32(m_scanparam->resolution_dst));
return success();
case Msg::GetDefault:
case Msg::Reset:
m_scanparam->resolution_dst = 200.0f;
data = Capability::createOneValue<CapType::IXResolution>(Fix32(200.0f));
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IXResolution>();
if (mech < 100.0f || mech > 600.0f)
return badValue();
m_scanparam->resolution_dst = (float)mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IYResolution] = msgSupportGetAllSetReset;
m_caps[CapType::IYResolution] = m_caps[CapType::IXResolution];
m_query[CapType::IXNativeResolution] = msgSupportGetAll;
m_caps[CapType::IXNativeResolution] = std::bind(enmGet<Fix32>, _1, _2, Fix32(200.0));
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) {
CapabilityPrintf(msg, enum2str(CapType::ISupportedSizes), msg == Msg::Set ? to_string((int)data.currentItem<UInt16>()) : "");
if (Msg::Set == msg) {
//if (m_scanparam->is_autocrop)
// return success();
auto paper = data.currentItem<UInt16>();
if (std::distance(paperSizeList.begin(), std::find(paperSizeList.begin(), paperSizeList.end(), paper)) == paperSizeList.size())
return badValue();
else {
m_scanparam->papertype = (BYTE)paper;
if (paper == (BYTE)PaperSize::None || paper == (BYTE)PaperSize::UsStatement) {
m_scanparam->paperAlign = PaperAlign::Rot0;
m_scanparam->en_sizecheck = 0;
}
if (paper == (BYTE)PaperSize::UsStatement) {
m_autosize = (UInt16)AutoSize::None;
m_autoboarderdetcet = false;
m_scanparam->is_autocrop = 0;
}
else {
m_autosize = (paper == (BYTE)PaperSize::None) ? (UInt16)AutoSize::Auto : (UInt16)AutoSize::None;
m_autoboarderdetcet = paper == (BYTE)PaperSize::None;
m_scanparam->is_autocrop = paper == (BYTE)PaperSize::None ? 1 : 0;
}
return success();
}
}
return CapSupGetAllReset<BYTE, PaperSize, CapType::ISupportedSizes>(msg, data, { PaperSize::A4,PaperSize::A5,PaperSize::A6,
PaperSize::IsoB5,PaperSize::IsoB6,PaperSize::UsLetter,
PaperSize::UsLegal,PaperSize::None,(PaperSize)PaperSizeEx::K16
#ifndef G300
#if defined G200
,PaperSize::A3,PaperSize::UsLedger,PaperSize::IsoB4,
PaperSize::MaxSize,PaperSize::UsStatement,(PaperSize)PaperSizeEx::K8,(PaperSize)PaperSizeEx::K16,(PaperSize)PaperSizeEx::Trigeminy
#elif defined G400
,PaperSize::A3,PaperSize::UsLedger,PaperSize::IsoB4,PaperSize::MaxSize,PaperSize::UsStatement,
(PaperSize)PaperSizeEx::K8,(PaperSize)PaperSizeEx::K16,(PaperSize)PaperSizeEx::Trigeminy
#endif
#endif //
}, m_scanparam->papertype, PaperSize::None,
std::distance(paperSizeList.begin(), std::find(paperSizeList.begin(), paperSizeList.end(), m_scanparam->papertype)) == paperSizeList.size() ? 0 : std::distance(paperSizeList.begin(),
std::find(paperSizeList.begin(), paperSizeList.end(), m_scanparam->papertype)),
std::distance(paperSizeList.begin(), std::find(paperSizeList.begin(), paperSizeList.end(), 0)));
};
#ifdef G200
#ifndef ISG100
m_query[(CapType)(CapTypeEx::TwEx_SizeDetect)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_SizeDetect)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_SizeDetect), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
if (m_scanparam->papertype == (uint8_t)PaperSize::None || m_scanparam->papertype == (uint8_t)PaperSize::MaxSize || m_scanparam->papertype == (uint8_t)PaperSize::UsStatement ||
m_scanparam->papertype == (uint8_t)PaperSizeEx::Trigeminy)
return badValue();
auto mech = data.currentItem<Bool>();
m_scanparam->en_sizecheck = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, CapType(CapTypeEx::TwEx_SizeDetect)>(msg, data, { FALSE,TRUE }, m_scanparam->en_sizecheck, false, m_scanparam->en_sizecheck, 0);
};
#endif // !ISG100
#endif // G200
m_query[CapType::IOrientation] = msgSupportGetAllSetReset;
m_caps[CapType::IOrientation] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::IOrientation), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IOrientation>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IOrientation>();
if ((mech == Orientation::Landscape) && (m_scanparam->papertype == (uint8_t)PaperSize::None || m_scanparam->papertype == (uint8_t)PaperSize::MaxSize ||
m_scanparam->papertype == (uint8_t)PaperSize::UsStatement || m_scanparam->papertype == (uint8_t)PaperSizeEx::Trigeminy || m_scanparam->papertype == (uint8_t)PaperSize::A3 ||
m_scanparam->papertype == (uint8_t)PaperSize::IsoB4 || m_scanparam->papertype == (uint8_t)PaperSizeEx::K8 || m_scanparam->papertype == (uint8_t)PaperSize::UsLedger))
return badValue();
if (mech == Orientation::Landscape || mech == Orientation::Portrait) {
m_scanparam->paperAlign = (PaperAlign)mech;
return success();
}
return badValue();
}
return CapSupGetAllReset<PaperAlign, Orientation, CapType::IOrientation>(msg, data, { Orientation::Portrait, Orientation::Landscape }, m_scanparam->paperAlign, Orientation::Portrait, m_scanparam->paperAlign == 0 ? 0 : 1, 0);
};
m_query[CapType::IRotation] = msgSupportGetAllSetReset;
m_caps[CapType::IRotation] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::IRotation), msg == Msg::Set ? to_string((float)data.currentItem<Fix32>()) : "");
if (Msg::Set == msg) {
auto res = data.currentItem<Fix32>();
if (std::distance(imageRotateList.begin(), std::find(imageRotateList.begin(), imageRotateList.end(), res)) == imageRotateList.size())
return badValue();
else {
m_scanparam->imageRotateDegree = (float)res;
if (res != 0.0f)
m_scanparam->is_autotext = 0;
return success();
}
}
return CapSupGetAllReset<float, Fix32, CapType::IRotation>(msg, data, { Fix32(0.0f),Fix32(90.0f),Fix32(180.0f),Fix32(270.0f) }, m_scanparam->imageRotateDegree, Fix32(0.0),
std::distance(imageRotateList.begin(), std::find(imageRotateList.begin(), imageRotateList.end(), m_scanparam->imageRotateDegree)), 0);
};
#ifndef G200
scanner->Get_Scanner_PaperOn(); //<2F><><EFBFBD><EFBFBD>G300 G400 USBͨ<42>ŵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD>޷<EFBFBD>read_bulk <20>𵽼<EFBFBD><F0B5BDBC><EFBFBD>USB<53><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endif // !G200
m_query[CapType::SerialNumber] = msgSupportGetAll;
//m_caps[CapType::SerialNumber] = std::bind(oneValGetString, _1, _2, scanner->GetSerialNum());
m_caps[CapType::SerialNumber] = [this](Msg msg, Capability& data)->Result {
Str255 str;
str.setData(scanner->GetSerialNum().c_str(), scanner->GetSerialNum().size());
return CapSupGetAll<Str255, Str255, CapType::SerialNumber>(msg, data, str, str);
};
m_query[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = msgSupportGetAll;
//m_caps[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = std::bind(oneValGetString, _1, _2, scanner->GetFWVersion());
m_caps[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = [this](Msg msg, Capability& data)->Result {
Str255 str;
str.setData(scanner->GetFWVersion().c_str(), scanner->GetFWVersion().size());
return CapSupGetAllEx<Str255, (CapType)CapTypeEx::TwEx_HardwareVersion>(msg, data, str, str);
};
#ifndef G400
m_query[(CapType)(CapTypeEx::TwEx_ENCODE)] = msgSupportGetAll;
//m_caps[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = std::bind(oneValGetString, _1, _2, scanner->GetFWVersion());
m_caps[(CapType)(CapTypeEx::TwEx_ENCODE)] = [this](Msg msg, Capability& data)->Result {
Str255 str;
str.setData(scanner->get_scannercode().c_str(), 32);
return CapSupGetAllEx<Str255, (CapType)CapTypeEx::TwEx_ENCODE>(msg, data, str, str);
};
#endif
m_query[CapType::FeederLoaded] = msgSupportGetAll;
m_caps[CapType::FeederLoaded] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::FeederLoaded));
return CapSupGetAll<Bool, Bool, CapType::FeederLoaded>(msg, data, Bool(scanner->Get_Scanner_PaperOn()), Bool(scanner->Get_Scanner_PaperOn()));
};
m_query[CapType::Indicators] = msgSupportGetAllSetReset;
m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::Indicators), msg == Msg::Set ? to_string((int)data.currentItem<CapType::Indicators>()) : "");
if (Msg::Set == msg) {
auto show = data.currentItem<CapType::Indicators>();
m_bIndicator = show;
return success();
}
return CapSupGetAllReset<bool, Bool, CapType::Indicators>(msg, data, { FALSE,TRUE }, m_bIndicator, TRUE, m_bIndicator ? 1 : 0, 1);
};
m_query[CapType::CustomDsData] = msgSupportGetAll;
m_caps[CapType::CustomDsData] = [this](Msg msg, Capability& data) -> Result {
return CapSupGetAllEx<Bool, CapType::CustomDsData>(msg, data, Bool(true), Bool(true));
};
m_query[CapType::EnableDsUiOnly] = msgSupportGetAll;
m_caps[CapType::EnableDsUiOnly] = std::bind(enmGet<Bool>, _1, _2, Bool(true));
m_query[CapType::PaperDetectable] = msgSupportGetAll;
m_caps[CapType::PaperDetectable] = std::bind(oneValGet<Bool>, _1, _2, Bool(true));
m_query[CapType::FeederEnabled] = msgSupportGetAllSetReset;
m_caps[CapType::FeederEnabled] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::FeederEnabled), msg == Msg::Set ? to_string((int)data.currentItem<CapType::FeederEnabled>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::FeederEnabled>();
m_bFeederEnabled = mech;
return success();
}
return CapSupGetAllReset<bool, Bool, CapType::PaperDetectable>(msg, data, m_bFeederEnabled, Bool(true));
};
m_query[CapType::Duplex] = msgSupportGetAll;
m_caps[CapType::Duplex] = std::bind(oneValGet<Duplex>, _1, _2, Duplex::OnePass);
m_query[CapType::DuplexEnabled] = msgSupportGetAllSetReset;
m_caps[CapType::DuplexEnabled] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::DuplexEnabled), msg == Msg::Set ? to_string((int)data.currentItem<CapType::DuplexEnabled>()) : "");
if (Msg::Set == msg) {
bool mech = data.currentItem<CapType::DuplexEnabled>();
m_scanparam->is_duplex = mech;
if (!mech){
m_scanparam->is_backrotate180 = 0;//<2F><><EFBFBD><EFBFBD><E6B1B3><EFBFBD><EFBFBD>ת180<38><EFBFBD><E3B2BB><EFBFBD><EFBFBD>
m_scanparam->is_switchfrontback = 0;
m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = m_scanparam->en_fold = 0;
}
return success();
}
return CapSupGetAllReset<BYTE, Bool, CapType::DuplexEnabled>(msg, data, m_scanparam->is_duplex, Bool(true));
};
m_query[CapType::AutoFeed] = msgSupportGetAllSetReset;
m_caps[CapType::AutoFeed] = [this](Msg msg, Capability& data) -> Result {
CapabilityPrintf(msg, enum2str(CapType::AutoFeed), msg == Msg::Set ? to_string((int)data.currentItem<CapType::AutoFeed>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::AutoFeed>();
m_bAutoFeed = mech;
return success();
}
return CapSupGetAllReset<bool, Bool, CapType::AutoFeed>(msg, data, { false,true }, m_bAutoFeed, true, m_bAutoFeed ? 1 : 0, 1);
};
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<CapType::IImageFileFormat>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IImageFileFormat>();
if (mech == ImageFileFormat::Bmp ||
mech == ImageFileFormat::Tiff ||
mech == ImageFileFormat::Jfif) {
m_capImageFileFormat = mech;
return success();
}
else
return badValue();
}
return CapSupGetAllReset < ImageFileFormat, ImageFileFormat, CapType::IImageFileFormat>(msg, data, { ImageFileFormat::Bmp, ImageFileFormat::Tiff,ImageFileFormat::Jfif },
m_capImageFileFormat, ImageFileFormat::Bmp, m_capImageFileFormat == ImageFileFormat::Bmp ? 0 : (m_capImageFileFormat == ImageFileFormat::Tiff ? 1 : 2), 0);
};
//custom define
m_query[CapType::IAutomaticDeskew] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticDeskew] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutomaticDeskew), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutomaticDeskew>()) : "");
if (Msg::Set == msg) {
auto atuodsw = data.currentItem<CapType::IAutomaticDeskew>();
m_scanparam->autodescrew = (bool)atuodsw;
return success();
}
return CapSupGetAllReset<BYTE, bool, CapType::IAutomaticDeskew>(msg, data, m_scanparam->autodescrew, true);
};
m_query[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_SwitchFrontBack), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
if ((!m_scanparam->is_duplex) && mech == TRUE)
return badValue();
m_scanparam->is_switchfrontback = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_SwitchFrontBack>(msg, data, m_scanparam->is_switchfrontback, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_SwitchFrontBack>(msg, data, { FALSE,TRUE }, m_scanparam->is_switchfrontback, (Bool)false, m_scanparam->is_switchfrontback ? 1 : 0, 0);
};
m_query[CapType::IAutomaticRotate] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutomaticRotate), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutomaticRotate>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IAutomaticRotate>();
m_scanparam->is_autotext = (bool)mech;
if (mech)
m_scanparam->imageRotateDegree = 0.0f;
return success();
}
return CapSupGetAllReset<BYTE, bool, CapType::IAutomaticRotate>(msg, data, m_scanparam->is_autotext, false);
};
m_query[CapType::IAutomaticCropUsesFrame] = msgSupportGetAll;
m_caps[CapType::IAutomaticCropUsesFrame] = [this](Msg msg, Capability& data)->Result {
return CapSupGetAll<BYTE, bool, CapType::IAutomaticCropUsesFrame>(msg, data, m_scanparam->is_autocrop, false);
};
m_query[CapType::AutoScan] = msgSupportGetAllSetReset;
m_caps[CapType::AutoScan] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::AutoScan), msg == Msg::Set ? to_string((int)data.currentItem<CapType::AutoScan>()) : "");
if (Msg::Set == msg) {
auto autoscan = data.currentItem<CapType::AutoScan>();
m_autoscan = autoscan;
return success();
}
//return CapSupGetAllReset<Bool, Bool, CapType::AutoScan>(msg, data, { FALSE,TRUE }, m_autoscan, Bool(true), m_autoscan ? 1 : 0, 0);
return CapSupGetAllReset<Bool, Bool, CapType::AutoScan>(msg, data, m_autoscan, FALSE);
};
m_query[CapType::IAutoSize] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoSize] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutoSize), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutoSize>()) : "");
if (Msg::Set == msg) {
auto autosize = data.currentItem<CapType::IAutoSize>();
if (autosize == AutoSize::Auto) {
if (m_scanparam->papertype == (BYTE)PaperSize::UsStatement) {
m_scanparam->is_autocrop = 0;
m_autoboarderdetcet = false;
}
else {
m_scanparam->is_autocrop = 1;
m_scanparam->papertype = (BYTE)Twpp::PaperSize::None;
m_scanparam->paperAlign = PaperAlign::Rot0;
m_autoboarderdetcet = true;
}
}
else {
m_autoboarderdetcet = false;
m_scanparam->is_autocrop = 0;
}
m_autosize = (UInt16)autosize;
return success();
}
return CapSupGetAllReset<UInt16, AutoSize, CapType::IAutoSize>(msg, data, { AutoSize::None, AutoSize::Auto }, m_autosize, AutoSize::None, (m_autosize == (UInt16)AutoSize::Auto) ? 1 : 0, 0);
};
m_query[CapType::IAutomaticBorderDetection] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticBorderDetection] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutomaticBorderDetection), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutomaticBorderDetection>()) : "");
if (Msg::Set == msg) {
auto autodetectborder = data.currentItem<CapType::IAutomaticBorderDetection>();
if (autodetectborder) {
if (m_scanparam->papertype != (BYTE)PaperSize::UsStatement) {
m_scanparam->is_autocrop = true;
m_scanparam->papertype = (BYTE)Twpp::PaperSize::None;
m_scanparam->paperAlign = PaperAlign::Rot0;
m_autosize = (UInt16)AutoSize::Auto;
}
}
else {
m_autosize = (UInt16)AutoSize::None;
}
m_autoboarderdetcet = autodetectborder;
return success();
}
return CapSupGetAllReset<Bool, Bool, CapType::IAutomaticBorderDetection>(msg, data, { false,true }, m_autoboarderdetcet, false, m_autoboarderdetcet ? 1 : 0, 0);
};
//m_query[CapType::IImageMerge] = msgSupportGetAllSetReset;
//m_caps[CapType::IImageMerge] = [this](Msg msg, Capability& data)->Result {
// if (Msg::Set == msg) {
// auto autocrop = data.currentItem<CapType::IImageMerge>();
// m_scanparam->en_fold = (BYTE)autocrop;
// if ((UInt16)autocrop != 0){
// m_scanparam->is_duplex = 1;
// m_scanparam->autodescrew = 1;//<2F>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD>ʱ Ĭ<><C4AC><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ƫ
// m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = 0;
// }
// return success();
// }
// return CapSupGetAllResetEx<BYTE, UInt16, CapType::IImageMerge>(msg, data, m_scanparam->en_fold, 0);
//};
m_query[CapType(CapTypeEx::TwEx_EnFold)] = msgSupportGetAllSetReset;
m_caps[CapType(CapTypeEx::TwEx_EnFold)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_EnFold), msg == Msg::Set ? to_string((int)data.currentItem<Int32>()) : "");
if (Msg::Set == msg) {
auto autocrop = data.currentItem<Int32>();
m_scanparam->en_fold = (Int32)autocrop;
if ((UInt16)autocrop != 0) {
m_scanparam->is_duplex = 1;
m_scanparam->autodescrew = 1;//<2F>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD>ʱ Ĭ<><C4AC><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD>ƫ
m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = 0;
}
return success();
}
return CapSupGetAllResetEx<BYTE, Int32, (CapType)CapTypeEx::TwEx_EnFold>(msg, data, m_scanparam->en_fold, 0);
//return CapSupGetAllResetEx<BYTE, Int32, (CapType)CapTypeEx::TwEx_EnFold>(msg, data, { 0,1 }, m_scanparam->en_fold, 0, m_scanparam->en_fold ? 1 : 0, 0);
};
m_query[CapType::IAutoDiscardBlankPages] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IAutoDiscardBlankPages), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IAutoDiscardBlankPages>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IAutoDiscardBlankPages>();
if ((mech == DiscardBlankPages::Auto) || (mech == DiscardBlankPages::Disabled)||((int)mech == 65535))
{
if ((int)mech == 65535 || mech == DiscardBlankPages::Auto)
{
m_scanparam->is_autodiscradblank_normal = 1;
m_scanparam->is_duplex = 1;
m_scanparam->en_fold = 0;
m_scanparam->is_autodiscradblank_vince = 0;
}
else
{
m_scanparam->is_autodiscradblank_normal = 0;
}
return success();
}
return badValue();
}
DiscardBlankPages autodiscradblank;
if (Msg::GetDefault == msg || (Msg::Reset == msg)) {
m_scanparam->is_autodiscradblank_normal = false;
}
m_scanparam->is_autodiscradblank_normal ? (autodiscradblank = DiscardBlankPages::Auto) : (autodiscradblank = DiscardBlankPages::Disabled);
return CapSupGetAllReset<DiscardBlankPages, DiscardBlankPages, CapType::IAutoDiscardBlankPages>(msg, data, autodiscradblank, DiscardBlankPages::Disabled);
};
/*costom caps*/
//<2F><><EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD>ҳ<EFBFBD><D2B3>Ʊ
m_query[(CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IAutoDiscardBlankVince), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_autodiscradblank_vince = mech;
if (mech) {
m_scanparam->is_duplex = 1;
m_scanparam->en_fold = 0;
m_scanparam->is_autodiscradblank_normal = 0;
}
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IAutoDiscardBlankVince>(msg, data, m_scanparam->is_autodiscradblank_vince, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IAutoDiscardBlankVince>(msg, data, { FALSE,TRUE }, m_scanparam->is_autodiscradblank_vince, Bool(false), m_scanparam->is_autodiscradblank_vince ? 1 : 0, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IBackRotate180), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
if (m_scanparam->is_duplex && mech)
m_scanparam->is_backrotate180 = mech;
else
return badValue();
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IBackRotate180>(msg, data, m_scanparam->is_backrotate180, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IBackRotate180>(msg, data, { FALSE,TRUE }, m_scanparam->is_backrotate180, Bool(false), m_scanparam->is_backrotate180 ? 1 : 0, 0);
};
//<2F><><EFBFBD>ڿ<EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_IFillBackground)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFillBackground)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFillBackground), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->fillbackground = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IFillBackground>(msg, data, m_scanparam->fillbackground, true);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IFillBackground>(msg, data, { FALSE,TRUE }, m_scanparam->fillbackground, Bool(true), m_scanparam->fillbackground ? 1 : 0, 1);
};
//<2F>ü<EFBFBD><C3BC><EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_CroporDesaskewIndent)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_CroporDesaskewIndent)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CroporDesaskewIndent), msg == Msg::Set ? to_string((int)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
if ((mech > 30 || mech < 5) && ((bool)m_scanparam->is_autocrop == true))
return badValue();
m_scanparam->indent = mech;
return success();
}
return CapSupGetAllResetEx<int, UInt32, (CapType)CapTypeEx::TwEx_CroporDesaskewIndent>(msg, data, m_scanparam->indent, 5);
};
//<2F>Զ<EFBFBD><D4B6>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_CropNoise)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_CropNoise)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CropNoise), msg == Msg::Set ? to_string((int)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
if ((mech > 20 || mech < 0) && ((bool)m_scanparam->is_autocrop == true))
return badValue();
m_scanparam->noise = mech;
return success();
}
return CapSupGetAllResetEx<int, UInt32, (CapType)CapTypeEx::TwEx_CropNoise>(msg, data, m_scanparam->noise, 8);
};
//<2F>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD>к;<D0BA>ƫ<EFBFBD>Ķ<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ֵ
m_query[(CapType)(CapTypeEx::TwEx_CroporDesaskewThreshold)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_CroporDesaskewThreshold)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CroporDesaskewThreshold), msg == Msg::Set ? to_string((int)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
if (mech > 50 || mech < 30)
return badValue();
m_scanparam->AutoCrop_threshold = mech;
return success();
}
return CapSupGetAllResetEx<int, UInt32, (CapType)CapTypeEx::TwEx_CroporDesaskewThreshold>(msg, data, m_scanparam->AutoCrop_threshold, 40);
};
//<2F>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD>ʽ
m_query[(CapType)(CapTypeEx::TwEx_FillBackgroundMode)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_FillBackgroundMode)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_FillBackgroundMode), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_convex = mech;
return success();
}
return CapSupGetAllResetEx<bool, Bool, (CapType)CapTypeEx::TwEx_FillBackgroundMode>(msg, data, m_scanparam->is_convex, Bool(true));
};
//<2F><EFBFBD><EEB4A9>
m_query[(CapType)(CapTypeEx::TwEx_IFillHole)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFillHole)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFillHole), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->fillhole.is_fillhole = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IFillHole>(msg, data, m_scanparam->fillhole.is_fillhole, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IFillHole>(msg, data, { FALSE,TRUE }, m_scanparam->fillhole.is_fillhole, Bool(false), m_scanparam->fillhole.is_fillhole ? 1 : 0, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_IFillHoleRatio)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFillHoleRatio)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFillHoleRatio), msg == Msg::Set ? to_string((int)data.currentItem<Int32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Int32>();
if (mech > 0 && mech < 50) {
m_scanparam->fillhole.fillholeratio = (int)mech;
return success();
}
return badValue();
}
return CapSupGetAllResetEx<int, Int32, (CapType)CapTypeEx::TwEx_IFillHoleRatio>(msg, data, m_scanparam->fillhole.fillholeratio, 10);
};
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ż<EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_IDetachNoise)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IDetachNoise)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IDetachNoise), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
if (m_scanparam->pixtype != 0)
return badValue();
auto mech = data.currentItem<Bool>();
m_scanparam->detachnoise.is_detachnoise = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IDetachNoise>(msg, data, m_scanparam->detachnoise.is_detachnoise, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IDetachNoise>(msg, data, { FALSE,TRUE }, m_scanparam->detachnoise.is_detachnoise, FALSE, m_scanparam->detachnoise.is_detachnoise ? 1 : 0, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_IDetachNoiseValue)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IDetachNoiseValue)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IDetachNoiseValue), msg == Msg::Set ? to_string((int)data.currentItem<Int32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Int32>();
if (mech > 9 && mech < 51) {
m_scanparam->detachnoise.detachnoise = (int)mech;
return success();
}
return badValue();
}
return CapSupGetAllResetEx<int, Int32, (CapType)CapTypeEx::TwEx_IDetachNoiseValue>(msg, data, m_scanparam->detachnoise.detachnoise, 10);
};
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_IFadeBack)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFadeBack)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFadeBack), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
if (m_scanparam->pixtype != 2)
return badValue();
auto mech = data.currentItem<Bool>();
m_scanparam->fadeback = mech;
return success();
}
return CapSupGetAllResetEx<bool, Bool, (CapType)CapTypeEx::TwEx_IFadeBack>(msg, data, m_scanparam->fadeback, false);
};
m_query[(CapType)(CapTypeEx::TwEx_IFadeBackValue)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFadeBackValue)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFadeBackValue), msg == Msg::Set ? to_string((int)data.currentItem<Int32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Int32>();
if (mech > 0 && mech < 129) {
m_scanparam->fadeback_range = (int)mech;
return success();
}
return badValue();
}
return CapSupGetAllResetEx<int, Int32, (CapType)CapTypeEx::TwEx_IFadeBackValue>(msg, data, m_scanparam->fadeback_range, 40);
};
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_IMultiOutputRed)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IMultiOutputRed)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IMultiOutputRed), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
if (m_scanparam->pixtype == (BYTE)PixelType::Rgb)
m_scanparam->multi_output_red = mech;
else
return badValue();
//m_scanparam->multi_output_red = 0;//<2F>Dz<EFBFBD>ɫ <20><><EFBFBD><EFBFBD>ʹ<EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IMultiOutputRed>(msg, data, m_scanparam->multi_output_red, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_IMultiOutputRed>(msg, data, { FALSE,TRUE }, m_scanparam->multi_output_red, FALSE, m_scanparam->multi_output_red ? 1 : 0, 0);
};
//<2F><><EFBFBD><EFBFBD><E2BFA8><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_HsvCorrect)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_HsvCorrect)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_HsvCorrect), msg == Msg::Set ? to_string((int)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
if (mech && m_scanparam->pixtype != (int)PixelType::Rgb)
return badValue();
m_scanparam->hsvcorrect = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_HsvCorrect>(msg, data, m_scanparam->hsvcorrect, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_HsvCorrect>(msg, data, { FALSE,TRUE }, m_scanparam->hsvcorrect, FALSE, m_scanparam->hsvcorrect ? 1 : 0, 0);
};
m_query[CapType::IFilter] = msgSupportGetAllSetReset;
m_caps[CapType::IFilter] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IFilter), msg == Msg::Set ? to_string((int)data.currentItem<CapType::IFilter>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IFilter>();
if (mech == Filter::None || mech == Filter::Red || mech == Filter::Green || mech == Filter::Blue) {
if (((Filter)mech != Filter::None) && (m_scanparam->pixtype == (int)PixelType::Rgb))
return badValue();
m_scanparam->filter = (BYTE)mech;
if (mech != Filter::None) {
m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None;
}
return success();
}
return badValue();
}
return CapSupGetAllReset<BYTE, Filter, CapType::IFilter>(msg, data, { Filter::Red,Filter::Green,Filter::Blue,Filter::None }, m_scanparam->filter, Filter::None, m_scanparam->filter, 3);
};
//<2F><>ɫ<EFBFBD><C9AB>ǿ
m_query[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IEnhanceColor), msg == Msg::Set ? to_string((int)data.currentItem<Int16>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Int16>();
if (m_scanparam->pixtype == (int)PixelType::Rgb)
{
m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None;
m_scanparam->filter = (BYTE)Filter::None;
return badValue();
}
else
{
if (mech == Enchace_Color::Enhance_None || mech == Enchace_Color::Enhance_Red || mech == Enchace_Color::Enhance_Green || mech == Enchace_Color::Enhance_Blue)
{
m_scanparam->enhance_color = (BYTE)mech;
if (mech != (BYTE)Enchace_Color::Enhance_None)
m_scanparam->filter = (BYTE)Filter::None;
return success();
}
}
}
return CapSupGetAllResetEx<BYTE, Enchace_Color, (CapType)CapTypeEx::TwEx_IEnhanceColor>(msg, data, m_scanparam->enhance_color, (Enchace_Color)0);
//return CapSupGetAllResetEx<BYTE, Enchace_Color, (CapType)CapTypeEx::TwEx_IEnhanceColor>(msg, data, { Enchace_Color::Enhance_None,Enchace_Color::Enhance_Red,Enchace_Color::Enhance_Green,Enchace_Color::Enhance_Blue }, m_scanparam->enhance_color, Enchace_Color::Enhance_None, m_scanparam->enhance_color, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_Sharpen)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_Sharpen)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_Sharpen), msg == Msg::Set ? to_string((int)data.currentItem<Int16>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Int16>();
if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
return badValue();
m_scanparam->sharpen = (BYTE)mech;
return success();
}
return CapSupGetAllResetEx<BYTE, SharpenBlur, (CapType)CapTypeEx::TwEx_Sharpen>(msg, data, m_scanparam->sharpen, SharpenBlur::Sharpen_Normal);
//return CapSupGetAllResetEx<BYTE, SharpenBlur, (CapType)CapTypeEx::TwEx_Sharpen>(msg, data, { SharpenBlur::Sharpen_None,SharpenBlur::Sharpen_Normal,SharpenBlur::Sharpen_More,SharpenBlur::Sharpen_Blur,SharpenBlur::Sharpen_Blur_More }, m_scanparam->sharpen, SharpenBlur::Sharpen_None, m_scanparam->sharpen, 0);
};
/*<2A><><EFBFBD><EFBFBD> <20>Աȶ<D4B1> gamma range<67><65><EFBFBD><EFBFBD> Range <20><><EFBFBD><EFBFBD>*/
m_query[CapType::IBrightness] = msgSupportGetAllSetReset;
m_caps[CapType::IBrightness] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IBrightness), msg == Msg::Set ? to_string((float)data.currentItem<CapType::IBrightness>()) : "");
switch (msg) {
case Msg::Get:
data = Capability::createRange<CapType::IBrightness>(Fix32(-1000.0f), Fix32(1000.0f), Fix32(333.3f), Fix32(m_scanparam->brightness), Fix32(0.0));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IBrightness>(Fix32(m_scanparam->brightness));
return success();
case Msg::GetDefault:
case Msg::Reset:
m_scanparam->brightness = 0.0f;
data = Capability::createOneValue<CapType::IBrightness>(Fix32(0.0f));
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IBrightness>();
if (mech > 1000.0f || mech < -1000.0f)
return badValue();
m_scanparam->brightness = (float)mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IContrast] = msgSupportGetAllSetReset;
m_caps[CapType::IContrast] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IContrast), msg == Msg::Set ? to_string((float)data.currentItem<CapType::IContrast>()) : "");
switch (msg) {
case Msg::Get:
data = Capability::createRange<CapType::IContrast>(Fix32(-1000.0f), Fix32(1000.0f), Fix32(333.3f), Fix32(m_scanparam->contrast), Fix32(0.0));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IContrast>(Fix32(m_scanparam->contrast));
return success();
case Msg::GetDefault:
case Msg::Reset:
m_scanparam->contrast = 0.0f;
data = Capability::createOneValue<CapType::IContrast>(Fix32(0.0f));
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IContrast>();
if (mech > 1000.0f || mech < -1000.0f)
return badValue();
m_scanparam->contrast = (float)mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IGamma] = msgSupportGetAllSetReset;
m_caps[CapType::IGamma] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::IGamma), msg == Msg::Set ? to_string((float)data.currentItem<CapType::IGamma>()) : "");
switch (msg) {
case Msg::Get:
data = Capability::createRange<CapType::IGamma>(Fix32(0.0f), Fix32(5.0f), Fix32(1.0f), Fix32(m_scanparam->gamma), Fix32(1.0));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IGamma>(Fix32(m_scanparam->gamma));
return success();
case Msg::GetDefault:
case Msg::Reset:
m_scanparam->gamma = 1.0f;
data = Capability::createOneValue<CapType::IGamma>(Fix32(0.0f));
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IGamma>();
if (mech > 5.0f || mech < 0.0f)
return badValue();
m_scanparam->gamma = (float)mech;
return success();
}
default:
return capBadOperation();
}
};
/*<2A><><EFBFBD><EFBFBD>ΪӲ<CEAA><D3B2>Э<EFBFBD><D0AD>*/
m_query[(CapType)(CapTypeEx::TwEx_ScrewDetectEnable)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_ScrewDetectEnable)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_ScrewDetectEnable), msg == Msg::Set ? to_string((float)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_skrewdetect = mech;
return success();
}
Bool en = m_scanparam->hardwarecaps.en_skrewdetect == 0 ? Bool(false) : Bool(true);
return CapSupGetAllResetEx<Bool, Bool, (CapType)(CapTypeEx::TwEx_ScrewDetectEnable)>(msg, data,(Bool)m_scanparam->hardwarecaps.en_skrewdetect , Bool(true));
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_ScrewDetectEnable>(msg, data, { FALSE ,TRUE }, m_scanparam->hardwarecaps.en_skrewdetect, TRUE, m_scanparam->hardwarecaps.en_skrewdetect ? 1 : 0, 1);
};
m_query[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_ScrewLevel), msg == Msg::Set ? to_string((float)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
if (mech >= 1 && mech <= 5) {
m_scanparam->hardwarecaps.skrewdetectlevel = mech;
return success();
}
return badValue();
}
return CapSupGetAllResetEx<BYTE, UInt32, (CapType)CapTypeEx::TwEx_ScrewLevel>(msg, data, m_scanparam->hardwarecaps.skrewdetectlevel, (UInt32)3);
//return oneValGetSet<UInt8>(msg,data,m_scanparam->hardwarecaps.skrewdetectlevel,3);
};
//װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_StableDetectEnable)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_StableDetectEnable)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_StableDetectEnable), msg == Msg::Set ? to_string((float)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_stapledetect = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_StableDetectEnable>(msg, data, m_scanparam->hardwarecaps.en_stapledetect, false);
//return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_StableDetectEnable>(msg, data, { FALSE,TRUE }, m_scanparam->hardwarecaps.en_stapledetect, FALSE, m_scanparam->hardwarecaps.en_stapledetect==0 ? 0 : 1, 0);
};
//<2F>۽Ǽ<DBBD><C7BC><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_DogEarDelection)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_DogEarDelection)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_DogEarDelection), msg == Msg::Set ? to_string((float)data.currentItem<Bool>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_dogeardetection = mech;
return success();
}
return CapSupGetAllResetEx<BYTE, Bool, (CapType)CapTypeEx::TwEx_DogEarDelection>(msg, data, m_scanparam->is_dogeardetection, FALSE);
};
//<2F>۽Ǽ<DBBD><C7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>۶<EFBFBD><DBB6>㵽ʵ<E3B5BD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_DogEarDistance)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_DogEarDistance)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_DogEarDistance), msg == Msg::Set ? to_string((float)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
if (mech >= 10 && mech <= 300)
m_scanparam->dogeardistance = mech;
else
return badValue();
return success();
}
return CapSupGetAllResetEx<UInt32, UInt32, (CapType)CapTypeEx::TwEx_DogEarDistance>(msg, data, m_scanparam->dogeardistance, 50);
};
//˫<>ż<EFBFBD><C5BC><EFBFBD> <20><><EFBFBD>ٷ<EFBFBD><D9B7><EFBFBD>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>Э<EFBFBD><D0AD><EFBFBD>޸<EFBFBD>Ϊbool<6F><6C> <20><><EFBFBD><EFBFBD>Уʹ<D0A3><CAB9>bool<6F><6C><EFBFBD>ͣ<EFBFBD><CDA3><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ñ<EFBFBD>׼twainЭ<6E><D0AD>
m_query[CapType::DoubleFeedDetection] = msgSupportGetAllSetReset;
m_caps[CapType::DoubleFeedDetection] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapType::DoubleFeedDetection), msg == Msg::Set ? to_string((float)data.currentItem<UInt16>()) : "");
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<UInt16>(CapType::DoubleFeedDetection, { 0 ,1}, m_scanparam->hardwarecaps.en_doublefeed ? 0 : 1, 0);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::GetCurrent:
data = Capability::createOneValue<UInt16>(CapType::DoubleFeedDetection, (UInt16)m_scanparam->hardwarecaps.en_doublefeed ? 0 : 1);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->hardwarecaps.en_doublefeed = 1;
data = Capability::createOneValue<UInt16>(CapType::DoubleFeedDetection, 0);
return { ReturnCode::Success, ConditionCode::Success };
case Msg::Set: {
auto mech = data.currentItem<UInt16>();
m_scanparam->hardwarecaps.en_doublefeed = mech ? 0 : 1;
return success();
}
default:
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
/*if (Msg::Set == msg) {
auto mech = data.currentItem<UInt16>();
m_scanparam->hardwarecaps.en_doublefeed = mech ? 1 : 0;
return success();
}
return CapSupGetAllResetEx<BYTE, UInt16, CapType::DoubleFeedDetection>(msg, data, m_scanparam->hardwarecaps.en_doublefeed, TRUE);*/
};
#ifdef G200
//<2F>͹<EFBFBD><CDB9><EFBFBD>ģʽ
m_query[(CapType)(CapTypeEx::TwEx_LowPowerMode)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_LowPowerMode)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_LowPowerMode), msg == Msg::Set ? to_string((float)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
m_scanparam->hardwarecaps.lowpowermode = (LowPowerMode)mech;
return success();
}
return CapSupGetAllResetEx<LowPowerMode, UInt32, (CapType)CapTypeEx::TwEx_LowPowerMode>(msg, data, m_scanparam->hardwarecaps.lowpowermode, LowPowerMode::Min_30);
//return CapSupGetAllResetEx<LowPowerMode, UInt32, (CapType)CapTypeEx::TwEx_LowPowerMode>(msg, data,
// { LowPowerMode::Min_None,LowPowerMode::Min_5,LowPowerMode::Min_10,LowPowerMode::Min_20, LowPowerMode::Min_30, LowPowerMode::Min_60, LowPowerMode::Min_120, LowPowerMode::Min_240 },
// m_scanparam->hardwarecaps.lowpowermode, LowPowerMode::Min_30, (BYTE)m_scanparam->hardwarecaps.lowpowermode, 4);
};
#endif // LANXUM
m_query[(CapType)(CapTypeEx::TwEx_CropModel)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_CropModel)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CropModel), msg == Msg::Set ? to_string((float)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt32>();
if (m_scanparam->fillbackground ||
m_scanparam->autodescrew ||
m_scanparam->is_autocrop ||
m_scanparam->en_fold)
{
return badValue();
}
m_scanparam->normalCrop = (bool)mech;
return success();
}
return CapSupGetAllResetEx<bool, UInt32, (CapType)CapTypeEx::TwEx_CropModel>(msg, data, m_scanparam->normalCrop, false);
};
//ͼ<><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_ImageSplit)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_ImageSplit)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CropModel), msg == Msg::Set ? to_string((float)data.currentItem<UInt32>()) : "");
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_split = mech;
return success();
}
return CapSupGetAllResetEx<bool, Bool, (CapType)CapTypeEx::TwEx_ImageSplit>(msg, data, m_scanparam->is_split, false);
};
#ifdef UV
m_query[(CapType)(CapTypeEx::TwEx_UVModel)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_UVModel)] = [this](Msg msg, Capability& data)->Result {
CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_UVModel), msg == Msg::Set ? to_string((float)data.currentItem<Bool>()) : "");
switch (msg) {
case Msg::Get:{
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_UVModel), Bool(m_scanparam->hardwarecaps.en_uv));
//data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_UVModel), { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_uv), 0);
return success();
}
case Msg::Reset:
m_scanparam->hardwarecaps.en_uv = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_UVModel), m_scanparam->hardwarecaps.en_uv);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_UVModel), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_uv = mech?1:0;
return success();
}
default:
return capBadOperation();
}
};
#endif
return success();
}
Result HuagaoDs::identityCloseDs(const Identity&) {
// no need to explicitly release any resources if using RAII
// TWPP will free the whole source on its own after this method
if (guiIndicator->GetSafeHwnd())
guiIndicator->DestroyWindow();
if (guiTwain.get())
guiTwain.reset();
if (guiBridge.get())
guiBridge.reset();
scanner.reset();
bmpData.reset();
if (hMutex)
{
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
//saveGscanCapSetting();
return success();
}
Result HuagaoDs::pendingXfersGet(const Identity&, PendingXfers& data) {
data.setCount(m_pendingXfers);
return success();
}
Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) {
//!< end xfer if set count 0
if (bmpData->size() > 0)
{
bmpData.reset(new std::vector<unsigned char>);
}
int ret = scanner->aquire_bmpdata(*bmpData.get());
if (ret != 0) {
scanner->Set_ErrorCode(0);
if (guiIndicator->GetSafeHwnd())
guiIndicator->ShowWindow(SW_HIDE);
if (ret != -1) {
int index = scanner->geterrorindex();
if (ret == 82 && ((typeid(*scanner.get()) == typeid(GScanO1003399))))
showmsg("<EFBFBD><EFBFBD>ʾ", "<EFBFBD>ڵ<EFBFBD>" + to_string(index) + "ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۽ǣ<EFBFBD>ֹͣɨ<EFBFBD>", ret);
else if(ret==75 && ((typeid(*scanner.get()) == typeid(GScanO1003399))))
showmsg("<EFBFBD><EFBFBD>ʾ", "<EFBFBD>ڵ<EFBFBD>" + to_string(index) + "ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹͣɨ<EFBFBD>", ret);
else
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[(UsbSupported)ret], ret);
FileTools::writelog(log_ERROR, msgs[(UsbSupported)ret]);
#ifndef G200
scanner->clear_hwerror();
#endif // G200
}
else
{
if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince))
{
int num = scanner->get_scannum() * (m_scanparam->is_duplex ? 2 : 1) * (m_scanparam->multi_output_red ? 2 : 1) / (m_scanparam->en_fold ? 2 : 1) * (m_scanparam->is_split ? 2 : 1);
if ((num - scanner->get_imgTransfered()) != 0)
{
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[LOSE_IMAGE]);
FileTools::writelog(log_ERROR, msgs[LOSE_IMAGE]);
}
}
}
m_pendingXfers = 0;
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
//setState(DsState::Enabled);
}
else {
//setState(DsState::Open);
}
}
else {
m_pendingXfers = 1;
//setState( DsState::XferReady );
}
data.setCount(m_pendingXfers);
return success();
}
Result HuagaoDs::pendingXfersReset(const Identity&, PendingXfers& data) {
data.setCount(0);
if (scanner.get())
{
scanner->Stop_scan();
//scanner->reset();
scanner->ResetScanner();
}
//guiIndicator.reset();
if (guiIndicator->GetSafeHwnd())
guiIndicator->DestroyWindow();
return success();
}
Result HuagaoDs::setupMemXferGet(const Identity&, SetupMemXfer& data) {
auto bpl = bytesPerLine();
auto max = bpl * static_cast<UInt32>(header()->biHeight);
data.setMinSize(bpl);
data.setPreferredSize(max);
data.setMaxSize(max);
return success();
}
Result HuagaoDs::userInterfaceDisable(const Identity&, UserInterface& ui) {
if (guiTwain.get())
guiTwain.reset();
#if TWPP_DETAIL_OS_WIN
if (guiBridge.get())
guiBridge.reset();
#endif
return success();
}
Result HuagaoDs::userInterfaceEnable(const Identity&, UserInterface& ui) {
m_pendingXfers = 1;
m_memXferYOff = 0;
if (!ui.showUi()) {
// this is an exception when we want to set state explicitly, notifyXferReady can be called only in enabled state
// with hidden UI, the usual workflow DsState::Enabled -> notifyXferReady() -> DsState::XferReady is a single step
#ifndef G200
while (!scanner->Get_Scanner_PaperOn())
{
if (MessageBox(NULL, L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD>", L"<EFBFBD><EFBFBD>ʾ", MB_YESNO | MB_SYSTEMMODAL) == IDNO)
return seqError();
}
#endif // !G200
if (!scanner->IsConnected())
scanner->open(vid, pid);
if (!scanner->IsConnected())
{
MessageBox(NULL, L"USB<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>USB<53><42><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", L"<EFBFBD><EFBFBD>ʾ", MB_OK | MB_SYSTEMMODAL);
return seqError();
}
this_thread::sleep_for(chrono::milliseconds(100)); //ɨ<><C9A8>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ӳ<EFBFBD> <20><>ֹusb<73><62><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD>Ϣδ<CFA2><CEB4>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
auto ret = startScan();
//if (ret.status().condition() == Twpp::CC::NoMedia)
// return ret;
if (ret == success()) {
m_pendingXfers = 1;
}
else {
m_pendingXfers = 0;
return seqError();
}
return success();
}
return showTwainUI(ui);
}
Result HuagaoDs::userInterfaceEnableUiOnly(const Identity&, UserInterface& ui) {
// as a minimal source, we do not support GUI that just saves settings
return showTwainUI(ui, true);
}
Result HuagaoDs::imageInfoGet(const Identity&, ImageInfo& data) {
// our image does not change
if (m_pendingXfers == 0 || bmpData->size() == 0)
return success();
auto dib = header();
data.setBitsPerPixel(static_cast<Int16>(dib->biBitCount));
data.setHeight(dib->biHeight);
data.setPixelType(dib->biClrUsed == 2 ? PixelType::BlackWhite : (dib->biClrUsed == 256 ? PixelType::Gray : PixelType::Rgb));
data.setPlanar(false);
data.setWidth(dib->biWidth);
data.setXResolution(m_scanparam->resolution_dst);
data.setYResolution(m_scanparam->resolution_dst);
data.compression(m_compression);
switch (dib->biClrUsed)
{
case 2:
case 256:
data.setSamplesPerPixel(1);
data.bitsPerSample()[0] = 8;
break;
case 0:
data.setSamplesPerPixel(3);
data.bitsPerSample()[0] = 8;
data.bitsPerSample()[1] = 8;
data.bitsPerSample()[2] = 8;
default:
break;
}
return success();
}
Result HuagaoDs::imageLayoutGet(const Identity&, ImageLayout& data) {
// our image does not change
auto dib = header();
data.setDocumentNumber(1);
data.setFrameNumber(1);
data.setPageNumber(1);
data.setFrame(Frame(0, 0, static_cast<float>(dib->biWidth) / m_scanparam->resolution_dst, static_cast<float>(dib->biHeight) / m_scanparam->resolution_dst));
return success();
}
Result HuagaoDs::imageLayoutGetDefault(const Identity& origin, ImageLayout& data) {
return imageLayoutGet(origin, data);
}
Result HuagaoDs::imageLayoutSet(const Identity& origin, ImageLayout& lay) {
// we dont support setting image frame
ImageLayout def;
imageLayoutGetDefault(origin, def);
return lay.frame() == def.frame() ? success() : badValue();
}
Result HuagaoDs::imageLayoutReset(const Identity& origin, ImageLayout& data) {
return imageLayoutGet(origin, data);
}
Result HuagaoDs::imageMemXferGet(const Identity& origin, ImageMemXfer& data) {
if (!m_pendingXfers) {
return seqError();
}
// we can call our TWPP methods, but be careful about states
SetupMemXfer setup;
setupMemXferGet(origin, setup);
// just a simple stored BMP image
auto dib = header();
auto bpl = bytesPerLine();
auto memSize = data.memory().size();
if (memSize > setup.maxSize() || memSize < setup.minSize()) {
return badValue();
}
auto maxRows = memSize / bpl;
auto rows = std::min<UInt32>(maxRows, static_cast<UInt32>(dib->biHeight) - m_memXferYOff);
if (rows == 0) {
return seqError(); // image already transfered in this session
}
cv::Mat mat;
vector<uchar> cmpdata;
if (m_compression == Compression::Group4)
{
mat = cv::imdecode(*bmpData.get(), cv::IMREAD_GRAYSCALE);
G4Tiff gt(mat, G4Tiff::Mode::MemoryMode, "", 120, m_scanparam->resolution_dst);
gt.GetCompressedData(cmpdata);
}
data.setBytesPerRow(bpl);
data.setColumns(static_cast<UInt32>(dib->biWidth));
data.setRows(rows);
data.setBytesWritten(m_compression == Compression::None ? bpl * rows : cmpdata.size());
data.setXOffset(0);
data.setYOffset(m_memXferYOff);
data.setCompression(m_compression);
auto lock = data.memory().data();
char* out = lock.data();
// bottom-up BMP -> top-down memory transfer
if (m_compression == Compression::None)
{
auto begin = bmpEnd() - (bpl * (m_memXferYOff + 1));
for (UInt32 i = 0; i < rows; i++) {
// copy bytes
std::copy(begin, begin + bpl, out);
char* line = out;
out += bpl;
begin -= bpl;
if (dib->biBitCount == 24)
{
//BGR BMP -> RGB memory transfer
for (; line + 3 < out; line += 3) {
std::swap(line[0], line[2]);
}
}
}
}
else
{
std::copy(cmpdata.data(), cmpdata.data() + cmpdata.size(), out);
}
m_memXferYOff += rows;
if (m_memXferYOff >= static_cast<UInt32>(std::abs(dib->biHeight))) {
m_pendingXfers = 0;
m_memXferYOff = 0;
bmpData.reset(new std::vector<unsigned char>);
return { ReturnCode::XferDone, ConditionCode::Success };
}
return success();
}
static int xtfer = 0;
Result HuagaoDs::imageNativeXferGet(const Identity& id, ImageNativeXfer& data) {
if (!m_pendingXfers) {
return seqError();
}
if (m_haveError)
return { ReturnCode::Cancel, ConditionCode::Success };
if (data)
data.release();
// it does not get easier than that if we already have BMP
data = ImageNativeXfer(bmpSize());
std::copy(bmpBegin(), bmpEnd(), data.data<char>().data());
bmpData.reset(new std::vector<unsigned char>);
//FileTools::write_log("<22><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>ͼƬ ===> Twain transfered num of " + to_string(++xtfer) + " images");
FileTools::writelog(log_INFO, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>ͼƬ ===> Twain transfered num of " + to_string(++xtfer) + " images");
return { ReturnCode::XferDone, ConditionCode::Success };
}
Twpp::Result HuagaoDs::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data)
{
if (!scanner.get())
return seqError();
if (scanner->IsConnected()) {
scanner->Stop_scan();
}
data.setCount(scanner->Get_IsImageQueueEmpty() ? 0 : 1);
return success();
}
Twpp::Result HuagaoDs::setupFileXferGet(const Twpp::Identity& origin, Twpp::SetupFileXfer& data)
{
data.setFilePath(m_fileXfer.filePath());
data.setFormat(m_fileXfer.format());
return success();
}
Twpp::Result HuagaoDs::setupFileXferGetDefault(const Twpp::Identity& origin, Twpp::SetupFileXfer& data)
{
Str255 str("HGTwain.bmp");
data.setFilePath(str);
data.setFormat(ImageFileFormat::Bmp);
return success();
}
Twpp::Result HuagaoDs::setupFileXferSet(const Twpp::Identity& origin, Twpp::SetupFileXfer& data)
{
m_fileXfer.setFilePath(data.filePath());
m_fileXfer.setFormat(data.format());
return success();
}
Twpp::Result HuagaoDs::setupFileXferReset(const Twpp::Identity& origin, Twpp::SetupFileXfer& data)
{
m_fileXfer.setFormat(Twpp::ImageFileFormat::Bmp);
std::string templateName = "HG";
char* tempPath = mktemp((char*)templateName.c_str());
if (tempPath) {
Str255 str;
str.setData(tempPath, strlen(tempPath));
m_fileXfer.setFilePath(str);
return success();
}
return badProtocol();
}
static int indeximg = 0;
Twpp::Result HuagaoDs::imageFileXferGet(const Twpp::Identity& origin)
{
if (!m_pendingXfers)
return seqError();
string filename = m_fileXfer.filePath().string();
switch (m_fileXfer.format())
{
case ImageFileFormat::Bmp: {
FILE* pfile = fopen(filename.c_str(), "wb");
if (pfile) {
if (bmpData->size() > 0) {
fwrite(bmpData->data(), 1, bmpData->size(), pfile);
bmpData.reset(new std::vector<unsigned char>);
fclose(pfile);
return Result(ReturnCode::XferDone, ConditionCode::Success);
}
}
return Result(ReturnCode::Failure, ConditionCode::BadValue);
}
case ImageFileFormat::Tiff:
case ImageFileFormat::Jfif: {
BITMAPINFOHEADER& bmpinfo = *((BITMAPINFOHEADER*)header());
int decodetype;
if (bmpinfo.biBitCount == 24)
decodetype = cv::IMREAD_COLOR;
else
decodetype = cv::IMREAD_GRAYSCALE;
cv::Mat ims = cv::imdecode(*bmpData.get(), decodetype);
if (m_compression == Compression::Group4 && m_fileXfer.format() == ImageFileFormat::Tiff)
{
if (!ims.empty() && ims.channels() == 3)
cvtColor(ims, ims, cv::COLOR_BGR2GRAY);
G4Tiff gsave(ims, G4Tiff::Mode::FileMode, filename, 120, m_scanparam->resolution_dst);
gsave.SaveG4Tiff();
}
else
{
std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(m_jpegQuality);
cv::imwrite(filename, ims, compression_params);
}
bmpData.reset(new std::vector<unsigned char>);
ims.release();
return Result(ReturnCode::XferDone, ConditionCode::Success);
}
default:
break;
}
return badProtocol();
}
Twpp::Result HuagaoDs::showTwainUI(Twpp::UserInterface& ui, bool bUiOnly)
{
// as a minimal source, we do not support GUI that just saves settings
if (ui.parent()) {
guiBridge.reset(new CDialog());
HWND appWindow = static_cast<HWND>(ui.parent().raw());
guiBridge->Create(IDD_BACK, CWnd::FromHandle(appWindow));
HWND bridgeWindow = guiBridge->GetSafeHwnd();
long bridgeFlags = GetWindowLong(bridgeWindow, GWL_STYLE);
SetWindowLong(bridgeWindow, GWL_STYLE, bridgeFlags | WS_CHILD);
SetParent(bridgeWindow, appWindow);
}
//!< show ui to scan button push
auto scanFunction = [this](const GScanCap& caps) {
if (!scanner->IsConnected())
{
scanner->open(vid, pid);
if (!scanner->IsConnected())
return checkDeviceOnline();
}
#ifndef G200
while (!scanner->Get_Scanner_PaperOn())
{
if (scanner->get_ErrorCode() == SLEEPING) {
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[(UsbSupported)81]);
scanner->Set_ErrorCode(0);
return seqError();
}
if (MessageBox(NULL, L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><EFBFBD>", L"<EFBFBD><EFBFBD>ʾ", MB_YESNO | MB_SYSTEMMODAL) == IDNO) {
m_pendingXfers = 0;
return seqError();
}
}
#endif // !G200
m_pendingXfers = 1;
m_scanparam.reset(new GScanCap(caps));
saveGscanCapSetting();
if (!scanner->IsConnected())
{
MessageBox(NULL, L"USB<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>쳣,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>USB<53><42><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD><C2B4><EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", L"<EFBFBD><EFBFBD>ʾ", MB_OK | MB_SYSTEMMODAL);
return seqError();
}
if (startScan() == success()) {
notifyXferReady();
}
else {
m_pendingXfers = 0;
}
};
//!< ui only to confirm button push
auto confirmFunction = [this](const GScanCap& caps) {
m_scanparam.reset(new GScanCap(caps));
saveGscanCapSetting();
notifyCloseOk();
};
//!< cancel button push
auto cancelFunction = [this]() {
//if (m_modal)
//{
// ::EnableWindow(parent, true);
//}
notifyCloseCancel();
};
CWnd* parent = guiBridge.get();
TwGlue glue = { scanFunction, cancelFunction };
TwGlue glueUiOnly = { confirmFunction, cancelFunction };
std::string serialnum = scanner->GetSerialNum();
std::string hardwareversion = scanner->GetFWVersion();
std::string macadder = scanner->GetMacAdder();
uint32_t mbversion = scanner->GetMotorFPGA();
guiTwain.reset(new CTwainUI(bUiOnly ? glueUiOnly : glue, *m_scanparam, bUiOnly ? "ȷ<EFBFBD><EFBFBD>" : "ɨ<EFBFBD><EFBFBD>", hardwareversion, serialnum,macadder,mbversion));
guiTwain->Create(IDD_TWAINUI, parent);
CRect newRect;
::GetWindowRect(static_cast<HWND>(ui.parent().raw()), &newRect);
if (newRect.top <= 0 || newRect.left <= 0)
newRect.top = newRect.left = 20;
SetWindowPos(guiTwain->m_hWnd, HWND_TOPMOST, newRect.left + 20, newRect.top + 100, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOACTIVATE);
//SetWindowPos(guiTwain->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE);
guiTwain->ShowWindow(SW_SHOWNORMAL);
return success();
}
void HuagaoDs::DeviceEvent_callback(int eventID, void* usrdata)
{
HuagaoDs* This = (HuagaoDs*)usrdata;
This->onDeviceEvent(eventID);
}
void HuagaoDs::CapabilityPrintf(Twpp::Msg msg, std::string capability, std::string value)
{
if (!is_printfcapability)
return;
switch (msg)
{
case Msg::Reset:
FileTools::writelog(log_INFO, (std::string)enum2str(Msg::Reset) + "\t" + capability);
break;
case Msg::Get:
FileTools::writelog(log_INFO, (std::string)enum2str(Msg::Get) + "\t" + capability);
break;
case Msg::GetCurrent:
FileTools::writelog(log_INFO, (std::string)enum2str(Msg::GetCurrent) + "\t" + capability);
break;
case Msg::GetDefault:
FileTools::writelog(log_INFO, (std::string)enum2str(Msg::GetDefault) + "\t" + capability);
break;
case Msg::Set:
FileTools::writelog(log_INFO, (std::string)enum2str(Msg::Set) + "\t" + capability+"\t value = "+value);
break;
default:
break;
}
}
void HuagaoDs::onDeviceEvent(int eventID)
{
//if (mapDeviceEvent.count(eventID))
//{
// DeviceEvent::Type dev_type = mapDeviceEvent[eventID];
// auto evt = DeviceEvent::simple((DeviceEvent::Type)dev_type, "HuaGo Device Event");
// devEvent.push(evt);
// notifyDeviceEvent();
//}
}
const BITMAPINFOHEADER* HuagaoDs::header() const noexcept {
return reinterpret_cast<const BITMAPINFOHEADER*>(bmpData->data() + sizeof(BITMAPFILEHEADER));
}
UInt32 HuagaoDs::bytesPerLine() const noexcept {
auto dib = header();
return static_cast<UInt32>(dib->biWidth * dib->biBitCount + 31) / 32 * 4;
}
UInt32 HuagaoDs::bmpSize() const noexcept {
return static_cast<UInt32>(bmpData->size()) - sizeof(BITMAPFILEHEADER);
}
const char* HuagaoDs::bmpBegin() const noexcept {
return (const char*)bmpData->cbegin()._Ptr + sizeof(BITMAPFILEHEADER);
}
const char* HuagaoDs::bmpEnd() const noexcept {
return (const char*)bmpData->cend()._Ptr;
}
void HuagaoDs::updataGscanCap()
{
GscanJsonConfig js;
GScanCap cfs = js.ReadGscanCap();
cfs.resolution_native = 200.0f;
cfs.threshold = 128;
if (cfs.is_autocrop)
{
m_autoboarderdetcet = true;
m_autosize = (UInt16)AutoSize::Auto;
}
m_scanparam.reset(new GScanCap(cfs));
}
Twpp::Result HuagaoDs::startScan()
{
xtfer = 0;
//if (!scanner->IsConnected())
//{
// scanner->open(vid, pid);
// if (!scanner->IsConnected())
// return checkDeviceOnline();
//}
scanner->ResetScanner();
scanner->reset();
FileTools::writelog(log_INFO, "start scan");
#ifdef G200
#ifndef ANDROIDSERIAL
if (scanner->notifyscan() < 1)
return seqError();
#endif // !ANDROIDSERIAL
scanner->clear_hwerror();
#endif //
#ifdef G200
if (scanner->Get_Roller_num() > 450000)
#elif defined G300
if (scanner->Get_Roller_num() > 150000)
#else
if (scanner->Get_Roller_num() > 200000)
#endif // G200
{
Twain_config config;
if (config.getrollermsgdate() < chrono::duration_cast<chrono::duration<int, ratio<24 * 60 * 60>>>(chrono::system_clock::now().time_since_epoch()).count()){
hgmsg(_T("ֽ<EFBFBD>ִ<EFBFBD>ֽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>÷<EFBFBD>Χ<EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD>ֽʧ<EFBFBD>ܡ<EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD>쳣Ƶ<EFBFBD>ο<EFBFBD><EFBFBD>ܻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD>⼰ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>̹<EFBFBD><EFBFBD><EFBFBD><EFBFBD>滻ֽ<EFBFBD>֣<EFBFBD>"));
config.setrollermsgdata(chrono::duration_cast<chrono::duration<int, ratio<24 * 60 * 60>>>(chrono::system_clock::now().time_since_epoch()).count());
}
}
//m_scanparam->brightness = -142;
//m_scanparam->contrast = 1000; // С<><D0A1>ר<EFBFBD><D7A8>
scanner->config_params(*m_scanparam);
std::string info = "papertype= " + to_string(m_scanparam->papertype) +
"\nAutoCrop_threshold= " + to_string(m_scanparam->AutoCrop_threshold) +
"\nautodescrew = " + to_string(m_scanparam->autodescrew) +
"\nautomaticcolor= " + to_string(m_scanparam->automaticcolor) +
"\nbrightness = " + to_string(m_scanparam->brightness) +
"\ncontrast = " + to_string(m_scanparam->contrast) +
"\nis_detachnoise = " + to_string(m_scanparam->detachnoise.is_detachnoise) +
"\ndetachnoise = " + to_string(m_scanparam->detachnoise.detachnoise) +
"\nen_fold = " + to_string(m_scanparam->en_fold) +
"\nen_sizecheck = " + to_string(m_scanparam->en_sizecheck) +
"\nenhance_color = " + to_string(m_scanparam->enhance_color) +
"\nfillbackground = " + to_string(m_scanparam->fillbackground) +
"\nfilter = " + to_string(m_scanparam->filter) +
"\nis_fillhole = " + to_string(m_scanparam->fillhole.is_fillhole) +
"\ngamma = " + to_string(m_scanparam->gamma) +
"\ncapturepixtype = " + to_string(m_scanparam->hardwarecaps.capturepixtype) +
"\nen_doublefeed = " + to_string(m_scanparam->hardwarecaps.en_doublefeed) +
"\nhsvcorrect = " + to_string(m_scanparam->hsvcorrect) +
"\nimageRotateDegree = " + to_string(m_scanparam->imageRotateDegree) +
"\nindent = " + to_string(m_scanparam->indent) +
"\nis_autocontrast = " + to_string(m_scanparam->is_autocontrast) +
"\nis_autocrop = " + to_string(m_scanparam->is_autocrop) +
"\nis_autocontrast = " + to_string(m_scanparam->is_autocontrast) +
"\nis_autodiscradblank_normal = " + to_string(m_scanparam->is_autodiscradblank_normal) +
"\nis_autodiscradblank_vince = " + to_string(m_scanparam->is_autodiscradblank_vince) +
"\nis_autotext = " + to_string(m_scanparam->is_autotext) +
"\nis_convex = " + to_string(m_scanparam->is_convex) +
"\nis_duplex = " + to_string(m_scanparam->is_duplex) +
"\nis_switchfrontback = " + to_string(m_scanparam->is_switchfrontback) +
"\nis_dogeardetection = " + to_string(m_scanparam->is_dogeardetection) +
"\nmulti_output_red = " + to_string(m_scanparam->multi_output_red) +
"\nnoise = " + to_string(m_scanparam->noise) +
"\npaperAlign = " + to_string(m_scanparam->paperAlign) +
"\npixtype = " + to_string(m_scanparam->pixtype) +
"\nresolution_dst = " + to_string(m_scanparam->resolution_dst) +
"\nscannum = " + to_string(m_scanparam->scannum) +
"\nsharpen = " + to_string(m_scanparam->sharpen);
FileTools::writelog(log_TRACE,info);
if (m_bIndicator) {
//!< cancel button push
auto stopFunc = [this]() {
if (scanner.get())
scanner->Stop_scan();
//guiIndicator.reset();//ȡ<><C8A1>ɨ<EFBFBD><C9A8> <20>رս<D8B1><D5BD><EFBFBD>ָʾ<D6B8><CABE>
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
onDeviceEvent(USER_STOP);
};
guiIndicator = new CIndicatorDlg(stopFunc);
scanner->regist_indicatortext_callback([this](int aquire, int updata) { if (guiIndicator->GetSafeHwnd()) guiIndicator->setindicatortext(aquire, updata); });
guiIndicator->Create(IDD_INDICATOR, guiTwain.get() ? guiTwain.get() : guiBridge.get());//guiTwain ? guiTwain.get() : guiBridge.get()
guiIndicator->ShowWindow(SW_SHOWNORMAL);
}
scanner->UpdateScanInfo(0, 0);
scanner->Scanner_StartScan(m_scanparam->scannum);
if (bmpData->size() > 0)
{
bmpData.reset(new std::vector<unsigned char>);
}
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(false);
}
int retCode = scanner->aquire_bmpdata(*bmpData.get());
if (retCode != 0) {
scanner->Set_ErrorCode(0);
if (guiIndicator->GetSafeHwnd())
guiIndicator->DestroyWindow();
//if(guiIndicator.get())
// guiIndicator.reset();
if (retCode != -1) {
CString str;
str.Format(_T("%d"), retCode);
m_pendingXfers = 0;
m_memXferYOff = 0;
m_haveError = true;
//ShellExecute(guiTwain ? guiTwain->m_hWnd : NULL, TEXT("open"), GetHidedlgPath(), str, NULL, SW_HIDE);
int index = scanner->geterrorindex();
if (retCode == 82 && ((typeid(*scanner.get()) == typeid(GScanO1003399))))
showmsg("<EFBFBD><EFBFBD>ʾ", "<EFBFBD>ڵ<EFBFBD>" + to_string(index) + "ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>۽ǣ<EFBFBD>ֹͣɨ<EFBFBD>", retCode);
else if (retCode == 75 && ((typeid(*scanner.get()) == typeid(GScanO1003399))))
showmsg("<EFBFBD><EFBFBD>ʾ", "<EFBFBD>ڵ<EFBFBD>" + to_string(index) + "ҳ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֹͣɨ<EFBFBD>", retCode);
else
showmsg("<EFBFBD><EFBFBD>ʾ", msgs[(UsbSupported)retCode], retCode);
FileTools::writelog(log_ERROR, msgs[(UsbSupported)retCode]);
#ifndef G200
scanner->clear_hwerror();
#endif //
}
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
if (retCode == 2)
return { ReturnCode::Failure, ConditionCode::NoMedia };//<2F><>ֽ
return seqError();
}
if (bmpData->size() > 0) {
m_haveError = false;
return success();
}
else {
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
return seqError();
}
}
void HuagaoDs::saveGscanCapSetting()
{
TCHAR szIniFile[MAX_PATH] = { 0 };
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_LOCAL_APPDATA, TRUE);
_tcscat(szIniFile, HUAGAO_SCAN);
_tcscat(szIniFile, TWAIN_INIPATH);
_tcscat(szIniFile, TEXT("\\"));
_tcscat(szIniFile, TWAIN_JSON_NAME);
GscanJsonConfig js;
//vector<GScanCap> vc;
//vc.push_back(*m_scanparam);
std::string savepath = TCHAR2STRING(szIniFile);
js.SaveGscancapJson(*m_scanparam, savepath);
//js.WriteJsonArrayToFile(vc, savepath);
}