2019-12-05 08:35:04 +00:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "GScanO200.h"
|
|
|
|
|
#include "UsbScanEx.h"
|
|
|
|
|
#include "opencv2/opencv.hpp"
|
|
|
|
|
#include "twain.h"
|
|
|
|
|
#include "UsbScanEx.h"
|
2019-12-05 11:26:19 +00:00
|
|
|
|
#include "StopWatch.h"
|
2019-12-05 08:35:04 +00:00
|
|
|
|
|
|
|
|
|
GScanO200::GScanO200()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GScanO200::~GScanO200()
|
|
|
|
|
{
|
|
|
|
|
if (m_threadUsb && m_threadUsb->joinable()) {
|
|
|
|
|
devState = DEV_STOP;
|
|
|
|
|
m_threadUsb->join();
|
|
|
|
|
m_threadUsb.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::open(int vid, int pid)
|
|
|
|
|
{
|
|
|
|
|
auto usbs = UsbScan_List::find_vid_pid(vid, pid);
|
|
|
|
|
|
|
|
|
|
if (!usbs.empty()) {
|
|
|
|
|
m_usb = *usbs.begin();
|
|
|
|
|
m_usb->open();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int GScanO200::aquire_image(cv::Mat& image)
|
|
|
|
|
{
|
|
|
|
|
StopWatch sw;
|
2019-12-05 11:26:19 +00:00
|
|
|
|
sw.reset();
|
2019-12-05 08:35:04 +00:00
|
|
|
|
double timeout;
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if (Get_IsImageQueueEmpty())
|
|
|
|
|
{
|
|
|
|
|
DoEvents();
|
2019-12-05 11:26:19 +00:00
|
|
|
|
if (sw.elapsed_s() > 15.00)
|
2019-12-05 08:35:04 +00:00
|
|
|
|
{
|
|
|
|
|
if (m_threadUsb && m_threadUsb->joinable()) {
|
|
|
|
|
devState = DEV_STOP;
|
|
|
|
|
m_threadUsb->join();
|
|
|
|
|
m_threadUsb.reset();
|
|
|
|
|
}
|
|
|
|
|
m_pImages.release_img_prc_thread();//<2F>ͷ<EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
|
|
|
|
|
Stop_scan();//ֹͣɨ<D6B9><C9A8>
|
|
|
|
|
ResetScanner();
|
|
|
|
|
return HARDWARE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_scan())
|
|
|
|
|
{
|
|
|
|
|
if (devState == DEV_WRONG)
|
|
|
|
|
{
|
|
|
|
|
return get_ErrorCode();
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (m_pImages.valid())
|
|
|
|
|
{
|
|
|
|
|
image = popMat();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL GScanO200::IsConnected()
|
|
|
|
|
{
|
|
|
|
|
return m_usb && m_usb->is_connected();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GScanO200::GetFWVersion()
|
|
|
|
|
{
|
|
|
|
|
return std::string();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GScanO200::GetSerialNum()
|
|
|
|
|
{
|
|
|
|
|
if (m_usb->is_connected())
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
if (SerialNum.empty())
|
|
|
|
|
{
|
|
|
|
|
SerialNum = " ";
|
|
|
|
|
USBCB usbcb = { GET_SERIAL,12,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
m_usb->read_bulk(&SerialNum[0], 12);
|
|
|
|
|
}
|
|
|
|
|
return SerialNum;
|
|
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GScanO200::is_scan()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
return devState == DEV_ISRUNNING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL GScanO200::Get_Scanner_PaperOn()
|
|
|
|
|
{
|
|
|
|
|
if (!m_usb->is_open())
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
USBCB usbcb = { GET_PAPER_STATUS ,0,0 };
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
m_usb->read_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
return usbcb.u32_Data != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::config_params(SFreeImage& params)
|
|
|
|
|
{
|
|
|
|
|
if (m_usb->is_connected())
|
|
|
|
|
{
|
|
|
|
|
hgConfigClass cfg(params);
|
|
|
|
|
UINT32 cfgdata = cfg.GetData();
|
|
|
|
|
USBCB usbcb = { CONFIGURED_DATA,cfgdata,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(USBCB));
|
|
|
|
|
setdecodepixtype(params.m_HardWareParams.PixType);
|
|
|
|
|
m_pImages.setparam(params);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::Scanner_StartScan(UINT16 count)
|
|
|
|
|
{
|
|
|
|
|
if (m_usb->is_connected())
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
USBCB usbcb = { START_COMMAND,(UINT32)count ,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
if (m_threadUsb && m_threadUsb->joinable()) {
|
|
|
|
|
m_threadUsb->join();
|
|
|
|
|
}
|
|
|
|
|
m_threadUsb.reset(new std::thread(&GScanO200::usbmain, this));
|
|
|
|
|
m_pImages.SetScanningStatus(true);
|
|
|
|
|
m_pImages.run();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::Stop_scan()
|
|
|
|
|
{
|
|
|
|
|
if (!m_usb->is_connected())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
USBCB usbcb = { STOP ,0,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::ResetScanner()
|
|
|
|
|
{
|
|
|
|
|
if (!m_usb->is_connected())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
USBCB usbcb = { INIT_HARDWARE_SYS ,0,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GScanO200::Get_IsImageQueueEmpty()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
return m_pImages.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::reset()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
while (!m_pImages.empty())
|
|
|
|
|
{
|
|
|
|
|
m_pImages.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::setdecodepixtype(int twpixtype)
|
|
|
|
|
{
|
|
|
|
|
if (twpixtype == TWPT_RGB)
|
|
|
|
|
pixType = TJPF_BGR;
|
|
|
|
|
else
|
|
|
|
|
pixType = TJPF_GRAY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT32 GScanO200::get_ErrorCode()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
return Error_Code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GScanO200::Set_ErrorCode(UINT32 value)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lck(m_imgLocker);
|
|
|
|
|
Error_Code = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD GScanO200::usbmain()
|
|
|
|
|
{
|
|
|
|
|
cv::Mat imgData;
|
|
|
|
|
cv::Mat bufferF;
|
|
|
|
|
cv::Mat bufferB;
|
|
|
|
|
devState = DEV_ISRUNNING;
|
|
|
|
|
while (devState == DEV_ISRUNNING)
|
|
|
|
|
{
|
|
|
|
|
if (!m_usb->is_connected())
|
|
|
|
|
{
|
|
|
|
|
this_thread::sleep_for(chrono::milliseconds(200));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
USBCB usbcb = Get_Scanner_Status();
|
|
|
|
|
switch (usbcb.u32_Data)
|
|
|
|
|
{
|
|
|
|
|
case HAVE_IMAGE:
|
|
|
|
|
{
|
|
|
|
|
int totalNum = usbcb.u32_Count;
|
|
|
|
|
DWORD transferCount = 0;
|
|
|
|
|
imgData = Get_Img_Data(totalNum);
|
|
|
|
|
if (imgData.empty()) { //!< transfer data error
|
|
|
|
|
Stop_scan();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bufferF = cv::Mat(imgData.rows, imgData.cols, CV_8UC1);
|
|
|
|
|
bufferB = cv::Mat(imgData.rows, imgData.cols, CV_8UC1);
|
|
|
|
|
int j = 0;
|
|
|
|
|
int k = 0;
|
|
|
|
|
for (int i = 0; i < totalNum / 1024; i++)
|
|
|
|
|
{
|
|
|
|
|
if (imgData.data[1023 + i * 1024] == 0)
|
|
|
|
|
{
|
|
|
|
|
j++;
|
|
|
|
|
memcpy(&(bufferB.data[(j - 1) * 1023]), &(imgData.data[(j + k - 1) * 1024]), 1023);
|
|
|
|
|
}
|
|
|
|
|
else if (imgData.data[1023 + i * 1024] == 255)
|
|
|
|
|
{
|
|
|
|
|
k++;
|
|
|
|
|
memcpy(&(bufferF.data[(k - 1) * 1023]), &(imgData.data[(j + k - 1) * 1024]), 1023);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
vector<cv::Mat> mats;
|
|
|
|
|
mats.push_back(bufferB);
|
|
|
|
|
mats.push_back(bufferF);
|
|
|
|
|
pushMat(JpegBuffer(mats, pixType, 0));
|
|
|
|
|
imgData.release();
|
|
|
|
|
bufferB.release();
|
|
|
|
|
bufferF.release();
|
|
|
|
|
Pop_Image();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case STOP_SCAN:
|
|
|
|
|
{
|
|
|
|
|
m_pImages.SetScanningStatus(false);
|
|
|
|
|
devState = DEV_STOP;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case COUNT_MODE:
|
|
|
|
|
case NO_FEED:
|
|
|
|
|
case OPEN_COVER:
|
|
|
|
|
case FEED_IN_ERROR:
|
|
|
|
|
case PAPER_JAM:
|
|
|
|
|
case DETECT_DOUBLE_FEED:
|
|
|
|
|
case DETECT_STAPLE:
|
|
|
|
|
case PAPER_SKEW:
|
|
|
|
|
case HARDWARE_ERROR:
|
|
|
|
|
case PC_SCAN_BUSY_or_ERROR:
|
|
|
|
|
m_pImages.SetScanningStatus(false);
|
|
|
|
|
Set_ErrorCode(usbcb.u32_Data);
|
|
|
|
|
devState = DEV_WRONG;
|
|
|
|
|
break;
|
|
|
|
|
case NORMAL:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
this_thread::sleep_for(chrono::milliseconds(20));
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
USBCB GScanO200::Get_Scanner_Status()
|
|
|
|
|
{
|
|
|
|
|
if (!m_usb->is_connected())
|
|
|
|
|
{
|
|
|
|
|
USBCB errorType = { NO_COMMAND ,PC_SCAN_BUSY_or_ERROR ,0 };
|
|
|
|
|
return errorType;
|
|
|
|
|
}
|
|
|
|
|
USBCB usbcb = { GET_DSP_STATUS ,0,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
m_usb->read_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
return usbcb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cv::Mat GScanO200::Get_Img_Data(int bufferSize)
|
|
|
|
|
{
|
|
|
|
|
cv::Mat iData(1, bufferSize, CV_8UC1);
|
|
|
|
|
StopWatch sw;
|
|
|
|
|
int readed = 0;
|
2019-12-05 11:26:19 +00:00
|
|
|
|
while (readed < bufferSize && sw.elapsed_ms() < 3000){
|
2019-12-05 08:35:04 +00:00
|
|
|
|
USBCB usbcb = { GET_IMAGE,0,(UINT32)bufferSize };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
readed = m_usb->read_bulk(iData.data, bufferSize);
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-05 11:26:19 +00:00
|
|
|
|
if (sw.elapsed_ms() > 3000)
|
2019-12-05 08:35:04 +00:00
|
|
|
|
return cv::Mat();
|
|
|
|
|
|
|
|
|
|
return iData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
void GScanO200::Pop_Image()
|
|
|
|
|
{
|
|
|
|
|
if (!m_usb->is_open())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
USBCB usbcb = { POP_IMAGE ,0,0 };
|
|
|
|
|
m_usb->write_bulk(&usbcb, sizeof(usbcb));
|
|
|
|
|
}
|