twain3.0/huagao/huagaods.cpp

2387 lines
82 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 "Device/PublicFunc.h"
#include "Device/GScanO200.h"
#include "Device/GScanO400.h"
#include "Device/filetools.h"
#include "Device/GScanVirtual.h"
#include <list>
#include <map>
#include <opencv2/opencv.hpp>
#include "GscanJsonConfig.h"
#include "G4Tiff.h"
#include "Device/UsbScanEx.h"
#ifdef WIN32
#include <Psapi.h>
#endif // WIN32
//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_DBAreaNum = 0x8027,
TwEx_DBDevnMax = 0x8028,
TwEx_StableDetectEnable = 0x8090,
TwEx_UVModel = 0x8093,
TwEx_SwitchFrontBack = 0x8094,
TwEx_HsvCorrect = 0x8095,
TwEx_DogEarDelection = 0x8096,
TwEx_FillBacngroundMode = 0x8097,
TwEx_CroporDesaskewIndent = 0x8098,
TwEx_CropNoise=0x8099,
TwEx_CroporDesaskewThreshold=0x8100,
TwEx_IDetachNoise = 0x8101,
TwEx_IDetachNoiseValue = 0x8102,
TwEx_SizeDetect
};
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.4.2"),
DataGroup::Image,
#ifdef MAKEHUAGAO
"HUAGO",
#elif defined LANXUM
"LANXUM",
#else // MAKEHUAGAO
"ZHIBEN",
#endif
#ifdef G200
#ifdef ISG100
"G100 Series",
#else // ISG100
"G200 Series",
#endif
#elif defined(G300) // G200
#ifdef LANXUM
"G4260F Series",
#else // ISG100
"G300 Series",
#endif
#elif defined(G400) // G200
#ifdef LANXUM
"G4260F Series",
#else // ISG100
"G400 Series",
#endif
#endif
#ifdef G200
#ifdef ISG100
#ifndef MAKEHUAGAO
"ZhibenScan G100 TWAIN"
#else // !MAKEHUAGAO
"HUAGOSCAN G100 TWAIN"
#endif
#else // ISG100
#ifndef MAKEHUAGAO
"ZhibenScan G200 TWAIN"
#else // !MAKEHUAGAO
"HUAGOSCAN G200 TWAIN"
#endif
#endif
#elif defined G300 // G200
#ifdef MAKEHUAGAO
"HUAGOSCAN G300 TWAIN"
#elif defined LANXUM //!LANXUM
"LANXUM G4260F TWAIN"
#else // !MAKEHUAGAO
"ZhibenScan G300 TWAIN"
#endif
#elif defined(G400) // G200
#ifdef MAKEHUAGAO
"HUAGOSCAN G400 TWAIN"
#elif defined LANXUM //!LANXUM
"LANXUM G52XXF 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 };
#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 };
#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::None };
#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)}
};
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);
#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;
//}
HuagaoDs::HuagaoDs()
: m_scanparam(new GScanCap)
,bmpData(new std::vector<unsigned char>)
, hMutex(NULL)
{
/*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><><EFBFBD><EFBFBD>", MB_OK| MB_SYSTEMMODAL);
//}));
}
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&) {
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]));
GScanCap *cap = new GScanCap(js.JsonToGscancap(json::parse(str)));
m_scanparam.reset(cap);
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);
}
void HuagaoDs::dogear_callback(int indexpaper)
{
CString text;
text.Format(_T("74 %d"), indexpaper);
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE);
scanner->Stop_scan();
//scanner->reset();
scanner->ResetScanner();
onDeviceEvent(DOG_EAR);
}
Result HuagaoDs::identityOpenDs(const Identity&) {
//writelog("identityOpenDs");
auto usblist= UsbScan_List::find_all_usb();
if (!usblist.empty())
{
for each (auto &usb in usblist)
{
if (usb.vid == 0x064b && usb.pid == 0x7823){
if (!scanner.get()) {
#ifdef G100
scanner.reset(new GScanO200());
#endif //
#ifdef G200
scanner.reset(new GScanO200());
#endif // G200
#ifdef G300
scanner.reset(new GScanO400());
#endif // G300
#ifdef G400
scanner.reset(new GScanO400());
#endif // G400
vid = 0x064b; pid = 0x7823;
break;
}
}
#ifdef G100
if(usb.vid == 0x3072 && usb.pid == 0x100)
#endif //
#ifdef G200
if (usb.vid == 0x3072 && usb.pid == 0x200)
#endif // G200
#ifdef G300
if (usb.vid == 0x3072 && usb.pid == 0x300)
#endif // G300
#ifdef G400
if (usb.vid == 0x3072 && usb.pid == 0x400)
#endif // G400
{
pid = usb.pid; vid = usb.vid;
if(pid<=200&& (!scanner.get()))
scanner.reset(new GScanO200());
else
scanner.reset(new GScanO400());
break;
}
}
}
if (vid ==0|| pid == 0)
{
MessageBox(NULL, L"δ<EFBFBD>ҵ<EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><EFBFBD><EFBFBD>ǣ<EFBFBD>",L"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>",MB_OK);
return seqError();
}
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);
#ifdef LANXUM
scanner->open(0x31c9, 0x8200);
#else
scanner->open(vid, pid);
#endif
if (!scanner->IsConnected()) {
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
return checkDeviceOnline();
}
else
{
scanner->regist_deviceevent_callback(DeviceEvent_callback, this);
scanner->DogEar_callback(std::bind(&HuagaoDs::dogear_callback, this, std::placeholders::_1));
}
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);
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("202"), NULL, SW_HIDE);
return seqError();
}
//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_query[CapType::XferCount] = msgSupportGetAllSetReset;
m_caps[CapType::XferCount] = [this](Msg msg, Capability& data) -> Result {
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
{
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 {
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 {
if( Msg::Set==msg) {
auto mech = data.currentItem<CapType::IPixelType>();
if (mech == PixelType::Rgb || mech == PixelType::Gray || mech == PixelType::BlackWhite)
{
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;
m_scanparam->automaticcolor = FALSE;
}
else{
m_scanparam->multi_output_red = 0;//<2F>Dz<EFBFBD>ɫģʽ<C4A3><EFBFBD><C2B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
// m_scanparam->sharpen = SharpenBlur::Sharpen_None;
if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
{
if (m_scanparam->filter == 3 && m_scanparam->enhance_color == 0)
{
m_scanparam->filter = (byte)Filter::None;
m_scanparam->enhance_color = (byte)Enchace_Color::Enhance_Red;
}
}
}
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 {
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 {
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 {
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 {
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) {
if (Msg::Set == msg) {
auto res = data.currentItem<Fix32>();
if(std::distance(resList.begin(), std::find(resList.begin(), resList.end(), res))==resList.size())
return badValue();
else{
m_scanparam->resolution_dst = (float)res;
return success();
}
}
return CapSupGetAllReset<float, Fix32, CapType::IXResolution>(msg, data, { Fix32(100.0),Fix32(150.0),Fix32(200.0),Fix32(240.0),Fix32(300.0),Fix32(600.0) }, m_scanparam->resolution_dst,200.0,
std::distance(resList.begin(), std::find(resList.begin(), resList.end(), m_scanparam->resolution_dst)) == resList.size() ? 2 : std::distance(resList.begin(), std::find(resList.begin(), resList.end(), m_scanparam->resolution_dst)), 2);
};
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) {
if (Msg::Set == msg) {
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
#ifndef G300
#if defined G200
,PaperSize::A3,PaperSize::UsLedger,PaperSize::IsoB4,
PaperSize::MaxSize,PaperSize::UsStatement
#elif defined G400
,PaperSize::A3,PaperSize::UsLedger,PaperSize::IsoB4
#endif
#endif //
},m_scanparam->papertype, PaperSize::A3,
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(), 11)));
};
#ifdef G200
#ifndef ISG100
m_query[(CapType)(CapTypeEx::TwEx_SizeDetect)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_SizeDetect)] = [this](Msg msg, Capability& data)->Result {
if( Msg::Set == msg) {
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 {
if( Msg::Set == msg) {
auto mech = data.currentItem<CapType::IOrientation>();
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 {
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);
};
m_query[CapType::FeederLoaded] = msgSupportGetAll;
m_caps[CapType::FeederLoaded] = [this](Msg msg, Capability& data) -> Result {
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 {
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 {
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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::DuplexEnabled>();
m_scanparam->is_duplex = mech;
m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = m_scanparam->en_fold = 0;
if (!mech)
m_scanparam->is_backrotate180 = 0;//<2F><><EFBFBD><EFBFBD><E6B1B3><EFBFBD><EFBFBD>ת180<38><EFBFBD><E3B2BB><EFBFBD><EFBFBD>
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 {
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 {
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 {
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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_switchfrontback = mech;
return success();
}
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 {
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 {
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, 1);
};
m_query[CapType::IAutoSize] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoSize] = [this](Msg msg, Capability& data)->Result {
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 {
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::IAutoDiscardBlankPages] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IAutoDiscardBlankPages>();
if ((mech != DiscardBlankPages::Auto) || (mech != DiscardBlankPages::Disabled))
return badValue();
m_scanparam->is_autodiscradblank_normal = (Int32)mech == (Int32)DiscardBlankPages::Auto;
m_scanparam->is_duplex = 1;
m_scanparam->en_fold = 0;
m_scanparam->is_autodiscradblank_vince = 0;
return success();
}
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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_autodiscradblank_vince = mech;
m_scanparam->is_duplex = 1;
m_scanparam->en_fold = 0;
if (mech)
m_scanparam->is_autodiscradblank_normal = 0;
return success();
}
return CapSupGetAllResetEx<byte, Bool, (CapType)CapTypeEx::TwEx_IAutoDiscardBlankVince>(msg, data, { FALSE,TRUE }, m_scanparam->is_autodiscradblank_normal, Bool(false), m_scanparam->is_autodiscradblank_normal ? 1 : 0, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_backrotate180 = mech;
if (mech)
m_scanparam->is_duplex = 1;
return success();
}
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 {
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, { 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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt8>();
if ((mech > 30 || mech < 5) && ((bool)m_scanparam->is_autocrop == true))
return badValue();
m_scanparam->indent = mech;
return success();
}
return CapSupGetAllResetEx<int, UInt8, (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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt8>();
if ((mech > 50 || mech < 30) && ((bool)m_scanparam->is_autocrop == true))
return badValue();
m_scanparam->noise = mech;
return success();
}
return CapSupGetAllResetEx<int, UInt8, (CapType)CapTypeEx::TwEx_CropNoise>(msg, data, m_scanparam->noise, 40);
};
//<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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt8>();
if ((mech > 50 || mech < 30) && ((bool)m_scanparam->is_autocrop == true))
return badValue();
m_scanparam->AutoCrop_threshold = mech;
return success();
}
return CapSupGetAllResetEx<int, UInt8, (CapType)CapTypeEx::TwEx_CroporDesaskewThreshold>(msg, data, m_scanparam->AutoCrop_threshold, 40);
};
//<2F>ڿ<EFBFBD><DABF><EFBFBD><EFBFBD>ʽ
m_query[(CapType)(CapTypeEx::TwEx_FillBacngroundMode)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_FillBacngroundMode)] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->is_convex = mech;
return success();
}
return CapSupGetAllResetEx<bool, Bool, (CapType)CapTypeEx::TwEx_FillBacngroundMode>(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 {
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, { FALSE,TRUE }, m_scanparam->fillhole.is_fillhole, Bool(true), 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 {
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 {
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, { 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 {
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><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_IMultiOutputRed)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IMultiOutputRed)] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
if (m_scanparam->pixtype == (byte)PixelType::Rgb)
m_scanparam->multi_output_red = mech;
else
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, { 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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->hsvcorrect = mech;
return success();
}
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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<CapType::IFilter>();
if (mech == Filter::None || mech == Filter::Red || mech == Filter::Green || mech == Filter::Blue) {
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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<Int16>();
if (m_scanparam->pixtype == (byte)PixelType::Rgb){
m_scanparam->enhance_color = (byte)Enchace_Color::Enhance_None;
}
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;
if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
{
if (m_scanparam->filter == (byte)Filter::None && m_scanparam->enhance_color == (byte)Enchace_Color::Enhance_None)
{
m_scanparam->filter = (byte)Filter::None;
m_scanparam->enhance_color = (byte)Enchace_Color::Enhance_Red;
}
}
return success();
}
}
return badValue();
}
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 {
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, { 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 {
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 {
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 {
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();
}
};
//m_query[(CapType)(CapTypeEx::TwEx_DBAreaNum)] = msgSupportGetAllSetReset;
//m_caps[(CapType)(CapTypeEx::TwEx_DBAreaNum)] = [this](Msg msg, Capability& data)->Result {
// switch (msg) {
// case Msg::Get:
// data = Capability::createOneValue<UInt16>((CapType)(CapTypeEx::TwEx_DBAreaNum), m_scanparam->areanum);
// return success();
// case Msg::Reset:
// m_scanparam->areanum = 8;
// case Msg::GetCurrent:
// data = Capability::createOneValue<UInt16>((CapType)(CapTypeEx::TwEx_DBAreaNum), m_scanparam->areanum);
// return success();
// case Msg::GetDefault:
// data = Capability::createOneValue<UInt16>((CapType)(CapTypeEx::TwEx_DBAreaNum), UInt16(8));
// return success();
// case Msg::Set: {
// auto mech = data.currentItem<UInt16>();
// if (mech >= 5 && mech <= 40) {
// m_scanparam->areanum = mech;
// return success();
// }
// return badValue();
// }
// default:
// return capBadOperation();
// }
//};
//m_query[(CapType)(CapTypeEx::TwEx_DBDevnMax)] = msgSupportGetAllSetReset;
//m_caps[(CapType)(CapTypeEx::TwEx_DBDevnMax)] = [this](Msg msg, Capability& data)->Result {
// switch (msg) {
// case Msg::Get:
// data = Capability::createOneValue<UInt16>((CapType)(CapTypeEx::TwEx_DBDevnMax), m_scanparam->devnmax);
// return success();
// case Msg::Reset:
// m_scanparam->devnmax = 200;
// case Msg::GetCurrent:
// data = Capability::createOneValue<UInt16>((CapType)(CapTypeEx::TwEx_DBDevnMax), m_scanparam->devnmax);
// return success();
// case Msg::GetDefault:
// data = Capability::createOneValue<UInt16>((CapType)(CapTypeEx::TwEx_DBDevnMax), UInt16(200));
// return success();
// case Msg::Set: {
// auto mech = data.currentItem<UInt16>();
// if (mech >= 150 && mech <= 400) {
// m_scanparam->devnmax = mech;
// return success();
// }
// return badValue();
// }
// 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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_skrewdetect = mech;
return success();
}
return CapSupGetAllResetEx<byte, Bool, (CapType)CapTypeEx::TwEx_ScrewDetectEnable>(msg, data, { FALSE,TRUE }, m_scanparam->sharpen, TRUE, m_scanparam->hardwarecaps.en_skrewdetect ? 1 : 0, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem<UInt8>();
if (mech >= 1 && mech <= 5) {
m_scanparam->hardwarecaps.skrewdetectlevel = mech;
return success();
}
return badValue();
}
return CapSupGetAllResetEx<byte, UInt8, (CapType)CapTypeEx::TwEx_ScrewLevel>(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 {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_stapledetect = mech;
return success();
}
return CapSupGetAllResetEx<byte, UInt8, (CapType)CapTypeEx::TwEx_StableDetectEnable>(msg, data, { FALSE,TRUE }, m_scanparam->hardwarecaps.en_stapledetect, FALSE, m_scanparam->hardwarecaps.en_stapledetect ? 1 : 0, 0);
};
m_query[(CapType)(CapTypeEx::TwEx_DogEarDelection)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_DogEarDelection)] = [this](Msg msg, Capability& data)->Result {
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);
};
//˫<>ż<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>
m_query[CapType::DoubleFeedDetection] = msgSupportGetAllSetReset;
m_caps[CapType::DoubleFeedDetection] = [this](Msg msg, Capability& data)->Result {
if (Msg::Set == msg) {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_doublefeed = mech;
return success();
}
return CapSupGetAllResetEx<byte, Bool, CapType::DoubleFeedDetection>(msg, data, m_scanparam->hardwarecaps.en_doublefeed, TRUE);
};
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 (guiIndicator.get())
// guiIndicator.reset();
//guiIndicator->ShowWindow(SW_HIDE);
if (ret != -1) {
CString str;
str.Format(_T("%d"), ret);
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), str, NULL, SW_HIDE);
#ifndef G200
scanner->clear_hwerror();
#endif // G200
}
m_pendingXfers = 0;
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
}
else {
m_pendingXfers = 1;
}
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) {
//FileTools::write_log("D:\\1.txt", "userInterfaceDisable enter");
if(guiTwain.get())
guiTwain.reset();
#if TWPP_DETAIL_OS_WIN
if(guiBridge.get())
guiBridge.reset();
#endif
//FileTools::write_log("D:\\1.txt", "userInterfaceDisable exit");
return success();
}
Result HuagaoDs::userInterfaceEnable(const Identity&, UserInterface& ui) {
m_pendingXfers = 1;
m_memXferYOff = 0;
scanner->ResetMsgFiter();
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
setState(DsState::Enabled);
auto ret = startScan();
//if (ret.status().condition() == Twpp::CC::NoMedia)
// return ret;
if (ret == success()) {
m_pendingXfers = 1;
}
else {
m_pendingXfers = 0;
//setState(DsState::Open);
}
auto notified = notifyXferReady();
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();
}
//#define LOG_NORMAL
#ifdef LOG_NORMAL
static int xtfer = 0;
#endif
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>);
//std::string info = "Twain transfered num of " + to_string(++xtfer)+" images";
FileTools::write_log("Twain transfered num of " + to_string(++xtfer) + " images");
return { ReturnCode::XferDone, ConditionCode::Success };
}
Twpp::Result HuagaoDs::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data)
{
//FileTools::write_log("D:\\1.txt", "pendingXfersStopFeeder enter");
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);
//if (ui.modalUi()) {
// long appFlags = GetWindowLong(appWindow, GWL_STYLE);
// SetWindowLong(appWindow, GWL_STYLE, appFlags | WS_DISABLED);
//}
//if (ui.modalUi())
//{
// m_modal = true;
// parent = appWindow;
// ::EnableWindow(appWindow, false);
//}
}
//!< show ui to scan button push
auto scanFunction = [this](const GScanCap& caps) {
#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) {
m_pendingXfers = 0;
return;
}
}
#endif // !G200
m_pendingXfers = 1;
m_scanparam.reset(new GScanCap(caps));
saveGscanCapSetting();
if (scanner->get_ErrorCode() == USB_DISCONNECTED)
{
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;
}
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();
guiTwain.reset(new CTwainUI(bUiOnly ? glueUiOnly : glue, *m_scanparam, bUiOnly ? "ȷ<EFBFBD><EFBFBD>" : "ɨ<EFBFBD><EFBFBD>", hardwareversion, serialnum));
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);
guiTwain->ShowWindow(SW_SHOWNORMAL);
return success();
}
void HuagaoDs::DeviceEvent_callback(int eventID, void* usrdata)
{
HuagaoDs* This = (HuagaoDs*)usrdata;
This->onDeviceEvent(eventID);
}
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;
//FileTools::write_log("D:\\2.txt", "is_autodiscradblank_normal = " + to_string(cfs.is_autodiscradblank_normal) + "is_autodiscradblank_vince =" + to_string(cfs.is_autodiscradblank_vince));
if (cfs.is_autocrop)
{
m_autoboarderdetcet = true;
m_autosize = (UInt16)AutoSize::Auto;
}
m_scanparam.reset(new GScanCap(cfs));
}
Twpp::Result HuagaoDs::startScan()
{
xtfer = 0;
//FileTools::write_log("D:\\1.txt", "RESET TWAIN TRANSFERED IMAGE COUNT");
if (!scanner->IsConnected())
{
#ifdef LANXUM
scanner->open(0x31c9, 0x8200);
#else
scanner->open(vid, pid);
#endif
if (!scanner->IsConnected())
return checkDeviceOnline();
}
scanner->ResetScanner();
std::string info = "\n m_scanparam->is_autocrop :" + to_string(m_scanparam->is_autocrop);
info += "\n m_scanparam->colorenable :" + to_string(m_scanparam->automaticcolor);
info += "\n m_scanparam->colorenabletype :" + to_string(m_scanparam->automaticcolortype);
info += "\n m_scanparam->papertype :" + to_string(m_scanparam->papertype);
info += "\n m_scanparam->fillbackground :" + to_string(m_scanparam->fillbackground);
info += "\n m_scanparam->autodescrew :" + to_string(m_scanparam->autodescrew);
info += "\n m_scanparam->brightness :" + to_string(m_scanparam->brightness);
info += "\n m_scanparam->Caption :" + m_scanparam->Caption;
info += "\n m_scanparam->contrast :" + to_string(m_scanparam->contrast);
info += "\n m_scanparam->discardblank_percent :" + to_string(m_scanparam->discardblank_percent);
info += "\n m_scanparam->enhance_color :" + to_string(m_scanparam->enhance_color);
info += "\n m_scanparam->en_fold :" + to_string(m_scanparam->en_fold);
info += "\n m_scanparam->hardwarecaps.capturepixtype :" + to_string(m_scanparam->hardwarecaps.capturepixtype);
info += "\n m_scanparam->hardwarecaps.en_doublefeed :" + to_string(m_scanparam->hardwarecaps.en_doublefeed);
info += "\n m_scanparam->hardwarecaps.en_stapledetect :" + to_string(m_scanparam->hardwarecaps.en_stapledetect);
info += "\n m_scanparam->hardwarecaps.en_skrewdetect :" + to_string(m_scanparam->hardwarecaps.en_skrewdetect);
info += "\n m_scanparam->hardwarecaps.skrewdetectlevel :" + to_string(m_scanparam->hardwarecaps.skrewdetectlevel);
info += "\n m_scanparam->imageRotateDegree :" + to_string(m_scanparam->imageRotateDegree);
info += "\n m_scanparam->is_duplex :" + to_string(m_scanparam->is_duplex);
info += "\n m_scanparam->pixtype :" + to_string(m_scanparam->pixtype);
info += "\n m_scanparam->resolution_dst :" + to_string(m_scanparam->resolution_dst);
info += "\n m_scanparam->resolution_native :" + to_string(m_scanparam->resolution_native);
info += "\n m_scanparam->paperAlign :" + to_string((int)m_scanparam->paperAlign);
info += "\n m_scanparam->gamma :" + to_string(m_scanparam->gamma);
info += "\n m_scanparam->threshold :" + to_string(m_scanparam->threshold);
info += "\n m_scanparam->is_autocontrast :" + to_string(m_scanparam->is_autocontrast);
info += "\n m_scanparam->is_autocrop :" + to_string(m_scanparam->is_autocrop);
info += "\n m_scanparam->fillhole.fillholeratio :" + to_string(m_scanparam->fillhole.fillholeratio);
info += "\n m_scanparam->fillhole.is_fillhole :" + to_string(m_scanparam->fillhole.is_fillhole);
info += "\n m_scanparam->is_autodiscradblank_normal :" + to_string(m_scanparam->is_autodiscradblank_normal);
info += "\n m_scanparam->is_autodiscradblank_vince :" + to_string(m_scanparam->is_autodiscradblank_vince);
info += "\n m_scanparam->is_switchfrontback :" + to_string(m_scanparam->is_switchfrontback);
info += "\n m_scanparam->multi_output_red :" + to_string(m_scanparam->multi_output_red);
info += "\n m_scanparam->hsvcorrect :" + to_string(m_scanparam->hsvcorrect);
info += "\n m_scanparam->filter :" + to_string(m_scanparam->filter);
info += "\n m_scanparam->sharpen :" + to_string(m_scanparam->sharpen);
info += "\n m_scanparam->scannum :" + to_string(m_scanparam->scannum);
info += "\n m_scanparam->is_backrotate180 :" + to_string(m_scanparam->is_backrotate180);
info += "\n m_scanparam->is_autotext :" + to_string(m_scanparam->is_autotext);
info += "\n m_scanparam->SavePath :" + m_scanparam->SavePath;
info += "\n m_scanparam->noise :" + to_string(m_scanparam->noise);
info += "\n m_scanparam->indent :" + to_string(m_scanparam->indent);
info += "\n m_scanparam->AutoCrop_threshold :" + to_string(m_scanparam->AutoCrop_threshold);
info += "\n m_scanparam->is_convex :" + to_string(m_scanparam->is_convex);
FileTools::write_log(info);
#ifndef G200
scanner->clear_hwerror();
#endif //
scanner->config_params(*m_scanparam);
//FileTools::write_log("D:\\2.txt", "is_autodiscradblank_normal = " + to_string(m_scanparam->is_autodiscradblank_normal) + " 222is_autodiscradblank_vince =" + to_string(m_scanparam->is_autodiscradblank_vince));
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);
guiIndicator->Create(IDD_INDICATOR, guiTwain.get() ? guiTwain.get() : guiBridge.get());//guiTwain ? guiTwain.get() : guiBridge.get()
guiIndicator->ShowWindow(SW_SHOWNORMAL);
}
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) {
//MessageBox(guiTwain ? guiTwain->m_hWnd : NULL, noticeMsgMap[retCode], _T("<22><>ʾ"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
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);
#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);
}