添加RK3399扫描流程

This commit is contained in:
masayume 2021-07-11 16:19:57 +08:00
parent cfe838b394
commit 7d0e35e591
14 changed files with 1726 additions and 53 deletions

462
3rdparty/cyusb/inc/CyAPI.h vendored Normal file
View File

@ -0,0 +1,462 @@
//______________________________________________________________________________
//
// Copyright (c) Cypress Semiconductor, 2003
// All rights reserved.
//
//______________________________________________________________________________
#ifndef CyUSBH
#define CyUSBH
#ifndef __USB200_H__
#define __USB200_H__
#include <Windows.h>
#pragma pack(push,1) ///
typedef struct _USB_DEVICE_DESCRIPTOR { //设备描述符
UCHAR bLength; //长度
UCHAR bDescriptorType; //描述符类型
USHORT bcdUSB; //USB
UCHAR bDeviceClass; //设备类
UCHAR bDeviceSubClass; //设备派生类
UCHAR bDeviceProtocol; //设备协议
UCHAR bMaxPacketSize0; //最大数据包尺寸
USHORT idVendor; //厂商ID
USHORT idProduct; //产品ID
USHORT bcdDevice; //设备
UCHAR iManufacturer; //制造商
UCHAR iProduct; //产品
UCHAR iSerialNumber; //序列号
UCHAR bNumConfigurations;//配置
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
typedef struct _USB_ENDPOINT_DESCRIPTOR { //端点描述符
UCHAR bLength; //长度
UCHAR bDescriptorType; //描述符类型
UCHAR bEndpointAddress; //端点地址
UCHAR bmAttributes; //端点属性
USHORT wMaxPacketSize; //最大数据包尺寸
UCHAR bInterval; //间隔
} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
typedef struct _USB_CONFIGURATION_DESCRIPTOR { //配置描述符
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
typedef struct _USB_INTERFACE_DESCRIPTOR { //接口描述符
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
typedef struct _USB_STRING_DESCRIPTOR { //字符串描述符
UCHAR bLength;
UCHAR bDescriptorType;
WCHAR bString[1];
} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR;
typedef struct _USB_COMMON_DESCRIPTOR { //USB串口描述符
UCHAR bLength;
UCHAR bDescriptorType;
} USB_COMMON_DESCRIPTOR, *PUSB_COMMON_DESCRIPTOR;
#pragma pack(pop)
#endif
//______________________________________________________________________________
class CCyIsoPktInfo { //包信息
public:
LONG Status; //包状态
LONG Length; //包长度
};
//______________________________________________________________________________
// {AE18AA60-7F6A-11d4-97DD-00010229B959}
static GUID CYUSBDRV_GUID = {0xae18aa60, 0x7f6a, 0x11d4, 0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59};
typedef enum {TGT_DEVICE, TGT_INTFC, TGT_ENDPT, TGT_OTHER } CTL_XFER_TGT_TYPE;
typedef enum {REQ_STD, REQ_CLASS, REQ_VENDOR } CTL_XFER_REQ_TYPE;
typedef enum {DIR_TO_DEVICE, DIR_FROM_DEVICE } CTL_XFER_DIR_TYPE;
typedef enum {XMODE_BUFFERED, XMODE_DIRECT } XFER_MODE_TYPE;
const int MAX_ENDPTS = 16;
const int MAX_INTERFACES = 8;
const int USB_STRING_MAXLEN = 256;
////////////////////////////////////////////////////////////////////////////////
//
// The CCyEndPoint ABSTRACT Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyUSBEndPoint
{
protected:
bool WaitForIO(OVERLAPPED *ovLapStatus);
virtual PUCHAR BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); //直接传输模式
virtual PUCHAR BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); //缓冲传输模式
public:
CCyUSBEndPoint(void);
CCyUSBEndPoint(CCyUSBEndPoint& ept);
CCyUSBEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor);
HANDLE hDevice;
// The fields of an EndPoint Descriptor
UCHAR DscLen;
UCHAR DscType;
UCHAR Address;
UCHAR Attributes;
USHORT MaxPktSize;
USHORT PktsPerFrame;
UCHAR Interval;
// Other fields
ULONG TimeOut;
ULONG UsbdStatus;
ULONG NtStatus;
DWORD bytesWritten;
DWORD LastError;
bool bIn;
XFER_MODE_TYPE XferMode;
bool XferData(PUCHAR buf, LONG &len, CCyIsoPktInfo* pktInfos = NULL);
bool XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos, bool pktMode);
virtual PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov) = 0;
virtual bool FinishDataXfer(PUCHAR buf, LONG &len, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos = NULL);
bool WaitForXfer(OVERLAPPED *ov, ULONG tOut);
ULONG GetXferSize(void);
void SetXferSize(ULONG xfer);
bool Reset(void);
bool Abort(void);
private:
};
////////////////////////////////////////////////////////////////////////////////
//
// The Control Endpoint Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyControlEndPoint : public CCyUSBEndPoint
{
private:
public:
CCyControlEndPoint(void);
CCyControlEndPoint(CCyControlEndPoint& ept);
CCyControlEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor);
CTL_XFER_TGT_TYPE Target;
CTL_XFER_REQ_TYPE ReqType;
CTL_XFER_DIR_TYPE Direction;
UCHAR ReqCode;
WORD Value;
WORD Index;
bool Read(PUCHAR buf, LONG &len);
bool Write(PUCHAR buf, LONG &len);
PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov);
};
////////////////////////////////////////////////////////////////////////////////
//
// The Isoc Endpoint Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyIsocEndPoint : public CCyUSBEndPoint
{
protected:
virtual PUCHAR BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov);
virtual PUCHAR BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov);
public:
CCyIsocEndPoint(void);
CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor);
PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov);
CCyIsoPktInfo* CreatePktInfos(LONG bufLen, int &packets);
};
////////////////////////////////////////////////////////////////////////////////
//
// The Bulk Endpoint Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyBulkEndPoint : public CCyUSBEndPoint
{
public:
CCyBulkEndPoint(void);
CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor);
PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov);
};
////////////////////////////////////////////////////////////////////////////////
//
// The Interrupt Endpoint Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyInterruptEndPoint : public CCyUSBEndPoint
{
public:
CCyInterruptEndPoint(void);
CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor);
PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov);
};
////////////////////////////////////////////////////////////////////////////////
//
// The Interface Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyUSBInterface
{
private:
protected:
public:
CCyUSBEndPoint *EndPoints[MAX_ENDPTS]; // Holds pointers to all the interface's endpoints, plus a pointer to the Control endpoint zero
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints; // Not counting the control endpoint
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
UCHAR bAltSettings;
USHORT wTotalLength; // Needed in case Intfc has additional (non-endpt) descriptors
CCyUSBInterface(HANDLE h, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor);
CCyUSBInterface(CCyUSBInterface& ifc); // Copy Constructor
~CCyUSBInterface(void);
};
////////////////////////////////////////////////////////////////////////////////
//
// The Config Class
//
////////////////////////////////////////////////////////////////////////////////
class CCyUSBConfig
{
private:
protected:
public:
CCyUSBInterface *Interfaces[MAX_INTERFACES];
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
UCHAR AltInterfaces;
CCyUSBConfig(void);
CCyUSBConfig(CCyUSBConfig& cfg); // Copy Constructor
CCyUSBConfig(HANDLE h, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr);
~CCyUSBConfig(void);
};
////////////////////////////////////////////////////////////////////////////////
//
// The USB Device Class - This is the main class that contains members of all the
// other classes.
//
// To use the library, create an instance of this Class and call it's Open method
//
////////////////////////////////////////////////////////////////////////////////
class CCyUSBDevice
{
// The public members are accessible (i.e. corruptible) by the user of the library
// Algorithms of the class don't rely on any public members. Instead, they use the
// private members of the class for their calculations.
public:
CCyUSBDevice(HANDLE hnd = NULL, GUID guid = CYUSBDRV_GUID, BOOL bOpen = true);
~CCyUSBDevice(void);
CCyUSBEndPoint **EndPoints; // Shortcut to USBCfgs[CfgNum]->Interfaces[IntfcIndex]->Endpoints
CCyUSBEndPoint *EndPointOf(UCHAR addr);
CCyControlEndPoint *ControlEndPt;
CCyIsocEndPoint *IsocInEndPt;
CCyIsocEndPoint *IsocOutEndPt;
CCyBulkEndPoint *BulkInEndPt;
CCyBulkEndPoint *BulkOutEndPt;
CCyInterruptEndPoint *InterruptInEndPt;
CCyInterruptEndPoint *InterruptOutEndPt;
USHORT StrLangID;
ULONG UsbdStatus;
ULONG NtStatus;
ULONG DriverVersion;
ULONG USBDIVersion;
char DeviceName[USB_STRING_MAXLEN];
char FriendlyName[USB_STRING_MAXLEN];
wchar_t Manufacturer[USB_STRING_MAXLEN];
wchar_t Product[USB_STRING_MAXLEN];
wchar_t SerialNumber[USB_STRING_MAXLEN];
CHAR DevPath[USB_STRING_MAXLEN];
USHORT BcdUSB;
USHORT VendorID;
USHORT ProductID;
UCHAR USBAddress;
UCHAR DevClass;
UCHAR DevSubClass;
UCHAR DevProtocol;
UCHAR MaxPacketSize;
USHORT BcdDevice;
UCHAR ConfigValue;
UCHAR ConfigAttrib;
UCHAR MaxPower;
UCHAR IntfcClass;
UCHAR IntfcSubClass;
UCHAR IntfcProtocol;
bool bHighSpeed;
DWORD BytesXfered;
UCHAR DeviceCount(void);
UCHAR ConfigCount(void);
UCHAR IntfcCount(void);
UCHAR AltIntfcCount(void);
UCHAR EndPointCount(void);
UCHAR Config(void) { return CfgNum; } // Normally 0
void SetConfig(UCHAR cfg);
UCHAR Interface(void) { return IntfcNum; } // Usually 0
// No SetInterface method since only 1 intfc per device (per Windows)
UCHAR AltIntfc(void);
bool SetAltIntfc(UCHAR alt);
GUID DriverGUID(void) { return DrvGuid; }
HANDLE DeviceHandle(void) { return hDevice; }
void UsbdStatusString(ULONG stat, PCHAR s);
bool CreateHandle(UCHAR dev);
void DestroyHandle();
bool Open(UCHAR dev);
void Close(void);
bool Reset(void);
bool ReConnect(void);
bool Suspend(void);
bool Resume(void);
bool IsOpen(void) { return (hDevice != INVALID_HANDLE_VALUE); }
UCHAR PowerState(void);
void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR descr);
void GetConfigDescriptor(PUSB_CONFIGURATION_DESCRIPTOR descr);
void GetIntfcDescriptor(PUSB_INTERFACE_DESCRIPTOR descr);
CCyUSBConfig GetUSBConfig(int index);
private:
USB_DEVICE_DESCRIPTOR USBDeviceDescriptor;
PUSB_CONFIGURATION_DESCRIPTOR USBConfigDescriptors[2];
CCyUSBConfig *USBCfgs[2];
HANDLE hWnd;
HANDLE hDevice;
HANDLE hDevNotification;
HANDLE hHndNotification;
GUID DrvGuid;
UCHAR Devices;
UCHAR Interfaces;
UCHAR AltInterfaces;
UCHAR Configs;
UCHAR DevNum;
UCHAR CfgNum;
UCHAR IntfcNum; // The current selected interface's bInterfaceNumber
UCHAR IntfcIndex; // The entry in the Config's interfaces table matching to IntfcNum and AltSetting
void GetDevDescriptor(void);
void GetCfgDescriptor(int descIndex);
void GetString(wchar_t *s, UCHAR sIndex);
void SetStringDescrLanguage(void);
void SetAltIntfcParams(UCHAR alt);
bool IoControl(ULONG cmd, PUCHAR buf, ULONG len);
void SetEndPointPtrs(void);
void GetDeviceName(void);
void GetFriendlyName(void);
void GetDriverVer(void);
void GetUSBDIVer(void);
void GetSpeed(void);
void GetUSBAddress(void);
//void CloseEndPtHandles(void);
bool RegisterForPnpEvents(HANDLE h);
};
//---------------------------------------------------------------------------
#endif

BIN
3rdparty/cyusb/lib/windows/x64/CyAPI.lib vendored Normal file

Binary file not shown.

BIN
3rdparty/cyusb/lib/windows/x86/CyAPI.lib vendored Normal file

Binary file not shown.

128
huagao/Device/CyUsbEx.cpp Normal file
View File

@ -0,0 +1,128 @@
#include "CyUsbEx.h"
#include "CyAPI.h"
CyUsbEx::CyUsbEx(int index)
{
m_index = index;
m_timeout = 100;
}
bool CyUsbEx::open()
{
if (is_open())
return true;
m_usb.reset(new CCyUSBDevice());
m_usb->Open(m_index);
m_usb->Reset();
if (m_usb->IsOpen())
{
if (m_usb->BulkOutEndPt)
m_usb->BulkOutEndPt->TimeOut = m_timeout;
if (m_usb->BulkInEndPt)
m_usb->BulkInEndPt->TimeOut = m_timeout;
if (m_usb->InterruptInEndPt)
m_usb->InterruptInEndPt->TimeOut = 400;
}
return is_open();
}
bool CyUsbEx::close()
{
if (is_open())
{
m_usb->Close();
m_usb.reset();
}
return true;
}
bool CyUsbEx::is_open()
{
if (m_usb.get() != NULL)
return m_usb->IsOpen();
return false;
}
bool CyUsbEx::is_connected()
{
return is_open();
}
void CyUsbEx::set_timeout(int timeout)
{
m_timeout = timeout;
}
int CyUsbEx::read_bulk(void* data, int len)
{
LONG llen = len;
m_usb->BulkInEndPt->XferData((UCHAR*)data, llen);
return llen;
}
int CyUsbEx::write_bulk(void* data, int len)
{
LONG llen = len;
m_usb->BulkOutEndPt->XferData((UCHAR*)data, llen);
return llen;
}
int CyUsbEx::read_int(void* data, int len)
{
LONG llen = len;
m_usb->InterruptInEndPt->XferData((UCHAR*)data, llen);
return llen;
}
int CyUsbEx::control_msg(int rtype, int req, int value, int index, int len, void* data)
{
if (!m_usb.get() || !m_usb->ControlEndPt)
return -1;
m_usb->ControlEndPt->Index = index;
m_usb->ControlEndPt->Value = value;
m_usb->ControlEndPt->ReqType = (CTL_XFER_REQ_TYPE)((rtype >> 5) & 0x03);
m_usb->ControlEndPt->Direction = (CTL_XFER_DIR_TYPE)(rtype >> 7);//
m_usb->ControlEndPt->Target = (CTL_XFER_TGT_TYPE)(rtype & 0x3);
m_usb->ControlEndPt->ReqCode = req;
LONG llen = len;
m_usb->ControlEndPt->XferData((UCHAR*)data, llen);
return llen;
}
void CyUsbEx::set_usbhotplug_callback(usbhotplug_callback callback, void* userdata)
{
return;
}
std::list<std::shared_ptr<IUsb>> CyUsbList::find_all()
{
std::list<std::shared_ptr<IUsb>> usblists;
CCyUSBDevice usbDevice;
for (int i = 0; i < usbDevice.DeviceCount(); i++)
usblists.push_back(std::shared_ptr<IUsb>(new CyUsbEx(i)));
return usblists;
}
std::list<std::shared_ptr<IUsb>> CyUsbList::find_vid_pid(int vid, int pid)
{
std::list<std::shared_ptr<IUsb>> usblists;
CCyUSBDevice usbDevice;
for (int i = 0; i < usbDevice.DeviceCount(); i++) {
usbDevice.Open(i);
if (usbDevice.IsOpen() && (usbDevice.VendorID == vid) && (usbDevice.ProductID == pid)) {
usblists.push_back(std::shared_ptr<IUsb>(new CyUsbEx(i)));
usbDevice.Close();
}
}
return usblists;
}

37
huagao/Device/CyUsbEx.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include "IUsb.h"
#include <memory>
#include <list>
class CCyUSBDevice;
class CyUsbList {
public:
static std::list<std::shared_ptr<IUsb>> find_all();
static std::list<std::shared_ptr<IUsb>> find_vid_pid(int vid, int pid);
};
class CyUsbEx :
public IUsb
{
public:
CyUsbEx(int index);
// ͨ¹ý IUsb ¼Ì³Ð
virtual bool open() override;
virtual bool close() override;
virtual bool is_open() override;
virtual bool is_connected() override;
virtual void set_timeout(int timeout) override;
virtual int read_bulk(void* data, int len) override;
virtual int write_bulk(void* data, int len) override;
virtual int read_int(void* data, int len) override;
virtual int control_msg(int rtype, int req, int value, int index, int len, void* data) override;
virtual void set_usbhotplug_callback(usbhotplug_callback callback = NULL, void* userdata = NULL) override;
private:
std::shared_ptr<CCyUSBDevice> m_usb;
int m_index;
int m_timeout;
};

View File

@ -72,15 +72,19 @@ typedef enum tagUsbSupported {
// PC繁忙或出错
PC_SCAN_BUSY_or_ERROR = 73,
//摺角
DOG_EAR=74,
DOG_EAR = 74,
//幅面检测错误
SIZE_ERROR=75,
SIZE_ERROR = 75,
//取图超时
AQUIRE_IMAGE_TIMEOUT=76,
AQUIRE_IMAGE_TIMEOUT = 76,
//获取图片与扫描张数不匹配
LOSE_IMAGE=77,
LOSE_IMAGE = 77,
//usb读取数据错误
USB_BULK_ERROR=78,
USB_BULK_ERROR = 78,
//v4l2取图失败
V4L2_AQULRE_ERROR = 79,
//扫描仪内部图片丢失
V4L2_IMAGE_EMPTY = 80,
//USB 未连接
USB_DISCONNECTED = 200,
//用户点击停止
@ -109,7 +113,9 @@ static map<UsbSupported, string> msgs = {
{UsbSupported::SIZE_ERROR,"幅面检测异常!"},
{UsbSupported::AQUIRE_IMAGE_TIMEOUT,"取图超时!"},
{UsbSupported::LOSE_IMAGE,"上传图片与扫描张数不匹配!"},
{UsbSupported::USB_BULK_ERROR,"USB数据读取错误"}
{UsbSupported::USB_BULK_ERROR,"USB数据读取错误"},
{UsbSupported::V4L2_AQULRE_ERROR,"扫描仪取图失败!"},
{UsbSupported::V4L2_IMAGE_EMPTY,"扫描仪图像处理异常!"},
};
enum tagEventIndex

View File

@ -0,0 +1,652 @@
#include "GScanO1003399.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "scn_config.h"
#include "PaperSize.h"
#include "GScan.h"
static std::mutex mx_ctrl;
static int scanner_read_reg(std::shared_ptr<IUsb>& usb, int addr)
{
int val = 0;
std::lock_guard<std::mutex> lck(mx_ctrl);
usb->control_msg(0xc0, USB_REQ_GET_DEV_REGS, addr, 0, 4, &val);
return val;
}
static void scanner_write_reg(std::shared_ptr<IUsb>& usb, int addr, int val)
{
std::lock_guard<std::mutex> lck(mx_ctrl);
usb->control_msg(0x40, USB_REQ_SET_DEV_REGS, addr, 0, 4, &val);
}
static void scanner_cmd(std::shared_ptr<IUsb>& usb, int cmd)
{
scanner_write_reg(usb, 0, cmd);
}
GScanO1003399::GScanO1003399():
m_imgthread(1)
{
im_data.reset(new std::vector<char>());
open(0, 0);
devState = DEV_STOP;
}
GScanO1003399::~GScanO1003399()
{
if (m_usbthread.get() && m_usbthread->joinable())
{
b_usbthread = false;
m_usbthread->join();
m_usbthread.reset();
}
if (fu_rx.valid())
fu_rx.wait();
}
void GScanO1003399::open(int vid, int pid)
{
//auto lsusb=CyUsbList::find_vid_pid(vid, pid);
//if (!lsusb.empty())
//{
// m_usb = *lsusb.begin();
// m_usb->open();
//}
if (m_usb.get()&&m_usb->is_connected())
return;
auto lsusb = CyUsbList::find_all();
if (!lsusb.empty())
{
m_usb = *lsusb.begin();
m_usb->open();
}
}
void GScanO1003399::regist_deviceevent_callback(deviceevent_callback callback, void* usrdata)
{
}
void GScanO1003399::DogEar_callback(std::function<void(int)> fun)
{
}
static int aquirenum = 0;
static int getimgnum = 0;
int GScanO1003399::aquire_bmpdata(std::vector<unsigned char>& bmpdata)
{
StopWatch sw;
while (true)
{
if ((m_imagedata.Size() < 1)&&(!is_runing()))
{
DoEvents();
this_thread::sleep_for(chrono::milliseconds(1));
if (!is_runing())
{
if (devState == DEV_WRONG)
return get_ErrorCode();
return -1;
}
if (sw.elapsed_s() > 30.0)
{
devState = DEV_STOP;
if (fu_rx.valid())
fu_rx.wait();
Stop_scan();
ResetScanner();
return AQUIRE_IMAGE_TIMEOUT;
}
}
else
{
if ((m_imagedata.Size() > 0))
{
FileTools::writelog(log_INFO, "aquire_bmpdata num =" + to_string(aquirenum++));
bmpdata = *(m_imagedata.Take());
UpdateScanInfo(get_imgnReaded(), countNTransfered());
return 0;
}
DoEvents();
this_thread::sleep_for(chrono::milliseconds(2));
}
}
}
BOOL GScanO1003399::IsConnected()
{
return m_usb.get()&&m_usb->is_connected();
}
std::string GScanO1003399::GetFWVersion()
{
std::string fw;
if (m_usb.get() && m_usb->is_connected())
{
scanner_write_reg(m_usb, SR_GET_FWVERSION, 0);
fw.resize(10);
read_data(&fw[0], fw.length(), 200);
}
return fw;
}
std::string GScanO1003399::GetSerialNum()
{
std::string sn;
if (m_usb.get() && m_usb->is_connected())
{
scanner_write_reg(m_usb, SR_GET_SERIALNUM, 0);
sn.resize(14);
read_data(&sn[0], sn.length(), 200);
}
return sn;
}
std::uint32_t GScanO1003399::GetMotorFPGA()
{
return std::uint32_t();
}
std::uint32_t GScanO1003399::GetScanFPGA()
{
return std::uint32_t();
}
bool GScanO1003399::is_scan()
{
//return devState==DEV_ISRUNNING;
return is_runing() || (m_imagedata.Size() > 0);
}
BOOL GScanO1003399::Get_Scanner_PaperOn()
{
return scanner_read_reg(m_usb, SR_PAPER_READY);
}
int GScanO1003399::Get_Roller_num()
{
return 0;
}
void GScanO1003399::config_params(GScanCap& param)
{
m_param = param;
HGScanConfig cfg;
cfg = { 0 };
#ifdef G200
PaperStatus ps = { param.papertype,param.paperAlign };
cfg.g200params.paper = SupPaperTyps.count(ps)>0 ? SupPaperTyps[ps] : 0;
if (param.filter != 3 || param.enhance_color != 0 || param.hsvcorrect)
cfg.g200params.color = 1;//color
else
{
cfg.g200params.color = SupPixelTypes.count(param.pixtype) > 0 ? SupPixelTypes[param.pixtype] : 2;
}
cfg.g200params.dpi = SupResolutions.count(param.resolution_native)>0 ? SupResolutions[param.resolution_native] : 1;
cfg.g200params.double_feed_enbale = (unsigned int)param.hardwarecaps.en_doublefeed;
cfg.g200params.stable_enbale = (unsigned int)param.hardwarecaps.en_stapledetect;
cfg.g200params.screw_detect_enable = (unsigned int)param.hardwarecaps.en_skrewdetect;
cfg.g200params.screw_detect_level = (unsigned int)cfg.g200params.screw_detect_enable ? secrewMaps[param.hardwarecaps.skrewdetectlevel] : 0;
cfg.g200params.enable_sizecheck = param.en_sizecheck == 1 ? 1 : 0;
cfg.g200params.unused_one = cfg.g200params.sizeerror_errorratio = 0;
param.resolution_dst >= 240.0f ? 1 : 0;
#else
cfg.g400params.doubleFeeded = param.hardwarecaps.en_doublefeed == 0 ? 0 : 1;
cfg.g400params.dpi = G400_DPI::G400_D200;//gcap.resolution_dst <= 200.0f ? G400_DPI::G400_D200 : (gcap.resolution_dst <= 300.0f ? G400_DPI::G400_D300 : G400_DPI::G400_D600);
cfg.g400params.enableLed = 1;
if (param.filter != 3 || param.enhance_color)
cfg.g400params.isColor = 1;
else
cfg.g400params.isColor = SupPixelTypes[param.pixtype];
cfg.g400params.enableStable = 0;//gcap.hardwarecaps.en_stapledetect==0?0:1;
cfg.g400params.isCorrect = 1;//1 »úÆ÷УÕý
PaperStatus ps = { param.papertype,param.paperAlign };
cfg.g400params.pageSize = SupPaperTyps[ps];
CSize size;
#ifdef G300
size = Device::PaperSize().GetPaperSize(TwSS::A4, 200.0f, gcap.paperAlign);//G300 ×î´óÖ§³ÖA4·ùÃæ
#else
size = Device::PaperSize().GetPaperSize(param.papertype, 200.0f, param.paperAlign);
#endif// G300
cfg.g400params.dstHeight = (int)((size.cy + 200) / 100);
cfg.g400params.reversed1 = cfg.g400params.reversed2 = 0;
#endif // G200
config_scanparam(cfg);
config_imgprocparam({0});
GScanCap_3399 param39{ 0 };
param39.AutoCrop_threshold = param.AutoCrop_threshold;
param39.autodescrew = param.autodescrew;
param39.automaticcolor = param.automaticcolor;
param39.automaticcolortype = param39.automaticcolortype;
param39.brightness = param.brightness;
param39.contrast = param.contrast;
param39.detachnoise = param.detachnoise;
param39.discardblank_percent = param.discardblank_percent;
param39.en_fold = param.en_fold;
param39.en_sizecheck = param.en_sizecheck;
param39.enhance_color = param.enhance_color;
param39.fillbackground = param.fillbackground;
param39.fillhole = param.fillhole;
param39.filter = param.filter;
param39.gamma = param.gamma;
param39.hardwarecaps = param.hardwarecaps;
param39.hsvcorrect = param.hsvcorrect;
param39.imageRotateDegree = param.imageRotateDegree;
param39.indent = param.indent;
param39.is_autocontrast = param.is_autocontrast;
param39.is_autocrop = param.is_autocrop;
param39.is_autodiscradblank_normal = param.is_autodiscradblank_normal;
param39.is_autodiscradblank_vince = param.is_autodiscradblank_vince;
param39.is_autotext = param.is_autotext;
param39.is_backrotate180 = param.is_backrotate180;
param39.is_convex = param.is_convex;
param39.is_dogeardetection = param.is_dogeardetection;
param39.is_duplex = param.is_duplex;
param39.is_switchfrontback = param.is_switchfrontback;
param39.multi_output_red = param.multi_output_red;
param39.noise = param.noise;
param39.paperAlign = param.paperAlign;
param39.papertype = param.papertype;
param39.pixtype = param.pixtype;
param39.resolution_dst = param.resolution_dst;
param39.resolution_native = param.resolution_native;
param39.scannum = param.scannum;
param39.sharpen = param.sharpen;
param39.threshold = param.threshold;
m_usb->write_bulk(&param39, sizeof(param39));
}
void GScanO1003399::Scanner_StartScan(UINT16 count)
{
scanflag = true;
Set_ErrorCode(0);
getimgnum = 0;
aquirenum = 0;
reset();
devState = DEV_ISRUNNING;
if (scan_mode())
{
devState = DEV_WRONG;
Set_ErrorCode(COUNT_MODE);
return;
}
//if (!Get_Scanner_PaperOn())
//{
// devState = DEV_WRONG;
// Set_ErrorCode(NO_FEED);
// return;
//}
start();
if (!m_usbthread.get()) {
b_usbthread = true;
m_usbthread.reset(new thread(&GScanO1003399::usb_run, this));
}
}
void GScanO1003399::Stop_scan()
{
if (devState != DEV_ISRUNNING)
return;
stop();
scanflag = false;
if (fu_rx.valid())
fu_rx.wait();
devState == DEV_ISRUNNING ? devState = DEV_STOP : devState = DEV_WRONG;
}
int GScanO1003399::notifyscan()
{
return 0;
}
void GScanO1003399::ResetScanner()
{
}
bool GScanO1003399::Get_IsImageQueueEmpty()
{
return m_imagedata.Size() < 1;
}
void GScanO1003399::reset()
{
devState = DEV_STOP;
m_imagedata.Clear();
}
void GScanO1003399::clear_hwerror()
{
}
UINT32 GScanO1003399::get_ErrorCode()
{
return Error_Code;
}
void GScanO1003399::Set_ErrorCode(UINT32 value)
{
Error_Code = value;
}
int GScanO1003399::get_scanned_num()
{
return 0;
}
void GScanO1003399::set_sleep_time(int mode)
{
}
bool GScanO1003399::set_scannercode(std::string str)
{
return false;
}
std::string GScanO1003399::get_scannercode()
{
return std::string();
}
void GScanO1003399::usb_run()
{
unsigned char buff[64];
while (b_usbthread)
{
if (!m_usb.get() || !m_usb->is_connected())
{
this_thread::sleep_for(chrono::milliseconds(20));
continue;
}
memset(buff, 0, sizeof(buff));
auto length = m_usb->read_int(buff, sizeof(buff));
if (((length) == sizeof(buff)) || im_dev_count())
{
HGEIntInfo info = *(HGEIntInfo*)&buff;
switch (info.From)
{
case IMG:
if (is_runing())
im_rx();
break;
case MtBoard:
FileTools::writelog(log_ERROR, "Got MotorBoard error code = " + to_string(info.Code));
break;
case FPGA:
FileTools::writelog(log_ERROR, "Got FPGA Error code = " + to_string(info.Code));
break;
case V4L2:
FileTools::writelog(log_ERROR, "Got V4L2 Error code = " + to_string(info.Code));
break;
default:
FileTools::writelog(log_ERROR, "Got Unkown error code ! From =" + to_string(info.From) + " Code = " + to_string(info.Code));
break;
}
if ((codeconvter(info) != 0))
{
scanflag = false;
devState = codeconvter(info) == -1 ? DEV_STOP : DEV_WRONG;
}
if (codeconvter(info) > 0)
{
Set_ErrorCode(codeconvter(info));
stop();
}
this_thread::sleep_for(chrono::microseconds(10));
}
}
}
void GScanO1003399::start()
{
scanner_cmd(m_usb, SC_START);
}
void GScanO1003399::stop()
{
scanner_cmd(m_usb, SC_STOP);
}
bool GScanO1003399::is_runing()
{
return scanner_read_reg(m_usb, SR_STATUS) & 0x01;
}
int GScanO1003399::scan_mode()
{
return scanner_read_reg(m_usb, SR_OS) & 0x01;
}
int GScanO1003399::count()
{
return scanner_read_reg(m_usb, SR_SCAN_COUNT);
}
void GScanO1003399::abort_dev_tx()
{
scanner_write_reg(m_usb, SR_IM_ABORT, 1); //!< to-list
}
void GScanO1003399::config_scanparam(const HG_ScanConfig& cfg)
{
scanner_write_reg(m_usb, SR_CONFIG_SCAN_PARAM, cfg.value);
}
void GScanO1003399::config_imgprocparam(const HGImgProcParms& imgprocparams)
{
scanner_write_reg(m_usb, SR_CONFIF_IMGPROCPARAM,imgprocparams.value);
}
bool GScanO1003399::is_rx()
{
return false;
}
bool GScanO1003399::rx_cmd()
{
scanner_write_reg(m_usb, 8, 1);
return true;
}
bool GScanO1003399::is_dev_tx()
{
return scanner_read_reg(m_usb, SR_IM_TXING);
}
void GScanO1003399::im_rx()
{
if (!is_rx() && !is_dev_tx())
{
fu_rx = m_imgthread.enqueue([this] {
do
{
/* code */
auto &buffi = im_data;
int count = front_datasize();
buffi->resize(count);
rx_cmd();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
count = read_data(buffi->data(), count, count / (0.01 * 1024 * 1024));
pop_dev_im();
vector<cv::Mat> mats;
auto& buffs = G400Decode(buffi).getImageBuffs();
UpdateScanInfo(countNReaded(), get_imgTransfered());
imgproce(buffs);
} while (im_dev_count());
});
}
}
int GScanO1003399::read_data(void* data, int length, int timeout)
{
int readed = 0;
int reading = 0;
const int buffer_size = 2 * 1024 * 1024;
StopWatch sw;
while (readed < length && sw.elapsed_ms() < timeout) {
reading = std::max(0, std::min(length - readed, buffer_size));
reading = m_usb->read_bulk((unsigned char*)data + readed, reading);
if (reading > 0) {
readed += reading;
}
}
return readed;
}
void GScanO1003399::pop_dev_im()
{
scanner_write_reg(m_usb, SR_IM_POP, 1); //!< to-list
}
int GScanO1003399::front_datasize()
{
return scanner_read_reg(m_usb, SR_IM_FRONT_SIZE);
}
int GScanO1003399::im_dev_count()
{
return scanner_read_reg(m_usb, SR_IM_COUNT); //!< to-list ;
}
void GScanO1003399::imgproce(std::vector<std::shared_ptr<std::vector<char>>>& buffs)
{
vector<cv::Mat> mats;
for (auto& buf : buffs) {
cv::ImreadModes rmc;
//int rm;
if (m_param.filter != 3 || m_param.enhance_color || m_param.hsvcorrect) {
rmc = cv::IMREAD_COLOR;
//rm = 1;
}
else {
rmc = m_param.pixtype == 2 ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE;
//rm = scanParam.pixtype == 2 ? 1 : 6;
}
try
{
cv::Mat mat = cv::imdecode(*buf, rmc);
if (mat.empty()) {
FileTools::writelog(log_ERROR, "decode image data error");
continue;
}
buf.reset();
mats.push_back(mat);
FileTools::writelog(log_INFO, "push_back image num= " + to_string(getimgnum++));
}
catch (const std::exception& e)
{
//writelog(e.what());
FileTools::writelog(log_ERROR, e.what());
}
}
buffs.clear();
if (m_param.automaticcolor)
{
CImageApplyColorRecognition(m_param.automaticcolortype == 1 ? CImageApplyColorRecognition::ColorRecognitionMode::Color_Gray : CImageApplyColorRecognition::ColorRecognitionMode::Color_Mono).apply(mats,m_param.is_duplex);
}
for (int i = 0; i < mats.size(); i++) {
//if (!m_param.is_duplex && i == 1) {
// mats[i].release();
// break;
//}
if (!mats[i].empty()) {
IMat2Bmp idata;
if (m_param.pixtype == 1 && m_param.hsvcorrect)
if (mats[i].channels() == 3)
cvtColor(mats[i], mats[i], cv::COLOR_BGR2GRAY);
idata = (m_param.pixtype == 0 || (((m_param.automaticcolortype == 0) && (m_param.automaticcolor == true)) && (mats[i].channels() == 1))) ? (IMat2Bmp)Mat2BmpBw(mats[i], m_param.resolution_dst) : Mat2Bmp(mats[i], m_param.resolution_dst);
//if (!m_param.multi_output_red)
// mats[i].release();
m_imagedata.Put(idata.getBmpDataBuffer());
}
}
if (m_param.multi_output_red) {
for (int i = 0; i < mats.size(); i++) {
if (!mats[i].empty()) {
ImageMultiOutput m_mlt;
cv::Mat ret = m_mlt.GetMultiFilterMat(mats[i], 2);
mats[i].release();
if (!ret.empty()) {
if (!m_param.is_duplex && i == 1) {
ret.release();
break;
}
Mat2Bmp mb(ret, m_param.resolution_dst);
m_imagedata.Put(mb.getBmpDataBuffer());
ret.release();
}
}
}
}
mats.clear();
}
int GScanO1003399::codeconvter(HGEIntInfo code)
{
if (code.From == HGType::FPGA)
{
switch (code.Code)
{
default:
break;
}
}
if (code.From == HGType::MtBoard)
{
switch (code.Code)
{
case 0x00002:
return NO_FEED;
case 0x00004:
return OPEN_COVER;
case 0x00008:
return FEED_IN_ERROR;
case 0x00010:
return PAPER_JAM;
case 0x00020:
return DETECT_DOUBLE_FEED;
case 0x00040:
return DETECT_STAPLE;
case 0x00080:
return PAPER_SKEW;
case 0x10000:
return AQUIRE_IMAGE_TIMEOUT;
case 0x20000:
return SIZE_ERROR;
default:
break;
}
}
if (code.From == HGType::V4L2)
{
switch (code.Code)
{
case 0:
return V4L2_AQULRE_ERROR;
case 1:
return V4L2_IMAGE_EMPTY;
default:
break;
}
}
return 0;
}

View File

@ -0,0 +1,85 @@
#pragma once
#include "stdafx.h"
#include "IGDevice.h"
#include "GScan.h"
#include "CyUsbEx.h"
#include "IConfig.h"
#include "G400ScanConfig.h"
#include <memory>
#include <future>
#include <functional>
#include "ThreadPool.h"
#include "StopWatch.h"
#include "ImageMatQueue.h"
#include "opencv2/opencv.hpp"
class GScanO1003399 :public IScanner
{
public:
GScanO1003399();
virtual ~GScanO1003399();
virtual void open(int vid, int pid) override;
virtual void regist_deviceevent_callback(deviceevent_callback callback, void* usrdata = 0) override;
virtual void DogEar_callback(std::function<void(int)> fun) override;
virtual int aquire_bmpdata(std::vector<unsigned char>& bmpdata) override;
virtual BOOL IsConnected() override;
virtual std::string GetFWVersion() override;
virtual std::string GetSerialNum() override;
virtual std::uint32_t GetMotorFPGA() override;
virtual std::uint32_t GetScanFPGA() override;
virtual bool is_scan() override;
virtual BOOL Get_Scanner_PaperOn() override;
virtual int Get_Roller_num() override;
virtual void config_params(GScanCap& param) override;
virtual void Scanner_StartScan(UINT16 count) override;
virtual void Stop_scan() override;
virtual int notifyscan() override;
virtual void ResetScanner() override;
virtual bool Get_IsImageQueueEmpty() override;
virtual void reset() override;
virtual void clear_hwerror() override;
virtual UINT32 get_ErrorCode() override;
virtual void Set_ErrorCode(UINT32 value) override;
virtual int get_scanned_num() override;
virtual void set_sleep_time(int mode) override;
virtual bool set_scannercode(std::string str) override;
virtual std::string get_scannercode() override;
private:
void usb_run();
void im_rx();
void start();
void stop();
bool is_runing();
int scan_mode();
int count();
void abort_dev_tx();
void config_scanparam(const HG_ScanConfig& cfg);
void config_imgprocparam(const HGImgProcParms& imgprocparams);
bool is_rx();
bool rx_cmd();
bool is_dev_tx();
int read_data(void* data, int length, int timeout);
void pop_dev_im();
int front_datasize();
int im_dev_count();
void imgproce(std::vector<std::shared_ptr<std::vector<char>>>& buffs);
int codeconvter(HGEIntInfo code);
private:
volatile int devState;
volatile int Error_Code;
volatile bool scanflag;
GScanCap m_param;
std::shared_ptr<IUsb> m_usb;
volatile bool b_usbthread;
std::future<void> fu_rx;
ThreadPool m_imgthread;
std::shared_ptr<std::thread> m_usbthread;
std::shared_ptr<std::vector<char>> im_data;
BlockingQueue<std::shared_ptr<std::vector<unsigned char>>> m_imagedata;
};

View File

@ -6,6 +6,8 @@
#include "PaperSize.h"
#define FOR_LANXUM
using u32 = unsigned int;
static std::map<PaperStatus, unsigned int> SupPaperTyps = {
#ifdef G200
#ifdef FOR_LANXUM
@ -26,9 +28,15 @@ static std::map<PaperStatus, unsigned int> SupPaperTyps = {
{{TwSS::USLedger,PaperAlign::Rot0},12},
{{TwSS::USLegal,PaperAlign::Rot0},13},
{{TwSS::None,PaperAlign::Rot0},0},
#ifdef G1003399
{{TwSS::USStatement,PaperAlign::Rot0},17},
{{TwSS::MaxSize,PaperAlign::Rot0},19},
{{TwSS::Trigeminy,PaperAlign::Rot0},17}
#else
{{TwSS::USStatement,PaperAlign::Rot0},16},
{{TwSS::MaxSize,PaperAlign::Rot0},16},
{{TwSS::Trigeminy,PaperAlign::Rot0},16}
#endif
#else
{{TwSS::A3,PaperAlign::Rot0},0},
{{TwSS::A4,PaperAlign::Rot0},1},
@ -102,6 +110,108 @@ static std::map<BYTE, BYTE> secrewMaps = {
{4,3},
{5,4}
};
enum HGType
{
MtBoard = 1,
FPGA,
V4L2,
IMG,
STOPSCAN,
};
struct HGEIntInfo
{
HGType From;
unsigned int Code;
};
#define USB_REQ_GET_FPGA_REGS 0x40
#define USB_REQ_SET_FPGA_REGS 0x41
#define USB_REQ_GET_MOTOR_REGS 0x42
#define USB_REQ_SET_MOTOR_REGS 0x43
#define USB_REQ_GET_DEV_STATUS 0x60
#define USB_REQ_GET_DEV_CONFIGURATION 0x61
#define USB_REQ_SET_DEV_CONFIGURATION 0x62
#define USB_REQ_GET_DEV_REGS 0x63
#define USB_REQ_SET_DEV_REGS 0x64
enum Scanner_Reg_Defs
{
SR_CMD,
SR_STATUS,
SR_SCAN_COUNT,
SR_OS,
SR_SENSORS,
SR_MOTOR,
SR_IM_TYPE,
SR_IM_COUNT,
SR_IM_TX,
SR_IM_FRONT_SIZE,
SR_IM_CLEAR,
SR_IM_TXING,
SR_IM_POP,
SR_IM_ABORT,
SR_COUNT,
SR_CONFIG_SCAN_PARAM,
SR_GET_FWVERSION,
SR_SET_FWERSION,
SR_GET_SERIALNUM,
SR_SET_SERIALNUM,
SR_CONFIF_IMGPROCPARAM,
SR_PAPER_READY,
};
enum Scanner_Cmd_Defs
{
SC_START,
SC_STOP,
SC_CLEAR,
SC_COUNT
};
typedef union HG_ImgProcParms
{
unsigned int value;
struct
{
u32 papertype : 5;
u32 scanside : 3;
u32 res : 10;
u32 rotate : 2;
u32 autodescrew : 1;
u32 fillbackground : 1;
u32 filter : 4;
u32 enhancecolor : 2;
u32 fillhole : 1;
u32 reversed : 3;
}imgprocparams;
}HGImgProcParms;
///用于CIS 自动校正参数保存
typedef struct
{
u32 gainF[6];
u32 gainB[6];
u32 offsetsF[6];
u32 offsetsB[6];
u32 expF[3];
u32 expB[3];
u32 sp;
}HGCISConfig;
typedef struct
{
HGCISConfig colorCorrect;
HGCISConfig color;
HGCISConfig grayCorrect;
HGCISConfig gray;
}HGCorrectConfigs;
typedef union Config_Param {
unsigned int value;
struct {
@ -121,6 +231,39 @@ typedef union Config_Param {
};
} ConfigParam;
typedef union HG_ScanConfig
{
unsigned int value;
struct
{
unsigned int paper : 5;
unsigned int color : 1;
unsigned int dpi : 2;
unsigned int double_feed_enbale : 1;
unsigned int stable_enbale : 1;
unsigned int screw_detect_enable : 1;
unsigned int screw_detect_level : 3;//第十四位
unsigned int unused_one : 6;
unsigned int pc_correct : 1;
unsigned int enable_sizecheck : 1;
unsigned int enabledsp_cache : 1;
unsigned int sizeerror_errorratio : 9;
}g200params;
struct
{
unsigned int pageSize : 5;
unsigned int isColor : 1;
unsigned int dpi : 2;
unsigned int doubleFeeded : 1;
unsigned int enableStable : 1;
unsigned int enableLed : 1;
unsigned int reversed1 : 6;
unsigned int isCorrect : 1;
unsigned int dstHeight : 8;
unsigned int reversed2 : 6;
}g400params;
}HGScanConfig;
class IConfig
{
public:

View File

@ -6,7 +6,7 @@ class IUsb
public:
virtual ~IUsb() {}
virtual bool open() = 0;
virtual void set_usbhotplug_callback(usbhotplug_callback callback=NULL,void* userdata=NULL)=0;
virtual void set_usbhotplug_callback(usbhotplug_callback callback=0,void* userdata=0)=0;
virtual bool close() = 0;
virtual bool is_open() = 0;
virtual bool is_connected() = 0;

View File

@ -84,7 +84,8 @@ const std::string AUTOCROP_THRESHOLD = "AutoCrop_Threshold";
const std::string NOISE = "Noise";
const std::string LOWPOWERMODE = "ilowpowermode";
#pragma pack(push)
#pragma pack(4)
/******************
****
*******************/
@ -186,7 +187,7 @@ typedef struct Scan_Rect {
int y;
}ScanRect;
enum PaperAlign :byte {
enum PaperAlign :uint8_t {
Rot0 = 0,
Rot270 = 3,
AutoTextOrientation = 5
@ -212,12 +213,12 @@ typedef enum SharpenBlur :short {
struct GScanCap
{
byte papertype; /**< the current paper source ADF or Flatbed*/
uint8_t papertype; /**< the current paper source ADF or Flatbed*/
PaperAlign paperAlign;
byte en_sizecheck; /**< 尺寸检测*/
uint8_t en_sizecheck; /**< 尺寸检测*/
float imageRotateDegree;
byte is_duplex; /**< True to use duplex false for simplex, ignored if flatbed*/
byte en_fold; /**<对折*/
uint8_t is_duplex; /**< True to use duplex false for simplex, ignored if flatbed*/
uint8_t en_fold; /**<对折*/
int pixtype; /**< type of pixels to transfer image as */
int automaticcolor; /**<顔色自動識別*/
int automaticcolortype; /**<顔色自動識別后非彩色上傳類型*/
@ -228,34 +229,79 @@ struct GScanCap
float contrast; /**< Contrast */
float brightness; /**< Brightness */
float threshold; /**< Threshold */
byte is_autocontrast; /**< 自动对比度*/
byte is_autocrop; /**< 自动裁切*/
byte is_autodiscradblank_normal; /**< 自动丢弃空白页通用*/
uint8_t is_autocontrast; /**< 自动对比度*/
uint8_t is_autocrop; /**< 自动裁切*/
uint8_t is_autodiscradblank_normal; /**< 自动丢弃空白页通用*/
int discardblank_percent; /**<跳过空白页阀值*/
byte is_autodiscradblank_vince;/**自动丢弃空白页发票*/
byte is_switchfrontback; /**交换正反面*/
byte autodescrew; /**< 自动纠偏*/
byte multi_output_red; /*多流输出*/
byte hsvcorrect; /**<答题卡除红*/
byte filter; /**< 除色*/
byte sharpen;
byte enhance_color; /**< 颜色增强*/
byte fillbackground; /**< 填黑框*/
uint8_t is_autodiscradblank_vince;/**自动丢弃空白页发票*/
uint8_t is_switchfrontback; /**交换正反面*/
uint8_t autodescrew; /**< 自动纠偏*/
uint8_t multi_output_red; /*多流输出*/
uint8_t hsvcorrect; /**<答题卡除红*/
uint8_t filter; /**< 除色*/
uint8_t sharpen;
uint8_t enhance_color; /**< 颜色增强*/
uint8_t fillbackground; /**< 填黑框*/
bool is_convex; /**< 填黑框模式true为凸多边形填充false为凹多边形填充默认true*/
int noise; /**< 除噪像素能够消除noise宽度的背景竖条纹干扰默认40*/
int indent; /**< 轮廓缩进裁剪、纠偏或者黑底填充时对探索到的纸张轮廓进行缩进indent像素默认5*/
int AutoCrop_threshold; /**< 自动裁剪二值化阈值,取值范围(0, 255)默认40*/
unsigned short scannum; /**< 扫描张数*/
byte is_backrotate180; /**< 背面旋转180*/
byte is_dogeardetection; /**<折角检测*/
uint8_t is_backrotate180; /**< 背面旋转180*/
uint8_t is_dogeardetection; /**<折角检测*/
HardwareCaps hardwarecaps; /**< 硬件扫描参数*/
FillHole fillhole;
DetachNoise detachnoise; /**< 黑白降噪*/
byte is_autotext; /**< 自动文本方向识别*/
uint8_t is_autotext; /**< 自动文本方向识别*/
std::string Caption;
std::string SavePath;
};
struct GScanCap_3399
{
uint8_t papertype; /**< the current paper source ADF or Flatbed*/
PaperAlign paperAlign;
uint8_t en_sizecheck; /**< 尺寸检测*/
float imageRotateDegree;
uint8_t is_duplex; /**< True to use duplex false for simplex, ignored if flatbed*/
uint8_t en_fold; /**<对折*/
int pixtype; /**< type of pixels to transfer image as */
int automaticcolor; /**<顔色自動識別*/
int automaticcolortype; /**<顔色自動識別后非彩色上傳類型*/
//ScanRect scanrect;
float resolution_dst; /**< horizontal resolution */
float resolution_native;
float gamma; /**< Gamma */
float contrast; /**< Contrast */
float brightness; /**< Brightness */
float threshold; /**< Threshold */
uint8_t is_autocontrast; /**< 自动对比度*/
uint8_t is_autocrop; /**< 自动裁切*/
uint8_t is_autodiscradblank_normal; /**< 自动丢弃空白页通用*/
int discardblank_percent; /**<跳过空白页阀值*/
uint8_t is_autodiscradblank_vince;/**自动丢弃空白页发票*/
uint8_t is_switchfrontback; /**交换正反面*/
uint8_t autodescrew; /**< 自动纠偏*/
uint8_t multi_output_red; /*多流输出*/
uint8_t hsvcorrect; /**<答题卡除红*/
uint8_t filter; /**< 除色*/
uint8_t sharpen;
uint8_t enhance_color; /**< 颜色增强*/
uint8_t fillbackground; /**< 填黑框*/
bool is_convex; /**< 填黑框模式true为凸多边形填充false为凹多边形填充默认true*/
int noise; /**< 除噪像素能够消除noise宽度的背景竖条纹干扰默认40*/
int indent; /**< 轮廓缩进裁剪、纠偏或者黑底填充时对探索到的纸张轮廓进行缩进indent像素默认5*/
int AutoCrop_threshold; /**< 自动裁剪二值化阈值,取值范围(0, 255)默认40*/
unsigned short scannum; /**< 扫描张数*/
uint8_t is_backrotate180; /**< 背面旋转180*/
uint8_t is_dogeardetection; /**<折角检测*/
HardwareCaps hardwarecaps; /**< 硬件扫描参数*/
FillHole fillhole;
DetachNoise detachnoise; /**< 黑白降噪*/
uint8_t is_autotext; /**< 自动文本方向识别*/
};
typedef struct Paper_Status {
Paper_Status(unsigned int paper, unsigned int orentate) :Paper(paper), Orentate(orentate) {}
Paper_Status():Paper(0), Orentate(0){}
@ -296,6 +342,7 @@ enum G400_DPI {
G400_D600
};
#pragma pack(pop)
#define CAPTION_LEN 256
#define TWAIN_IMAGE_FILE_LIST_NAME TEXT(".dat")

View File

@ -0,0 +1,98 @@
#ifndef THREAD_POOL_H
#define THREAD_POOL_H
#include <vector>
#include <queue>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>
class ThreadPool {
public:
ThreadPool(size_t);
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>;
~ThreadPool();
private:
// need to keep track of threads so we can join them
std::vector< std::thread > workers;
// the task queue
std::queue< std::function<void()> > tasks;
// synchronization
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
// the constructor just launches some amount of workers
inline ThreadPool::ThreadPool(size_t threads)
: stop(false)
{
for(size_t i = 0;i<threads;++i)
workers.emplace_back(
[this]
{
for(;;)
{
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock,
[this]{ return this->stop || !this->tasks.empty(); });
if(this->stop && this->tasks.empty())
return;
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
}
);
}
// add new work item to the pool
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type>
{
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex);
// don't allow enqueueing after stopping the pool
if(stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task](){ (*task)(); });
}
condition.notify_one();
return res;
}
// the destructor joins all threads
inline ThreadPool::~ThreadPool()
{
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for(std::thread &worker: workers)
worker.join();
}
#endif

View File

@ -16,6 +16,7 @@
#include "Device/PublicFunc.h"
#include "Device/GScanO200.h"
#include "Device/GScanO400.h"
#include "Device/GScanO1003399.h"
#include "Device/filetools.h"
#include "Device/GScanVirtual.h"
#include <list>
@ -96,7 +97,7 @@ static constexpr const Identity srcIdent(
#endif
#ifdef G200
#ifdef ISG100
#if defined (ISG100) || defined (G1003399)
#ifdef LANXUM
"G62S Series",
#else // ISG100
@ -126,7 +127,7 @@ static constexpr const Identity srcIdent(
#endif
#ifdef G200
#ifdef ISG100
#if defined (ISG100) || defined (G1003399)
#ifdef MAKEHUAGAO
"HUAGOSCAN G100 TWAIN"
#elif defined LANXUM //!LANXUM
@ -345,19 +346,24 @@ void HuagaoDs::showmsg(std::string caption, std::string text, int retcode)
if (scanner.get()) {
int losemun = scanner->get_lose_image_num();
int num = 0;
bool is_duplex = m_scanparam->is_duplex;
#ifdef G1003399
is_duplex = false;
#endif // G1003399
if ((retcode == 64 || retcode == 8 || retcode == 16) && losemun > 0)//64 ->SStop
losemun--;
if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince))
{
if (m_scanparam->is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red)
if (is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red)
num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered();
else if (m_scanparam->is_duplex && m_scanparam->en_fold)
else if (is_duplex && m_scanparam->en_fold)
num = scanner->get_imgnReaded() - scanner->get_imgTransfered();
else if (m_scanparam->is_duplex && m_scanparam->multi_output_red)
else if (is_duplex && m_scanparam->multi_output_red)
num = scanner->get_imgnReaded() * 4 - scanner->get_imgTransfered();
else if ((!m_scanparam->is_duplex) && m_scanparam->multi_output_red)
else if ((!is_duplex) && m_scanparam->multi_output_red)
num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered();
else if (!m_scanparam->is_duplex)
else if (!is_duplex)
num = scanner->get_imgnReaded() - scanner->get_imgTransfered();
else
num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered();
@ -770,6 +776,7 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
showmsg("警告", msgs[(UsbSupported)202]);
return { ReturnCode::Failure, ConditionCode::CapBadOperation };
}
#ifndef G1003399
auto usblist = UsbScan_List::find_all_usb();
if (!usblist.empty())
{
@ -790,16 +797,8 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
}
}
}
FileTools::writelog(log_INFO, "open ds find device vid=" + to_string(vid) + "\tpid=" + to_string(pid));
m_haveError = false;
updataGscanCap();
bmpData->resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header());
bmInfo.biHeight = 2000;
bmInfo.biWidth = 2000;
bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1);
m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1);
FileTools::writelog(log_INFO, "open ds find device vid=" + to_string(vid) + "\tpid=" + to_string(pid));
if (vid == 0 || pid == 0)
{
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
@ -811,6 +810,10 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
return checkDeviceOnline();
}
scanner->open(vid, pid);
#else
scanner.reset(new GScanO1003399());
#endif // G1003399
if (!scanner->IsConnected()) {
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), CString("201"), NULL, SW_HIDE);
@ -826,8 +829,6 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
scanner->regist_deviceevent_callback(DeviceEvent_callback, this);
auto dgcall = [&](int pagenum)
{
CString text;
text.Format(_T("74 %d"), pagenum);
//ShellExecute(NULL, TEXT("open"), GetHidedlgPath(), text, NULL, SW_HIDE);
showmsg("警告", "" + to_string(pagenum) + "检测到折角!");
scanner->Stop_scan();
@ -837,6 +838,15 @@ Result HuagaoDs::identityOpenDs(const Identity&) {
};
scanner->DogEar_callback(dgcall);
}
m_haveError = false;
updataGscanCap();
bmpData->resize(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER& bmInfo = *((BITMAPINFOHEADER*)header());
bmInfo.biHeight = 2000;
bmInfo.biWidth = 2000;
bmInfo.biBitCount = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1);
m_iBitdepth = m_scanparam->pixtype == 2 ? 24 : (m_scanparam->pixtype == 1 ? 8 : 1);
//MessageBox(NULL, L"2", L"", 0);
// init caps
// there are caps a minimal source must support
@ -1916,15 +1926,20 @@ Result HuagaoDs::pendingXfersEnd(const Identity&, PendingXfers& data) {
if (!(m_scanparam->is_autodiscradblank_normal || m_scanparam->is_autodiscradblank_vince))
{
int num = 0;
if (m_scanparam->is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red)
bool is_duplex = m_scanparam->is_duplex;
#ifdef G1003399
is_duplex = false;
#endif // G1003399
if (is_duplex && m_scanparam->en_fold && m_scanparam->multi_output_red)
num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered();
else if (m_scanparam->is_duplex && m_scanparam->en_fold)
else if (is_duplex && m_scanparam->en_fold)
num = scanner->get_imgnReaded() - scanner->get_imgTransfered();
else if (m_scanparam->is_duplex && m_scanparam->multi_output_red)
else if (is_duplex && m_scanparam->multi_output_red)
num = scanner->get_imgnReaded() * 4 - scanner->get_imgTransfered();
else if ((!m_scanparam->is_duplex) && m_scanparam->multi_output_red)
else if ((!is_duplex) && m_scanparam->multi_output_red)
num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered();
else if (!m_scanparam->is_duplex)
else if (!is_duplex)
num = scanner->get_imgnReaded() - scanner->get_imgTransfered();
else
num = scanner->get_imgnReaded() * 2 - scanner->get_imgTransfered();
@ -1991,13 +2006,13 @@ 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
//#ifndef G200
#ifndef G200
while (!scanner->Get_Scanner_PaperOn())
{
if (MessageBox(NULL, L"检测到无纸,请添加纸张", L"提示", MB_YESNO | MB_SYSTEMMODAL) == IDNO)
return seqError();
}
//#endif // !G200
#endif // !G200
auto ret = startScan();

Binary file not shown.