1.修复检查有无纸协议异常;

2.修复BitDepth协议设置异常;
3.调整TWAIN UI刷新机制,由实际设置的协议值来更新UI,以避免实际设置的值与UI显示的值不一致;
4.调整配置参数保存逻辑,由OpenDS和CloseDS接口进行更新协议和保存协议;
This commit is contained in:
lovelyyoung 2020-06-20 11:01:35 +08:00
parent 9d99bc37d0
commit 5f8576b688
2 changed files with 1925 additions and 1758 deletions

View File

@ -20,10 +20,10 @@
#include "Device/GScanVirtual.h"
#include <list>
#include <map>
#include "Device/JsonConfig.h"
#include "opencv2/opencv.hpp"
#include <opencv2/opencv.hpp>
#include "GscanJsonConfig.h"
//#include "TiffG4Compression.h"
//#include "G4Tiff.h"
//custom define caps enum
enum class CapTypeEx : unsigned short {
Base = 0x8000,//custom caps enum value must bigger than CapTypeEx::Base value,otherwise might make conflict
@ -40,7 +40,9 @@ enum class CapTypeEx : unsigned short {
TwEx_Sharpen = 0x8022,
TwEx_DBAreaNum = 0x8027,
TwEx_DBDevnMax = 0x8028,
TwEx_StableDetectEnable = 0x8090
TwEx_StableDetectEnable = 0x8090,
TwEx_UVModel = 0x8093,
TwEx_SwitchFrontBack = 0x8094
};
using namespace Twpp;
@ -61,11 +63,32 @@ using namespace std::placeholders;
TWPP_ENTRY_MFC(HuagaoDs)
static constexpr const Identity srcIdent(
Version(3, 3, Language::English, Country::China, "v3.3.2.1"),
Version(3, 3, Language::English, Country::China, "v3.3.2.3"),
DataGroup::Image,
"HUAGOSCAN TWAIN",
"HUAGO",
#ifdef G200
#ifdef ISG100
"G100 Series",
#else // ISG100
"G200 Series",
#endif
#elif defined(G300) // G200
"G300 Series",
"HUAGOSCAN TWAIN"
#elif defined(G400) // G200
"G400 Series",
#endif
#ifdef G200
#ifdef ISG100
"HUAGOSCAN G100 TWAIN"
#else // ISG100
"HUAGOSCAN G200 TWAIN"
#endif
#elif defined(G300) // G200
"HUAGOSCAN G300 TWAIN"
#elif defined(G400) // G200
"HUAGOSCAN G400 TWAIN"
#endif
#if defined(_MSC_VER)
""
#elif defined(__GNUC__)
@ -85,7 +108,7 @@ static list<float> resList = { 100.0,150.0,200.0,240.0,300.0 };
static list<UInt16> paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A4,(UInt16)PaperSize::A5,(UInt16)PaperSize::A6,
(UInt16)PaperSize::IsoB4,(UInt16)PaperSize::IsoB5,(UInt16)PaperSize::IsoB6,
(UInt16)PaperSize::UsLetter,(UInt16)PaperSize::UsLegal,(UInt16)PaperSize::UsLedger,
(UInt16)PaperSize::MaxSize,(UInt16)PaperSize::None,(UInt16)PaperSize::UsStatement };
(UInt16)PaperSize::MaxSize,(UInt16)Twpp::PaperSize::None,(UInt16)PaperSize::UsStatement };
static list<float> imageRotateList = { 0.0,90.0,180.0,270.0 };
@ -116,15 +139,16 @@ static std::unique_ptr<CDialog, void(*)(CDialog*)> guiBridge(nullptr, DeleteWnd)
static std::unique_ptr<CDialogEx, void(*)(CDialog*)> guiIndicator(nullptr, DeleteWnd);
#ifndef HG_VIRTUAL
static std::unique_ptr<IGScan> scanner(new GScanO200());
static std::unique_ptr<IScanner> scanner(new GScanO200());
#else
static std::unique_ptr<IGScan> scanner(new GScanVirtual());
static std::unique_ptr<IScanner> scanner(new GScanVirtual());
#endif
HuagaoDs::HuagaoDs()
: m_scanparam(new GScanCap)
, hMutex(NULL)
{
/*string ss1= getOSInfo();
string ss2=getManufactureID();
@ -133,7 +157,6 @@ HuagaoDs::HuagaoDs()
DWORD dwNum;
CString aas[10];
GetDiskInfo(dwNum,aas);*/
initGScanCap();
}
HuagaoDs::~HuagaoDs()
@ -262,11 +285,6 @@ static constexpr Result checkDeviceOnline() noexcept {
return { ReturnCode::Failure,ConditionCode::CheckDeviceOnline };
}
//void HuagaoDs::updateScanParam()
//{
//
//}
Result HuagaoDs::capCommon(const Identity&, Msg msg, Capability& data) {
auto it = m_caps.find(data.type());
if (it != m_caps.end()) {
@ -326,6 +344,11 @@ Result HuagaoDs::eventProcess(const Identity&, Event& event) {
return { ReturnCode::NotDsEvent, ConditionCode::Success };
}
//Twpp::Result HuagaoDs::deviceEventGet(const Twpp::Identity & origin, Twpp::DeviceEvent & data)
//{
// data = DeviceEvent::simple(DeviceEvent::Type::PaperJam, Str255("HuaGo G200 Twain Device Error"));
// return success();
//}
//add------------------设置jpg图像dpi---------------------------
void HuagaoDs::SetResoluton(const char* path, int resolution)
{
@ -354,12 +377,13 @@ void HuagaoDs::SetResoluton(const char* path, int resolution)
Result HuagaoDs::identityOpenDs(const Identity&) {
//writelog("identityOpenDs");
updataGscanCap();
bmpData.resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header());
bmInfo.biHeight = 2000;
bmInfo.biWidth = 2000;
bmInfo.biBitCount = 24;
updataGscanCap();
bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 0);
m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 0);
scanner->open(0x064B, 0x7823);
if (!scanner->IsConnected()) {
MessageBox(NULL, _T("未找到扫描仪!请检查电源或者USB连接线是否接通!"), _T("提示"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
@ -368,7 +392,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
hMutex = CreateMutex(NULL, FALSE, _T("LookitApp"));
if (GetLastError() == ERROR_ALREADY_EXISTS) { //如果已经存在同名的Mutex会得到这个错误.
CloseHandle(hMutex);
MessageBox(NULL, _T("设备已被其他程序占用,请关闭占用程序之后再重试!"), _T(" "), MB_OK);
MessageBox(NULL, _T("设备已被其他程序占用,请关闭占用程序之后再重试!"), _T("提示"), MB_OK);
return seqError();
}
@ -412,6 +436,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return badValue();
}
m_capXferCount = item;
m_scanparam->scannum = m_capXferCount;
return success();
}
@ -421,16 +446,79 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_scanparam->scannum = m_capXferCount;
return { ReturnCode::CheckStatus, ConditionCode::BadValue };
}
return ret;
};
m_query[CapType::ICompression] = msgSupportGetAllSetReset;
m_caps[CapType::ICompression] = std::bind(enmGetSetConst<Compression>, _1, _2, Compression::None);
m_caps[CapType::ICompression] = [this](Msg msg, Capability& data)->Result
{
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::ICompression>(
{ Compression::None, Compression::Group4 }, m_compression == Compression::None ? 0 : 1, 0);
return success();
case Msg::Reset:
m_compression = Compression::None;
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::ICompression>(m_compression);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::ICompression>(Compression::None);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::ICompression>();
if (Compression::None == mech || mech == Compression::Group4) {
m_compression = mech;
return success();
}
else {
return badValue();
}
}
default:
return capBadOperation();
}
};
m_query[CapType::IBitDepth] = msgSupportGetAllSetReset;
m_caps[CapType::IBitDepth] = std::bind(enmGetSetConst<UInt16>, _1, _2, UInt16(header()->biBitCount));
m_caps[CapType::IBitDepth] = [this](Msg msg, Capability& data) -> Result {
switch (msg)
{
case Msg::Get:
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
return success();
case Msg::Reset:
m_iBitdepth = 24;
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
break;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IBitDepth>(24);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IBitDepth>();
if (mech == 1 || mech == 8 || mech == 24)
{
m_iBitdepth = (UINT16)mech;
m_scanparam->pixtype = m_iBitdepth == 1 ? (int)PixelType::BlackWhite : (m_iBitdepth == 8 ? (int)PixelType::Gray : (int)PixelType::Rgb);
return success();
}
return badValue();
}
default:
return capBadOperation();
}
};
m_query[CapType::IBitOrder] = msgSupportGetAllSetReset;
m_caps[CapType::IBitOrder] = std::bind(enmGetSetConst<BitOrder>, _1, _2, BitOrder::MsbFirst);
@ -467,9 +555,25 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<CapType::IPixelType>();
if (mech == PixelType::Rgb || mech == PixelType::Gray || mech == PixelType::BlackWhite)
{
m_scanparam->pixtype = (int)mech;
if (m_scanparam->pixtype == (int)PixelType::Rgb)
{
m_scanparam->filter = (byte)Filter::None;
m_scanparam->enhance_color = (byte)Enchace_Color::Enhance_None;
}
else
{
m_scanparam->multi_output_red = 0;//非彩色模式下多流输出不可用
if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
m_scanparam->sharpen = SharpenBlur::Sharpen_None;
}
m_iBitdepth = mech == PixelType::Rgb ? 24 : (mech == PixelType::Gray ? 8 : 1);
return success();
}
return badValue();
}
default:
return capBadOperation();
@ -596,9 +700,6 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_query[CapType::IYNativeResolution] = msgSupportGetAll;
m_caps[CapType::IYNativeResolution] = m_caps[CapType::IXNativeResolution];
m_query[CapType::FeederLoaded] = msgSupportGetAll;
m_caps[CapType::FeederLoaded] = std::bind(enmGet<Bool>, _1, _2, Bool(scanner->Get_Scanner_PaperOn()));
m_query[CapType::ISupportedSizes] = msgSupportGetAllSetReset;
m_caps[CapType::ISupportedSizes] = [this](Msg msg, Capability& data) {
switch (msg) {
@ -640,6 +741,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
}
if (contains) {
m_scanparam->papertype = (byte)res;
if (res == (byte)PaperSize::None)
m_scanparam->autodescrew = 1;//设置papertype为NONE 则默认自动裁切
return success();
}
return badValue();
@ -654,7 +757,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IOrientation>(
{ Orientation::Portrait, Orientation::Landscape,Orientation::AutoText }, m_scanparam->paperAlign, 0);
{ Orientation::Portrait, Orientation::Landscape }, m_scanparam->paperAlign, 0);
return success();
case Msg::Reset:
@ -669,7 +772,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<CapType::IOrientation>();
if (mech == Orientation::Landscape || mech == Orientation::Portrait || mech == Orientation::AutoText) {
if (mech == Orientation::Landscape || mech == Orientation::Portrait) {
m_scanparam->paperAlign = (PaperAlign)mech;
return success();
}
@ -689,7 +792,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
std::list<float>::iterator it = imageRotateList.begin();
int i = 0;
for (it, i; it != imageRotateList.end(); ++it, i++) {
if (*it == m_scanparam->imageRotateDegree) {
if ((m_scanparam->imageRotateDegree + 1) >= *it && (m_scanparam->imageRotateDegree - 1) <= *it) {
index = i;
break;
}
@ -715,13 +818,15 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
std::list<float>::iterator resIter = imageRotateList.begin();
bool contains = false;
for (resIter; resIter != imageRotateList.end(); resIter++) {
if (*resIter == res) {
if (((float)res + 1) >= *resIter && ((float)res - 1) <= *resIter) {
contains = true;
break;
}
}
if (contains) {
m_scanparam->imageRotateDegree = (float)res;
if (res != 0.0f)
m_scanparam->is_autotext = 0;
return success();
}
return badValue();
@ -732,12 +837,20 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
}
};
#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_query[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = msgSupportGetAll;
m_caps[(CapType)(CapTypeEx::TwEx_HardwareVersion)] = std::bind(oneValGetString, _1, _2, scanner->GetFWVersion());
m_query[CapType::FeederLoaded] = msgSupportGetAll;
m_caps[CapType::FeederLoaded] = std::bind(oneValGet<Bool>, _1, _2, Bool(scanner->Get_Scanner_PaperOn()));
m_query[CapType::Indicators] = msgSupportGetAllSetReset;
m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
@ -774,12 +887,27 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_query[CapType::PaperDetectable] = msgSupportGetAll;
m_caps[CapType::PaperDetectable] = std::bind(enmGet<Bool>, _1, _2, Bool(true));
m_query[CapType::FeederEnabled] = msgSupportGetAll;
m_query[CapType::FeederEnabled] = msgSupportGetAllSetReset;
m_caps[CapType::FeederEnabled] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createOneValue<CapType::FeederEnabled>(true);
return success();
case Msg::Reset:
m_bFeederEnabled = true;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::FeederEnabled>(m_bFeederEnabled);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::FeederEnabled>(true);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::FeederEnabled>();
m_bFeederEnabled = mech;
return success();
}
default:
return capBadOperation();
}
@ -809,6 +937,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<CapType::DuplexEnabled>();
m_scanparam->is_duplex = mech;
if (!mech)
m_scanparam->is_backrotate180 = 0;//单面背面旋转180°不可用
return success();
}
@ -859,12 +989,10 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return success();
}
case Msg::Reset:
m_capImageFileFormat = ImageFileFormat::Bmp;
// fallthrough
case Msg::GetCurrent:
m_capImageFileFormat = ImageFileFormat::Bmp;
data = Capability::createOneValue<CapType::IImageFileFormat>(m_capImageFileFormat);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IImageFileFormat>(ImageFileFormat::Bmp);
return success();
@ -877,10 +1005,9 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_capImageFileFormat = mech;
return success();
}
else {
else
return badValue();
}
}
default:
return capBadOperation();
}
@ -895,8 +1022,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
{ Bool(), Bool(true) }, Bool(m_scanparam->autodescrew == 0 ? false : true));
return success();
case Msg::Reset:
m_scanparam->autodescrew = true;
case Msg::GetCurrent:
m_scanparam->autodescrew = true;
data = Capability::createOneValue<CapType::IAutomaticDeskew>(m_scanparam->autodescrew);
return success();
@ -915,6 +1042,30 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
}
};
m_query[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = msgSupportGetAllSetReset;
m_caps[(CapType)(CapTypeEx::TwEx_SwitchFrontBack)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)((CapType)(CapTypeEx::TwEx_SwitchFrontBack)), { Bool(),Bool(true) }, Bool(m_scanparam->is_switchfrontback), 0);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->is_switchfrontback = false;
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_SwitchFrontBack)), m_scanparam->is_switchfrontback);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_SwitchFrontBack)), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->is_switchfrontback = mech;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutomaticRotate] = msgSupportGetAllSetReset;
m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
@ -922,19 +1073,18 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
data = Capability::createEnumeration<CapType::IAutomaticRotate>(
{ Bool(), Bool(true) }, Bool(m_scanparam->is_autotext));
case Msg::Reset:
m_scanparam->is_autotext = false;
// fallthrough
case Msg::GetCurrent:
m_scanparam->is_autotext = false;
data = Capability::createOneValue<CapType::IAutomaticRotate>(m_scanparam->is_autotext);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutomaticRotate>(false);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IAutomaticRotate>();
m_scanparam->is_autotext = (bool)mech;
if (mech)
m_scanparam->imageRotateDegree = 0.0f;
return success();
}
@ -951,9 +1101,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
{ Bool(), Bool(true) }, Bool(m_scanparam->is_autocrop));
return success();
case Msg::Reset:
m_scanparam->is_autocrop = false;
// fallthrough
case Msg::GetCurrent:
m_scanparam->is_autocrop = false;
data = Capability::createOneValue<CapType::IAutomaticCropUsesFrame>(m_scanparam->is_autocrop);
return success();
@ -964,6 +1113,34 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto autocrop = data.currentItem<CapType::IAutomaticCropUsesFrame>();
m_scanparam->is_autocrop = (bool)autocrop;
if (autocrop)
m_scanparam->papertype = (byte)PaperSize::None;
return success();
}
default:
return capBadOperation();
}
};
m_query[CapType::IAutoSize] = msgSupportGetAllSetReset;
m_caps[CapType::IAutoSize] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutoSize>(
{ AutoSize::None, AutoSize::Auto,AutoSize::Current }, (UInt16)m_autosize, 0);
return success();
// fallthrough
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutoSize>((AutoSize)m_autosize);
return success();
case Msg::Reset:
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutoSize>(AutoSize::None);
return success();
case Msg::Set: {
auto autosize = data.currentItem<CapType::IAutoSize>();
m_autosize = (byte)autosize;
return success();
}
default:
@ -978,9 +1155,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
case Msg::Reset:
m_scanparam->en_fold = 0;//默认不对折
// fallthrough
case Msg::GetCurrent:
m_scanparam->en_fold = 0;//默认不对折
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
@ -991,6 +1167,11 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto autocrop = data.currentItem<CapType::IImageMerge>();
m_scanparam->en_fold = (byte)autocrop;
if ((UInt16)autocrop != 0)
{
m_scanparam->is_duplex = 1;
m_scanparam->autodescrew = 1;//合并可用时 默认自动纠偏
}
return success();
}
default:
@ -1007,16 +1188,17 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
0);
return success();
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->is_autodiscradblank_normal = false;
data = Capability::createOneValue<CapType::IAutoDiscardBlankPages>(DiscardBlankPages::Disabled);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutoDiscardBlankPages>(m_scanparam->is_autodiscradblank_normal ? DiscardBlankPages::Auto : DiscardBlankPages::Disabled);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutoDiscardBlankPages>(DiscardBlankPages::Disabled);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IAutoDiscardBlankPages>();
m_scanparam->is_autodiscradblank_normal = mech == DiscardBlankPages::Auto;
m_scanparam->is_autodiscradblank_normal = (Int32)mech == (Int32)DiscardBlankPages::Auto;
return success();
}
default:
@ -1033,16 +1215,18 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
data = Capability::createEnumeration<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), { Bool(),Bool(true) }, Bool(m_scanparam->is_autodiscradblank_vince), 0);
return success();
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->is_autodiscradblank_vince = false;
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), Bool(false));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), m_scanparam->is_autodiscradblank_vince);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)((CapType)(CapTypeEx::TwEx_IAutoDiscardBlankVince)), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->is_autodiscradblank_vince = mech;
if (mech)
m_scanparam->is_autodiscradblank_normal = 0;
return success();
}
default:
@ -1057,16 +1241,18 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), { Bool(),Bool(true) }, Bool(m_scanparam->is_backrotate180), 0);
return success();
case Msg::Reset:
case Msg::GetDefault:
m_scanparam->is_backrotate180 = false;
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), Bool(false));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), m_scanparam->is_backrotate180);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IBackRotate180), Bool(false));
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
m_scanparam->is_backrotate180 = mech;
if (mech)
m_scanparam->is_duplex = 1;
return success();
}
default:
@ -1081,11 +1267,11 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Get:
data = Capability::createEnumeration<Bool>((CapType)(CapTypeEx::TwEx_IFillBackground), { Bool(),Bool(true) }, Bool(m_scanparam->fillbackground), 0);
return success();
case Msg::Reset:
m_scanparam->fillbackground = false;
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IFillBackground), m_scanparam->fillbackground);
return success();
case Msg::Reset:
m_scanparam->fillbackground = false;
case Msg::GetDefault:
data = Capability::createOneValue<Bool>((CapType)(CapTypeEx::TwEx_IFillBackground), Bool(false));
return success();
@ -1141,7 +1327,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<Int32>();
if (mech > 0 && mech < 50) {
m_scanparam->fillhole.fillholeratio = (float)mech;
m_scanparam->fillhole.fillholeratio = (int)mech;
return success();
}
return badValue();
@ -1168,7 +1354,12 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return success();
case Msg::Set: {
auto mech = data.currentItem<Bool>();
if (m_scanparam->pixtype == (byte)PixelType::Rgb)
m_scanparam->multi_output_red = mech;
else
{
m_scanparam->multi_output_red = 0;//非彩色 不能使用多流除红
}
return success();
}
default:
@ -1186,6 +1377,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return success();
case Msg::Reset:
m_scanparam->filter = (byte)Filter::None;
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IFilter>((Filter)m_scanparam->filter);
return success();
@ -1196,6 +1388,10 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
auto mech = data.currentItem<CapType::IFilter>();
if (mech == Filter::None || mech == Filter::Red || mech == Filter::Green || mech == Filter::Blue) {
m_scanparam->filter = (byte)mech;
if (mech != Filter::None)
{
m_scanparam->enhance_color = (byte)Enchace_Color::Enhance_None;
}
return success();
}
return badValue();
@ -1210,10 +1406,14 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[(CapType)(CapTypeEx::TwEx_IEnhanceColor)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Enchace_Color>((CapType)(CapTypeEx::TwEx_IEnhanceColor), { Enchace_Color::Enhance_None,Enchace_Color::Enhance_Red,Enchace_Color::Enhance_Green,Enchace_Color::Enhance_Blue }, m_scanparam->enhance_color, 0);
data = Capability::createEnumeration<Enchace_Color>((CapType)(CapTypeEx::TwEx_IEnhanceColor),
{ Enchace_Color::Enhance_None,Enchace_Color::Enhance_Red,Enchace_Color::Enhance_Green,Enchace_Color::Enhance_Blue },
m_scanparam->enhance_color,
0);
return success();
case Msg::Reset:
m_scanparam->enhance_color = Enchace_Color::Enhance_None;
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Int16>((CapType)(CapTypeEx::TwEx_IEnhanceColor), (Enchace_Color)(m_scanparam->enhance_color));
return success();
@ -1222,9 +1422,22 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return success();
case Msg::Set: {
auto mech = data.currentItem<Int16>();
if (m_scanparam->pixtype == (byte)PixelType::Rgb)
{
m_scanparam->enhance_color = (byte)Enchace_Color::Enhance_None;
}
else
{
if (mech == Enchace_Color::Enhance_None || mech == Enchace_Color::Enhance_Red || mech == Enchace_Color::Enhance_Green || mech == Enchace_Color::Enhance_Blue)
{
m_scanparam->enhance_color = (byte)mech;
if (mech != (byte)Enchace_Color::Enhance_None)
m_scanparam->filter = (byte)Filter::None;
return success();
}
}
return badValue();
}
default:
return capBadOperation();
}
@ -1234,7 +1447,9 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[(CapType)(CapTypeEx::TwEx_Sharpen)] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<SharpenBlur>((CapType)(CapTypeEx::TwEx_IEnhanceColor), { SharpenBlur::Sharpen_None,SharpenBlur::Sharpen_Normal,SharpenBlur::Sharpen_More,SharpenBlur::Sharpen_Blur,SharpenBlur::Sharpen_Blur_More }, m_scanparam->sharpen, 0);
data = Capability::createEnumeration<SharpenBlur>((CapType)(CapTypeEx::TwEx_Sharpen), { SharpenBlur::Sharpen_None,SharpenBlur::Sharpen_Normal,SharpenBlur::Sharpen_More,SharpenBlur::Sharpen_Blur,SharpenBlur::Sharpen_Blur_More },
m_scanparam->sharpen,
0);
return success();
case Msg::Reset:
m_scanparam->sharpen = SharpenBlur::Sharpen_None;
@ -1246,6 +1461,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return success();
case Msg::Set: {
auto mech = data.currentItem<Int16>();
if (m_scanparam->pixtype == (int)PixelType::BlackWhite)
return badValue();
m_scanparam->sharpen = (byte)mech;
return success();
}
@ -1495,17 +1712,22 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
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
//writelog("identityCloseDs");
if (guiIndicator.get())
guiIndicator.reset();
if (guiTwain.get())
guiTwain.reset();
if (guiBridge.get())
guiBridge.reset();
scanner.reset();
if (hMutex)
{
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
guiIndicator.reset();
guiTwain.reset();
guiBridge.reset();
scanner.reset();
saveGscanCapSetting();
return success();
}
@ -1524,6 +1746,9 @@ Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) {
guiIndicator.reset();
if (ret != -1) {
MessageBox(guiTwain ? guiTwain->m_hWnd : NULL, noticeMsgMap[ret], _T("提示"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
#ifndef G200
scanner->clear_hwerror();
#endif // G200
}
m_pendingXfers = 0;
if (guiTwain.get()) {
@ -1543,6 +1768,10 @@ Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) {
Result HuagaoDs::pendingXfersReset(const Identity&, PendingXfers& data) {
data.setCount(0);
scanner->Stop_scan();
scanner->reset();
scanner->ResetScanner();
guiIndicator.reset();
return success();
}
@ -1571,7 +1800,6 @@ Result HuagaoDs::userInterfaceEnable(const Identity&, UserInterface& ui) {
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
updataGscanCap();
setState(DsState::Enabled);
if (startScan() == success()) {
m_pendingXfers = 1;
@ -1598,13 +1826,12 @@ Result HuagaoDs::imageInfoGet(const Identity&, ImageInfo& data) {
auto dib = header();
data.setBitsPerPixel(static_cast<Int16>(dib->biBitCount));
data.setHeight(dib->biHeight);
//dib->biClrUseddib->biClrUsed==2?T
data.setPixelType(dib->biClrUsed == 2 ? PixelType::BlackWhite : (dib->biClrUsed == 256 ? PixelType::Gray : PixelType::Rgb));
data.setPlanar(false);
data.setWidth(dib->biWidth);
data.setXResolution(m_scanparam->resolution_dst);
data.setYResolution(m_scanparam->resolution_dst);
data.compression(Compression::None);
switch (dib->biClrUsed)
{
case 2:
@ -1673,11 +1900,16 @@ Result HuagaoDs::imageMemXferGet(const Identity& origin, ImageMemXfer& data) {
if (rows == 0) {
return seqError(); // image already transfered in this session
}
//cv::Mat mat = cv::imdecode(bmpData, cv::IMREAD_GRAYSCALE);
//G4Tiff gt(mat);
//vector<uchar> cmpdata;
//gt.GetCompressedData(cmpdata);
////int aa = 1;
data.setBytesPerRow(bpl);
data.setColumns(static_cast<UInt32>(dib->biWidth));
data.setRows(rows);
data.setBytesWritten(rows * bpl);
data.setBytesWritten(bpl*rows);
//data.setBytesWritten(cmpdata.size());
data.setXOffset(0);
data.setYOffset(m_memXferYOff);
data.setCompression(Compression::None);
@ -1685,6 +1917,7 @@ Result HuagaoDs::imageMemXferGet(const Identity& origin, ImageMemXfer& data) {
auto lock = data.memory().data();
char* out = lock.data();
//std::copy(cmpdata.data(), cmpdata.data() + cmpdata.size(), out);
// bottom-up BMP -> top-down memory transfer
auto begin = bmpEnd() - (bpl * (m_memXferYOff + 1));
for (UInt32 i = 0; i < rows; i++) {
@ -1695,11 +1928,14 @@ Result HuagaoDs::imageMemXferGet(const Identity& origin, ImageMemXfer& data) {
out += bpl;
begin -= bpl;
if (dib->biBitCount == 24)
{
//BGR BMP -> RGB memory transfer
for (; line + 3 < out; line += 3) {
std::swap(line[0], line[2]);
}
}
}
m_memXferYOff += rows;
@ -1738,6 +1974,7 @@ Twpp::Result HuagaoDs::pendingXfersStopFeeder(const Identity& origin, PendingXfe
if (scanner->IsConnected()) {
scanner->Stop_scan();
}
data.setCount(scanner->Get_IsImageQueueEmpty() ? 0 : 1);
return success();
}
@ -1844,9 +2081,9 @@ Twpp::Result HuagaoDs::showTwainUI(Twpp::UserInterface& ui, bool bUiOnly)
auto scanFunction = [this](const GScanCap& caps) {
m_pendingXfers = 1;
m_scanparam.reset(new GScanCap(caps));
//scanner->config_params(*m_scanparam);
if (startScan() == success()) {
notifyXferReady();
//FileTools::write_log("E:\\Users\\huago\\Desktop\\1.txt", "notifyXferReady");
}
else {
m_pendingXfers = 0;
@ -1870,7 +2107,7 @@ Twpp::Result HuagaoDs::showTwainUI(Twpp::UserInterface& ui, bool bUiOnly)
TwGlue glueUiOnly = { confirmFunction, cancelFunction };
std::string serialnum = scanner->GetSerialNum();
std::string hardwareversion = scanner->GetFWVersion();
guiTwain.reset(new CTwainUI(bUiOnly ? glueUiOnly : glue, bUiOnly ? "确定" : "扫描", hardwareversion, serialnum));
guiTwain.reset(new CTwainUI(bUiOnly ? glueUiOnly : glue, *m_scanparam, bUiOnly ? "确定" : "扫描", hardwareversion, serialnum));
guiTwain->Create(IDD_TWAINUI, parent);
guiTwain->ShowWindow(SW_SHOWNORMAL);
return success();
@ -1897,109 +2134,13 @@ const char* HuagaoDs::bmpEnd() const noexcept {
return (const char*)bmpData.cend()._Ptr;
}
void HuagaoDs::initGScanCap()
{
m_scanparam->autodescrew = 1;
m_scanparam->brightness = 0.0f;
m_scanparam->contrast = 0.0f;
m_scanparam->fillbackground = 1;
m_scanparam->fillhole.is_fillhole = 1;
m_scanparam->fillhole.fillholeratio = 0.1f;
m_scanparam->filter = (byte)Filter::None;
m_scanparam->sharpen = (byte)SharpenBlur::Sharpen_None;
m_scanparam->gamma = 1.0;
m_scanparam->en_fold = 0;
m_scanparam->hardwarecaps.capturepixtype = (int)(PixelType::Gray);
m_scanparam->hardwarecaps.en_doublefeed = 1;
m_scanparam->hardwarecaps.en_skrewdetect = 0;
m_scanparam->hardwarecaps.en_stapledetect = 0;
m_scanparam->hardwarecaps.skrewdetectlevel = 3;
m_scanparam->is_autocontrast = 0;
m_scanparam->is_autocrop = 0;
m_scanparam->is_autodiscradblank_normal = 0;
m_scanparam->is_autodiscradblank_vince = 0;
//m_scanparam->areanum = 8;
//m_scanparam->devnmax = 200;
m_scanparam->is_backrotate180 = 0;
m_scanparam->is_duplex = 1;
m_scanparam->multi_output_red = 0;
m_scanparam->papertype = 11;//A3
m_scanparam->paperAlign = PaperAlign::Rot0;
m_scanparam->resolution_native = 200.0f;
m_scanparam->resolution_dst = 200.0f;
m_scanparam->scannum = -1;
m_scanparam->is_autotext = 0;
m_scanparam->enhance_color = 0;
m_scanparam->pixtype = (int)(PixelType::Gray);
ScanRect rect = { 0 };//to be define
m_scanparam->scanrect = rect;
m_scanparam->threshold = 128.0f;
}
void HuagaoDs::updataGscanCap()
{
JsonConfig js;
CONFIGPARAMS cfs = js.ReadDefaultConfig();
m_scanparam->autodescrew = cfs.EnAutoDescrew ? 1 : 0;
m_scanparam->brightness = cfs.Brightness;
m_scanparam->contrast = cfs.Contrast;
m_scanparam->fillbackground = cfs.EnFillBlack ? 1 : 0;
m_scanparam->fillhole.is_fillhole = cfs.EnOutHole ? 1 : 0;
m_scanparam->fillhole.fillholeratio = cfs.OutHoleRatio;
m_scanparam->sharpen = (SharpenBlur)cfs.Sharpen;
if (cfs.Filter) {
if (cfs.Filter <= 3) {
m_scanparam->filter = filterMaps[cfs.Filter];
m_scanparam->enhance_color = 0;//红色增强 none
}
else {
m_scanparam->filter = (byte)Filter::None;//不除色
m_scanparam->enhance_color = filterMaps[cfs.Filter];
}
}
else {
m_scanparam->filter = (byte)Filter::None;
m_scanparam->enhance_color = EnchaceColor::Enhance_None;
}
m_scanparam->gamma = cfs.Gamma;
m_scanparam->hardwarecaps.en_doublefeed = cfs.EnUltrasonicDetect ? 1 : 0;
m_scanparam->hardwarecaps.en_skrewdetect = cfs.EnScrewDetect ? 1 : 0;
m_scanparam->hardwarecaps.en_stapledetect = cfs.EnBindingDetect ? 1 : 0;
m_scanparam->hardwarecaps.skrewdetectlevel = cfs.ScrewDetectLevel;
m_scanparam->is_autocontrast = cfs.EnAutoContrast ? 1 : 0;
m_scanparam->is_autocrop = cfs.EnAutoCrop ? 1 : 0;
m_scanparam->is_autodiscradblank_normal = cfs.EnDiscardBlank ? 1 : 0;
m_scanparam->is_autodiscradblank_vince = cfs.EnDiscardBlankVince ? 1 : 0;
m_scanparam->is_backrotate180 = cfs.EnBackRotate180 ? 1 : 0;
m_scanparam->is_duplex = cfs.Duplex >= 1 ? 1 : 0;
m_scanparam->en_fold = cfs.EnFlod ? 1 : 0;
m_scanparam->multi_output_red = cfs.EnMultiOutPutR ? 1 : 0;
PaperStatus ps = paperStatusMap[cfs.PaperSize];
m_scanparam->papertype = ps.Paper;//A3
m_scanparam->paperAlign = (PaperAlign)ps.Orentate;
m_scanparam->resolution_dst = resolutions[cfs.Resolution];
#ifdef REAL300DPI
m_scanparam->resolution_native = m_scanparam->resolution_dst > 240.0f ? 300.0f : 200.0f;
#else // REAL300DPI
m_scanparam->resolution_native = 200.0f;
#endif
m_scanparam->scannum = cfs.ScanCount;
m_scanparam->is_autotext = cfs.Orentation == 4 ? 1 : 0;
if (cfs.Orentation != 4) {
m_scanparam->imageRotateDegree = rotateDegrees[cfs.Orentation];
}
m_scanparam->pixtype = colorModes[cfs.Pixtype];
if (cfs.Filter || cfs.EnMultiOutPutR) {
m_scanparam->hardwarecaps.capturepixtype = (byte)(PixelType::Rgb);
}
else {
m_scanparam->hardwarecaps.capturepixtype = m_scanparam->pixtype;
}
ScanRect rect = { 0 };//to be define
m_scanparam->scanrect = rect;
m_scanparam->threshold = 128.0f;
GscanJsonConfig js;
GScanCap cfs = js.ReadGscanCap();
cfs.resolution_native = 200.0f;
cfs.threshold = 128;
m_scanparam.reset(new GScanCap(cfs));
}
Twpp::Result HuagaoDs::startScan()
@ -2008,6 +2149,7 @@ Twpp::Result HuagaoDs::startScan()
return checkDeviceOnline();
scanner->ResetScanner();
#ifndef G200
scanner->clear_hwerror();
#endif //
@ -2018,6 +2160,9 @@ Twpp::Result HuagaoDs::startScan()
auto stopFunc = [this]() {
scanner->Stop_scan();
guiIndicator.reset();//取消扫描 关闭进度指示器
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
};
guiIndicator.reset(new CIndicatorDlg(stopFunc));
guiIndicator->Create(IDD_INDICATOR, guiTwain ? guiTwain.get() : guiBridge.get());
@ -2035,8 +2180,13 @@ Twpp::Result HuagaoDs::startScan()
if (retCode != 0) {
scanner->Set_ErrorCode(0);
guiIndicator.reset();
if (retCode != -1)
if (retCode != -1) {
MessageBox(guiTwain ? guiTwain->m_hWnd : NULL, noticeMsgMap[retCode], _T("提示"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
#ifndef G200
scanner->clear_hwerror();
#endif //
}
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
@ -2055,3 +2205,18 @@ Twpp::Result HuagaoDs::startScan()
return seqError();
}
}
void HuagaoDs::saveGscanCapSetting()
{
TCHAR szIniFile[MAX_PATH] = { 0 };
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_LOCAL_APPDATA, TRUE);
_tcscat(szIniFile, HUAGAO_SCAN);
_tcscat(szIniFile, TWAIN_INIPATH);
_tcscat(szIniFile, TEXT("\\"));
_tcscat(szIniFile, TWAIN_JSON_NAME);
GscanJsonConfig js;
vector<GScanCap> vc;
vc.push_back(*m_scanparam);
std::string savepath = TCHAR2STRING(szIniFile);
js.WriteJsonArrayToFile(vc, savepath);
}

View File

@ -38,6 +38,7 @@ protected:
virtual Twpp::Result capabilityResetAll(const Twpp::Identity& origin) override;
virtual Twpp::Result capabilitySet(const Twpp::Identity& origin, Twpp::Capability& data) override;
virtual Twpp::Result eventProcess(const Twpp::Identity& origin, Twpp::Event& data) override;
//virtual Twpp::Result deviceEventGet(const Twpp::Identity& origin, Twpp::DeviceEvent& data) override;
virtual Twpp::Result identityOpenDs(const Twpp::Identity& origin) override;
virtual Twpp::Result identityCloseDs(const Twpp::Identity& origin) override;
virtual Twpp::Result pendingXfersGet(const Twpp::Identity& origin, Twpp::PendingXfers& data) override;
@ -57,7 +58,6 @@ protected:
virtual Twpp::Result pendingXfersStopFeeder(const Twpp::Identity& origin, Twpp::PendingXfers& data) override;
virtual Twpp::Result imageFileXferGet(const Twpp::Identity& origin) override;
//virtual Twpp::Result pendingXfersStopFeeder(const Twpp::Identity& origin, Twpp::PendingXfers& data) override;
virtual Twpp::Result setupFileXferGet(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) override;
virtual Twpp::Result setupFileXferGetDefault(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) override;
virtual Twpp::Result setupFileXferSet(const Twpp::Identity& origin, Twpp::SetupFileXfer& data) override;
@ -67,12 +67,12 @@ protected:
private:
Twpp::Result showTwainUI(Twpp::UserInterface& data, bool bUiOnly = false);
Twpp::Result startScan();
void saveGscanCapSetting();
const BITMAPINFOHEADER* header() const noexcept;
Twpp::UInt32 bytesPerLine() const noexcept;
Twpp::UInt32 bmpSize() const noexcept;
const char* bmpBegin() const noexcept;
const char* bmpEnd() const noexcept;
void initGScanCap();
void updataGscanCap();
Twpp::Result capCommon(const Twpp::Identity& origin, Twpp::Msg msg, Twpp::Capability& data);
@ -82,16 +82,18 @@ private:
Twpp::SetupFileXfer m_fileXfer;
Twpp::UInt32 m_memXferYOff = 0;
Twpp::UInt16 m_pendingXfers = 0;
Twpp::UInt16 m_autosize = 0;
Twpp::Int16 m_capXferCount = -1;
Twpp::Fix32 m_brightness = 0.0f;
Twpp::XferMech m_capXferMech = Twpp::XferMech::Native;
Twpp::PixelType m_capPixelType = Twpp::PixelType::Rgb;
unsigned short m_jpegQuality = 80;
Twpp::Compression m_compression= Twpp::Compression::None;
bool m_bIndicator = true;
bool m_bFeederEnabled = true;
bool m_bAutoFeed = true;
UINT16 m_iBitdepth;
Twpp::ImageFileFormat m_capImageFileFormat = Twpp::ImageFileFormat::Bmp;
std::vector<unsigned char> bmpData;