twain3.0/huagao/Device/GScanO1003399.cpp

1182 lines
30 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "GScanO1003399.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "ImageProcess/ImageMulti.h"
#include "scn_config.h"
#include "UsbScanEx.h"
#include "PaperSize.h"
#include "GScan.h"
#include "aes.h"
#include "hex.h"
#include "modes.h"
#include <cstring>
static std::mutex mx_ctrl;
static int scanner_read_reg(std::shared_ptr<IUsb>& usb, int addr)
{
std::lock_guard<std::mutex> lck(mx_ctrl);
if (usb.get() && usb->is_connected()) {
int val = 0;
usb->control_msg(0xc0, USB_REQ_GET_DEV_REGS, addr, 0, 4, &val);
return val;
}
return 0;
}
static void scanner_write_reg(std::shared_ptr<IUsb>& usb, int addr, int val)
{
std::lock_guard<std::mutex> lck(mx_ctrl);
if (usb.get() && usb->is_connected())
{
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():preProcImgindex(0)
{
im_data.reset(new std::vector<char>());
//open(0x3072, 0x139);
if (!m_usbthread.get()) {
b_usbthread = true;
m_usbthread.reset(new thread(&GScanO1003399::usb_run, this));
}
devState = DEV_STOP;
}
GScanO1003399::~GScanO1003399()
{
imagecount = 0;
if (m_usbthread.get() && m_usbthread->joinable())
{
b_usbthread = false;
m_usbthread->join();
m_usbthread.reset();
}
m_usb.reset();
scanflag = false;
b_imgprothread = false;
imgs.ShutDown();
m_autopaper_timeout = false;
if (m_autopaper_ft.valid())
m_autopaper_ft.get();
while (m_paths.Size() > 0)
{
remove(m_paths.Take().c_str());
}
m_paths.ShutDown();
if (m_imgprocthread.get() && m_imgprocthread->joinable())
{
m_imgprocthread->join();
}
}
void GScanO1003399::open(int vid, int pid)
{
if (m_usb.get() && m_usb->is_connected())
return;
auto lsusb = UsbScan_List::find_vid_pid(vid, pid);
if (!lsusb.empty())
{
m_usb = *lsusb.begin();
m_usb->open();
if (m_usb->is_open()) {
m_usb->set_usbhotplug_callback(usbhotplug_callback, this);
scanner_write_reg(m_usb, SR_IM_CLEAR, 0);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
}
void GScanO1003399::regist_deviceevent_callback(deviceevent_callback callback, void* usrdata)
{
huagods = usrdata;
dev_callback = callback;
}
void GScanO1003399::usbhotplug_callback(bool isconnect, void* userdata)
{
GScanO1003399* This = (GScanO1003399*)userdata;
This->usbhotplug(isconnect);
}
void GScanO1003399::usbhotplug(bool isleft)
{
FileTools::writelog(log_ERROR, "enable usb callback ");
if (isleft) {
devState = DEV_WRONG;
Error_Code = USB_DISCONNECTED;
scanflag = false;
if (m_usb.get())
m_usb.reset();
if (huagods)
dev_callback(USB_DISCONNECTED, huagods);
}
}
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 ((imagecount == 0) && (!scanflag) || (sw.elapsed_s() > 60))
{
if (is_scan() || (m_param.hardwarecaps.is_autopaper && (sw.elapsed_s() > 60)))
{
sw.reset();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
DoEvents();
this_thread::sleep_for(chrono::milliseconds(1));
if (sw.elapsed_s() > 60.0)
{
devState = DEV_STOP;
Stop_scan();
ResetScanner();
int roller_num_new = count();
set_scannum(abs(roller_num_new - roller_num));
return AQUIRE_IMAGE_TIMEOUT;
}
if (!scanflag)
{
int roller_num_new = count();
set_scannum(abs(roller_num_new - roller_num));
if (devState == DEV_WRONG)
return get_ErrorCode();
return -1;
}
}
else
{
if ((m_imagedata.Size() > 0))
{
FileTools::writelog(log_INFO, "aquire_bmpdata num =" + to_string(aquirenum++));
bmpdata = *(m_imagedata.Take());
UpdateScanInfo(get_imgnReaded(), countNTransfered());
imagecount--;
FileTools::writelog(log_INFO, "imagecount =" + to_string(imagecount));
sw.reset();
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::GetMacAdder()
{
std::string mac;
auto fwver = GetFWVersion();
if ((fwver[5] == 'B' && atoi(fwver.substr(6, 4).c_str()) >= 111)||(fwver[5] > 'B')) {
if (m_usb.get() && m_usb->is_connected())
{
scanner_write_reg(m_usb, SR_GET_MACADDR, 0);
mac.resize(17);
read_data(&mac[0], mac.length(), 200);
}
}
else
mac = "The firmware version does not support reading";
return mac;
}
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()
{
std::string fw;
if (m_usb.get() && m_usb->is_connected())
{
fw.resize(scanner_read_reg(m_usb, SR_GET_MBVERSION_LENGHT));
scanner_write_reg(m_usb, SR_GET_MBVERSION,0);
m_usb->read_bulk(&fw[0], fw.size());
//read_data(&fw[0], fw.length(), 200);
}
return atoi(fw.c_str());
}
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_GET_PAPERON));
//return true;
}
int GScanO1003399::Get_Roller_num()
{
return count();
}
void GScanO1003399::config_params(GScanCap& param)
{
fwversion = GetFWVersion();
m_param = param;
HGScanConfig cfg;
cfg = { 0 };
PaperStatus ps = { param.papertype,param.paperAlign };
//if (fwversion.substr(2, 8) == "393B0430")
//{
if (param.papertype == 0)
cfg.g200params.paper = 12; //220513 <20><>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD>Ĭ<EFBFBD>Ϲ̶<CFB9><CCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD>
else
cfg.g200params.paper = SupPaperTyps_39.count(ps) > 0 ? SupPaperTyps_39[ps] : 0;
//}
//else {
// cfg.g200params.paper = SupPaperTyps_39.count(ps) > 0 ? SupPaperTyps_39[ps] : 0;
//}
if (param.filter != 3 || param.enhance_color != 0 || param.hsvcorrect )//|| param.hsvFilter != 0 || param.fadeback != 0)
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 = 0;
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.is_autopaper = param.hardwarecaps.is_autopaper;
cfg.g200params.enable_sizecheck = param.en_sizecheck == 1 ? 1 : 0;
cfg.g200params.is_textcorrect = cfg.g200params.en_autosize = cfg.g200params.sizeerror_errorratio = 0;
//cfg.g200params.is_fixedpaper = param.en_fixedpaper;
cfg.g200params.is_fixedpaper = true; //220513 <20><>Ӱ<EFBFBD><D3B0><EFBFBD><EFBFBD>Ĭ<EFBFBD>Ϲ̶<CFB9><CCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɼ<EFBFBD>
cfg.g200params.en_anlogic_key = true;
//cfg.g200params.enabledsp_cache = true;
#ifdef G200
if ((fwversion[5] == 'A' && (atoi(fwversion.substr(6, 4).c_str()) > 1220)) || (fwversion[5] == 'B' && (atoi(fwversion.substr(6, 4).c_str()) <= 430)))
{
if (param.resolution_dst == 500)
param.resolution_dst = 501;
}
#endif // G200
config_scanparam(cfg);
config_imgprocparam({sizeof(GScanCap_3399)});
GScanCap_3399 param39{ 0 };
param39.AutoCrop_threshold = param.AutoCrop_threshold;
param39.autodescrew = param.autodescrew;
param39.automaticcolor = param.automaticcolor;
param39.automaticcolortype = param.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.HsvFilterType = param.hsvFilter;
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.is_high_imagequality ? param.resolution_dst : ( param.resolution_dst >= 500.0f ?300.0f: 200.0f);
//param39.resolution_dst = param.resolution_dst > 300 ? 300 : param.resolution_dst;
param39.resolution_native = param.is_high_imagequality? param.resolution_native : (param.resolution_dst >= 500.0f ? 300.0f : 200.0f);
if (param39.resolution_dst >= 300 && param39.resolution_dst < 500)
param39.noise = param39.noise * 1.5;
else if(param39.resolution_dst>=500)
param39.noise = param39.noise * 3;
param39.scannum = param.scannum;
param39.sharpen = param.sharpen;
param39.threshold = param.threshold;
param39.multiOutput = MultiOutput::Unused;
param39.normalCrop = param.normalCrop;
param39.fadeback = param.fadeback;
param39.fadebackrange = param.fadeback_range;
param39.dogeardistabce = param.dogeardistance;
param39.fillholeratio_up = param.fillholeratio_up;
param39.fillholeratio_down = param.fillholeratio_down;
param39.fillholeratio_left = param.fillholeratio_left;
param39.fillholeratio_right = param.fillholeratio_right;
param39.is_colorcast = param.is_colorcast;
param39.fillhole.fillholeratio = std::max(std::max(std::max(param.fillholeratio_down, param.fillholeratio_up), std::max(param.fillholeratio_left, param.fillholeratio_right)),1);
m_usb->write_bulk(&param39, sizeof(param39));
m_param .resolution_native = param.resolution_dst >= 500.0f ? 300.0f : 200.0f;
}
void GScanO1003399::Scanner_StartScan(UINT16 count)
{
auto fwver = fwversion;
if ((fwver[5] == 'A' && atoi(fwver.substr(6, 4).c_str()) >= 1209)||(fwver[5] > 'A'))
{
#ifdef G200
if (GetMotorFPGA() >= 35211210)
is_kernelsnap_211209 = true;
else
is_kernelsnap_211209 = false;
#else
is_kernelsnap_211209 = true;
#endif
}
else
is_kernelsnap_211209 = false;
error_index = autopaperstop = 0;
is_back = false;
roller_num = this->count();
scanflag = true;
while (m_paths.Size() > 0)
{
remove(m_paths.Take().c_str());
}
Set_ErrorCode(0);
getimgnum = aquirenum = imagecount = 0;
keeplastimg = is_kernelsnap_211209 ? false : true;//true
scanner_write_reg(m_usb, SR_IM_CLEAR, 0);
reset();
devState = DEV_ISRUNNING;
if (scanner_read_reg(m_usb, SR_GET_SLEEP_STAUTUS) != 1)
{
devState = DEV_WRONG;
Set_ErrorCode(SLEEPING);
scanflag = false;
return;
}
//if (!Get_Scanner_PaperOn()) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɨ<EFBFBD><C9A8>ʹ<EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//{
// devState = DEV_WRONG;
// Set_ErrorCode(NO_FEED);
// scanflag = false;
// return;
//}
if (scan_mode())
{
devState = DEV_WRONG;
Set_ErrorCode(COUNT_MODE);
scanflag = false;
return;
}
start();
bool procmode = (m_param.resolution_dst > 200.0f || m_param.papertype == 52 || m_param.papertype == 54 || m_param.papertype == 131);
if (m_imgprocthread.get() && m_imgprocthread->joinable())
{
b_imgprothread = false;
m_imgprocthread->join();
}
preProcImgindex = 0;
m_imgprocthread.reset(new thread(&GScanO1003399::proc, this, procmode));
}
void GScanO1003399::Stop_scan()
{
stop();
if (m_param.hardwarecaps.is_autopaper)
{
m_autopaper_timeout = false;
autopaperstop = true;
if (!is_scan() && imagecount == 0)
scanflag = false;
}
if ((devState == DEV_WRONG) || (devState == DEV_STOP))
return;
devState = DEV_STOP;
}
int GScanO1003399::notifyscan()
{
return 1;
}
void GScanO1003399::ResetScanner()
{
//m_imagedata.Clear();
}
bool GScanO1003399::Get_IsImageQueueEmpty()
{
return m_imagedata.Size() < 1;
}
void GScanO1003399::reset()
{
devState = DEV_STOP;
m_paths.Clear();
imgs.Clear();
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 (m_param.hardwarecaps.is_autopaper) {
m_autopaper_timeout = false;
}
if (is_runing() && (im_dev_count() > 0))
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));
stop();
break;
case STOPSCAN:
FileTools::writelog(log_INFO, "StopScan");
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)
{
Set_ErrorCode(codeconvter(info));
}
if ((codeconvter(info) == -1))
{
while (!scanner_read_reg(m_usb, SR_GET_IMAGEPROCESSDONE))
this_thread::sleep_for(chrono::microseconds(30));
if (scanner_read_reg(m_usb, SR_GET_KEEP_LAST_PAPER) && (!is_kernelsnap_211209))
{
FileTools::writelog(log_ERROR, "keep last paper true");
this_thread::sleep_for(chrono::milliseconds(100));
while (im_dev_count() > ((m_param.is_duplex && !m_param.en_fold) ? 2 : 1))
im_rx();
if (!is_kernelsnap_211209) {
if (m_param.is_duplex && !m_param.en_fold)
pop_dev_im();
pop_dev_im();
}
}
else
{
keeplastimg = false;
while (im_dev_count())
im_rx();
}
if ((devState != DEV_WRONG) && (get_ErrorCode()<=0))
devState = DEV_STOP;
else if ((devState != DEV_WRONG) && (get_ErrorCode() > 0))
devState = DEV_WRONG;
if (m_param.hardwarecaps.is_autopaper) {
if (devState == DEV_STOP && autopaperstop == false)
scanflag = true;
else
scanflag = false;
}
else
scanflag = false;
if (m_param.hardwarecaps.is_autopaper) {
if ((devState != DEV_WRONG) && (!autopaperstop))
{
m_autopaper_ft = std::async(std::launch::async, [this] {
m_autopaper_timeout = true;
StopWatch sw;
while (sw.elapsed_s() < m_param.autopaper_timeout)
{
if (m_autopaper_timeout == false)
break;
CString str;
str.Format(L"\t <20><>ֽɨ<D6BD><C9A8><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD> %d<><64> ", std::max(m_param.autopaper_timeout - (int)ceil(sw.elapsed_s()), 0));
this->UpdateScanInfo(str);
std::this_thread::sleep_for(std::chrono::milliseconds(30));
}
this->UpdateScanInfo(L" ");
if ((m_autopaper_timeout == false) || scanner_read_reg(m_usb, SR_STATUS))
return;
else
Stop_scan();
});
}
}
}
this_thread::sleep_for(chrono::microseconds(10));
}
}
}
void GScanO1003399::start()
{
if ((fwversion[5] == 'B' && atoi(fwversion.substr(6, 4).c_str()) >= 500) || (fwversion[5] > 'B')) {
if (scanner_read_reg(m_usb, SR_GET_LOCK_STATES)) {
std::string keys;
if (m_token.length() != 32)
{
if (m_token.length() > 32)
{
keys = m_token.substr(0, 32);
}
else
{
auto fillstr = [](std::string str)-> std::string {
for (int i = 0; i < 32 - str.length();)
str += "0";
return str.c_str();
};
keys = fillstr(m_token);
}
}
else
keys = m_token;
//keys = m_token;
std::uint8_t key[CryptoPP::AES::DEFAULT_KEYLENGTH] = { 0 };
for (int i = 0; i < 16; i++)
{
key[i] = _strtoi64(keys.substr(i * 2, 2).c_str(), nullptr, 16);
}
std::string plain = GetSerialNum();
std::string cipher;
std::string encoded;
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption encode;
encode.SetKey(key, 16);
//CryptoPP::StringSource(plain, true, new CryptoPP::StreamTransformationFilter(encode, new CryptoPP::StringSink(cipher), CryptoPP::BlockPaddingSchemeDef::W3C_PADDING));
//encoded.clear();
//CryptoPP::StringSource(cipher, true, new CryptoPP::HexEncoder(new CryptoPP::StringSink(encoded)));
CryptoPP::StringSink* str_cip = new CryptoPP::StringSink(cipher);
CryptoPP::StreamTransformationFilter* ecb_filter = new CryptoPP::StreamTransformationFilter(encode, str_cip, CryptoPP::BlockPaddingSchemeDef::W3C_PADDING);
CryptoPP::StringSource* source_plain = new CryptoPP::StringSource(plain, true, ecb_filter);
encoded.clear();
CryptoPP::StringSink* str_encode = new CryptoPP::StringSink(encoded);
CryptoPP::HexEncoder* hex_encode = new CryptoPP::HexEncoder(str_encode);
CryptoPP::StringSource* source_cipher = new CryptoPP::StringSource(cipher, true, hex_encode);
delete str_cip;
delete ecb_filter;
delete source_plain;
delete str_encode;
delete hex_encode;
delete source_cipher;
scanner_write_reg(m_usb, SR_DECODE_TOKEN, encoded.length());
m_usb->write_bulk(&encoded[0], encoded.length());
m_token = "null";
}
}
scanner_cmd(m_usb, SC_START);
}
void GScanO1003399::stop()
{
scanner_cmd(m_usb, SC_STOP);
}
bool GScanO1003399::is_runing()
{
int val = scanner_read_reg(m_usb, SR_STATUS) & 0x3;
return (val > 0) && (val < 4);
}
int GScanO1003399::scan_mode()
{
return scanner_read_reg(m_usb, SR_OS) & 0x01;
}
int GScanO1003399::count()
{
return scanner_read_reg(m_usb, SR_GET_ROLLER_NUM);
}
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_dev_tx())
return;
if (keeplastimg)
{
if (m_param.is_duplex && !m_param.en_fold) {
if(im_dev_count()<3)
return;
}
if(im_dev_count()<2)
return;
}
std::shared_ptr<std::vector<char>> buffi(new std::vector<char>);
//auto& buffi = im_data;
int count = front_datasize();
int recv_count = 0;
buffi->resize(count);
rx_cmd();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
recv_count = read_data(buffi->data(), count, count / (0.005 * 1024 * 1024)); //
if (count != recv_count)
{
FileTools::writelog(log_INFO, "SR_IM_ABORT ");
scanner_write_reg(m_usb, SR_IM_ABORT, 0);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
return;
}
pop_dev_im();
//vector<cv::Mat> mats;
//m_param.multi_output_red? imagecount += 2: imagecount++;
imagecount += 1 * (m_param.multi_output_red ? 2 : 1) * (m_param.is_split ? 2 : 1) * (m_param.en_multi_output ? (m_param.multioutput < 0 ? 1 : (m_param.multioutput == 0 ? 3 : 2)) : 1);
FileTools::writelog(log_INFO, "imagecount im rx =" + to_string(imagecount));
UpdateScanInfo(countNReaded(), get_imgTransfered());
if (m_param.resolution_dst > 200.0f || m_param.papertype == 52 || m_param.papertype == 54 || m_param.papertype == 131)
{
auto path = cv::tempfile();
auto fd = fopen(path.c_str(), "wb+");
if (fd)
{
fwrite(buffi->data(), buffi->size(), 1, fd);
fclose(fd);
m_paths.Put(path);
}
else {
FileTools::writelog(log_ERROR, "img temp file save error flie name =" + path);
}
}
else {
imgs.Put(buffi);
}
}
int GScanO1003399::read_data(void* data, int length, int timeout)
{
if (!m_usb.get() && !m_usb->is_connected())
{
FileTools::writelog(log_INFO, "!m_usb->is_connected");
return 0;
}
timeout = std::max(1500, timeout);
int readed = 0;
int reading = 0;
const int buffer_size = 512 * 1024;
StopWatch sw;
while (readed < length) {
if (sw.elapsed_ms() < timeout &&m_usb.get())
{
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;
sw.reset();
}
}
else
{
FileTools::writelog(log_INFO, "read usb image data time out ,time = " + std::to_string(sw.elapsed_ms()));
break;
}
}
return readed;
}
void GScanO1003399::pop_dev_im()
{
if(im_dev_count()>0)
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 ;
}
static int num = 0;
void GScanO1003399::imgproce(std::shared_ptr<std::vector<char>>& buff)
{
preProcImgindex++;
auto& buffs= G400Decode(buff).getImageBuffs();
vector<cv::Mat> mats;
StopWatch sw;
bool isbwimg = false;
for (auto& buf : buffs) {
cv::ImreadModes rmc = m_param.pixtype == 2 ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE;
try
{
if (buf->at(0) == -119 && buf->at(1) == 0x50 && buf->at(2) == 0x4e && buf->at(3) == 0x47)
{
isbwimg = true;
rmc = cv::IMREAD_GRAYSCALE;
}
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)
{
FileTools::writelog(log_ERROR, e.what());
}
}
sw.reset();
buffs.clear();
if (m_param.is_high_imagequality == false && m_param.resolution_dst != m_param.resolution_native) {
for (auto& node : mats)
{
cv::resize(node, node, cv::Size(0, 0), m_param.resolution_dst / m_param.resolution_native, m_param.resolution_dst / m_param.resolution_native);
}
}
if (m_param.is_autotext)
{
//m_autotext->apply(mats, m_param.is_duplex);
TCHAR szIniFile[MAX_PATH] = { 0 };
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
#ifdef LANXUM
_tcscat(szIniFile, _T("\\twain_32\\LANXUMSCAN\\tessdata\\osd.traineddata"));
#elif defined AUGE
_tcscat(szIniFile, _T("\\twain_32\\AuGeScan\\tessdata\\osd.traineddata"));
#elif defined HANVON
_tcscat(szIniFile, _T("\\twain_32\\HanvonScan\\tessdata\\osd.traineddata"));
#elif defined MAKERIGHTWAY
_tcscat(szIniFile, _T("\\twain_32\\RIGHTWAYSCAN\\tessdata\\osd.traineddata"));
#elif defined CUMTENN
_tcscat(szIniFile, _T("\\twain_32\\CumTennScan\\tessdata\\osd.traineddata"));
#elif defined NOLOGO
_tcscat(szIniFile, _T("\\twain_32\\Scan\\tessdata\\osd.traineddata"));
#elif defined ZHUOYUYUN
_tcscat(szIniFile, _T("\\twain_32\\ZhuoYuYunScan\\tessdata\\osd.traineddata"));
#else
_tcscat(szIniFile, _T("\\twain_32\\HuaGoScan\\tessdata\\osd.traineddata"));
#endif //
int iLen = WideCharToMultiByte(CP_ACP, 0, szIniFile, -1, NULL, 0, NULL, NULL);
char* chRtn = new char[iLen * sizeof(char)];
WideCharToMultiByte(CP_ACP, 0, szIniFile, -1, chRtn, iLen, NULL, NULL);
CImageApplyRotation autotext(CImageApplyRotation::RotationType::AutoTextOrientation, false, m_param.resolution_dst, chRtn);
autotext.apply(mats, m_param.is_duplex);
delete[] chRtn;
}
if (m_param.automaticcolor)
{
CImageApplyColorRecognition(m_param.automaticcolortype == 1 ? CImageApplyColorRecognition::ColorRecognitionMode::Color_Gray : CImageApplyColorRecognition::ColorRecognitionMode::Color_Mono).apply(mats,m_param.is_duplex);
}
//for (auto& node : mats)
//{
// cv::putText(node, "Top left", cv::Point(100, 100), CV_FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(0, 0, 255), 4, 8);
//}
if (m_param.is_split)
{
if (!is_back)
{
CImageApplyRotation autotext(CImageApplyRotation::RotationType::Rotate_90_clockwise, false, m_param.resolution_dst, NULL);
autotext.apply(mats[0], false);
if (m_param.is_duplex)
is_back = true;
}
else if (is_back && m_param.is_duplex)
{
CImageApplyRotation autotext(CImageApplyRotation::RotationType::Rotate_90_anti_clockwise, false, m_param.resolution_dst, NULL);
autotext.apply(mats[0], true);
is_back = false;
}
CImageApplySplit m_split;
std::vector<cv::Mat> tmp;
for (auto& var : mats)
{
if (!var.empty())
{
int side = (preProcImgindex % 2) == 1 ? 0 : 1;
auto sptmp = m_split.apply(var, m_param.is_duplex? side:0);
for (auto& matvar : sptmp)
{
if (!matvar.empty())
tmp.push_back(matvar);
}
}
}
if(is_back && tmp.size()>=2)
std::swap(tmp[0], tmp[1]);
mats.swap(tmp);
}
for (int i = 0; i < mats.size(); i++) {
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);
//cv::imwrite("D:\\img\\" + to_string(num++) + ".jpg", mats[i]);
if (m_param.en_multi_output) {
MultiOut(mats[i]);
}
else
{
idata = (isbwimg || m_param.pixtype == 0 || (((m_param.automaticcolortype == 0) && (m_param.automaticcolor == true)) && (mats[i].channels() == 1))) ? (IMat2Bmp)Mat2BmpBw(mats[i], m_param.resolution_dst) : (IMat2Bmp)Mat2Bmp(mats[i], m_param.resolution_dst);
m_imagedata.Put(idata.getBmpDataBuffer());
idata.~IMat2Bmp();
}
}
}
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()) {
Mat2Bmp mb(ret, m_param.resolution_dst);
m_imagedata.Put(mb.getBmpDataBuffer());
ret.release();
}
}
}
}
mats.clear();
}
void GScanO1003399::MultiOut(cv::Mat& pDid)
{
IMageMulti imgmulti(m_param.multioutput);
auto rets = imgmulti.apply(pDid);
switch (m_param.multioutput)
{
case 0: {
for (int x = 0; x < rets.size(); x++) {
if (rets[x].empty())
continue;
if (x == 2)
m_imagedata.Put(Mat2BmpBw(rets[x], m_param.resolution_dst).getBmpDataBuffer());
else
m_imagedata.Put(Mat2Bmp(rets[x], m_param.resolution_dst).getBmpDataBuffer());
}
break;
}
case 1: {
for (auto& node : rets) {
if (node.empty())
continue;
m_imagedata.Put(Mat2Bmp(node, m_param.resolution_dst).getBmpDataBuffer());
}
break;
}
case 2:
case 3: {
for (int x = 0; x < rets.size(); x++) {
if (rets[x].empty())
continue;
if (x == 1)
m_imagedata.Put(Mat2BmpBw(rets[x], m_param.resolution_dst).getBmpDataBuffer());
else
{
m_param.multioutput == 2 ? void(0):cv::cvtColor(rets[x], rets[x], cv::COLOR_BGR2GRAY);
m_imagedata.Put(Mat2Bmp(rets[x], m_param.resolution_dst).getBmpDataBuffer());
}
}
break;
}
default:
break;
}
}
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 0x00100:
return DEVICE_LOCKED;
case 0x10000:
return AQUIRE_IMAGE_TIMEOUT;
case 0x20000:
return SIZE_ERROR;
case 0x40000:
return PAPER_HOLE;
case 0x80000:
return MLTOP_TIMEOUT;
default:
break;
}
}
if (code.From == HGType::V4L2)
{
switch (code.Code)
{
case 0:
return V4L2_AQULRE_ERROR;
case 1:
return V4L2_IMAGE_EMPTY;
default:
break;
}
}
if (code.From == HGType::IMG)
{
switch (code.Code)
{
case 1:
error_index = code.Img_Index;
return HAVE_DOGEAR;
case 2:
error_index = code.Img_Index;
return SIZE_ERROR;
default:
break;
}
}
if (code.From == HGType::STOPSCAN)
{
switch (code.Code)
{
case 0:
{
return -1;
}
case 1:
if (m_param.hardwarecaps.is_autopaper)
{
autopaperstop = true;
if (!is_scan() && imagecount == 0)
scanflag = false;
}
if (devState == DEV_ISRUNNING)
devState = DEV_STOP;
return 0;
default:
break;
}
}
return 0;
}
void GScanO1003399::proc(bool bcachemode)
{
b_imgprothread = true;
while (b_imgprothread)
{
if (m_imagedata.Size() > 0)
{
this_thread::sleep_for(chrono::milliseconds(10));
continue;
}
std::shared_ptr<std::vector<char>> buffer;
if (bcachemode) {
if (m_paths.Size() < 1)
{
this_thread::sleep_for(chrono::milliseconds(10));
continue;
}
auto path = m_paths.Take();
if (!path.empty())
{
auto fd = fopen(path.c_str(), "rb+");
if (fd)
{
auto lenght = FileTools::get_file_size(path.c_str());
buffer.reset(new std::vector<char>);
buffer->resize(lenght);
fread(buffer->data(), lenght, 1, fd);
fclose(fd);
remove(path.c_str());
}
else {
FileTools::writelog(log_ERROR, "img tmp file read error file name =" + path);
}
}
}
else
{
if (imgs.Size() < 1)
{
std::this_thread::sleep_for(chrono::milliseconds(2));
continue;
}
buffer = imgs.Take();
}
if (m_param.resolution_dst > 500)
std::this_thread::sleep_for(std::chrono::milliseconds(4399));
imgproce(buffer);
}
}