1.增加Group4压缩(支持file、memory传输)

2.增加deviceevent事件
3.调整部分协议类型,以支持五岳以及星立方软件调用
4.解决进度指示器关闭异常(针对方正系统)
5.调整TWAIN UI窗体显示位置,以避免遮挡三方系统模态窗体
6.增加扫描前检查USB是否打开,未打开则open,以避免程序异常(异常处理)
This commit is contained in:
lovelyyoung 2020-08-31 15:44:24 +08:00
parent 695c4fe302
commit 382e47ec7a
5 changed files with 288 additions and 167 deletions

View File

@ -2,66 +2,19 @@
#include "G4Tiff.h"
#include <io.h>
G4Tiff::G4Tiff(cv::Mat & mat, int threshold)
G4Tiff::G4Tiff(cv::Mat & mat,Mode mode,std::string path,int threshold,int res):m_threshold(threshold)
,m_res(res)
,m_mode(mode)
{
m_tmppath = cv::tempfile(".tif");
if (mat.channels() != 1)
throw std::runtime_error("mat channel error");
TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w");
if (!pTiffHandle)
{
printf("can't open TIFF descriptor\n");
}
int width = mat.cols;
int height = mat.rows;
try
{
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width), "width");
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height), "length");
except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, 1), "bits per sample");
except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, 1), "samples per pixel");
except(TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, height), "rows per strip");
//except(TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4), "compression");
except(TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, COMPRESSION_CCITT_T6), "compression");
except(TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE), "photometric");
except(TIFFSetField(pTiffHandle, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB), "photometric");
except(TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG), "planar config");
// not necessary
except(TIFFSetField(pTiffHandle, TIFFTAG_XRESOLUTION, 200.0), "res x");
except(TIFFSetField(pTiffHandle, TIFFTAG_YRESOLUTION, 200.0), "res y");
except(TIFFSetField(pTiffHandle, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH), "res unit");
std::vector<uchar> _buffer(width / 8 + 8, 0);
//std::vector<uchar> _buffer(width / 8 + 1, 0);
uchar* buffer = &_buffer[0];
//int bytes = int(width / 8.0 + 0.5);
for (int y = 0; y < height; ++y)
{
uint8_t* src_row = mat.ptr(y);
for (int x = 0; x < width; ++x, ++src_row)
{
uint8_t eight_pixels = buffer[x / 8];
eight_pixels = eight_pixels << 1;
if (*src_row < threshold)
eight_pixels = eight_pixels | 1; //
buffer[x / 8] = eight_pixels;
}
except(TIFFWriteScanline(pTiffHandle, buffer, y, 0) != -1, "write scanline");
}
}
catch (const std::runtime_error& e)
{
printf("TIFF writing: %s\n", e.what());
TIFFClose(pTiffHandle);
}
TIFFClose(pTiffHandle);
m_tmppath = mode == Mode::MemoryMode ? cv::tempfile(".tif") : path;
m_mat = mat;
if (mode == Mode::MemoryMode)
save(mat);
}
G4Tiff::~G4Tiff()
{
if (m_mode == Mode::MemoryMode)
{
if (_access(m_tmppath.c_str(), 0) == 0)
{
@ -70,6 +23,7 @@ G4Tiff::~G4Tiff()
throw std::runtime_error("File is not exist");
}
}
}
void G4Tiff::GetCompressedData(std::vector<uchar>& cmpeddata)
{
@ -90,15 +44,66 @@ void G4Tiff::GetCompressedData(std::vector<uchar>& cmpeddata)
cmpeddata.resize(size);
fread(cmpeddata.data(), 1, size, file);
}
}
fclose(file);
}
void G4Tiff::SaveG4Tiff()
{
save(m_mat);
}
//TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w");
//TIFFGetField()
//TIFFClose(pTiffHandle);
void G4Tiff::save(cv::Mat& mat)
{
if (mat.channels() != 1)
throw std::runtime_error("mat channel error");
TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w");
if (!pTiffHandle)
{
printf("can't open TIFF descriptor\n");
}
int width = mat.cols;
int height = mat.rows;
try
{
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width), "width");
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height), "length");
except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, 1), "bits per sample");
except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, 1), "samples per pixel");
except(TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, height), "rows per strip");
except(TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, COMPRESSION_CCITT_T6), "compression");
except(TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE), "photometric");
except(TIFFSetField(pTiffHandle, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB), "photometric");
except(TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG), "planar config");
// not necessary
except(TIFFSetField(pTiffHandle, TIFFTAG_XRESOLUTION, m_res), "res x");
except(TIFFSetField(pTiffHandle, TIFFTAG_YRESOLUTION, m_res), "res y");
except(TIFFSetField(pTiffHandle, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH), "res unit");
std::vector<uchar> _buffer(width / 8 + 8, 0);
//std::vector<uchar> _buffer(width / 8 + 1, 0);
uchar* buffer = &_buffer[0];
//int bytes = int(width / 8.0 + 0.5);
for (int y = 0; y < height; ++y)
{
uint8_t* src_row = mat.ptr(y);
for (int x = 0; x < width; ++x, ++src_row)
{
uint8_t eight_pixels = buffer[x / 8];
eight_pixels = eight_pixels << 1;
if (*src_row < m_threshold)
eight_pixels = eight_pixels | 1; //
buffer[x / 8] = eight_pixels;
}
except(TIFFWriteScanline(pTiffHandle, buffer, y, 0) != -1, "write scanline");
}
}
catch (const std::runtime_error& e)
{
printf("TIFF writing: %s\n", e.what());
TIFFClose(pTiffHandle);
}
TIFFClose(pTiffHandle);
}
void G4Tiff::except(bool condition, const std::string & message)

View File

@ -6,12 +6,30 @@
class G4Tiff
{
public:
G4Tiff(cv::Mat& mat,int threshold=120);
enum class Mode
{
FileMode,
MemoryMode
};
G4Tiff(cv::Mat& mat, Mode mode, std::string path, int threshold=120,int res=200);
~G4Tiff();
public:
/*
*
*/
void GetCompressedData(std::vector<uchar>& cmpeddata);
/*
* 使
*/
void SaveG4Tiff();
private:
void save(cv::Mat& mat);
private:
void except(bool condition, const std::string& message = "");
std::string m_tmppath;
int m_threshold;
int m_res;
Mode m_mode;
cv::Mat m_mat;
};

View File

@ -22,8 +22,8 @@
#include <map>
#include <opencv2/opencv.hpp>
#include "GscanJsonConfig.h"
//#include "TiffG4Compression.h"
//#include "G4Tiff.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
@ -135,34 +135,52 @@ static list<UInt16> paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A
static list<float> imageRotateList = { 0.0,90.0,180.0,270.0 };
//static map<unsigned int, CString> noticeMsgMap = { {OPEN_COVER,_T("扫描仪开盖")},
// {NO_FEED,_T("无纸!")},
// {FEED_IN_ERROR,_T("搓纸失败!")},
// {PAPER_JAM,_T("卡纸!")},
// {DETECT_DOUBLE_FEED,_T("双张!")},
// {DETECT_STAPLE,_T("订书针!")},
// {PAPER_SKEW,_T("纸张歪斜!")},
// {COUNT_MODE,_T("计数模式,请退出计数模式!")},
// {HARDWARE_ERROR,_T("硬件错误")},
// {FPGA_ERROR,_T("FPGA 异常")},
// {USB_DISCONNECTED,_T("USB连接异常")}
//};
enum class DeviceEventType : UInt16
{
CustomEvents = 0x8000,
Dev_OPENCOVER,
Dev_NOFEED,
Dev_FEEDERROR,
Dev_STABLE,
Dev_SKREW,
Dev_COUNTMOE,
Dev_HARDWAREERROR,
Dev_FPGAERROR,
Dev_UserStop
};
static map<unsigned int, DeviceEvent::Type> mapDeviceEvent = {
{OPEN_COVER,(DeviceEvent::Type)(DeviceEventType::Dev_OPENCOVER)},
{NO_FEED,(DeviceEvent::Type)(DeviceEventType::Dev_NOFEED)},
{FEED_IN_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_FEEDERROR)},
{PAPER_JAM,DeviceEvent::Type::PaperJam},
{DETECT_DOUBLE_FEED,DeviceEvent::Type::PaperDoubleFeed},
{DETECT_STAPLE,(DeviceEvent::Type)(DeviceEventType::Dev_STABLE)},
{PAPER_SKEW,(DeviceEvent::Type)(DeviceEventType::Dev_SKREW)},
{COUNT_MODE,(DeviceEvent::Type)(DeviceEventType::Dev_COUNTMOE)},
{HARDWARE_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_HARDWAREERROR)},
{FPGA_ERROR,(DeviceEvent::Type)(DeviceEventType::Dev_FPGAERROR)},
{USB_DISCONNECTED,DeviceEvent::Type::CheckDeviceOnline},
{USER_STOP,(DeviceEvent::Type)(DeviceEventType::Dev_UserStop)}
};
static void DeleteWnd(CDialog* pWnd) {
if (pWnd && pWnd->GetSafeHwnd()) {
pWnd->DestroyWindow();
delete pWnd;
if(pWnd->m_hWnd)
DestroyWindow(pWnd->m_hWnd);
}
}
static std::unique_ptr<CDialog, void(*)(CDialog*)> guiTwain(nullptr, DeleteWnd);
static std::unique_ptr<CTwainUI, void(*)(CDialog*)> guiTwain(nullptr, DeleteWnd);
#if TWPP_DETAIL_OS_WIN
static std::unique_ptr<CDialog, void(*)(CDialog*)> guiBridge(nullptr, DeleteWnd);
#endif
static std::unique_ptr<CDialogEx, void(*)(CDialog*)> guiIndicator(nullptr, DeleteWnd);
//static std::unique_ptr<CIndicatorDlg, void(*)(CDialog*)> guiIndicator(nullptr, DeleteWnd);
static CIndicatorDlg* guiIndicator =NULL;
//#define HG_VIRTUAL
#ifndef HG_VIRTUAL
static std::unique_ptr<IScanner> scanner(new GScanO200());
static std::unique_ptr<IScanner> scanner; //(new GScanO200());
#else
static std::unique_ptr<IScanner> scanner(new GScanVirtual());
#endif
@ -409,6 +427,17 @@ Result HuagaoDs::eventProcess(const Identity&, Event& event) {
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)
{
@ -437,6 +466,9 @@ void HuagaoDs::SetResoluton(const char* path, int resolution)
Result HuagaoDs::identityOpenDs(const Identity&) {
//writelog("identityOpenDs");
if(!scanner.get())
scanner.reset(new GScanO200());
updataGscanCap();
bmpData.resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header());
@ -450,6 +482,10 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
return checkDeviceOnline();
}
else
{
scanner->regist_deviceevent_callback(DeviceEvent_callback, this);
}
hMutex = CreateMutex(NULL, FALSE, _T("LookitApp"));
if (GetLastError() == ERROR_ALREADY_EXISTS) { //如果已经存在同名的Mutex会得到这个错误.
CloseHandle(hMutex);
@ -493,7 +529,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::XferCount] = [this](Msg msg, Capability& data) -> Result {
if (msg == Msg::Set) {
auto item = data.currentItem<Int16>();
if (item > 65535 || item < -1) {
if (item > 65535 || item < -1||item == 0) {
return badValue();
}
m_scanparam->scannum = item;
@ -510,6 +546,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
};
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) {
@ -554,13 +591,14 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Reset:
m_iBitdepth = 8;
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
return success();
break;
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IBitDepth>(UInt16(m_iBitdepth));
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IBitDepth>(8);
data = Capability::createOneValue<CapType::IBitDepth>(24);
return success();
case Msg::Set: {
@ -655,7 +693,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<CapType::IJpegQuality>();
if ((int)mech < 0 || (int)mech > 100)
return capBadOperation();
return badValue();
m_jpegQuality = (int)mech;
return success();
}
@ -907,7 +945,17 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
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_caps[CapType::FeederLoaded] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue<CapType::FeederLoaded>(Bool(scanner->Get_Scanner_PaperOn()));
return success();
default:
return capBadOperation();
}
};
m_query[CapType::Indicators] = msgSupportGetAllSetReset;
m_caps[CapType::Indicators] = [this](Msg msg, Capability& data) -> Result {
@ -943,7 +991,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Get:
case Msg::GetCurrent:
case Msg::GetDefault:
data = Capability::createOneValue<CapType::CustomDsData>(true);
data = Capability::createOneValue<Bool>(CapType::CustomDsData,Bool(true));
return success();
default:
return capBadOperation();
@ -960,16 +1008,16 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::FeederEnabled] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createOneValue<CapType::FeederEnabled>(true);
data = Capability::createOneValue<CapType::FeederEnabled>(Bool(m_bFeederEnabled));
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::FeederEnabled>(m_bFeederEnabled);
data = Capability::createOneValue<CapType::FeederEnabled>(Bool(m_bFeederEnabled));
return success();
case Msg::GetDefault:
case Msg::Reset:
m_bFeederEnabled = true;
data = Capability::createOneValue<CapType::FeederEnabled>(true);
data = Capability::createOneValue<CapType::FeederEnabled>(Bool(true));
return success();
case Msg::Set: {
@ -989,9 +1037,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::DuplexEnabled] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
//MessageBox(NULL, m_scanparam->is_duplex?TEXT("Get duplex"): TEXT("Get not duplex"), TEXT("aa"), MB_OK);
data = Capability::createEnumeration<CapType::DuplexEnabled>(
{ Bool(), Bool(true) }, Bool(m_scanparam->is_duplex));
data = Capability::createOneValue<CapType::DuplexEnabled>(Bool(m_scanparam->is_duplex));
return success();
case Msg::GetCurrent:
@ -1006,6 +1052,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<CapType::DuplexEnabled>();
m_scanparam->is_duplex = mech;
//FileTools::write_log("D:\\1.txt", std::to_string(mech ? 1 : 0));
m_scanparam->is_autodiscradblank_normal = m_scanparam->is_autodiscradblank_vince = m_scanparam->en_fold = 0;
if (!mech)
m_scanparam->is_backrotate180 = 0;//单面背面旋转180°不可用
@ -1021,8 +1068,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::AutoFeed] = [this](Msg msg, Capability& data) -> Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::AutoFeed>(
{ Bool(), Bool(true) }, Bool(m_bAutoFeed));
data = Capability::createOneValue<CapType::AutoFeed>(m_bAutoFeed);
return success();
// fallthrough
case Msg::GetCurrent:
@ -1085,14 +1131,13 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return success();
}
case Msg::Reset:
case Msg::GetCurrent:
case Msg::GetDefault:
m_capImageFileFormat = ImageFileFormat::Bmp;
data = Capability::createOneValue<CapType::IImageFileFormat>(m_capImageFileFormat);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IImageFileFormat>(ImageFileFormat::Bmp);
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IImageFileFormat>(m_capImageFileFormat);
return success();
case Msg::Set: {
auto mech = data.currentItem<CapType::IImageFileFormat>();
if (mech == ImageFileFormat::Bmp ||
@ -1118,11 +1163,12 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
{ Bool(), Bool(true) }, Bool(m_scanparam->autodescrew == 0 ? false : true));
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->autodescrew = true;
data = Capability::createOneValue<CapType::IAutomaticDeskew>(m_scanparam->autodescrew);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutomaticDeskew>(m_scanparam->autodescrew);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::IAutomaticDeskew>(true);
return success();
@ -1166,8 +1212,6 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::IAutomaticRotate] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutomaticRotate>(
{ Bool(), Bool(true) }, Bool(m_scanparam->is_autotext));
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutomaticRotate>(m_scanparam->is_autotext);
return success();
@ -1225,11 +1269,12 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
{ Bool(), Bool(true) }, m_autoscan);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_autoscan = true;
data = Capability::createOneValue<CapType::AutoScan>(m_autoscan);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::AutoScan>(m_autoscan);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<CapType::AutoScan>(true);
return success();
@ -1287,11 +1332,10 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::IAutomaticBorderDetection] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutomaticBorderDetection>(
{ Bool(), Bool(true) }, m_autoboarderdetcet);
case Msg::GetCurrent:
data = Capability::createOneValue<CapType::IAutomaticBorderDetection>(m_autoboarderdetcet);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_autoboarderdetcet = false;
data = Capability::createOneValue<CapType::IAutomaticBorderDetection>(m_autoboarderdetcet);
return success();
@ -1328,10 +1372,12 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
case Msg::Reset:
case Msg::GetCurrent:
m_scanparam->en_fold = 0;//默认不对折
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, (UInt16)m_scanparam->en_fold);
return success();
case Msg::GetDefault:
data = Capability::createOneValue<UInt16>(CapType::IImageMerge, 0);
@ -1357,9 +1403,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::IAutoDiscardBlankPages] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<CapType::IAutoDiscardBlankPages>({ DiscardBlankPages::Disabled,DiscardBlankPages::Auto },
m_scanparam->is_autodiscradblank_normal ? 1 : 0,
0);
data = Capability::createOneValue<CapType::IAutoDiscardBlankPages>(m_scanparam->is_autodiscradblank_normal ? DiscardBlankPages::Auto : DiscardBlankPages::Disabled);
return success();
case Msg::Reset:
case Msg::GetDefault:
@ -1372,6 +1416,9 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
case Msg::Set: {
auto mech = data.currentItem<CapType::IAutoDiscardBlankPages>();
if ((mech != DiscardBlankPages::Auto) || (mech != DiscardBlankPages::Disabled))
return badValue();
m_scanparam->is_autodiscradblank_normal = (Int32)mech == (Int32)DiscardBlankPages::Auto;
m_scanparam->is_duplex = 1;
m_scanparam->en_fold = 0;
@ -1889,8 +1936,6 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
m_caps[CapType::DoubleFeedDetection] = [this](Msg msg, Capability& data)->Result {
switch (msg) {
case Msg::Get:
data = Capability::createEnumeration<Bool>(CapType::DoubleFeedDetection, { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_doublefeed), 0);
return success();
case Msg::GetCurrent:
data = Capability::createOneValue<Bool>(CapType::DoubleFeedDetection, m_scanparam->hardwarecaps.en_doublefeed);
return success();
@ -1915,8 +1960,8 @@ Result HuagaoDs::identityCloseDs(const Identity&) {
// no need to explicitly release any resources if using RAII
// TWPP will free the whole source on its own after this method
if (guiIndicator.get())
guiIndicator.reset();
if (guiIndicator)
guiIndicator->DestroyWindow();
if (guiTwain.get())
guiTwain.reset();
@ -1948,9 +1993,11 @@ Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) {
if (ret != 0) {
scanner->Set_ErrorCode(0);
if(guiIndicator.get())
if (guiIndicator)
guiIndicator->ShowWindow(SW_HIDE);
//if (guiIndicator.get())
// guiIndicator.reset();
//guiIndicator->ShowWindow(SW_HIDE);
if (ret != -1) {
CString str;
str.Format(_T("%d"), ret);
@ -1983,7 +2030,9 @@ Result HuagaoDs::pendingXfersReset(const Identity&, PendingXfers& data) {
scanner->reset();
scanner->ResetScanner();
}
guiIndicator.reset();
//guiIndicator.reset();
if (guiIndicator)
guiIndicator->DestroyWindow();
return success();
}
@ -2049,7 +2098,7 @@ Result HuagaoDs::imageInfoGet(const Identity&, ImageInfo& data) {
data.setWidth(dib->biWidth);
data.setXResolution(m_scanparam->resolution_dst);
data.setYResolution(m_scanparam->resolution_dst);
data.compression(Compression::None);
data.compression(m_compression);
switch (dib->biClrUsed)
{
case 2:
@ -2118,25 +2167,28 @@ 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;
cv::Mat mat;
vector<uchar> cmpdata;
if (m_compression == Compression::Group4)
{
mat = cv::imdecode(bmpData, cv::IMREAD_GRAYSCALE);
G4Tiff gt(mat,G4Tiff::Mode::MemoryMode,"",120,m_scanparam->resolution_dst);
gt.GetCompressedData(cmpdata);
}
data.setBytesPerRow(bpl);
data.setColumns(static_cast<UInt32>(dib->biWidth));
data.setRows(rows);
data.setBytesWritten(bpl*rows);
//data.setBytesWritten(cmpdata.size());
data.setBytesWritten(m_compression==Compression::None?bpl*rows: cmpdata.size());
data.setXOffset(0);
data.setYOffset(m_memXferYOff);
data.setCompression(Compression::None);
data.setCompression(m_compression);
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
if (m_compression == Compression::None)
{
auto begin = bmpEnd() - (bpl * (m_memXferYOff + 1));
for (UInt32 i = 0; i < rows; i++) {
// copy bytes
@ -2154,6 +2206,11 @@ Result HuagaoDs::imageMemXferGet(const Identity& origin, ImageMemXfer& data) {
}
}
}
}
else
{
std::copy(cmpdata.data(), cmpdata.data() + cmpdata.size(), out);
}
m_memXferYOff += rows;
@ -2266,13 +2323,23 @@ Twpp::Result HuagaoDs::imageFileXferGet(const Twpp::Identity& origin)
else
decodetype = cv::IMREAD_GRAYSCALE;
cv::Mat ims = cv::imdecode(bmpData, decodetype);
if (m_compression == Compression::Group4&& m_fileXfer.format()==ImageFileFormat::Tiff)
{
if (!ims.empty() && ims.channels() == 3)
cvtColor(ims, ims, cv::COLOR_BGR2GRAY);
G4Tiff gsave(ims, G4Tiff::Mode::FileMode, filename, 120, m_scanparam->resolution_dst);
gsave.SaveG4Tiff();
}
else
{
std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(m_jpegQuality);
cv::imwrite(filename, ims, compression_params);
}
return Result(ReturnCode::XferDone, ConditionCode::Success);
}
default:
@ -2334,11 +2401,29 @@ Twpp::Result HuagaoDs::showTwainUI(Twpp::UserInterface& ui, bool bUiOnly)
guiTwain->Create(IDD_TWAINUI, parent);
CRect newRect;
::GetWindowRect(static_cast<HWND>(ui.parent().raw()), &newRect);
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, newRect.left + 20, newRect.top + 100, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOACTIVATE);
guiTwain->ShowWindow(SW_SHOWNORMAL);
return success();
}
void HuagaoDs::DeviceEvent_callback(int eventID, void* usrdata)
{
HuagaoDs* This = (HuagaoDs*)usrdata;
This->onDeviceEvent(eventID);
}
void HuagaoDs::onDeviceEvent(int eventID)
{
//if (mapDeviceEvent.count(eventID))
//{
// //devEvent.push(DeviceEvent::)
// DeviceEvent::Type dev_type = mapDeviceEvent[eventID];
// auto evt = DeviceEvent::simple((DeviceEvent::Type)dev_type, "HuaGo Device Event");
// devEvent.push(evt);
// notifyDeviceEvent();
//}
}
const BITMAPINFOHEADER* HuagaoDs::header() const noexcept {
return reinterpret_cast<const BITMAPINFOHEADER*>(bmpData.data() + sizeof(BITMAPFILEHEADER));
}
@ -2378,8 +2463,12 @@ void HuagaoDs::updataGscanCap()
Twpp::Result HuagaoDs::startScan()
{
//if (!scanner->IsConnected())
// return checkDeviceOnline();
if (!scanner->IsConnected())
{
scanner->open(0x064B, 0x7823);
if (!scanner->IsConnected())
return checkDeviceOnline();
}
scanner->ResetScanner();
@ -2393,14 +2482,16 @@ Twpp::Result HuagaoDs::startScan()
if (m_bIndicator) {
//!< cancel button push
auto stopFunc = [this]() {
if(scanner.get())
scanner->Stop_scan();
guiIndicator.reset();//取消扫描 关闭进度指示器
//guiIndicator.reset();//取消扫描 关闭进度指示器
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
onDeviceEvent(USER_STOP);
};
guiIndicator.reset(new CIndicatorDlg(stopFunc));
guiIndicator->Create(IDD_INDICATOR, guiTwain ? guiTwain.get() : guiBridge.get());
guiIndicator = new CIndicatorDlg(stopFunc);
guiIndicator->Create(IDD_INDICATOR, guiTwain.get() ? guiTwain.get() : guiBridge.get());//guiTwain ? guiTwain.get() : guiBridge.get()
guiIndicator->ShowWindow(SW_SHOWNORMAL);
}
scanner->Scanner_StartScan(m_scanparam->scannum);
@ -2414,8 +2505,11 @@ Twpp::Result HuagaoDs::startScan()
int retCode = scanner->aquire_bmpdata(bmpData);
if (retCode != 0) {
scanner->Set_ErrorCode(0);
if(guiIndicator.get())
guiIndicator.reset();
if (guiIndicator)
guiIndicator->DestroyWindow();
//if(guiIndicator.get())
// guiIndicator.reset();
if (retCode != -1) {
//MessageBox(guiTwain ? guiTwain->m_hWnd : NULL, noticeMsgMap[retCode], _T("提示"), MB_SYSTEMMODAL | MB_OK | MB_ICONINFORMATION);
CString str;
@ -2426,7 +2520,6 @@ Twpp::Result HuagaoDs::startScan()
#endif //
}
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);
}
@ -2437,8 +2530,6 @@ Twpp::Result HuagaoDs::startScan()
return success();
}
else {
if(guiIndicator.get())
guiIndicator.reset();
if (guiTwain.get()) {
((CTwainUI*)(guiTwain.get()))->EnableID_OKorID_Cancel(true);

View File

@ -5,6 +5,7 @@
#include <unordered_map>
#include <vector>
#include <functional>
#include <queue>
namespace std {
@ -38,7 +39,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 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;
@ -77,8 +78,11 @@ protected:
/// \param data Custom data.
virtual Twpp::Result customDataSet(const Twpp::Identity& origin, Twpp::CustomData& data) override;
void SetResoluton(const char* path, int resolution);
private:
private://method
Twpp::Result showTwainUI(Twpp::UserInterface& data, bool bUiOnly = false);
static void DeviceEvent_callback(int eventID, void* usrdata);
void HuagaoDs::onDeviceEvent(int eventID);
Twpp::Result startScan();
void saveGscanCapSetting();
const BITMAPINFOHEADER* header() const noexcept;
@ -89,6 +93,7 @@ private:
void updataGscanCap();
Twpp::Result capCommon(const Twpp::Identity& origin, Twpp::Msg msg, Twpp::Capability& data);
private://field
std::unordered_map<Twpp::CapType, std::function<Twpp::Result(Twpp::Msg msg, Twpp::Capability& data)>> m_caps;
std::unordered_map<Twpp::CapType, Twpp::MsgSupport> m_query;
@ -109,7 +114,7 @@ private:
bool m_bAutoFeed = true;
UINT16 m_iBitdepth;
Twpp::ImageFileFormat m_capImageFileFormat = Twpp::ImageFileFormat::Bmp;
std::queue<Twpp::DeviceEvent> devEvent;
std::vector<unsigned char> bmpData;
std::unique_ptr<GScanCap> m_scanparam;
HANDLE hMutex;

View File

@ -88,6 +88,7 @@ SOURCES += huagaods.cpp \
ImageProcess/ImageProcess_Public.cpp \
ImageProcess/ImageApplyConcatenation.cpp \
GscanJsonConfig.cpp \
G4Tiff.cpp \
Sliders.cpp \
SmartEdit.cpp \
TabCtrlSSL.cpp \
@ -145,6 +146,7 @@ HEADERS += huagaods.hpp \
ImageProcess/ImageProcess_Public.h \
ImageProcess/ImageApplyConcatenation.h \
GscanJsonConfig.h \
G4Tiff.h \
MapFinder.h \
Sliders.h \
SmartEdit.h \