twain3.0/huagao/huagaods.cpp

2330 lines
71 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/filetools.h"
#include "Device/GScanVirtual.h"
#include <list>
#include <map>
#include <opencv2/opencv.hpp>
#include "GscanJsonConfig.h"
//#include "TiffG4Compression.h"
//#include "G4Tiff.h"
//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
};
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.2.3"),
DataGroup::Image,
"HUAGO",
#ifdef G200
#ifdef ISG100
"G100 Series",
#else // ISG100
"G200 Series",
#endif
#elif defined(G300) // G200
"G300 Series",
#elif defined(G400) // G200
"G400 Series",
#endif
#ifdef G200
#ifdef ISG100
"HUAGOSCAN G100 TWAIN"
#else // ISG100
"HUAGOSCAN G200 TWAIN"
#endif
#elif defined(G300) // G200
"HUAGOSCAN G300 TWAIN"
#elif defined(G400) // G200
"HUAGOSCAN G400 TWAIN"
#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());
static list<float> resList = { 100.0,150.0,200.0,240.0,300.0 };
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)Twpp::PaperSize::None,(UInt16)PaperSize::UsStatement };
static list<float> imageRotateList = { 0.0,90.0,180.0,270.0 };
//static map<unsigned int, CString> noticeMsgMap = { {OPEN_COVER,_T("ɨ<><C9A8><EFBFBD>ǿ<EFBFBD><C7BF><EFBFBD>")},
// {NO_FEED,_T("<22><>ֽ<EFBFBD><D6BD>")},
// {FEED_IN_ERROR,_T("<22><>ֽʧ<D6BD>ܣ<EFBFBD>")},
// {PAPER_JAM,_T("<22><>ֽ<EFBFBD><D6BD>")},
// {DETECT_DOUBLE_FEED,_T("˫<>ţ<EFBFBD>")},
// {DETECT_STAPLE,_T("<22><><EFBFBD><EFBFBD><EFBFBD>룡")},
// {PAPER_SKEW,_T("ֽ<><D6BD><EFBFBD><EFBFBD>б<EFBFBD><D0B1>")},
// {COUNT_MODE,_T("<22><><EFBFBD><EFBFBD>ģʽ<C4A3><CABD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>")},
// {HARDWARE_ERROR,_T("Ӳ<><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")},
// {FPGA_ERROR,_T("FPGA <20>쳣")},
// {USB_DISCONNECTED,_T("USB<53><42><EFBFBD><EFBFBD><EFBFBD>쳣")}
//};
static void DeleteWnd(CDialog* pWnd) {
if (pWnd && pWnd->GetSafeHwnd()) {
pWnd->DestroyWindow();
delete pWnd;
}
}
static std::unique_ptr<CDialog, 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<CDialogEx, void(*)(CDialog*)> guiIndicator(nullptr, DeleteWnd);
#ifndef HG_VIRTUAL
static std::unique_ptr<IScanner> scanner(new GScanO200());
#else
static std::unique_ptr<IScanner> scanner(new GScanVirtual());
#endif
HuagaoDs::HuagaoDs()
: m_scanparam(new GScanCap)
, hMutex(NULL)
{
/*string ss1= getOSInfo();
string ss2=getManufactureID();
string ss3=getCpuType();
string ss4= getMemoryInfo();
DWORD dwNum;
CString aas[10];
GetDiskInfo(dwNum,aas);*/
}
HuagaoDs::~HuagaoDs()
{
}
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
return Base::call(origin, dg, dat, msg, data);
}
catch (const CapabilityException&) {
return badValue();
}
}
// 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();
}
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->SendMessage((UINT)(event.message()));
}
event.setMessage(Msg::Null);
return { ReturnCode::NotDsEvent, ConditionCode::Success };
}
//Twpp::Result HuagaoDs::deviceEventGet(const Twpp::Identity & origin, Twpp::DeviceEvent & data)
//{
// data = DeviceEvent::simple(DeviceEvent::Type::PaperJam, Str255("HuaGo G200 Twain Device Error"));
// return success();
//}
//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);
}
Result HuagaoDs::identityOpenDs(const Identity&) {
//writelog("identityOpenDs");
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 : 0);
m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 0);
scanner->open(0x064B, 0x7823);
if (!scanner->IsConnected()) {
//MessageBox(NULL, _T("δ<>ҵ<EFBFBD>ɨ<EFBFBD><C9A8><EFBFBD><EFBFBD>!<21><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD>USB<53><42><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>ͨ!"), _T("<22><>ʾ"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
//CString str("201");
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
return checkDeviceOnline();
}
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);
//MessageBox(NULL, _T("<22><EFBFBD>ѱ<EFBFBD><D1B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ر<EFBFBD>ռ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD>"), _T("<22><>ʾ"), MB_OK);
//CString str("202");
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("202"), NULL, SW_HIDE);
return seqError();
}
// 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) {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault: {
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();
}
default:
return capBadOperation();
}
};
m_query[CapType::UiControllable] = msgSupportGetAll;
m_caps[CapType::UiControllable] = std::bind(enmGet<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) {
return badValue();
}
m_capXferCount = item;
m_scanparam->scannum = m_capXferCount;
return success();
}
auto ret = oneValGetSet<Int16>(msg, data, m_capXferCount, -1);
if (Twpp::success(ret) && m_capXferCount == 0) {
m_capXferCount = -1;
m_scanparam->scannum = m_capXferCount;
return { ReturnCode::CheckStatus, ConditionCode::BadValue };
}
return ret;
};
m_query[CapType::ICompression] = msgSupportGetAllSetReset;
m_caps[CapType::ICompression] = [this](Msg msg, Capability& data)->Result
{
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::ICompression>(
{ Compression::None, Compression::Group4 }, m_compression == Compression::None ? 0 : 1, 0);
return success();
case Msg::Reset:
m_compression = Compression::None;
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::ICompression>(m_compression);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::ICompression>(Compression::None);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::ICompression>();
if (Compression::None == mech || mech == Compression::Group4) {
m_compression = mech;
return success();
}
else {
return badValue();
}
}
default:
return capBadOperation();
}
};
m_query[CapType::IBitDepth] = msgSupportGetAllSetReset;
m_caps[CapType::IBitDepth] = [this](Msg msg, Capability& data) -> Result {
switch (msg)
{
case Msg::Get:
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
return success();
case Msg::Reset:
m_iBitdepth = 24;
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
break;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IBitDepth>(24);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IBitDepth>();
if (mech == 1 || mech == 8 || mech == 24)
{
m_iBitdepth = (UINT16)mech;
m_scanparam->pixtype = m_iBitdepth == 1 ? (int)PixelType::BlackWhite : (m_iBitdepth == 8 ? (int)PixelType::Gray : (int)PixelType::Rgb);
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
m_query[CapType::IBitOrder] = msgSupportGetAllSetReset;
m_caps[CapType::IBitOrder] = std::bind(enmGetSetConst<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) / RESOLUTIONX));
m_query[CapType::IPhysicalHeight] = msgSupportGetAll;
m_caps[CapType::IPhysicalHeight] = std::bind(oneValGet<Fix32>, _1, _2, Fix32(static_cast<float>(header()->biHeight) / RESOLUTIONX));
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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IPixelType>(
{ PixelType::BlackWhite, PixelType::Gray, PixelType::Rgb }, (int)(m_scanparam->pixtype), (int)PixelType::Gray);
return success();
case Msg::Reset:
m_scanparam->pixtype = (byte)PixelType::Gray;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IPixelType>((PixelType)(m_scanparam->pixtype));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IPixelType>(PixelType::Gray);
return success();
case Msg::Set: {
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;
}
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;
}
m_iBitdepth = mech == PixelType::Rgb ? 24 : (mech == PixelType::Gray ? 8 : 1);
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
//add------------------jpeg<65><67><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>---------------------
m_query[CapType::IJpegQuality] = msgSupportGetAllSetReset;
m_caps[CapType::IJpegQuality] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
data = Capability::createOneValue<UInt16>(CapType::IJpegQuality, (UInt16)m_jpegQuality);
return success();
case Msg::Reset:
m_jpegQuality = 80;
return success();
case Msg::GetDefault:
data = Capability::createOneValue<UInt16>(CapType::IJpegQuality, 80);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IJpegQuality>();
if ((int)mech < 0 || (int)mech > 100)
return capBadOperation();
m_jpegQuality = (int)mech;
return success();
}
default:
return capBadOperation();
}
};
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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IXferMech>(
{ XferMech::Native, XferMech::Memory, XferMech::File }, m_capXferMech == XferMech::Native ? 0 : (m_capXferMech == XferMech::Memory ? 1 : 2), 0);
return success();
case Msg::Reset:
m_capXferMech = XferMech::Native;
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IXferMech>(m_capXferMech);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IXferMech>(XferMech::Native);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IXferMech>();
if (mech == XferMech::Native || mech == XferMech::Memory || mech == XferMech::File) {
m_capXferMech = mech;
return success();
}
else {
return badValue();
}
}
default:
return capBadOperation();
}
};
m_query[CapType::IXResolution] = msgSupportGetAllSetReset;
m_caps[CapType::IXResolution] = [this](Msg msg, Capability& data) {
switch (msg) {
case Msg::Get: {
int index = -1;
std::list<float>::iterator it = resList.begin();
int i = 0;
for (it, i; it != resList.end(); ++it, i++) {
if (*it == m_scanparam->resolution_dst) {
index = i;
break;
}
}
data = Capability::createEnumeration(data.type(), { Fix32(100.0),Fix32(150.0),Fix32(200.0),Fix32(240.0),Fix32(300.0) }, index == -1 ? 2 : index, 2);
return success();
}
case Msg::GetCurrent: {
data = Capability::createOneValue(data.type(), Fix32(m_scanparam->resolution_dst));
return success();
}
case Msg::GetDefault:
case Msg::Reset: {
data = Capability::createOneValue(data.type(), Fix32(200.0));
return success();
}
case Msg::Set: {
auto res = data.currentItem<Fix32>();
std::list<float>::iterator resIter = resList.begin();
bool contains = false;
for (resIter; resIter != resList.end(); resIter++) {
if (*resIter == res) {
contains = true;
break;
}
}
if (contains) {
m_scanparam->resolution_dst = (float)res;
return success();
}
return badValue();
}
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) {
switch (msg) {
case Msg::Get: {
int index = -1;
std::list<UInt16>::iterator it = paperSizeList.begin();
int i = 0;
for (it, i; it != paperSizeList.end(); ++it, i++) {
if (*it == m_scanparam->papertype) {
index = i;
break;
}
}
data = Capability::createEnumeration(data.type(), { PaperSize::A3,PaperSize::A4,PaperSize::A5,
PaperSize::A6,PaperSize::IsoB4,PaperSize::IsoB5,
PaperSize::IsoB6,PaperSize::UsLetter,PaperSize::UsLegal,
PaperSize::UsLedger,PaperSize::MaxSize,PaperSize::None },
index == -1 ? 0 : index,
0);
return success();
}
case Msg::GetCurrent:
data = Capability::createOneValue(data.type(), UInt16(m_scanparam->papertype));
return success();
case Msg::GetDefault:
case Msg::Reset:
data = Capability::createOneValue(data.type(), UInt16(PaperSize::A3));
return success();
case Msg::Set: {
auto res = data.currentItem<UInt16>();
std::list<UInt16>::iterator resIter = paperSizeList.begin();
bool contains = false;
for (resIter; resIter != paperSizeList.end(); resIter++) {
if (*resIter == res) {
contains = true;
break;
}
}
if (contains) {
m_scanparam->papertype = (byte)res;
if (res == (byte)PaperSize::None)
{
m_scanparam->autodescrew = 1;//<2F><><EFBFBD><EFBFBD>papertypeΪNONE <20><>Ĭ<EFBFBD><C4AC><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
m_scanparam->paperAlign = PaperAlign::Rot0;
}
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
m_query[CapType::IOrientation] = msgSupportGetAllSetReset;
m_caps[CapType::IOrientation] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IOrientation>(
{ Orientation::Portrait, Orientation::Landscape }, m_scanparam->paperAlign, 0);
return success();
case Msg::Reset:
m_scanparam->paperAlign = PaperAlign::Rot0;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IOrientation>((Orientation)(m_scanparam->paperAlign));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IOrientation>(Orientation::Portrait);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IOrientation>();
if (mech == Orientation::Landscape || mech == Orientation::Portrait) {
m_scanparam->paperAlign = (PaperAlign)mech;
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
m_query[CapType::IRotation] = msgSupportGetAllSetReset;
m_caps[CapType::IRotation] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get: {
int index = -1;
std::list<float>::iterator it = imageRotateList.begin();
int i = 0;
for (it, i; it != imageRotateList.end(); ++it, i++) {
if ((m_scanparam->imageRotateDegree + 1) >= *it && (m_scanparam->imageRotateDegree - 1) <= *it) {
index = i;
break;
}
}
data = Capability::createEnumeration<CapType::IRotation>(
{ Fix32(0.0),Fix32(90.0),Fix32(180.0),Fix32(270.0) },
index == -1 ? 0 : index,
0);
return success();
}
case Msg::Reset:
m_scanparam->imageRotateDegree = 0.0;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IRotation>(Fix32(m_scanparam->imageRotateDegree));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IRotation>(Fix32(0.0));
return success();
case Msg::Set: {
auto res = data.currentItem<Fix32>();
std::list<float>::iterator resIter = imageRotateList.begin();
bool contains = false;
for (resIter; resIter != imageRotateList.end(); resIter++) {
if (((float)res + 1) >= *resIter && ((float)res - 1) <= *resIter) {
contains = true;
break;
}
}
if (contains) {
m_scanparam->imageRotateDegree = (float)res;
if (res != 0.0f)
m_scanparam->is_autotext = 0;
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
#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_query[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = msgSupportGetAll;
m_caps[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = std::bind(oneValGetString, _1, _2, scanner->GetFWVersion());
m_query[CapType::FeederLoaded] = msgSupportGetAll;
m_caps[CapType::FeederLoaded] = std::bind(oneValGet<Bool>, _1, _2, Bool(scanner->Get_Scanner_PaperOn()));
m_query[CapType::Indicators] = msgSupportGetAllSetReset;
m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::Indicators>(
{ Bool(), Bool(true) }, Bool(m_bIndicator));
return success();
case Msg::Reset:
m_bIndicator = true;
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::Indicators>(m_bIndicator);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::Indicators>(false);
return success();
case Msg::Set: {
auto show = data.currentItem<CapType::Indicators>();
m_bIndicator = show;
return success();
}
default:
return capBadOperation();
}
};
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(enmGet<Bool>, _1, _2, Bool(true));
m_query[CapType::FeederEnabled] = msgSupportGetAllSetReset;
m_caps[CapType::FeederEnabled] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createOneValue<CapType::FeederEnabled>(true);
return success();
case Msg::Reset:
m_bFeederEnabled = true;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::FeederEnabled>(m_bFeederEnabled);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::FeederEnabled>(true);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::FeederEnabled>();
m_bFeederEnabled = mech;
return success();
}
default:
return capBadOperation();
}
};
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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::DuplexEnabled>(
{ Bool(), Bool(true) }, Bool(m_scanparam->is_duplex));
return success();
case Msg::Reset:
m_scanparam->is_duplex = true;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::DuplexEnabled>(m_scanparam->is_duplex);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::DuplexEnabled>(false);
return success();
case Msg::Set: {
auto 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>
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::AutoFeed] = msgSupportGetAllSetReset;
m_caps[CapType::AutoFeed] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::AutoFeed>(
{ Bool(), Bool(true) }, Bool(m_bAutoFeed));
return success();
case Msg::Reset:
m_bAutoFeed = true;
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::AutoFeed>(m_bAutoFeed);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::AutoFeed>(true);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::AutoFeed>();
m_bAutoFeed = mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IImageFileFormat] = msgSupportGetAllSetReset;
m_caps[CapType::IImageFileFormat] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get: {
UInt32 capindex = 0;
if (m_capImageFileFormat == ImageFileFormat::Tiff) capindex = 1;
if (m_capImageFileFormat == ImageFileFormat::Jfif) capindex = 2;
data = Capability::createEnumeration<CapType::IImageFileFormat>(
{ ImageFileFormat::Bmp, ImageFileFormat::Tiff,ImageFileFormat::Jfif }, capindex, 0);
return success();
}
case Msg::Reset:
case Msg::GetCurrent:
m_capImageFileFormat = ImageFileFormat::Bmp;
data = Capability::createOneValue<CapType::IImageFileFormat>(m_capImageFileFormat);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IImageFileFormat>(ImageFileFormat::Bmp);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IImageFileFormat>();
if (mech == ImageFileFormat::Bmp ||
mech == ImageFileFormat::Tiff ||
mech == ImageFileFormat::Jfif) {
m_capImageFileFormat = mech;
return success();
}
else
return badValue();
}
default:
return capBadOperation();
}
};
//custom define
m_query[CapType::IAutomaticDeskew] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticDeskew] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutomaticDeskew>(
{ Bool(), Bool(true) }, Bool(m_scanparam->autodescrew == 0 ? false : true));
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->autodescrew = true;
data = Capability::createOneValue<CapType::IAutomaticDeskew>(m_scanparam->autodescrew);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutomaticDeskew>(true);
return success();
case Msg::Set: {
auto atuodsw = data.currentItem<CapType::IAutomaticDeskew>();
m_scanparam->autodescrew = (bool)atuodsw;
return success();
}
default:
return capBadOperation();
}
};
m_query[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)((CapType)(CapTypeEx::TwEx_SwitchFrontBack)), { Bool(),Bool(true) }, Bool(m_scanparam->is_switchfrontback), 0);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->is_switchfrontback = false;
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_SwitchFrontBack)), m_scanparam->is_switchfrontback);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_SwitchFrontBack)), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->is_switchfrontback = mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutomaticRotate] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutomaticRotate>(
{ Bool(), Bool(true) }, Bool(m_scanparam->is_autotext));
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->is_autotext = false;
data = Capability::createOneValue<CapType::IAutomaticRotate>(m_scanparam->is_autotext);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutomaticRotate>(false);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IAutomaticRotate>();
m_scanparam->is_autotext = (bool)mech;
if (mech)
m_scanparam->imageRotateDegree = 0.0f;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutomaticCropUsesFrame] = msgSupportGetAll;
m_caps[CapType::IAutomaticCropUsesFrame] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::Capability::createOneValue<CapType::IAutomaticCropUsesFrame>(m_scanparam->is_autocrop);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->is_autocrop = false;
data = Capability::createOneValue<CapType::IAutomaticCropUsesFrame>(m_scanparam->is_autocrop);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutomaticCropUsesFrame>(false);
return success();
//case Msg::Set: {
// auto autocrop = data.currentItem<CapType::IAutomaticCropUsesFrame>();
// m_scanparam->is_autocrop = (bool)autocrop;
// if (autocrop)
// m_scanparam->papertype = (byte)PaperSize::None;
// return success();
//}
default:
return capBadOperation();
}
};
m_query[CapType::AutoScan] = msgSupportGetAllSetReset;
m_caps[CapType::AutoScan] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::AutoScan>(
{ Bool(), Bool(true) }, m_autoscan);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_autoscan = true;
data = Capability::createOneValue<CapType::AutoScan>(m_autoscan);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::AutoScan>(true);
return success();
case Msg::Set: {
auto autoscan = data.currentItem<CapType::AutoScan>();
m_autoscan = autoscan;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutoSize] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoSize] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutoSize>(
{ AutoSize::None, AutoSize::Auto,AutoSize::Current }, (UInt16)m_autosize, 0);
return success();
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutoSize>((AutoSize)m_autosize);
return success();
case Msg::Reset:
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutoSize>(AutoSize::None);
return success();
case Msg::Set: {
auto autosize = data.currentItem<CapType::IAutoSize>();
if (autosize == AutoSize::Auto)
{
m_scanparam->is_autocrop = 1;
m_scanparam->papertype = (byte)Twpp::PaperSize::None;
m_scanparam->paperAlign = PaperAlign::Rot0;
}
m_autosize = (byte)autosize;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutomaticBorderDetection] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticBorderDetection] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutomaticBorderDetection>(
{ Bool(), Bool(true) }, m_autoboarderdetcet);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_autoscan = true;
data = Capability::createOneValue<CapType::IAutomaticBorderDetection>(m_autoboarderdetcet);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutomaticBorderDetection>(false);
return success();
case Msg::Set: {
auto autodetectborder = data.currentItem<CapType::IAutomaticBorderDetection>();
if (autodetectborder)
{
m_scanparam->is_autocrop = true;
m_scanparam->papertype = (byte)Twpp::PaperSize::None;
m_scanparam->paperAlign = PaperAlign::Rot0;
}
m_autoboarderdetcet = autodetectborder;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IImageMerge] = msgSupportGetAllSetReset;
m_caps[CapType::IImageMerge] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->en_fold = 0;//Ĭ<>ϲ<EFBFBD><CFB2><EFBFBD><EFBFBD><EFBFBD>
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, 0);
return success();
case Msg::Set: {
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>ƫ
}
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutoDiscardBlankPages] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutoDiscardBlankPages>({ DiscardBlankPages::Disabled,DiscardBlankPages::Auto },
m_scanparam->is_autodiscradblank_normal ? 1 : 0,
0);
return success();
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->is_autodiscradblank_normal = false;
data = Capability::createOneValue<CapType::IAutoDiscardBlankPages>(DiscardBlankPages::Disabled);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutoDiscardBlankPages>(m_scanparam->is_autodiscradblank_normal ? DiscardBlankPages::Auto : DiscardBlankPages::Disabled);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IAutoDiscardBlankPages>();
m_scanparam->is_autodiscradblank_normal = (Int32)mech == (Int32)DiscardBlankPages::Auto;
return success();
}
default:
return capBadOperation();
}
};
/*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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), { Bool(),Bool(true) }, Bool(m_scanparam->is_autodiscradblank_vince), 0);
return success();
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->is_autodiscradblank_vince = false;
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), Bool(false));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), m_scanparam->is_autodiscradblank_vince);
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->is_autodiscradblank_vince = mech;
if (mech)
m_scanparam->is_autodiscradblank_normal = 0;
return success();
}
default:
return capBadOperation();
}
};
m_query[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), { Bool(),Bool(true) }, Bool(m_scanparam->is_backrotate180), 0);
return success();
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->is_backrotate180 = false;
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), Bool(false));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), m_scanparam->is_backrotate180);
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->is_backrotate180 = mech;
if (mech)
m_scanparam->is_duplex = 1;
return success();
}
default:
return capBadOperation();
}
};
//<2F><><EFBFBD>ڿ<EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_IFillBackground)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFillBackground)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_IFillBackground), { Bool(),Bool(true) }, Bool(m_scanparam->fillbackground), 0);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IFillBackground), m_scanparam->fillbackground);
return success();
case Msg::Reset:
m_scanparam->fillbackground = false;
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IFillBackground), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->fillbackground = mech;
return success();
}
default:
return capBadOperation();
}
};
//<2F><EFBFBD><EEB4A9>
m_query[(CapType)(CapTypeEx::TwEx_IFillHole)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFillHole)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_IFillHole), { Bool(),Bool(true) }, Bool(m_scanparam->fillhole.is_fillhole), 0);
return success();
case Msg::Reset:
m_scanparam->fillhole.is_fillhole = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IFillHole), m_scanparam->fillhole.is_fillhole);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IFillHole), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->fillhole.is_fillhole = mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[(CapType)(CapTypeEx::TwEx_IFillHoleRatio)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IFillHoleRatio)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createOneValue<Int32>((CapType)(CapTypeEx::TwEx_IFillHoleRatio), m_scanparam->fillhole.fillholeratio);
return success();
case Msg::Reset:
m_scanparam->fillhole.fillholeratio = 10;
case Msg::GetCurrent:
data = Capability::createOneValue<Int32>((CapType)(CapTypeEx::TwEx_IFillHoleRatio), m_scanparam->fillhole.fillholeratio);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Int32>((CapType)(CapTypeEx::TwEx_IFillHoleRatio), Int32(10));
return success();
case Msg::Set: {
auto mech = data.currentItem<Int32>();
if (mech > 0 && mech < 50) {
m_scanparam->fillhole.fillholeratio = (int)mech;
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
//<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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_IMultiOutputRed), { Bool(),Bool(true) }, Bool(m_scanparam->multi_output_red), 0);
return success();
case Msg::Reset:
m_scanparam->multi_output_red = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IMultiOutputRed), m_scanparam->multi_output_red);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IMultiOutputRed), Bool(false));
return success();
case Msg::Set: {
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();
}
default:
return capBadOperation();
}
};
//<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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_HsvCorrect), { Bool(),Bool(true) }, Bool(m_scanparam->hsvcorrect), 0);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_HsvCorrect), m_scanparam->hsvcorrect);
return success();
case Msg::Reset:
m_scanparam->hsvcorrect = false;
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_HsvCorrect), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->hsvcorrect = mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IFilter] = msgSupportGetAllSetReset;
m_caps[CapType::IFilter] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IFilter>({ Filter::Red,Filter::Green,Filter::Blue,Filter::None },
m_scanparam->filter,
0);
return success();
case Msg::Reset:
m_scanparam->filter = (byte)Filter::None;
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IFilter>((Filter)m_scanparam->filter);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IFilter>(Filter::None);
return success();
case Msg::Set: {
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();
}
default:
return capBadOperation();
}
};
//<2F><>ɫ<EFBFBD><C9AB>ǿ
m_query[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Enchace_Color>((CapType)(CapTypeEx::TwEx_IEnhanceColor),
{ Enchace_Color::Enhance_None,Enchace_Color::Enhance_Red,Enchace_Color::Enhance_Green,Enchace_Color::Enhance_Blue },
m_scanparam->enhance_color,
0);
return success();
case Msg::Reset:
m_scanparam->enhance_color = Enchace_Color::Enhance_None;
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Int16>((CapType)(CapTypeEx::TwEx_IEnhanceColor), (Enchace_Color)(m_scanparam->enhance_color));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Int16>((CapType)(CapTypeEx::TwEx_IEnhanceColor), Enchace_Color::Enhance_None);
return success();
case Msg::Set: {
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;
return success();
}
}
return badValue();
}
default:
return capBadOperation();
}
};
m_query[(CapType)(CapTypeEx::TwEx_Sharpen)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_Sharpen)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<SharpenBlur>((CapType)(CapTypeEx::TwEx_Sharpen), { SharpenBlur::Sharpen_None,SharpenBlur::Sharpen_Normal,SharpenBlur::Sharpen_More,SharpenBlur::Sharpen_Blur,SharpenBlur::Sharpen_Blur_More },
m_scanparam->sharpen,
0);
return success();
case Msg::Reset:
m_scanparam->sharpen = SharpenBlur::Sharpen_None;
case Msg::GetCurrent:
data = Capability::createOneValue<Int16>((CapType)(CapTypeEx::TwEx_Sharpen), (SharpenBlur)(m_scanparam->sharpen));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Int16>((CapType)(CapTypeEx::TwEx_Sharpen), SharpenBlur::Sharpen_None);
return success();
case Msg::Set: {
auto mech = data.currentItem<Int16>();
if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
return badValue();
m_scanparam->sharpen = (byte)mech;
return success();
}
default:
return capBadOperation();
}
};
/*<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::Reset:
m_scanparam->brightness = 0.0f;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IBrightness>(Fix32(m_scanparam->brightness));
return success();
case Msg::GetDefault:
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::Reset:
m_scanparam->contrast = 0.0f;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IContrast>(Fix32(m_scanparam->contrast));
return success();
case Msg::GetDefault:
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::Reset:
m_scanparam->gamma = 1.0f;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IGamma>(Fix32(m_scanparam->gamma));
return success();
case Msg::GetDefault:
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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_ScrewDetectEnable), { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_skrewdetect), 0);
return success();
case Msg::Reset:
m_scanparam->hardwarecaps.en_skrewdetect = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_ScrewDetectEnable), m_scanparam->hardwarecaps.en_skrewdetect);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_ScrewDetectEnable), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_skrewdetect = mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createOneValue<UInt8>((CapType)(CapTypeEx::TwEx_ScrewLevel), m_scanparam->hardwarecaps.skrewdetectlevel);
return success();
case Msg::Reset:
m_scanparam->hardwarecaps.skrewdetectlevel = 3;
case Msg::GetCurrent:
data = Capability::createOneValue<UInt8>((CapType)(CapTypeEx::TwEx_ScrewLevel), m_scanparam->hardwarecaps.skrewdetectlevel);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<UInt8>((CapType)(CapTypeEx::TwEx_ScrewLevel), UInt8(3));
return success();
case Msg::Set: {
auto mech = data.currentItem<UInt8>();
if (mech >= 1 && mech <= 5) {
m_scanparam->hardwarecaps.skrewdetectlevel = mech;
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
//װ<><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_query[(CapType)(CapTypeEx::TwEx_StableDetectEnable)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_StableDetectEnable)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_StableDetectEnable), { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_stapledetect), 0);
return success();
case Msg::Reset:
m_scanparam->hardwarecaps.en_stapledetect = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_StableDetectEnable), m_scanparam->hardwarecaps.en_stapledetect);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_StableDetectEnable), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_stapledetect = mech;
return success();
}
default:
return capBadOperation();
}
};
//˫<>ż<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 {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>(CapType::DoubleFeedDetection, { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_doublefeed), 0);
return success();
case Msg::Reset:
m_scanparam->hardwarecaps.en_doublefeed = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>(CapType::DoubleFeedDetection, m_scanparam->hardwarecaps.en_doublefeed);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>(CapType::DoubleFeedDetection, Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->hardwarecaps.en_doublefeed = mech;
return success();
}
default:
return capBadOperation();
}
};
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.get())
guiIndicator.reset();
if (guiTwain.get())
guiTwain.reset();
if (guiBridge.get())
guiBridge.reset();
scanner.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.clear();
int ret = scanner->aquire_bmpdata(bmpData);
if (ret != 0) {
scanner->Set_ErrorCode(0);
guiIndicator.reset();
if (ret != -1) {
//ShellExecute(NULL, _T("open"), _T("aa.exe"), CString("1"), _T(""), SW_HIDE);
//MessageBox(guiTwain ? guiTwain->m_hWnd : NULL, noticeMsgMap[ret], _T("<22><>ʾ"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);//
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;
}
#ifdef LOG_NORMAL
FileTools::write_log("out.txt", "m_pendingXfers " + std::to_string(m_pendingXfers));
#endif // LOG_NORMAL
data.setCount(m_pendingXfers);
return success();
}
Result HuagaoDs::pendingXfersReset(const Identity&, PendingXfers& data) {
data.setCount(0);
scanner->Stop_scan();
scanner->reset();
scanner->ResetScanner();
guiIndicator.reset();
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) {
guiTwain.reset();
#if TWPP_DETAIL_OS_WIN
guiBridge.reset();
#endif
return success();
}
Result HuagaoDs::userInterfaceEnable(const Identity&, UserInterface& ui) {
m_pendingXfers = 1;
m_memXferYOff = 0;
//writelog("userInterfaceEnable");
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
setState(DsState::Enabled);
if (startScan() == success()) {
m_pendingXfers = 1;
auto notified = notifyXferReady();
return success();
}
else {
m_pendingXfers = 0;
setState(DsState::Open);
return seqError();
}
}
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
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(Compression::None);
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) / RESOLUTIONX, static_cast<float>(dib->biHeight) / RESOLUTIONX));
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 = cv::imdecode(bmpData, cv::IMREAD_GRAYSCALE);
//G4Tiff gt(mat);
//vector<uchar> cmpdata;
//gt.GetCompressedData(cmpdata);
//int aa = 1;
data.setBytesPerRow(bpl);
data.setColumns(static_cast<UInt32>(dib->biWidth));
data.setRows(rows);
data.setBytesWritten(bpl*rows);
//data.setBytesWritten(cmpdata.size());
data.setXOffset(0);
data.setYOffset(m_memXferYOff);
data.setCompression(Compression::None);
auto lock = data.memory().data();
char* out = lock.data();
//std::copy(cmpdata.data(), cmpdata.data() + cmpdata.size(), out);
// bottom-up BMP -> top-down memory transfer
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]);
}
}
}
m_memXferYOff += rows;
if (m_memXferYOff >= static_cast<UInt32>(std::abs(dib->biHeight))) {
m_pendingXfers = 0;
m_memXferYOff = 0;
return { ReturnCode::XferDone, ConditionCode::Success };
}
return success();
}
#ifdef LOG_NORMAL
static int xtfer = 0;
#endif
Result HuagaoDs::imageNativeXferGet(const Identity& id, ImageNativeXfer& data) {
if (!m_pendingXfers) {
return seqError();
}
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());
#ifdef LOG_NORMAL
FileTools::write_log("out.txt", "imageNativeXferGet " + std::to_string(++xtfer));
#endif // LOG
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();
}
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);
fclose(pfile);
return success();
}
}
return Result(ReturnCode::Failure, ConditionCode::BadValue);
}
break;
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, decodetype);
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);
return success();
}
break;
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);
//}
}
//!< show ui to scan button push
auto scanFunction = [this](const GScanCap& caps) {
m_pendingXfers = 1;
m_scanparam.reset(new GScanCap(caps));
if (startScan() == success()) {
notifyXferReady();
//FileTools::write_log("E:\\Users\\huago\\Desktop\\1.txt", "notifyXferReady");
}
else {
m_pendingXfers = 0;
}
};
//!< ui only to confirm button push
auto confirmFunction = [this](const GScanCap& caps) {
m_scanparam.reset(new GScanCap(caps));
notifyCloseOk();
};
//!< cancel button push
auto cancelFunction = [this]() {
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);
guiTwain->ShowWindow(SW_SHOWNORMAL);
return success();
}
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;
m_scanparam.reset(new GScanCap(cfs));
}
Twpp::Result HuagaoDs::startScan()
{
//if (!scanner->IsConnected())
// return checkDeviceOnline();
scanner->ResetScanner();
#ifndef G200
scanner->clear_hwerror();
#endif //
scanner->config_params(*m_scanparam);
if (m_bIndicator) {
//!< cancel button push
auto stopFunc = [this]() {
scanner->Stop_scan();
guiIndicator.reset();//ȡ<><C8A1>ɨ<EFBFBD><C9A8> <20>رս<D8B1><D5BD><EFBFBD>ָʾ<D6B8><CABE>
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
};
guiIndicator.reset(new CIndicatorDlg(stopFunc));
guiIndicator->Create(IDD_INDICATOR, guiTwain ? guiTwain.get() : guiBridge.get());
guiIndicator->ShowWindow(SW_SHOWNORMAL);
}
scanner->Scanner_StartScan(m_scanparam->scannum);
if (bmpData.size() > 0)
bmpData.clear();
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(false);
}
int retCode = scanner->aquire_bmpdata(bmpData);
if (retCode != 0) {
scanner->Set_ErrorCode(0);
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);
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);
}
return seqError();
}
if (bmpData.size() > 0) {
return success();
}
else {
guiIndicator.reset();
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.WriteJsonArrayToFile(vc, savepath);
}