#include "stdafx.h" #ifdef max #undef max #endif #ifdef min #undef min #endif #include #include "huagaods.hpp" #include "twglue.hpp" #include "resource.h" #include "CTwainUI.h" #include "CIndicatorDlg.h" //#include "Cmsgbox.h" #include "Device/PublicFunc.h" #include "Device/GScanO200.h" #include "Device/GScanO400.h" #include "Device/GScanO400Android.h" #include "Device/GScanO1003399.h" #include "Device/GScan439Android.h" #include "Device/filetools.h" #include "Device/GScanVirtual.h" #include #include #include "GscanJsonConfig.h" #include "G4Tiff.h" #include "Device/UsbScanEx.h" #ifdef WIN32 #include #include #pragma comment (lib,"Dbghelp.lib") #endif // WIN32 using namespace std; //custom define caps enum enum class CapTypeEx : unsigned short { Base = 0x8000,//custom caps enum value must bigger than CapTypeEx::Base value,otherwise might make conflict TwEx_IMultiOutputRed = 0x8026, TwEx_IFillHole = 0x8018, TwEx_IFillHoleRatio = 0x8092, TwEx_IFillBackground = 0x8004, TwEx_IBackRotate180 = 0x8005, TwEx_IAutoDiscardBlankVince = 0x8091, TwEx_IEnhanceColor = 0x8007, TwEx_HardwareVersion = 0x8025, TwEx_ScrewDetectEnable = 0x8006, TwEx_ScrewLevel = 0x8021, TwEx_Sharpen = 0x8022, TwEx_EnFold = 0x8037, TwEx_StableDetectEnable = 0x8090, TwEx_UVModel = 0x8093, TwEx_SwitchFrontBack = 0x8094, TwEx_HsvCorrect = 0x8095, TwEx_DogEarDelection = 0x8096, TwEx_FillBackgroundMode = 0x8097, TwEx_CroporDesaskewIndent = 0x8098, TwEx_CropNoise = 0x8099, TwEx_CroporDesaskewThreshold = 0x8100, TwEx_IDetachNoise = 0x8101, TwEx_IDetachNoiseValue = 0x8102, TwEx_SizeDetect = 0x8103, TwEx_LowPowerMode = 0x8104, TwEx_ENCODE = 0x8105, TwEx_CropModel=0x8106, TwEx_DogEarDistance = 0x8107, TwEx_ImageSplit = 0x8108, TwEx_IFadeBack = 0x8109, TwEx_IFadeBackValue = 0x8110, TwEx_IToBeScan = 0x8111, TwEx_IEnMultiOutPut = 0x8112, TwEx_IEnMultiOutPutType = 0x8113, TwEx_IFixedPaper = 0x8114, TwEx_IHighImageQuality = 0x8115, TwEx_SETTOKEN = 0x8116, TwEx_IHsvFilter = 0x8117, TwEx_ColorCast = 0x8118, TwEx_IToBeScanTimeOut = 0x8119, }; enum class PaperSizeEx : unsigned short { K8 = 0x81, K16 = 0x82, Trigeminy = 0x83, }; using namespace Twpp; using namespace std::placeholders; #define TWPP_ENTRY_MFC(SourceClass)\ extern "C" TWPP_DETAIL_EXPORT Twpp::ReturnCode TWPP_DETAIL_CALLSTYLE \ DS_Entry(Twpp::Identity* origin, Twpp::DataGroup dg, Twpp::Dat dat, Twpp::Msg msg, void* data){\ AFX_MANAGE_STATE(AfxGetStaticModuleState()); \ static_assert(\ std::is_base_of, SourceClass>::value ||\ std::is_base_of, SourceClass>::value,\ "Class " #SourceClass " is not derived from SourceFromThis."\ );\ return SourceClass::entry(origin, dg, dat, msg, data);\ } TWPP_ENTRY_MFC(HuagaoDs) static constexpr const Identity srcIdent( Version(3, 3, Language::English, Country::China, "v3.3.5.9"), DataGroup::Image, #ifdef MAKEHUAGAO "HUAGO", #elif defined HANVON "Hanvon", #elif defined AUGE "AUGE", #elif defined LANXUM "LANXUM", #elif defined ZHUOYUYUN "ZHUOYUYUN", #elif defined CUMTENN "CUMTENN", #elif defined MAKERIGHTWAY "RIGHTWAY", #elif defined NOLOGO "SCAN", #else // MAKEHUAGAO "ZHIBEN", #endif #ifdef G200 #ifdef ISG100 #ifdef LANXUM "G62S Series", #elif defined HANVON "HW-8000", #elif defined ZHUOYUYUN "ZY-2100S", #else // ISG100 "G100 Series", #endif #else // ISG100 #ifdef LANXUM "G73S Series", #elif defined HANVON "HW-9000", #elif defined ZHUOYUYUN "ZY-2100S", #elif defined CUMTENN "CTS A3", #else // ISG100 "G200 Series", #endif #endif #elif defined(G300) // G200 #ifdef LANXUM "G42S Series", #elif defined CUMTENN "CTS A4", #elif defined ZHUOYUYUN "ZY-2100S", #elif defined HANVON #ifdef ANDROIDSERIAL "HW-1000", #else "HW-1000NS", #endif // ANDROIDSERIAL #else // ISG100 "G300 Series",//兼容旧极课 pm changed ,G300 Series #endif #elif defined(G400) // G200 #ifdef LANXUM "G52S Series", #elif defined ZHUOYUYUN "ZY-2100S", #elif defined HANVON #ifdef ANDROIDSERIAL "HW-7000", #else "HW-7000NS", #endif // ANDROIDSERIAL #else // ISG100 "G400 Series", #endif #endif #ifdef G200 #ifdef ISG100 #ifdef MAKEHUAGAO "HUAGOSCAN G100 TWAIN" #elif defined NOLOGO "Scan G100 TWAIN" #elif defined AUGE "AUGESCAN G100 TWAIN" #elif defined ZHUOYUYUN "ZHUOYUYUNSCAN G100 TWAIN" #elif defined HANVON "Hanvon HW-8000 TAWIN" #elif defined LANXUM //!LANXUM "LANXUMSCAN G62S TWAIN" #else // !MAKEHUAGAO "ZhibenScan G100 TWAIN" #endif #else // ISG100 #ifdef MAKEHUAGAO "HUAGOSCAN G200 TWAIN" #elif defined ZHUOYUYUN "ZHUOYUYUNSCAN G200 TWAIN" #elif defined NOLOGO "Scan G200 TWAIN" #elif defined CUMTENN "CUMTENN CTS A3 TWAIN" #elif defined HANVON "Hanvon HW-9000 TAWIN" #elif defined LANXUM //!LANXUM "LANXUMSCAN G73S TWAIN" #else // !MAKEHUAGAO "ZhibenScan G200 TWAIN" #endif #endif #elif defined G300 // G200 #ifdef MAKEHUAGAO #ifdef UV "HUAGOSCAN G300UV TWAIN" #elif defined ANDROIDSERIAL "HUAGOSCAN G300 Android TWAIN"// 兼容旧极课 pm changed "HUAGOSCAN G300 TWAIN" #else "HUAGOSCAN G300 Linux TWAIN" #endif #elif defined UV && defined MAKERIGHTWAY "RIGHTWAYSCAN G300 TWAIN" #elif defined HANVON #ifdef ANDROIDSERIAL "Hanvon HW-1000 TAWIN" #else "Hanvon HW-1000NS TAWIN" #endif // ANDROIDSERIES #elif defined NOLOGO "Scan G300 TWAIN" #elif defined ZHUOYUYUN "ZHUOYUYUNSCAN G300 TWAIN" #elif defined CUMTENN "CUMTENN CTS A4 TWAIN" #elif defined LANXUM //!LANXUM "LANXUMSCAN G42S TWAIN" #else // !MAKEHUAGAO "ZhibenScan G300 TWAIN" #endif #elif defined(G400) // G200 #ifdef MAKEHUAGAO #ifdef ANDROIDSERIAL "HUAGOSCAN G400 Android TWAIN" #else "HUAGOSCAN G400 Linux TWAIN" #endif // ANDROIDSERIES #elif defined HANVON #ifdef ANDROIDSERIAL "Hanvon HW-7000 TAWIN" #else "Hanvon HW-7000NS TAWIN" #endif // ANDROIDSERIES #elif defined LANXUM //!LANXUM "LANXUMSCAN G52S TWAIN" #elif defined ZHUOYUYUN "ZHUOYUYUNSCAN G400 TWAIN" #elif defined NOLOGO "Scan G400 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 application(new CWinApp()); #ifdef LANXUM static list resList = { 100.0,150.0,200.0,240.0,300.0 }; #else static list resList = { 100.0,150.0,200.0,240.0,300.0,600.0 }; #endif // LANXUM //区分G200 G300、G400纸张幅面 #ifdef G200 static list paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6, (UInt16)PaperSize::IsoB4,(UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6, (UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::UsLedger, (UInt16)PaperSize::MaxSize,(UInt16)PaperSize::None,(UInt16)PaperSize::UsStatement, (UInt16)PaperSizeEx::K8,(UInt16)PaperSizeEx::K16,(UInt16)PaperSizeEx::Trigeminy }; #elif defined G300 static list paperSizeList = { (UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6, (UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6, (UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::None,(UInt16)PaperSizeEx::K16 }; #elif defined G400 static list paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6, (UInt16)PaperSize::IsoB4,(UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6, (UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::UsLedger, (UInt16)PaperSize::MaxSize,(UInt16)PaperSize::None,(UInt16)PaperSize::UsStatement , (UInt16)PaperSizeEx::K8,(UInt16)PaperSizeEx::K16,(UInt16)PaperSizeEx::Trigeminy }; #endif // G200 static list 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 mapDeviceEvent = { {OPEN_COVER,(DeviceEvent::Type)(DeviceEventType::Dev_OPENCOVER)}, {NO_FEED,(DeviceEvent::Type)(DeviceEventType::Dev_NOFEED)}, {FEED_IN_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_FEEDERROR)}, {PAPER_JAM,DeviceEvent::Type::PaperJam}, {DETECT_DOUBLE_FEED,DeviceEvent::Type::PaperDoubleFeed}, {DETECT_STAPLE,(DeviceEvent::Type)(DeviceEventType::Dev_STABLE)}, {PAPER_SKEW,(DeviceEvent::Type)(DeviceEventType::Dev_SKREW)}, {COUNT_MODE,(DeviceEvent::Type)(DeviceEventType::Dev_COUNTMOE)}, {HARDWARE_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_HARDWAREERROR)}, {FPGA_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_FPGAERROR)}, {USB_DISCONNECTED,DeviceEvent::Type::CheckDeviceOnline}, {USER_STOP,(DeviceEvent::Type)(DeviceEventType::Dev_UserStop)}, {DOG_EAR,(DeviceEvent::Type)(DeviceEventType::Dev_DogEar)} }; struct Vid_pid { WORD vid; WORD pid; }; #ifdef LANXUM static std::vector DeviceID{ {0x31c9,0x8200}, #ifdef G200 #ifdef ISG100 {0x31c9,0x8629}, {0x31c9,0x8620}, #else {0x31c9,0x8739}, {0x31c9,0x8730}, #endif // ISG100 #elif defined G300 {0x31c9,0x8420}, {0x31c9,0x8429}, #elif defined G400 {0x31c9,0x8520}, {0x31c9,0x8529}, #endif // ISG100 }; #elif defined ZHUOYUYUN static std::vector DeviceID{ {0x3072,0x2100}, }; #elif defined AUGE static std::vector DeviceID{ {0x3072,0x0130}, }; #elif defined HANVON static std::vector DeviceID{ #ifdef G200 #ifdef ISG100 {0x2903,0x8000}, #else {0x2903,0x9000}, #endif // ISG100 #elif defined G400 {0x2903,0x7000}, #ifdef ANDROIDSERIAL {0x2903,0x7002}, #else {0x2903,0x7039}, #endif // ANDROIDSERIAL #elif defined G300 {0x2903,0x1000}, #ifdef ANDROIDSERIAL {0x2903,0x1002}, #endif // ANDROIDSERIAL #endif // G200 }; #elif defined CUMTENN static std::vector DeviceID{ #ifdef G200 #ifdef ISG100 {0x3072,0x138}, #else {0x3072,0x238}, #endif // ISG100 #elif defined G300 {0x3072,0x0303}, #elif defined G400 {0x3072,0x0403}, #endif }; #else static std::vector DeviceID{ {0x64B,0x7823}, #ifdef G200 #ifdef ISG100 {0x3072,0x100}, {0x3072,0x139}, #else {0x3072,0x239}, {0x3072,0x200}, #endif // ISG100 #elif defined G300 {0x3072,0x0300}, #ifdef ANDROIDSERIAL {0x3072,0x0302}, #else {0x3072,0x0339}, #endif // ANDROIDSERIAL #elif defined G400 {0x3072,0x0400}, #ifdef ANDROIDSERIAL {0x3072,0x0402}, #else {0x3072,0x0439}, #endif // ANDROIDSERIAL #endif // ISG100 }; #endif static void DeleteWnd(CDialog* pWnd) { if (pWnd && pWnd->GetSafeHwnd()) { if (pWnd->m_hWnd) DestroyWindow(pWnd->m_hWnd); } } static std::unique_ptr guiTwain(nullptr, DeleteWnd); //static std::unique_ptr msgbox; #if TWPP_DETAIL_OS_WIN static std::unique_ptr guiBridge(nullptr, DeleteWnd); #endif //static std::unique_ptr guiIndicator(nullptr, DeleteWnd); static CIndicatorDlg* guiIndicator = NULL; //#define HG_VIRTUAL #ifndef HG_VIRTUAL static std::unique_ptr scanner; //(new GScanO200()); #else static std::unique_ptr scanner(new GScanVirtual()); #endif long __stdcall callback(EXCEPTION_POINTERS* ex) { if (scanner.get()) { if (scanner->IsConnected()) scanner->Stop_scan(); } HANDLE handle = CreateFile((FileTools::get_errorlog_path_w()+L"error.dmp").c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(!handle) return EXCEPTION_EXECUTE_HANDLER; MINIDUMP_EXCEPTION_INFORMATION dump; dump.ExceptionPointers = ex; dump.ThreadId = GetCurrentThreadId(); dump.ClientPointers = TRUE; MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), handle, MiniDumpWithFullMemory, &dump, NULL, NULL); FatalAppExit(-1, L"TWAIN Error Exit "); return EXCEPTION_EXECUTE_HANDLER; } static std::once_flag oc; HuagaoDs::HuagaoDs() : m_scanparam(new GScanCap) , bmpData(new std::vector) , hMutex(NULL) { std::call_once(oc, [&]() { log4cplus::Initializer(); SetUnhandledExceptionFilter(callback); //void* addr = (void*)GetProcAddress(LoadLibrary(L"kernel32.dll"), "SetUnhandledExceptionFilter"); //重写进程中SetUnhandledExceptionFilter函数地址,后续设置此函数将不再失效 //if (addr) //{ // uchar code[16]; // memset(code, 0, 16); // int size = 0; // code[size++] = 0x33; // code[size++] = 0xc0; // code[size++] = 0xc2; // code[size++] = 0x04; // code[size++] = 0x00; // DWORD dwoldflag, dwtempflag; // VirtualProtect(addr, size, PAGE_READWRITE, &dwoldflag); // WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL); // VirtualProtect(addr, size, dwoldflag, &dwtempflag); //} }); //log4cplus::Initializer(); //log4cplus::deinitialize(); /*string ss1= getOSInfo(); string ss2=getManufactureID(); string ss3=getCpuType(); string ss4= getMemoryInfo(); DWORD dwNum; CString aas[10]; GetDiskInfo(dwNum,aas);*/ //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"内存不足", L"提示", MB_OK| MB_SYSTEMMODAL); //})); } void HuagaoDs::showmsg(std::string caption, std::string text, int retcode) { if (scanner.get()) { int num = scanner->get_imgnReaded() * (m_scanparam->is_duplex ? 2 : 1) * (m_scanparam->multi_output_red ? 2 : 1) / (m_scanparam->en_fold ? 2 : 1) * (m_scanparam->is_split ? 2 : 1) * (m_scanparam->en_multi_output ? (m_scanparam->multioutput < 0 ? 1 : (m_scanparam->multioutput == 0 ? 3 : 2)) : 1); int imgread = scanner->get_imgnReaded(); IScanner* ptr = scanner.get(); if (typeid(*ptr) == typeid(GScanO1003399)) { //readnum = readnum / 2 * (m_scanparam->en_fold ? 2 : 1); num = scanner->get_imgnReaded() * (m_scanparam->multi_output_red ? 2 : 1) * (m_scanparam->is_split ? 2 : 1) * (m_scanparam->en_multi_output ? (m_scanparam->multioutput < 0 ? 1 : (m_scanparam->multioutput == 0 ? 3 : 2)) : 1); if(!m_scanparam->en_fold) imgread /= 2; } if (retcode == 200) { if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince)) { text += "请检查实际过纸张数!\n扫描统计信息:\n进纸(张)--\n扫描(张)" + to_string(imgread) + "\n扫描相差(张)--\n上传(页)" + to_string(scanner->get_imgTransfered()) + "\n上传相差(页)" + to_string(num - scanner->get_imgTransfered()); scanner->set_lose_image_num(0); } } else { if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince)) { text += "\n扫描统计信息:\n进纸(张)" + to_string(scanner->get_scannum()) + "\n扫描(张)" + to_string(imgread) + "\n扫描相差(张)" + to_string(scanner->get_scannum() - imgread) + "\n上传(页)" + to_string(scanner->get_imgTransfered()) + "\n上传相差(页)" + to_string(num - scanner->get_imgTransfered()); scanner->set_lose_image_num(0); } } } FileTools::kill_process(L"hidedlg.exe"); //system("taskkill /f /im hidedlg.exe"); ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString((text + " " + caption).c_str()), NULL, SW_HIDE); } void HuagaoDs::hgmsg(CString str) { ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), str, NULL, SW_HIDE); } HuagaoDs::~HuagaoDs() { if (memoryinfo.get()) { m_memoryfalg = false; if (memoryinfo->joinable()) memoryinfo->join(); } if (scanner.get()) scanner.reset(); } const Identity& HuagaoDs::defaultIdentity() noexcept { // remember, we return a reference, therefore the identity must not be placed on the stack of this method return srcIdent; } Result HuagaoDs::call(const Identity& origin, DataGroup dg, Dat dat, Msg msg, void* data) { try { // we can override almost anything from SourceFromThis, even the top-most source instance call //FileTools::write_log("D:\\1.txt", "call:datagroup-"+to_string((int)dg)+"dat-"+to_string(int(dat))+"msg-"+to_string(int(msg))); return Base::call(origin, dg, dat, msg, data); } catch (const CapabilityException& e) { FileTools::writelog(log_ERROR, e.what()); return badValue(); } } Result HuagaoDs::customDataGet(const Twpp::Identity& origin, Twpp::CustomData& data) { //从保存默认配置的文件路径读取字节流上传 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(); memcpy(pdata.data(), buf.c_str(), t); return success(); } Result HuagaoDs::customDataSet(const Twpp::Identity& origin, Twpp::CustomData& data) { GScanCap sc; //将字节流转GscanCaps GscanJsonConfig js; std::string str; str.resize(data.size()); auto pdata = data.lock(); memcpy((void*)str.c_str(), pdata, data.size()); //vector vc = js.parseJsonFromString(str); //m_scanparam.reset(new GScanCap(vc[0])); //std::unique_ptr cap(new GScanCap(js.JsonToGscancap(json::parse(str)))); m_scanparam.reset(new GScanCap(js.JsonToGscancap(json::parse(str)))); return success(); } // some helper functions to handle capability stuff template 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 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 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(); return {}; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template 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() == def ? Result() : Result(ReturnCode::Failure, ConditionCode::BadValue); default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template 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() == 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 Result CapSupGetAll(Msg msg, Capability& data, std::initializer_list values, T& currvalue, T defaultvalue, UInt32 currindex, UInt32 defaultindex) { switch (msg) { case Msg::Get: data = Capability::createEnumeration((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 Result CapSupGetAll(Msg msg, Capability& data, T1& currvalue, T2 defaultvalue) { switch (msg) { case Msg::Get: case Msg::GetCurrent: case Msg::GetDefault: data = Capability::createOneValue((T2)defaultvalue); return { ReturnCode::Success, ConditionCode::Success }; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template Result CapSupGetAllEx(Msg msg, Capability& data, T& currvalue, T defaultvalue) { switch (msg) { case Msg::Get: case Msg::GetCurrent: case Msg::GetDefault: data = Capability::createOneValue(cap, defaultvalue); return { ReturnCode::Success, ConditionCode::Success }; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template Result CapSupGetAllReset(Msg msg, Capability& data, std::initializer_list values, T1& currvalue, T2 defaultvalue, UInt32 currindex, UInt32 defaultindex) { switch (msg) { case Msg::Get: data = Capability::createEnumeration(values, currindex, defaultindex); return { ReturnCode::Success, ConditionCode::Success }; case Msg::GetCurrent: data = Capability::createOneValue((T2)currvalue); return { ReturnCode::Success, ConditionCode::Success }; case Msg::Reset: case Msg::GetDefault: currvalue = (T1)defaultvalue; data = Capability::createOneValue(defaultvalue); return { ReturnCode::Success, ConditionCode::Success }; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template Result CapSupGetAllReset(Msg msg, Capability& data, T1& currvalue, T2 defaultvalue) { switch (msg) { case Msg::Get: case Msg::GetCurrent: data = Capability::createOneValue((T2)currvalue); return { ReturnCode::Success, ConditionCode::Success }; case Msg::Reset: case Msg::GetDefault: currvalue = (T1)defaultvalue; data = Capability::createOneValue(defaultvalue); return { ReturnCode::Success, ConditionCode::Success }; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template Result CapSupGetAllResetEx(Msg msg, Capability& data, std::initializer_list values, T1& currvalue, T2 defaultvalue, UInt32 currindex, UInt32 defaultindex) { switch (msg) { case Msg::Get: data = Capability::createEnumeration(cap, values, currindex, defaultindex); return { ReturnCode::Success, ConditionCode::Success }; case Msg::GetCurrent: data = Capability::createOneValue(cap, (T2)currvalue); return { ReturnCode::Success, ConditionCode::Success }; case Msg::Reset: case Msg::GetDefault: currvalue = (T1)defaultvalue; data = Capability::createOneValue(cap, defaultvalue); return { ReturnCode::Success, ConditionCode::Success }; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } template Result CapSupGetAllResetEx(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 }; } } 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 //FileTools::writelog(log_ERROR, "eventProcess " + to_string((int)event.message())); 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------------------设置jpg图像dpi--------------------------- void HuagaoDs::SetResoluton(const char* path, int resolution) { FILE* file = fopen(path, "rb+"); if (!file) return; //获取文件大小 int len = _filelength(_fileno(file)); char* buf = new char[len]; fread(buf, sizeof(char), len, file); char* pResolution = (char*)&resolution; //设置使用图片密度单位 buf[0x0D] = 1; //水平密度,水平分辨率 buf[0x0E] = pResolution[1]; buf[0x0F] = pResolution[0]; //垂直密度,垂直分辨率 buf[0x10] = pResolution[1]; buf[0x11] = pResolution[0]; fseek(file, 0, SEEK_SET); //将数据写入文件,覆盖原始数据,让修改生效 fwrite(buf, sizeof(char), len, file); fclose(file); delete[]buf; } void HuagaoDs::dogear_callback(int indexpaper) { CString text; text.Format(_T("74 %d"), indexpaper); //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE); showmsg("提示","在"+to_string(indexpaper)+"检测到折角!"); scanner->Stop_scan(); //scanner->reset(); scanner->ResetScanner(); onDeviceEvent(DOG_EAR); } Result HuagaoDs::identityOpenDs(const Identity& origin) { #ifdef G400 hMutex = CreateMutex(NULL, FALSE, _T("LookitApp_4")); #elif defined G300 hMutex = CreateMutex(NULL, FALSE, _T("LookitApp_3")); #elif defined ISG100 hMutex = CreateMutex(NULL, FALSE, _T("LookitApp_1")); #else hMutex = CreateMutex(NULL, FALSE, _T("LookitApp_2")); #endif // G400 if (GetLastError() == ERROR_ALREADY_EXISTS) { //如果已经存在同名的Mutex会得到这个错误. CloseHandle(hMutex); hMutex = NULL; //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("202"), NULL, SW_HIDE); showmsg("提示", msgs[(UsbSupported)202]); return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } Twain_config().GetOrSetPintfCapability(is_printfcapability, true); auto usblist = UsbScan_List::find_all_usb(); if (!usblist.empty()) { for each (auto & usb in usblist) { for(int x=0;xopen(vid, pid); if (scanner->get_ErrorCode() == SLEEPING) { if (hMutex) { ReleaseMutex(hMutex); CloseHandle(hMutex); hMutex = NULL; } return seqError(); } if (!scanner->IsConnected()) { //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE); showmsg("提示", msgs[(UsbSupported)201]); if (hMutex) { CloseHandle(hMutex); hMutex = NULL; } return checkDeviceOnline(); } else { scanner->regist_deviceevent_callback(DeviceEvent_callback, this); auto dgcall = [&](int pagenum) { //ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE); showmsg("提示", "在" + to_string(pagenum) + "检测到折角!"); scanner->Stop_scan(); //scanner->reset(); scanner->ResetScanner(); onDeviceEvent(DOG_EAR); }; scanner->DogEar_callback(dgcall); } m_haveError = false; updataGscanCap(); bmpData->resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header()); bmInfo.biHeight = 2000; bmInfo.biWidth = 2000; bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1); m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1); //MessageBox(NULL, L"2", L"", 0); // init caps // there are caps a minimal source must support // query -> says which operations a cap supports // caps -> has handler for each specific cap m_query[CapType::SupportedCaps] = msgSupportGetAll; m_caps[CapType::SupportedCaps] = [this](Msg msg, Capability& data) { if ((msg == Msg::Get) || (Msg::GetCurrent == msg) || (Msg::GetDefault == msg)) { data = Capability::createArray(m_caps.size()); auto arr = data.array(); 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, _1, _2, Bool(true)); m_query[CapType::DeviceOnline] = msgSupportGetAll; //m_caps[CapType::DeviceOnline] = std::bind(enmGet, _1, _2, Bool(scanner->IsConnected())); m_caps[CapType::DeviceOnline] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::DeviceOnline)); switch (msg) { case Msg::Get: case Msg::GetCurrent: case Msg::GetDefault: data = Capability::createOneValue((Twpp::Bool)scanner->IsConnected()); return {}; default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } }; m_query[CapType::XferCount] = msgSupportGetAllSetReset; m_caps[CapType::XferCount] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::XferCount),msg==Msg::Set?to_string((int)data.currentItem()):""); if (msg == Msg::Set) { auto item = data.currentItem(); if (item > 65535 || item < -1 || item == 0) { return badValue(); } m_scanparam->scannum = item; return success(); } Int16 tmp_count = m_scanparam->scannum; auto ret = oneValGetSet(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, _1, _2, Compression::None); m_caps[CapType::ICompression] = [this](Msg msg, Capability& data)->Result{ CapabilityPrintf(msg, enum2str(CapType::ICompression), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (Compression::None == mech || mech == Compression::Group4) { if (mech == Compression::Group4) { if (m_scanparam->pixtype != 0) return badValue(); } m_compression = mech; return success(); } else return badValue(); } return CapSupGetAllReset(msg, data, { Compression::None, Compression::Group4 }, m_compression, Compression::None, m_compression == Compression::None ? 0 : 1, 0); }; m_query[CapType::IBitDepth] = msgSupportGetAllSetReset; m_caps[CapType::IBitDepth] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::IBitDepth), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); 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(msg, data, m_iBitdepth, 24); }; m_query[CapType::IBitOrder] = msgSupportGetAllSetReset; m_caps[CapType::IBitOrder] = std::bind(oneValGetSetConst, _1, _2, BitOrder::MsbFirst); m_query[CapType::IPlanarChunky] = msgSupportGetAllSetReset; m_caps[CapType::IPlanarChunky] = std::bind(enmGetSetConst, _1, _2, PlanarChunky::Chunky); m_query[CapType::IPhysicalWidth] = msgSupportGetAll; m_caps[CapType::IPhysicalWidth] = std::bind(oneValGet, _1, _2, Fix32(static_cast(header()->biWidth) / m_scanparam->resolution_dst)); m_query[CapType::IPhysicalHeight] = msgSupportGetAll; m_caps[CapType::IPhysicalHeight] = std::bind(oneValGet, _1, _2, Fix32(static_cast(header()->biHeight) / m_scanparam->resolution_dst)); m_query[CapType::IPixelFlavor] = msgSupportGetAllSetReset; m_caps[CapType::IPixelFlavor] = std::bind(enmGetSetConst, _1, _2, PixelFlavor::Chocolate); m_query[CapType::IPixelType] = msgSupportGetAllSetReset; m_caps[CapType::IPixelType] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::IPixelType), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if( Msg::Set==msg) { auto mech = data.currentItem(); if (mech == PixelType::Rgb || mech == PixelType::Gray || mech == PixelType::BlackWhite) { m_scanparam->automaticcolor = FALSE; m_scanparam->pixtype = (int)mech; if (m_scanparam->pixtype == (int)PixelType::Rgb){ m_scanparam->filter = (BYTE)Filter::None; m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None; } else{ m_scanparam->multi_output_red = 0;//非彩色模式下多流输出不可用 m_scanparam->detachnoise.is_detachnoise = false; m_scanparam->fadeback = false; m_scanparam->hsvFilter = 0; m_scanparam->hsvcorrect = 0; //if (mech == PixelType::BlackWhite) //{ // if (m_scanparam->filter == (uint8)Filter::None && m_scanparam->enhance_color == Enchace_Color::Enhance_None) // { // m_scanparam->enhance_color = 1; // } //} } m_iBitdepth = mech == PixelType::Rgb ? 24 : (mech == PixelType::Gray ? 8 : 1); return success(); } return badValue(); } return CapSupGetAllReset(msg, data, { PixelType::BlackWhite,PixelType::Gray,PixelType::Rgb }, m_scanparam->pixtype, PixelType::Rgb, m_scanparam->pixtype == (int)PixelType::Rgb ? 2 : (m_scanparam->pixtype == (int)PixelType::Gray ? 1 : 0), 2); }; m_query[CapType::IAutomaticColorEnabled] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticColorEnabled] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutomaticColorEnabled), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); 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(msg, data, { FALSE,TRUE }, m_scanparam->automaticcolor, false, m_scanparam->automaticcolor ? 1 : 0, 0); }; m_query[CapType::IAutomaticColorNonColorPixelType] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticColorNonColorPixelType] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutomaticColorNonColorPixelType), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (msg == Msg::Set) { auto mech = data.currentItem(); if (m_scanparam->automaticcolor == TRUE) { if ((UInt16)mech == 0 || (UInt16)mech == 1) { m_scanparam->automaticcolortype = (UInt16)mech; return success(); } } return seqError(); } return CapSupGetAllReset(msg, data, { PixelType::BlackWhite, PixelType::Gray }, m_scanparam->automaticcolortype, PixelType::Gray, m_scanparam->automaticcolortype, 1); }; //add------------------jpeg质量等级--------------------- m_query[CapType::IJpegQuality] = msgSupportGetAllSetReset; m_caps[CapType::IJpegQuality] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IJpegQuality), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if ((int)mech < 0 || (int)mech > 100) return badValue(); m_jpegQuality = (int)mech; return success(); } return CapSupGetAllResetEx(msg, data, m_jpegQuality, 80); }; m_query[CapType::IUnits] = msgSupportGetAllSetReset; m_caps[CapType::IUnits] = std::bind(enmGetSetConst, _1, _2, Unit::Inches); m_query[CapType::IXferMech] = msgSupportGetAllSetReset; m_caps[CapType::IXferMech] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::IXferMech), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech == XferMech::Native || mech == XferMech::Memory || mech == XferMech::File) { m_capXferMech = mech; return success(); } else { return badValue(); } } return CapSupGetAllReset(msg, data, { XferMech::Native, XferMech::File, XferMech::Memory }, m_capXferMech, XferMech::Native, (int)m_capXferMech, 0); }; m_query[CapType::IXResolution] = msgSupportGetAllSetReset; m_caps[CapType::IXResolution] = [this](Msg msg, Capability& data) { CapabilityPrintf(msg, enum2str(CapType::IXResolution), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); switch (msg) { case Msg::Get: data = Capability::createRange(Fix32(100.0f), Fix32(600.0f), Fix32(1.0f), Fix32(m_scanparam->resolution_dst), Fix32(200.0)); return success(); case Msg::GetCurrent: data = Capability::createOneValue(Fix32(m_scanparam->resolution_dst)); return success(); case Msg::GetDefault: case Msg::Reset: m_scanparam->resolution_dst = 200.0f; data = Capability::createOneValue(Fix32(200.0f)); return success(); case Msg::Set: { auto mech = data.currentItem(); if (mech < 100.0f || mech > 600.0f) return badValue(); m_scanparam->resolution_dst = (float)mech; return success(); } default: return capBadOperation(); } }; m_query[CapType::IYResolution] = msgSupportGetAllSetReset; m_caps[CapType::IYResolution] = m_caps[CapType::IXResolution]; m_query[CapType::IXNativeResolution] = msgSupportGetAll; m_caps[CapType::IXNativeResolution] = std::bind(enmGet, _1, _2, Fix32(200.0)); m_query[CapType::IYNativeResolution] = msgSupportGetAll; m_caps[CapType::IYNativeResolution] = m_caps[CapType::IXNativeResolution]; m_query[CapType::ISupportedSizes] = msgSupportGetAllSetReset; m_caps[CapType::ISupportedSizes] = [this](Msg msg, Capability& data) { CapabilityPrintf(msg, enum2str(CapType::ISupportedSizes), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { //if (m_scanparam->is_autocrop) // return success(); auto paper = data.currentItem(); 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; m_scanparam->en_fixedpaper = 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(msg, data, { PaperSize::A4,PaperSize::A5,PaperSize::A6, PaperSize::IsoB5,PaperSize::IsoB6,PaperSize::UsLetter, PaperSize::UsLegal,PaperSize::None,(PaperSize)PaperSizeEx::K16 #ifndef G300 #if defined G200 ,PaperSize::A3,PaperSize::UsLedger,PaperSize::IsoB4, PaperSize::MaxSize,PaperSize::UsStatement,(PaperSize)PaperSizeEx::K8,(PaperSize)PaperSizeEx::K16,(PaperSize)PaperSizeEx::Trigeminy #elif defined G400 ,PaperSize::A3,PaperSize::UsLedger,PaperSize::IsoB4,PaperSize::MaxSize,PaperSize::UsStatement, (PaperSize)PaperSizeEx::K8,(PaperSize)PaperSizeEx::K16,(PaperSize)PaperSizeEx::Trigeminy #endif #endif // }, m_scanparam->papertype, PaperSize::None, std::distance(paperSizeList.begin(), std::find(paperSizeList.begin(), paperSizeList.end(), m_scanparam->papertype)) == paperSizeList.size() ? 0 : std::distance(paperSizeList.begin(), std::find(paperSizeList.begin(), paperSizeList.end(), m_scanparam->papertype)), std::distance(paperSizeList.begin(), std::find(paperSizeList.begin(), paperSizeList.end(), 0))); }; #ifdef G200 m_query[(CapType)(CapTypeEx::TwEx_SizeDetect)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_SizeDetect)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_SizeDetect), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech) { if (m_scanparam->papertype == (uint8_t)PaperSize::None || m_scanparam->papertype == (uint8_t)PaperSize::MaxSize || m_scanparam->papertype == (uint8_t)PaperSize::UsStatement || m_scanparam->papertype == (uint8_t)PaperSizeEx::Trigeminy) return badValue(); } m_scanparam->en_sizecheck = mech; return success(); } return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->en_sizecheck, false, m_scanparam->en_sizecheck, 0); }; //敦南cis固件幅面扫描 m_query[(CapType)(CapTypeEx::TwEx_IFixedPaper)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IFixedPaper)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFixedPaper), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech) { if (m_scanparam->papertype == (uint8_t)PaperSize::None || m_scanparam->papertype == (uint8_t)PaperSize::MaxSize || m_scanparam->papertype == (uint8_t)PaperSize::UsStatement || m_scanparam->papertype == (uint8_t)PaperSizeEx::Trigeminy) return badValue(); } m_scanparam->en_fixedpaper = mech; return success(); } return CapSupGetAllResetEx(msg, data, { false,true }, m_scanparam->en_fixedpaper, false, m_scanparam->en_fixedpaper, 0); }; #endif // G200 m_query[CapType::IOrientation] = msgSupportGetAllSetReset; m_caps[CapType::IOrientation] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapTypeEx::IOrientation), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if ((mech == Orientation::Landscape) && (m_scanparam->papertype == (uint8_t)PaperSize::None || m_scanparam->papertype == (uint8_t)PaperSize::MaxSize || m_scanparam->papertype == (uint8_t)PaperSize::UsStatement || m_scanparam->papertype == (uint8_t)PaperSizeEx::Trigeminy || m_scanparam->papertype == (uint8_t)PaperSize::A3 || m_scanparam->papertype == (uint8_t)PaperSize::IsoB4 || m_scanparam->papertype == (uint8_t)PaperSizeEx::K8 || m_scanparam->papertype == (uint8_t)PaperSize::UsLedger)) return badValue(); if (mech == Orientation::Landscape || mech == Orientation::Portrait) { m_scanparam->paperAlign = (PaperAlign)mech; return success(); } return badValue(); } return CapSupGetAllReset(msg, data, { Orientation::Portrait, Orientation::Landscape }, m_scanparam->paperAlign, Orientation::Portrait, m_scanparam->paperAlign == 0 ? 0 : 1, 0); }; m_query[CapType::IRotation] = msgSupportGetAllSetReset; m_caps[CapType::IRotation] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapTypeEx::IRotation), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto res = data.currentItem(); 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(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(); //针对G300 G400 USB通信第一次无法read_bulk 起到激活USB的作用 #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(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(msg, data, str, str); }; m_query[(CapType)(CapTypeEx::TwEx_ENCODE)] = msgSupportGetAll; //m_caps[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = std::bind(oneValGetString, _1, _2, scanner->GetFWVersion()); m_caps[(CapType)(CapTypeEx::TwEx_ENCODE)] = [this](Msg msg, Capability& data)->Result { Str255 str; str.setData(scanner->get_scannercode().c_str(), 32); return CapSupGetAllEx(msg, data, str, str); }; m_query[CapType(CapTypeEx::TwEx_SETTOKEN)] = MsgSupport::Set; m_caps[CapType(CapTypeEx::TwEx_SETTOKEN)] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapTypeEx::SETTOKEN)); if (msg != Msg::Set) { Str32 str; str.setData("This operation is not supported ", 32); data = Capability::createOneValue(CapType(CapTypeEx::TwEx_SETTOKEN), str); return success(); } auto str = data.currentItem(); if(str.size()!=32) return { ReturnCode::Failure, ConditionCode::CapBadOperation }; //MessageBox(NULL, L"内存不足", L"", MB_OK | MB_SYSTEMMODAL); scanner->set_token(std::string(str.data())); return success(); //return CapSupGetAll(msg, data, Bool(scanner->Get_Scanner_PaperOn()), Bool(scanner->Get_Scanner_PaperOn())); }; m_query[CapType::FeederLoaded] = msgSupportGetAll; m_caps[CapType::FeederLoaded] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::FeederLoaded)); return CapSupGetAll(msg, data, Bool(scanner->Get_Scanner_PaperOn()), Bool(scanner->Get_Scanner_PaperOn())); }; m_query[CapType::Indicators] = msgSupportGetAllSetReset; m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::Indicators), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto show = data.currentItem(); m_bIndicator = show; return success(); } return CapSupGetAllReset(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(msg, data, Bool(true), Bool(true)); }; m_query[CapType::EnableDsUiOnly] = msgSupportGetAll; m_caps[CapType::EnableDsUiOnly] = std::bind(enmGet, _1, _2, Bool(true)); m_query[CapType::PaperDetectable] = msgSupportGetAll; m_caps[CapType::PaperDetectable] = std::bind(oneValGet, _1, _2, Bool(true)); m_query[CapType::FeederEnabled] = msgSupportGetAllSetReset; m_caps[CapType::FeederEnabled] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::FeederEnabled), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_bFeederEnabled = mech; return success(); } return CapSupGetAllReset(msg, data, m_bFeederEnabled, Bool(true)); }; m_query[CapType::Duplex] = msgSupportGetAll; m_caps[CapType::Duplex] = std::bind(oneValGet, _1, _2, Duplex::OnePass); m_query[CapType::DuplexEnabled] = msgSupportGetAllSetReset; m_caps[CapType::DuplexEnabled] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::DuplexEnabled), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { bool mech = data.currentItem(); m_scanparam->is_duplex = mech; if (!mech){ m_scanparam->is_backrotate180 = 0;//单面背面旋转180°不可用 m_scanparam->is_switchfrontback = 0; m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = m_scanparam->en_fold = 0; } //#ifdef LANXUM // if (mech) m_scanparam->is_autodiscradblank_normal = true; // else m_scanparam->is_autodiscradblank_normal = false; //#endif return success(); } return CapSupGetAllReset(msg, data, m_scanparam->is_duplex, Bool(true)); }; m_query[CapType::AutoFeed] = msgSupportGetAllSetReset; m_caps[CapType::AutoFeed] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::AutoFeed), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_bAutoFeed = mech; return success(); } return CapSupGetAllReset(msg, data, { false,true }, m_bAutoFeed, true, m_bAutoFeed ? 1 : 0, 1); }; m_query[CapType::IImageFileFormat] = msgSupportGetAllSetReset; m_caps[CapType::IImageFileFormat] = [this](Msg msg, Capability& data) -> Result { CapabilityPrintf(msg, enum2str(CapType::IImageFileFormat), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech == ImageFileFormat::Bmp || mech == ImageFileFormat::Tiff || mech == ImageFileFormat::Jfif) { m_capImageFileFormat = mech; return success(); } else return badValue(); } return CapSupGetAllReset < ImageFileFormat, ImageFileFormat, CapType::IImageFileFormat>(msg, data, { ImageFileFormat::Bmp, ImageFileFormat::Tiff,ImageFileFormat::Jfif }, m_capImageFileFormat, ImageFileFormat::Bmp, m_capImageFileFormat == ImageFileFormat::Bmp ? 0 : (m_capImageFileFormat == ImageFileFormat::Tiff ? 1 : 2), 0); }; //custom define m_query[CapType::IAutomaticDeskew] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticDeskew] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutomaticDeskew), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto atuodsw = data.currentItem(); m_scanparam->autodescrew = (bool)atuodsw; return success(); } return CapSupGetAllReset(msg, data, m_scanparam->autodescrew, true); }; m_query[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_SwitchFrontBack), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if ((!m_scanparam->is_duplex) && mech == TRUE) return badValue(); m_scanparam->is_switchfrontback = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_switchfrontback, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->is_switchfrontback, (Bool)false, m_scanparam->is_switchfrontback ? 1 : 0, 0); }; m_query[CapType::IAutomaticRotate] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutomaticRotate), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->is_autotext = (bool)mech; if (mech) m_scanparam->imageRotateDegree = 0.0f; return success(); } return CapSupGetAllReset(msg, data, m_scanparam->is_autotext, false); }; m_query[CapType::IAutomaticCropUsesFrame] = msgSupportGetAll; m_caps[CapType::IAutomaticCropUsesFrame] = [this](Msg msg, Capability& data)->Result { return CapSupGetAll(msg, data, m_scanparam->is_autocrop, false); }; m_query[CapType::AutoScan] = msgSupportGetAllSetReset; m_caps[CapType::AutoScan] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::AutoScan), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto autoscan = data.currentItem(); m_autoscan = autoscan; return success(); } //return CapSupGetAllReset(msg, data, { FALSE,TRUE }, m_autoscan, Bool(true), m_autoscan ? 1 : 0, 0); return CapSupGetAllReset(msg, data, m_autoscan, TRUE); }; m_query[CapType(CapTypeEx::TwEx_IHighImageQuality)] = msgSupportGetAllSetReset; m_caps[CapType(CapTypeEx::TwEx_IHighImageQuality)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IHighImageQuality), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto tmp = data.currentItem(); m_scanparam->is_high_imagequality = tmp; return success(); } //return CapSupGetAllReset(msg, data, { FALSE,TRUE }, m_autoscan, Bool(true), m_autoscan ? 1 : 0, 0); return CapSupGetAllResetEx(msg, data, m_scanparam->is_high_imagequality, false); }; m_query[CapType::IAutoSize] = msgSupportGetAllSetReset; m_caps[CapType::IAutoSize] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutoSize), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto autosize = data.currentItem(); 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(msg, data, { AutoSize::None, AutoSize::Auto }, m_autosize, AutoSize::None, (m_autosize == (UInt16)AutoSize::Auto) ? 1 : 0, 0); }; m_query[CapType::IAutomaticBorderDetection] = msgSupportGetAllSetReset; m_caps[CapType::IAutomaticBorderDetection] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutomaticBorderDetection), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto autodetectborder = data.currentItem(); 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(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(); // m_scanparam->en_fold = (BYTE)autocrop; // if ((UInt16)autocrop != 0){ // m_scanparam->is_duplex = 1; // m_scanparam->autodescrew = 1;//合并可用时 默认自动纠偏 // m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = 0; // } // return success(); // } // return CapSupGetAllResetEx(msg, data, m_scanparam->en_fold, 0); //}; m_query[CapType(CapTypeEx::TwEx_EnFold)] = msgSupportGetAllSetReset; m_caps[CapType(CapTypeEx::TwEx_EnFold)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_EnFold), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto autocrop = data.currentItem(); m_scanparam->en_fold = (Int32)autocrop; if ((UInt16)autocrop != 0) { m_scanparam->is_duplex = 1; m_scanparam->autodescrew = 1;//合并可用时 默认自动纠偏 m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = 0; } return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->en_fold, 0); //return CapSupGetAllResetEx(msg, data, { 0,1 }, m_scanparam->en_fold, 0, m_scanparam->en_fold ? 1 : 0, 0); }; m_query[CapType::IAutoDiscardBlankPages] = msgSupportGetAllSetReset; m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IAutoDiscardBlankPages), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if ((mech == DiscardBlankPages::Auto) || (mech == DiscardBlankPages::Disabled)||((int)mech == 65535)) { if ((int)mech == 65535 || mech == DiscardBlankPages::Auto) { m_scanparam->is_autodiscradblank_normal = 1; m_scanparam->is_duplex = 1; m_scanparam->en_fold = 0; m_scanparam->is_autodiscradblank_vince = 0; } else { m_scanparam->is_autodiscradblank_normal = 0; } return success(); } return badValue(); } DiscardBlankPages autodiscradblank; if (Msg::GetDefault == msg || (Msg::Reset == msg)) { m_scanparam->is_autodiscradblank_normal = false; } m_scanparam->is_autodiscradblank_normal ? (autodiscradblank = DiscardBlankPages::Auto) : (autodiscradblank = DiscardBlankPages::Disabled); return CapSupGetAllReset(msg, data, autodiscradblank, DiscardBlankPages::Disabled); }; /*costom caps*/ //跳过空白页发票 m_query[(CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IAutoDiscardBlankVince), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->is_autodiscradblank_vince = mech; if (mech) { m_scanparam->is_duplex = 1; m_scanparam->en_fold = 0; m_scanparam->is_autodiscradblank_normal = 0; } return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_autodiscradblank_vince, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->is_autodiscradblank_vince, Bool(false), m_scanparam->is_autodiscradblank_vince ? 1 : 0, 0); }; m_query[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IBackRotate180)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IBackRotate180), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech) { if (!m_scanparam->is_duplex) { return badValue(); } } m_scanparam->is_backrotate180 = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_backrotate180, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->is_backrotate180, Bool(false), m_scanparam->is_backrotate180 ? 1 : 0, 0); }; //填黑框 m_query[(CapType)(CapTypeEx::TwEx_IFillBackground)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IFillBackground)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFillBackground), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->fillbackground = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->fillbackground, true); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->fillbackground, Bool(true), m_scanparam->fillbackground ? 1 : 0, 1); }; //裁剪纠偏轮廓缩进像素 m_query[(CapType)(CapTypeEx::TwEx_CroporDesaskewIndent)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_CroporDesaskewIndent)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CroporDesaskewIndent), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if ((mech > 30 || mech < 5) && ((bool)m_scanparam->is_autocrop == true)) return badValue(); m_scanparam->indent = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->indent, 5); }; //自动裁剪降噪像素 m_query[(CapType)(CapTypeEx::TwEx_CropNoise)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_CropNoise)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CropNoise), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if ((mech > 20 || mech < 1) && ((bool)m_scanparam->is_autocrop == true)) return badValue(); m_scanparam->noise = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->noise, 8); }; //自动裁切和纠偏的二值化阀值 m_query[(CapType)(CapTypeEx::TwEx_CroporDesaskewThreshold)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_CroporDesaskewThreshold)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CroporDesaskewThreshold), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech > 50 || mech < 30) return badValue(); m_scanparam->AutoCrop_threshold = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->AutoCrop_threshold, 40); }; //黑框填充方式 m_query[(CapType)(CapTypeEx::TwEx_FillBackgroundMode)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_FillBackgroundMode)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_FillBackgroundMode), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->is_convex = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_convex, Bool(true)); }; //填穿孔 m_query[(CapType)(CapTypeEx::TwEx_IFillHole)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IFillHole)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFillHole), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->fillhole.is_fillhole = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->fillhole.is_fillhole, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->fillhole.is_fillhole, Bool(false), m_scanparam->fillhole.is_fillhole ? 1 : 0, 0); }; m_query[(CapType)(CapTypeEx::TwEx_IFillHoleRatio)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IFillHoleRatio)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFillHoleRatio), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech > 0 && mech < 50) { m_scanparam->fillhole.fillholeratio = (int)mech; m_scanparam->fillholeratio_up = m_scanparam->fillholeratio_down = m_scanparam->fillholeratio_left = m_scanparam->fillholeratio_right = int(mech); return success(); } return badValue(); } return CapSupGetAllResetEx(msg, data, m_scanparam->fillhole.fillholeratio, 10); }; //噪点优化 m_query[(CapType)(CapTypeEx::TwEx_IDetachNoise)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IDetachNoise)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IDetachNoise), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech) { if (m_scanparam->pixtype != 0) return badValue(); } m_scanparam->detachnoise.is_detachnoise = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->detachnoise.is_detachnoise, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->detachnoise.is_detachnoise, FALSE, m_scanparam->detachnoise.is_detachnoise ? 1 : 0, 0); }; m_query[(CapType)(CapTypeEx::TwEx_IDetachNoiseValue)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IDetachNoiseValue)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IDetachNoiseValue), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech > 9 && mech < 51) { m_scanparam->detachnoise.detachnoise = (int)mech; return success(); } return badValue(); } return CapSupGetAllResetEx(msg, data, m_scanparam->detachnoise.detachnoise, 10); }; //背景移除 m_query[(CapType)(CapTypeEx::TwEx_IFadeBack)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IFadeBack)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFadeBack), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech) { if (m_scanparam->pixtype != 2) return badValue(); } m_scanparam->fadeback = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->fadeback, false); }; m_query[(CapType)(CapTypeEx::TwEx_IFadeBackValue)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IFadeBackValue)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IFadeBackValue), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech > 0 && mech < 129) { m_scanparam->fadeback_range = (int)mech; return success(); } return badValue(); } return CapSupGetAllResetEx(msg, data, m_scanparam->fadeback_range, 40); }; //多流除红 m_query[(CapType)(CapTypeEx::TwEx_IMultiOutputRed)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IMultiOutputRed)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IMultiOutputRed), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->pixtype == (BYTE)PixelType::Rgb &&(!m_scanparam->en_multi_output)) m_scanparam->multi_output_red = mech; else return badValue(); //m_scanparam->multi_output_red = 0;//非彩色 不能使用多流除红 return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->multi_output_red, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->multi_output_red, FALSE, m_scanparam->multi_output_red ? 1 : 0, 0); }; //多流输出使能 m_query[(CapType)(CapTypeEx::TwEx_IEnMultiOutPut)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IEnMultiOutPut)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IEnMultiOutPut), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->pixtype == (BYTE)PixelType::Rgb && (!m_scanparam->multi_output_red)) m_scanparam->en_multi_output = mech; else return badValue(); return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->en_multi_output, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->en_multi_output, FALSE, m_scanparam->en_multi_output ? 1 : 0, 0); }; //多流输出类型 m_query[(CapType)(CapTypeEx::TwEx_IEnMultiOutPutType)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IEnMultiOutPutType)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IEnMultiOutPutType), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->pixtype == (BYTE)PixelType::Rgb && (!m_scanparam->multi_output_red) && m_scanparam->en_multi_output) m_scanparam->multioutput = mech; else return badValue(); return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->multioutput, 0); }; //答题卡除红 m_query[(CapType)(CapTypeEx::TwEx_HsvCorrect)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_HsvCorrect)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_HsvCorrect), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech){ if (m_scanparam->pixtype != (int)PixelType::Rgb) return badValue(); } m_scanparam->hsvcorrect = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->hsvcorrect, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->hsvcorrect, FALSE, m_scanparam->hsvcorrect ? 1 : 0, 0); }; m_query[CapType::IFilter] = msgSupportGetAllSetReset; m_caps[CapType::IFilter] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IFilter), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech == Filter::None || mech == Filter::Red || mech == Filter::Green || mech == Filter::Blue) { if (((Filter)mech != Filter::None) && (m_scanparam->pixtype == (int)PixelType::Rgb)) return badValue(); m_scanparam->filter = (BYTE)mech; if (mech != Filter::None) { m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None; } return success(); } return badValue(); } return CapSupGetAllReset(msg, data, { Filter::Red,Filter::Green,Filter::Blue,Filter::None }, m_scanparam->filter, Filter::None, m_scanparam->filter, 3); }; //颜色增强 m_query[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IEnhanceColor), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->pixtype == (int)PixelType::Rgb) { m_scanparam->enhance_color = (BYTE)Enchace_Color::Enhance_None; m_scanparam->filter = (BYTE)Filter::None; return badValue(); } else { if (mech == Enchace_Color::Enhance_None || mech == Enchace_Color::Enhance_Red || mech == Enchace_Color::Enhance_Green || mech == Enchace_Color::Enhance_Blue) { m_scanparam->enhance_color = (BYTE)mech; if (mech != (BYTE)Enchace_Color::Enhance_None) m_scanparam->filter = (BYTE)Filter::None; return success(); } } } return CapSupGetAllResetEx(msg, data, m_scanparam->enhance_color, (Enchace_Color)0); //return CapSupGetAllResetEx(msg, data, { Enchace_Color::Enhance_None,Enchace_Color::Enhance_Red,Enchace_Color::Enhance_Green,Enchace_Color::Enhance_Blue }, m_scanparam->enhance_color, Enchace_Color::Enhance_None, m_scanparam->enhance_color, 0); }; m_query[(CapType)(CapTypeEx::TwEx_Sharpen)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_Sharpen)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_Sharpen), msg == Msg::Set ? to_string((int)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->pixtype == (int)PixelType::BlackWhite) return badValue(); m_scanparam->sharpen = (BYTE)mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->sharpen, SharpenBlur::Sharpen_None); //return CapSupGetAllResetEx(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); }; /*亮度 对比度 gamma range类型 Range 类型*/ m_query[CapType::IBrightness] = msgSupportGetAllSetReset; m_caps[CapType::IBrightness] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IBrightness), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); switch (msg) { case Msg::Get: data = Capability::createRange(Fix32(-1000.0f), Fix32(1000.0f), Fix32(333.3f), Fix32(m_scanparam->brightness), Fix32(0.0)); return success(); case Msg::GetCurrent: data = Capability::createOneValue(Fix32(m_scanparam->brightness)); return success(); case Msg::GetDefault: case Msg::Reset: m_scanparam->brightness = 0.0f; data = Capability::createOneValue(Fix32(0.0f)); return success(); case Msg::Set: { auto mech = data.currentItem(); if (mech > 1000.0f || mech < -1000.0f) return badValue(); m_scanparam->brightness = (float)mech; return success(); } default: return capBadOperation(); } }; m_query[CapType::IContrast] = msgSupportGetAllSetReset; m_caps[CapType::IContrast] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IContrast), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); switch (msg) { case Msg::Get: data = Capability::createRange(Fix32(-1000.0f), Fix32(1000.0f), Fix32(333.3f), Fix32(m_scanparam->contrast), Fix32(0.0)); return success(); case Msg::GetCurrent: data = Capability::createOneValue(Fix32(m_scanparam->contrast)); return success(); case Msg::GetDefault: case Msg::Reset: m_scanparam->contrast = 0.0f; data = Capability::createOneValue(Fix32(0.0f)); return success(); case Msg::Set: { auto mech = data.currentItem(); if (mech > 1000.0f || mech < -1000.0f) return badValue(); m_scanparam->contrast = (float)mech; return success(); } default: return capBadOperation(); } }; m_query[CapType::IGamma] = msgSupportGetAllSetReset; m_caps[CapType::IGamma] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::IGamma), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); switch (msg) { case Msg::Get: data = Capability::createRange(Fix32(0.0f), Fix32(5.0f), Fix32(1.0f), Fix32(m_scanparam->gamma), Fix32(1.0)); return success(); case Msg::GetCurrent: data = Capability::createOneValue(Fix32(m_scanparam->gamma)); return success(); case Msg::GetDefault: case Msg::Reset: m_scanparam->gamma = 1.0f; data = Capability::createOneValue(Fix32(0.0f)); return success(); case Msg::Set: { auto mech = data.currentItem(); if (mech > 5.0f || mech < 0.0f) return badValue(); m_scanparam->gamma = (float)mech; return success(); } default: return capBadOperation(); } }; /*以下为硬件协议*/ m_query[(CapType)(CapTypeEx::TwEx_ScrewDetectEnable)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_ScrewDetectEnable)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_ScrewDetectEnable), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->hardwarecaps.en_skrewdetect = mech; return success(); } Bool en = m_scanparam->hardwarecaps.en_skrewdetect == 0 ? Bool(false) : Bool(true); return CapSupGetAllResetEx(msg, data,(Bool)m_scanparam->hardwarecaps.en_skrewdetect , Bool(true)); //return CapSupGetAllResetEx(msg, data, { FALSE ,TRUE }, m_scanparam->hardwarecaps.en_skrewdetect, TRUE, m_scanparam->hardwarecaps.en_skrewdetect ? 1 : 0, 1); }; m_query[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_ScrewLevel)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_ScrewLevel), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech >= 1 && mech <= 5) { m_scanparam->hardwarecaps.skrewdetectlevel = mech; return success(); } return badValue(); } return CapSupGetAllResetEx(msg, data, m_scanparam->hardwarecaps.skrewdetectlevel, (UInt32)3); //return oneValGetSet(msg,data,m_scanparam->hardwarecaps.skrewdetectlevel,3); }; //装订检测 m_query[(CapType)(CapTypeEx::TwEx_StableDetectEnable)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_StableDetectEnable)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_StableDetectEnable), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->hardwarecaps.en_stapledetect = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->hardwarecaps.en_stapledetect, false); //return CapSupGetAllResetEx(msg, data, { FALSE,TRUE }, m_scanparam->hardwarecaps.en_stapledetect, FALSE, m_scanparam->hardwarecaps.en_stapledetect==0 ? 0 : 1, 0); }; //折角检测 m_query[(CapType)(CapTypeEx::TwEx_DogEarDelection)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_DogEarDelection)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_DogEarDelection), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->is_dogeardetection = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_dogeardetection, FALSE); }; //折角检测理论顶点到实际轮廓的最小距离 m_query[(CapType)(CapTypeEx::TwEx_DogEarDistance)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_DogEarDistance)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_DogEarDistance), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech >= 10 && mech <= 300) m_scanparam->dogeardistance = mech; else return badValue(); return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->dogeardistance, 70); }; //双张检测 与官方标准定义有所差异 此协议修改为bool型 爱云校使用bool类型,其余使用标准twain协议 m_query[CapType::DoubleFeedDetection] = msgSupportGetAllSetReset; m_caps[CapType::DoubleFeedDetection] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapType::DoubleFeedDetection), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); std::vector names; Twain_config().GetOrSetDoubleNames(names,true); FileTools::writelog(log_INFO, " DoubleFeedDetection "+ FileTools::GetProcessName()); if (std::find(names.begin(), names.end(), FileTools::to_web_utf(FileTools::String2Wstring(FileTools::GetProcessName()))) == names.end()) { FileTools::writelog(log_INFO, " DoubleFeedDetection 11111 "); switch (msg) { case Msg::Get: data = Capability::createEnumeration(CapType::DoubleFeedDetection, { 0 ,1 }, m_scanparam->hardwarecaps.en_doublefeed ? 0 : 1, 0); return { ReturnCode::Success, ConditionCode::Success }; case Msg::GetCurrent: data = Capability::createOneValue(CapType::DoubleFeedDetection, (UInt16)m_scanparam->hardwarecaps.en_doublefeed ? 0 : 1); return { ReturnCode::Success, ConditionCode::Success }; case Msg::Reset: case Msg::GetDefault: m_scanparam->hardwarecaps.en_doublefeed = 1; data = Capability::createOneValue(CapType::DoubleFeedDetection, 0); return { ReturnCode::Success, ConditionCode::Success }; case Msg::Set: { auto mech = data.currentItem(); m_scanparam->hardwarecaps.en_doublefeed = mech ? 0 : 1; return success(); } default: return { ReturnCode::Failure, ConditionCode::CapBadOperation }; } } else{ FileTools::writelog(log_INFO, " DoubleFeedDetection 22222 "); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->hardwarecaps.en_doublefeed = mech ? 1 : 0; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->hardwarecaps.en_doublefeed, TRUE); } }; #ifdef G200 //低功耗模式 m_query[(CapType)(CapTypeEx::TwEx_LowPowerMode)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_LowPowerMode)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_LowPowerMode), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->hardwarecaps.lowpowermode = (LowPowerMode)mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->hardwarecaps.lowpowermode, LowPowerMode::Min_30); //return CapSupGetAllResetEx(msg, data, // { LowPowerMode::Min_None,LowPowerMode::Min_5,LowPowerMode::Min_10,LowPowerMode::Min_20, LowPowerMode::Min_30, LowPowerMode::Min_60, LowPowerMode::Min_120, LowPowerMode::Min_240 }, // m_scanparam->hardwarecaps.lowpowermode, LowPowerMode::Min_30, (BYTE)m_scanparam->hardwarecaps.lowpowermode, 4); }; #endif // LANXUM #if defined G200 || defined G300 #ifndef ANDROIDSERIAL //待纸扫描 m_query[(CapType)(CapTypeEx::TwEx_IToBeScan)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IToBeScan)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IToBeScan), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->hardwarecaps.is_autopaper = mech; m_scanparam->autopaper_timeout = 15; if (mech) m_scanparam->scannum = -1; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->hardwarecaps.is_autopaper, FALSE); }; m_query[(CapType)(CapTypeEx::TwEx_IToBeScanTimeOut)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IToBeScanTimeOut)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IToBeScanTimeOut), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (mech > 60 || mech < 15) return badValue(); m_scanparam->autopaper_timeout = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->autopaper_timeout, 15); }; #endif #endif m_query[(CapType)(CapTypeEx::TwEx_CropModel)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_CropModel)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_CropModel), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->fillbackground || m_scanparam->autodescrew || m_scanparam->is_autocrop || m_scanparam->en_fold) { return badValue(); } m_scanparam->normalCrop = (bool)mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->normalCrop, false); }; //图像拆分 m_query[(CapType)(CapTypeEx::TwEx_ImageSplit)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_ImageSplit)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_ImageSplit), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); m_scanparam->is_split = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_split, false); }; //色偏校正 m_query[(CapType)(CapTypeEx::TwEx_ColorCast)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_ColorCast)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_ColorCast), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { if (m_scanparam->pixtype != 2) return badValue(); auto mech = data.currentItem(); m_scanparam->is_colorcast = mech; return success(); } return CapSupGetAllResetEx(msg, data, m_scanparam->is_colorcast, false); }; m_query[(CapType)(CapTypeEx::TwEx_IHsvFilter)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_IHsvFilter)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_IHsvFilter), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); if (Msg::Set == msg) { auto mech = data.currentItem(); if (m_scanparam->pixtype != 2)//color return badValue(); m_scanparam->hsvFilter = mech?1:0; return success(); } bool hsv_v=(bool)(m_scanparam->hsvFilter); return CapSupGetAllResetEx(msg, data, hsv_v, false); }; #ifdef UV m_query[(CapType)(CapTypeEx::TwEx_UVModel)] = msgSupportGetAllSetReset; m_caps[(CapType)(CapTypeEx::TwEx_UVModel)] = [this](Msg msg, Capability& data)->Result { CapabilityPrintf(msg, enum2str(CapTypeEx::TwEx_UVModel), msg == Msg::Set ? to_string((float)data.currentItem()) : ""); switch (msg) { case Msg::Get:{ data = Capability::createOneValue((CapType)(CapTypeEx::TwEx_UVModel), Bool(m_scanparam->hardwarecaps.en_uv)); //data = Capability::createEnumeration((CapType)(CapTypeEx::TwEx_UVModel), { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_uv), 0); return success(); } case Msg::Reset: m_scanparam->hardwarecaps.en_uv = false; case Msg::GetCurrent: data = Capability::createOneValue((CapType)(CapTypeEx::TwEx_UVModel), m_scanparam->hardwarecaps.en_uv); return success(); case Msg::GetDefault: data = Capability::createOneValue((CapType)(CapTypeEx::TwEx_UVModel), Bool(false)); return success(); case Msg::Set: { auto mech = data.currentItem(); m_scanparam->hardwarecaps.en_uv = mech?1:0; return success(); } default: return capBadOperation(); } }; #endif return success(); } Result HuagaoDs::identityCloseDs(const Identity&) { // no need to explicitly release any resources if using RAII // TWPP will free the whole source on its own after this method if (guiIndicator->GetSafeHwnd()) guiIndicator->DestroyWindow(); if (guiTwain.get()) guiTwain.reset(); if (guiBridge.get()) guiBridge.reset(); scanner.reset(); bmpData.reset(); if (hMutex) { ReleaseMutex(hMutex); CloseHandle(hMutex); } //saveGscanCapSetting(); return success(); } Result HuagaoDs::pendingXfersGet(const Identity&, PendingXfers& data) { data.setCount(m_pendingXfers); return success(); } Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) { //!< end xfer if set count 0 if (bmpData->size() > 0) { bmpData.reset(new std::vector); } int ret = scanner->aquire_bmpdata(*bmpData.get()); if (ret != 0) { scanner->Set_ErrorCode(0); if (guiIndicator->GetSafeHwnd()) guiIndicator->ShowWindow(SW_HIDE); if (ret != -1) { int index = scanner->geterrorindex(); if (ret == 82 && ((typeid(*scanner.get()) == typeid(GScanO1003399)))) showmsg("提示", "在第" + to_string(index) + "页检测到折角,停止扫描!", ret); else if (ret == 75 && ((typeid(*scanner.get()) == typeid(GScanO1003399)))) showmsg("提示", "在第" + to_string(index) + "页检测到尺寸不符,停止扫描!", ret); else if (ret == 81 && ((typeid(*scanner.get()) == typeid(GScanO1003399)))) showmsg("提示", "设备处于休眠模式!请手动唤醒设备。", ret); else showmsg("提示", msgs[(UsbSupported)ret], ret); FileTools::writelog(log_ERROR, msgs[(UsbSupported)ret]); #ifndef G200 scanner->clear_hwerror(); #endif // G200 } else { if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince)) { int num = scanner->get_scannum() * (m_scanparam->is_duplex ? 2 : 1) * (m_scanparam->multi_output_red ? 2 : 1) / (m_scanparam->en_fold ? 2 : 1) * (m_scanparam->is_split ? 2 : 1) * (m_scanparam->en_multi_output ? (m_scanparam->multioutput < 0 ? 1 : (m_scanparam->multioutput == 0 ? 3 : 2)) : 1); if ((num - scanner->get_imgTransfered()) != 0) { showmsg("提示", msgs[LOSE_IMAGE]); FileTools::writelog(log_ERROR, msgs[LOSE_IMAGE]); } } } m_pendingXfers = 0; if (guiTwain.get()) { ((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true); //setState(DsState::Enabled); } else { //setState(DsState::Open); } } else { m_pendingXfers = 1; //setState( DsState::XferReady ); } data.setCount(m_pendingXfers); return success(); } Result HuagaoDs::pendingXfersReset(const Identity&, PendingXfers& data) { data.setCount(0); if (scanner.get()) { scanner->Stop_scan(); //scanner->reset(); scanner->ResetScanner(); } //guiIndicator.reset(); if (guiIndicator->GetSafeHwnd()) guiIndicator->DestroyWindow(); if (guiTwain.get()) { ((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true); } return success(); } Result HuagaoDs::setupMemXferGet(const Identity&, SetupMemXfer& data) { auto bpl = bytesPerLine(); auto max = bpl * static_cast(header()->biHeight); data.setMinSize(bpl); data.setPreferredSize(max); data.setMaxSize(max); return success(); } Result HuagaoDs::userInterfaceDisable(const Identity&, UserInterface& ui) { if (guiTwain.get()) guiTwain.reset(); #if TWPP_DETAIL_OS_WIN if (guiBridge.get()) guiBridge.reset(); #endif return success(); } Result HuagaoDs::userInterfaceEnable(const Identity&, UserInterface& ui) { m_pendingXfers = 1; m_memXferYOff = 0; if (!ui.showUi()) { // this is an exception when we want to set state explicitly, notifyXferReady can be called only in enabled state // with hidden UI, the usual workflow DsState::Enabled -> notifyXferReady() -> DsState::XferReady is a single step if (!scanner->IsConnected()) scanner->open(vid, pid); if (!scanner->IsConnected()) { MessageBox(NULL, L"USB连接异常,请连接USB后重新打开扫描软件", L"提示", MB_OK | MB_SYSTEMMODAL); return seqError(); } #ifndef G200 if (typeid(*scanner.get()) != typeid(GScanO1003399)) { while (!scanner->Get_Scanner_PaperOn()) { if (MessageBox(NULL, L"检测到无纸,请添加纸张", L"提示", MB_YESNO | MB_SYSTEMMODAL) == IDNO) return seqError(); } } #endif // !G200 this_thread::sleep_for(chrono::milliseconds(100)); //扫描前增加延迟 防止usb缓存中的消息未读取清空 误报扫描错误 auto ret = startScan(); //if (ret.status().condition() == Twpp::CC::NoMedia) // return ret; if (ret == success()) { m_pendingXfers = 1; } else { m_pendingXfers = 0; return seqError(); } return success(); } return showTwainUI(ui); } Result HuagaoDs::userInterfaceEnableUiOnly(const Identity&, UserInterface& ui) { // as a minimal source, we do not support GUI that just saves settings return showTwainUI(ui, true); } Result HuagaoDs::imageInfoGet(const Identity&, ImageInfo& data) { // our image does not change //if (m_pendingXfers == 0 || bmpData->size() == 0) if(bmpData->size() == 0) return success(); auto dib = header(); data.setBitsPerPixel(static_cast(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(dib->biWidth) / m_scanparam->resolution_dst, static_cast(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); } static int xtfer = 0; Result HuagaoDs::imageMemXferGet(const Identity& origin, ImageMemXfer& data) { if (!m_pendingXfers) { FileTools::writelog(log_INFO, "正在上传图片 ===> Twain imageNativeXferGet 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(); FileTools::writelog(log_INFO, "正在上传图片 ===> Twain imageNativeXferGet size error setup.maxsize = " + to_string(setup.maxSize()) +" setup.minsize "+ to_string(setup.minSize())); if (memSize > setup.maxSize() || memSize < setup.minSize()) { FileTools::writelog(log_INFO, "正在上传图片 ===> Twain imageNativeXferGet size error data.size = "+to_string(memSize) ); return badValue(); } auto maxRows = memSize / bpl; auto rows = std::min(maxRows, static_cast(dib->biHeight) - m_memXferYOff); if (rows == 0) { FileTools::writelog(log_INFO, "正在上传图片 ===> Twain imageNativeXferGet rows == 0"); return seqError(); // image already transfered in this session } cv::Mat mat; vector 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(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(); auto bmpsize = bmpData->size(); // 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(std::abs(dib->biHeight))) { m_pendingXfers = 0; m_memXferYOff = 0; //bmpData.reset(new std::vector); FileTools::writelog(log_INFO, "正在上传图片 ===> Twain imageNativeXferGet m_memXferYOff transfered num of " + to_string(++xtfer) + " images"); return { ReturnCode::XferDone, ConditionCode::Success }; } FileTools::writelog(log_INFO, "正在上传图片 ===> Twain imageNativeXferGet transfered num of " + to_string(++xtfer) + " images"); return success(); } 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().data()); //bmpData.reset(new std::vector); //FileTools::write_log("正在上传图片 ===> Twain transfered num of " + to_string(++xtfer) + " images"); FileTools::writelog(log_INFO, "正在上传图片 ===> Twain transfered num of " + to_string(++xtfer) + " images"); return { ReturnCode::XferDone, ConditionCode::Success }; } Twpp::Result HuagaoDs::pendingXfersStopFeeder(const Identity& origin, PendingXfers& data) { if (!scanner.get()) return seqError(); if (scanner->IsConnected()) { scanner->Stop_scan(); } data.setCount(scanner->Get_IsImageQueueEmpty() ? 0 : 1); return success(); } Twpp::Result HuagaoDs::setupFileXferGet(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) { data.setFilePath(m_fileXfer.filePath()); data.setFormat(m_fileXfer.format()); return success(); } Twpp::Result HuagaoDs::setupFileXferGetDefault(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) { Str255 str("HGTwain.bmp"); data.setFilePath(str); data.setFormat(ImageFileFormat::Bmp); return success(); } Twpp::Result HuagaoDs::setupFileXferSet(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) { m_fileXfer.setFilePath(data.filePath()); m_fileXfer.setFormat(data.format()); return success(); } Twpp::Result HuagaoDs::setupFileXferReset(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) { m_fileXfer.setFormat(Twpp::ImageFileFormat::Bmp); std::string templateName = "HG"; char* tempPath = mktemp((char*)templateName.c_str()); if (tempPath) { Str255 str; str.setData(tempPath, strlen(tempPath)); m_fileXfer.setFilePath(str); return success(); } return badProtocol(); } static int indeximg = 0; Twpp::Result HuagaoDs::imageFileXferGet(const Twpp::Identity& origin) { if (!m_pendingXfers) return seqError(); string filename = m_fileXfer.filePath().string(); switch (m_fileXfer.format()) { case ImageFileFormat::Bmp: { FILE* pfile = fopen(filename.c_str(), "wb"); if (pfile) { if (bmpData->size() > 0) { fwrite(bmpData->data(), 1, bmpData->size(), pfile); bmpData.reset(new std::vector); 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 compression_params; compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); compression_params.push_back(m_jpegQuality); std::vector imgdate; cv::imencode(".jpg", ims, imgdate, compression_params); std::ofstream out(filename,std::ios::binary | std::ios::out | std::ios::trunc); if (out.is_open()) out.write((const char*)imgdate.data(), imgdate.size()),out.close(); //cv::imwrite(filename, ims, compression_params); } bmpData.reset(new std::vector); 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(ui.parent().raw()); guiBridge->Create(IDD_BACK, CWnd::FromHandle(appWindow)); HWND bridgeWindow = guiBridge->GetSafeHwnd(); long bridgeFlags = GetWindowLong(bridgeWindow, GWL_STYLE); SetWindowLong(bridgeWindow, GWL_STYLE, bridgeFlags | WS_CHILD); SetParent(bridgeWindow, appWindow); } //!< show ui to scan button push auto scanFunction = [this](const GScanCap& caps) { if (!scanner->IsConnected()) { scanner->open(vid, pid); if (!scanner->IsConnected()) return checkDeviceOnline(); } #ifndef G200 if (typeid(*scanner.get()) != typeid(GScanO1003399)) { while (!scanner->Get_Scanner_PaperOn()) { if (MessageBox(NULL, L"检测到无纸,请添加纸张", L"提示", MB_YESNO | MB_SYSTEMMODAL) == IDNO) { m_pendingXfers = 0; return seqError(); } } } #endif // !G200 m_pendingXfers = 1; m_scanparam.reset(new GScanCap(caps)); saveGscanCapSetting(); if (!scanner->IsConnected()) { MessageBox(NULL, L"USB连接异常,请连接USB后重新打开扫描软件", L"提示", MB_OK | MB_SYSTEMMODAL); return seqError(); } if (startScan() == success()) { notifyXferReady(); } else { m_pendingXfers = 0; } }; //!< ui only to confirm button push auto confirmFunction = [this](const GScanCap& caps) { m_scanparam.reset(new GScanCap(caps)); saveGscanCapSetting(); notifyCloseOk(); }; //!< cancel button push auto cancelFunction = [this]() { //if (m_modal) //{ // ::EnableWindow(parent, true); //} notifyCloseCancel(); }; auto feedmodeFunction = [this](int mode, bool isget)->int { #ifdef G200 auto usb = scanner->GetUsb(); if (isget) { if (usb.get() && usb->is_connected()) { int val = 0; usb->control_msg(0xc0, USB_REQ_GET_DEV_REGS, SR_GET_FEEDMODE, 0, 4, &val); return val; } } else { return usb->control_msg(0x40, USB_REQ_SET_DEV_REGS, SR_SET_FEEDMODE, 0, 4, &mode); } return 0; #else return 0; #endif // G200 }; CWnd* parent = guiBridge.get(); TwGlue glue = { scanFunction, cancelFunction,feedmodeFunction }; TwGlue glueUiOnly = { confirmFunction, cancelFunction,feedmodeFunction }; std::string serialnum = scanner->GetSerialNum(); std::string hardwareversion = scanner->GetFWVersion(); std::string macadder = scanner->GetMacAdder(); uint32_t mbversion = scanner->GetMotorFPGA(); guiTwain.reset(new CTwainUI(bUiOnly ? glueUiOnly : glue, *m_scanparam, bUiOnly ? "确定" : "扫描", hardwareversion, serialnum,macadder,mbversion)); guiTwain->Create(IDD_TWAINUI, parent); CRect newRect; ::GetWindowRect(static_cast(ui.parent().raw()), &newRect); if (newRect.top <= 0 || newRect.left <= 0) newRect.top = newRect.left = 20; SetWindowPos(guiTwain->m_hWnd, HWND_TOP, newRect.left + 20, newRect.top + 100, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOACTIVATE); //SetWindowPos(guiTwain->m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE); guiTwain->ShowWindow(SW_SHOWNORMAL); return success(); } void HuagaoDs::DeviceEvent_callback(int eventID, void* usrdata) { HuagaoDs* This = (HuagaoDs*)usrdata; This->onDeviceEvent(eventID); } void HuagaoDs::CapabilityPrintf(Twpp::Msg msg, std::string capability, std::string value) { if (!is_printfcapability) return; switch (msg) { case Msg::Reset: FileTools::writelog(log_INFO, (std::string)enum2str(Msg::Reset) + "\t" + capability); break; case Msg::Get: FileTools::writelog(log_INFO, (std::string)enum2str(Msg::Get) + "\t" + capability); break; case Msg::GetCurrent: FileTools::writelog(log_INFO, (std::string)enum2str(Msg::GetCurrent) + "\t" + capability); break; case Msg::GetDefault: FileTools::writelog(log_INFO, (std::string)enum2str(Msg::GetDefault) + "\t" + capability); break; case Msg::Set: FileTools::writelog(log_INFO, (std::string)enum2str(Msg::Set) + "\t" + capability+"\t value = "+value); break; default: break; } } void HuagaoDs::onDeviceEvent(int eventID) { //if (mapDeviceEvent.count(eventID)) //{ // DeviceEvent::Type dev_type = mapDeviceEvent[eventID]; // auto evt = DeviceEvent::simple((DeviceEvent::Type)dev_type, "HuaGo Device Event"); // devEvent.push(evt); // notifyDeviceEvent(); //} } const BITMAPINFOHEADER* HuagaoDs::header() const noexcept { return reinterpret_cast(bmpData->data() + sizeof(BITMAPFILEHEADER)); } UInt32 HuagaoDs::bytesPerLine() const noexcept { auto dib = header(); return static_cast(dib->biWidth * dib->biBitCount + 31) / 32 * 4; } UInt32 HuagaoDs::bmpSize() const noexcept { return static_cast(bmpData->size()) - sizeof(BITMAPFILEHEADER); } const char* HuagaoDs::bmpBegin() const noexcept { return (const char*)bmpData->cbegin()._Ptr + sizeof(BITMAPFILEHEADER); } const char* HuagaoDs::bmpEnd() const noexcept { return (const char*)bmpData->cend()._Ptr; } void HuagaoDs::updataGscanCap() { GscanJsonConfig js; GScanCap cfs = js.ReadGscanCap(); cfs.resolution_native = 200.0f; cfs.threshold = 128; if (cfs.is_autocrop) { m_autoboarderdetcet = true; m_autosize = (UInt16)AutoSize::Auto; } m_scanparam.reset(new GScanCap(cfs)); } Twpp::Result HuagaoDs::startScan() { xtfer = 0; //if (!scanner->IsConnected()) //{ // scanner->open(vid, pid); // if (!scanner->IsConnected()) // return checkDeviceOnline(); //} bmpData.reset(new std::vector()); scanner->ResetScanner(); scanner->reset(); FileTools::writelog(log_INFO, "start scan"); #ifdef G200 scanner->clear_hwerror(); #else #ifndef ANDROIDSERIAL if (scanner->notifyscan() < 1) return seqError(); #endif // !ANDROIDSERIAL #endif // #ifdef G200 if (scanner->Get_Roller_num() > 450000) #elif defined G300 if (scanner->Get_Roller_num() > 150000) #else if (scanner->Get_Roller_num() > 200000) #endif // G200 { Twain_config config; if (config.getrollermsgdate() < chrono::duration_cast>>(chrono::system_clock::now().time_since_epoch()).count()){ hgmsg(_T("纸轮搓纸次数已超过设计使用范围,扫描过程中搓纸失败、歪斜、搓多张等异常频次可能会明显增多,请注意及时清洁、并联系设备供应商购买替换纸轮!")); config.setrollermsgdata(chrono::duration_cast>>(chrono::system_clock::now().time_since_epoch()).count()); } } //m_scanparam->brightness =300; // 楚雄一中 500 - 142 //m_scanparam->contrast = 0; // 小闲专用 scanner->config_params(*m_scanparam); std::string info = "papertype= " + to_string(m_scanparam->papertype) + "\nAutoCrop_threshold= " + to_string(m_scanparam->AutoCrop_threshold) + "\nautodescrew = " + to_string(m_scanparam->autodescrew) + "\nautomaticcolor= " + to_string(m_scanparam->automaticcolor) + "\nbrightness = " + to_string(m_scanparam->brightness) + "\ncontrast = " + to_string(m_scanparam->contrast) + "\nis_detachnoise = " + to_string(m_scanparam->detachnoise.is_detachnoise) + "\ndetachnoise = " + to_string(m_scanparam->detachnoise.detachnoise) + "\nen_fold = " + to_string(m_scanparam->en_fold) + "\nen_sizecheck = " + to_string(m_scanparam->en_sizecheck) + "\nenhance_color = " + to_string(m_scanparam->enhance_color) + "\nfillbackground = " + to_string(m_scanparam->fillbackground) + "\nfilter = " + to_string(m_scanparam->filter) + "\nis_fillhole = " + to_string(m_scanparam->fillhole.is_fillhole) + "\ngamma = " + to_string(m_scanparam->gamma) + "\ncapturepixtype = " + to_string(m_scanparam->hardwarecaps.capturepixtype) + "\nen_doublefeed = " + to_string(m_scanparam->hardwarecaps.en_doublefeed) + "\nhsvcorrect = " + to_string(m_scanparam->hsvcorrect) + "\nimageRotateDegree = " + to_string(m_scanparam->imageRotateDegree) + "\nindent = " + to_string(m_scanparam->indent) + "\nis_autocontrast = " + to_string(m_scanparam->is_autocontrast) + "\nis_autocrop = " + to_string(m_scanparam->is_autocrop) + "\nis_autocontrast = " + to_string(m_scanparam->is_autocontrast) + "\nis_autodiscradblank_normal = " + to_string(m_scanparam->is_autodiscradblank_normal) + "\nis_autodiscradblank_vince = " + to_string(m_scanparam->is_autodiscradblank_vince) + "\nis_autotext = " + to_string(m_scanparam->is_autotext) + "\nis_convex = " + to_string(m_scanparam->is_convex) + "\nis_duplex = " + to_string(m_scanparam->is_duplex) + "\nis_switchfrontback = " + to_string(m_scanparam->is_switchfrontback) + "\nis_dogeardetection = " + to_string(m_scanparam->is_dogeardetection) + "\nmulti_output_red = " + to_string(m_scanparam->multi_output_red) + "\nen_multi_output = " + to_string(m_scanparam->en_multi_output) + "\nmultioutput = " + to_string(m_scanparam->multioutput) + "\nnoise = " + to_string(m_scanparam->noise) + "\npaperAlign = " + to_string(m_scanparam->paperAlign) + "\npixtype = " + to_string(m_scanparam->pixtype) + "\nresolution_dst = " + to_string(m_scanparam->resolution_dst) + "\nscannum = " + to_string(m_scanparam->scannum) + "\nsharpen = " + to_string(m_scanparam->sharpen); FileTools::writelog(log_TRACE,info); scanner->UpdateScanInfo(0, 0); scanner->Scanner_StartScan(m_scanparam->scannum); if (bmpData->size() > 0) { bmpData.reset(new std::vector); } if (guiTwain.get()) { ((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(false); } int retCode = scanner->aquire_bmpdata(*bmpData.get()); if (retCode == 0) { if (m_bIndicator) { //!< cancel button push auto stopFunc = [this]() { if (scanner.get()) scanner->Stop_scan(); //guiIndicator.reset();//取消扫描 关闭进度指示器 //if (guiTwain.get()) { // ((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true); //} onDeviceEvent(USER_STOP); }; guiIndicator = new CIndicatorDlg(stopFunc); scanner->regist_indicatortext_callback([this](int aquire, int updata) { if (guiIndicator->GetSafeHwnd()) guiIndicator->setindicatortext(aquire, updata); }, [this](CString str) { if (guiIndicator->GetSafeHwnd()) guiIndicator->setindicatortext(str); }); guiIndicator->Create(IDD_INDICATOR, guiTwain.get() ? guiTwain.get() : guiBridge.get());//guiTwain ? guiTwain.get() : guiBridge.get() guiIndicator->ShowWindow(SW_SHOWNORMAL); } } if (retCode != 0) { scanner->Set_ErrorCode(0); if (guiIndicator->GetSafeHwnd()) guiIndicator->DestroyWindow(); //if(guiIndicator.get()) // guiIndicator.reset(); if (retCode != -1) { CString str; str.Format(_T("%d"), retCode); m_pendingXfers = 0; m_memXferYOff = 0; m_haveError = true; //ShellExecute(guiTwain ? guiTwain->m_hWnd : NULL, TEXT("open"), GetHidedlgPath(), str, NULL, SW_HIDE); int index = scanner->geterrorindex(); if (retCode == 82 && ((typeid(*scanner.get()) == typeid(GScanO1003399)))) showmsg("提示", "在第" + to_string(index) + "页检测到折角,停止扫描!", retCode); else if (retCode == 75 && ((typeid(*scanner.get()) == typeid(GScanO1003399)))) showmsg("提示", "在第" + to_string(index) + "页检测到尺寸不符,停止扫描!", retCode); else if (retCode == 81 && ((typeid(*scanner.get()) == typeid(GScanO1003399)))) showmsg("提示", "设备处于休眠模式!请手动唤醒设备。", retCode); else showmsg("提示", msgs[(UsbSupported)retCode], retCode); FileTools::writelog(log_ERROR, msgs[(UsbSupported)retCode]); #ifndef G200 scanner->clear_hwerror(); #endif // } if (guiTwain.get()) { ((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true); } if (retCode == 2) return { ReturnCode::Failure, ConditionCode::NoMedia };//无纸 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 vc; //vc.push_back(*m_scanparam); std::string savepath = TCHAR2STRING(szIniFile); js.SaveGscancapJson(*m_scanparam, savepath); //js.WriteJsonArrayToFile(vc, savepath); }