From 382e47ec7afc474069136f54a19d26c870445e8e Mon Sep 17 00:00:00 2001 From: lovelyyoung <1002639516@qq.com> Date: Mon, 31 Aug 2020 15:44:24 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=A2=9E=E5=8A=A0Group4=E5=8E=8B=E7=BC=A9?= =?UTF-8?q?=EF=BC=88=E6=94=AF=E6=8C=81file=E3=80=81memory=E4=BC=A0?= =?UTF-8?q?=E8=BE=93=EF=BC=89=202.=E5=A2=9E=E5=8A=A0deviceevent=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=203.=E8=B0=83=E6=95=B4=E9=83=A8=E5=88=86=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E7=B1=BB=E5=9E=8B=EF=BC=8C=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BA=94=E5=B2=B3=E4=BB=A5=E5=8F=8A=E6=98=9F=E7=AB=8B=E6=96=B9?= =?UTF-8?q?=E8=BD=AF=E4=BB=B6=E8=B0=83=E7=94=A8=204.=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=8C=87=E7=A4=BA=E5=99=A8=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=EF=BC=88=E9=92=88=E5=AF=B9=E6=96=B9=E6=AD=A3?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=EF=BC=89=205.=E8=B0=83=E6=95=B4TWAIN=20UI?= =?UTF-8?q?=E7=AA=97=E4=BD=93=E6=98=BE=E7=A4=BA=E4=BD=8D=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E4=BB=A5=E9=81=BF=E5=85=8D=E9=81=AE=E6=8C=A1=E4=B8=89=E6=96=B9?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=A8=A1=E6=80=81=E7=AA=97=E4=BD=93=206.?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=89=AB=E6=8F=8F=E5=89=8D=E6=A3=80=E6=9F=A5?= =?UTF-8?q?USB=E6=98=AF=E5=90=A6=E6=89=93=E5=BC=80=EF=BC=8C=E6=9C=AA?= =?UTF-8?q?=E6=89=93=E5=BC=80=E5=88=99open=EF=BC=8C=E4=BB=A5=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E7=A8=8B=E5=BA=8F=E5=BC=82=E5=B8=B8=EF=BC=88=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=A4=84=E7=90=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- huagao/G4Tiff.cpp | 137 ++++++++++---------- huagao/G4Tiff.h | 20 ++- huagao/huagaods.cpp | 283 ++++++++++++++++++++++++++++-------------- huagao/huagaods.hpp | 11 +- huagao/huagaotwds.pro | 4 +- 5 files changed, 288 insertions(+), 167 deletions(-) diff --git a/huagao/G4Tiff.cpp b/huagao/G4Tiff.cpp index 883883e6..4bece8f1 100644 --- a/huagao/G4Tiff.cpp +++ b/huagao/G4Tiff.cpp @@ -2,72 +2,26 @@ #include "G4Tiff.h" #include -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 _buffer(width / 8 + 8, 0); - //std::vector _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 (_access(m_tmppath.c_str(), 0) == 0) + if (m_mode == Mode::MemoryMode) { - if (!std::remove(m_tmppath.c_str())) {}//删除成功 - else - throw std::runtime_error("File is not exist"); + if (_access(m_tmppath.c_str(), 0) == 0) + { + if (!std::remove(m_tmppath.c_str())) {}//删除成功 + else + throw std::runtime_error("File is not exist"); + } } } @@ -90,15 +44,66 @@ void G4Tiff::GetCompressedData(std::vector& cmpeddata) cmpeddata.resize(size); fread(cmpeddata.data(), 1, size, file); } - - } fclose(file); +} - - //TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w"); - //TIFFGetField() - //TIFFClose(pTiffHandle); +void G4Tiff::SaveG4Tiff() +{ + save(m_mat); +} + +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 _buffer(width / 8 + 8, 0); + //std::vector _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) diff --git a/huagao/G4Tiff.h b/huagao/G4Tiff.h index 9321d336..52ae5aef 100644 --- a/huagao/G4Tiff.h +++ b/huagao/G4Tiff.h @@ -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& 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; }; diff --git a/huagao/huagaods.cpp b/huagao/huagaods.cpp index c2d643b5..a0f577ff 100644 --- a/huagao/huagaods.cpp +++ b/huagao/huagaods.cpp @@ -22,8 +22,8 @@ #include #include #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 paperSizeList = { (UInt16)PaperSize::A3,(UInt16)PaperSize::A static list imageRotateList = { 0.0,90.0,180.0,270.0 }; -//static map 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 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 guiTwain(nullptr, DeleteWnd); +static std::unique_ptr guiTwain(nullptr, DeleteWnd); #if TWPP_DETAIL_OS_WIN static std::unique_ptr guiBridge(nullptr, DeleteWnd); + #endif -static std::unique_ptr guiIndicator(nullptr, DeleteWnd); +//static std::unique_ptr guiIndicator(nullptr, DeleteWnd); +static CIndicatorDlg* guiIndicator =NULL; //#define HG_VIRTUAL #ifndef HG_VIRTUAL -static std::unique_ptr scanner(new GScanO200()); +static std::unique_ptr scanner; //(new GScanO200()); #else static std::unique_ptr 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(); - 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, _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(UInt16(m_iBitdepth)); + return success(); break; case Msg::GetCurrent: data = Capability::createOneValue(UInt16(m_iBitdepth)); return success(); case Msg::GetDefault: - data = Capability::createOneValue(8); + data = Capability::createOneValue(24); return success(); case Msg::Set: { @@ -655,7 +693,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) { case Msg::Set: { auto mech = data.currentItem(); 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, _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(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(true); + data = Capability::createOneValue(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(true); + data = Capability::createOneValue(Bool(m_bFeederEnabled)); return success(); case Msg::GetCurrent: - data = Capability::createOneValue(m_bFeederEnabled); + data = Capability::createOneValue(Bool(m_bFeederEnabled)); return success(); case Msg::GetDefault: case Msg::Reset: m_bFeederEnabled = true; - data = Capability::createOneValue(true); + data = Capability::createOneValue(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( - { Bool(), Bool(true) }, Bool(m_scanparam->is_duplex)); + data = Capability::createOneValue(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(); 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( - { Bool(), Bool(true) }, Bool(m_bAutoFeed)); + data = Capability::createOneValue(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(m_capImageFileFormat); return success(); - case Msg::GetDefault: - data = Capability::createOneValue(ImageFileFormat::Bmp); + case Msg::GetCurrent: + data = Capability::createOneValue(m_capImageFileFormat); return success(); - case Msg::Set: { auto mech = data.currentItem(); 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(m_scanparam->autodescrew); return success(); - + case Msg::GetCurrent: + data = Capability::createOneValue(m_scanparam->autodescrew); + return success(); case Msg::GetDefault: data = Capability::createOneValue(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( - { Bool(), Bool(true) }, Bool(m_scanparam->is_autotext)); case Msg::GetCurrent: data = Capability::createOneValue(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(m_autoscan); return success(); - + case Msg::GetCurrent: + data = Capability::createOneValue(m_autoscan); + return success(); case Msg::GetDefault: data = Capability::createOneValue(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( - { Bool(), Bool(true) }, m_autoboarderdetcet); + case Msg::GetCurrent: + data = Capability::createOneValue(m_autoboarderdetcet); return success(); case Msg::Reset: - case Msg::GetCurrent: m_autoboarderdetcet = false; data = Capability::createOneValue(m_autoboarderdetcet); return success(); @@ -1328,10 +1372,12 @@ Result HuagaoDs::identityOpenDs(const Identity&) { data = Capability::createOneValue(CapType::IImageMerge, (UInt16)m_scanparam->en_fold); return success(); case Msg::Reset: - case Msg::GetCurrent: m_scanparam->en_fold = 0;//默认不对折 data = Capability::createOneValue(CapType::IImageMerge, (UInt16)m_scanparam->en_fold); return success(); + case Msg::GetCurrent: + data = Capability::createOneValue(CapType::IImageMerge, (UInt16)m_scanparam->en_fold); + return success(); case Msg::GetDefault: data = Capability::createOneValue(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({ DiscardBlankPages::Disabled,DiscardBlankPages::Auto }, - m_scanparam->is_autodiscradblank_normal ? 1 : 0, - 0); + data = Capability::createOneValue(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(); + 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(CapType::DoubleFeedDetection, { Bool(),Bool(true) }, Bool(m_scanparam->hardwarecaps.en_doublefeed), 0); - return success(); case Msg::GetCurrent: data = Capability::createOneValue(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); - //guiIndicator.reset(); + //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,42 +2167,50 @@ 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 cmpdata; - //gt.GetCompressedData(cmpdata); - //int aa = 1; + cv::Mat mat; + vector 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(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 - auto begin = bmpEnd() - (bpl * (m_memXferYOff + 1)); - for (UInt32 i = 0; i < rows; i++) { - // copy bytes - std::copy(begin, begin + bpl, out); + 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; + 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]); + 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; @@ -2266,13 +2323,23 @@ Twpp::Result HuagaoDs::imageFileXferGet(const Twpp::Identity& origin) else decodetype = cv::IMREAD_GRAYSCALE; + cv::Mat ims = cv::imdecode(bmpData, decodetype); - std::vector compression_params; - compression_params.push_back(CV_IMWRITE_JPEG_QUALITY); - compression_params.push_back(m_jpegQuality); - - cv::imwrite(filename, ims, compression_params); + 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); + 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(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(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]() { - scanner->Stop_scan(); - guiIndicator.reset();//取消扫描 关闭进度指示器 + if(scanner.get()) + scanner->Stop_scan(); + //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); diff --git a/huagao/huagaods.hpp b/huagao/huagaods.hpp index cf98b0bf..60cf82e5 100644 --- a/huagao/huagaods.hpp +++ b/huagao/huagaods.hpp @@ -5,6 +5,7 @@ #include #include #include +#include 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> m_caps; std::unordered_map m_query; @@ -109,7 +114,7 @@ private: bool m_bAutoFeed = true; UINT16 m_iBitdepth; Twpp::ImageFileFormat m_capImageFileFormat = Twpp::ImageFileFormat::Bmp; - + std::queue devEvent; std::vector bmpData; std::unique_ptr m_scanparam; HANDLE hMutex; diff --git a/huagao/huagaotwds.pro b/huagao/huagaotwds.pro index ccb7bde6..27705b8d 100644 --- a/huagao/huagaotwds.pro +++ b/huagao/huagaotwds.pro @@ -87,7 +87,8 @@ SOURCES += huagaods.cpp \ ImageProcess/ImageApplySharpen.cpp \ ImageProcess/ImageProcess_Public.cpp \ ImageProcess/ImageApplyConcatenation.cpp \ - GscanJsonConfig.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 \