2020-03-11 01:58:06 +00:00
|
|
|
|
#include "StdAfx.h"
|
|
|
|
|
#include "ImageMatQueue.h"
|
|
|
|
|
#include "PublicFunc.h"
|
|
|
|
|
#include "ImageProcess/ImageApplyHeaders.h"
|
|
|
|
|
#include "ImageMultiOutput.h"
|
|
|
|
|
#include "jpeglib.h"
|
|
|
|
|
#include "filetools.h"
|
|
|
|
|
#include <math.h>
|
|
|
|
|
using namespace cv;
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
#define DECODE_COLOR_BGR 1
|
|
|
|
|
#define DECODE_GRAY 6
|
|
|
|
|
|
|
|
|
|
G200Decode::G200Decode(std::shared_ptr<std::vector<char>> buff)
|
|
|
|
|
{
|
|
|
|
|
const int int_buffer_size = 1024;
|
|
|
|
|
int buffer_size = buff->size();
|
|
|
|
|
int b_buffer_size = 0;
|
|
|
|
|
int f_buffer_size = 0;
|
|
|
|
|
std::shared_ptr<std::vector<char>> buffB(new std::vector<char>(buff->size()));
|
|
|
|
|
std::shared_ptr<std::vector<char>> buffF(new std::vector<char>(buff->size()));;
|
|
|
|
|
unsigned char* bbuf = (unsigned char*)(buffB->data());
|
|
|
|
|
unsigned char* fbuf = (unsigned char*)(buffF->data());
|
|
|
|
|
unsigned char* buf = (unsigned char*)(buff->data());
|
|
|
|
|
for (int i = 0; i < (buffer_size / int_buffer_size); i++) {
|
|
|
|
|
if (buf[(i + 1) * int_buffer_size - 1] == 0) {
|
|
|
|
|
memcpy(bbuf + b_buffer_size, buf + i * int_buffer_size, int_buffer_size - 1);
|
|
|
|
|
b_buffer_size += (int_buffer_size - 1);
|
|
|
|
|
}
|
|
|
|
|
else if (buf[(i + 1) * int_buffer_size - 1] == 255) {
|
|
|
|
|
memcpy(fbuf + f_buffer_size, buf + i * int_buffer_size, int_buffer_size - 1);
|
|
|
|
|
f_buffer_size += (int_buffer_size - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
buffB->resize(b_buffer_size);
|
|
|
|
|
buffF->resize(f_buffer_size);
|
|
|
|
|
m_buffs.push_back(buffB);
|
|
|
|
|
m_buffs.push_back(buffF);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageMatQueue::ImageMatQueue(void)
|
|
|
|
|
: bRun(false)
|
|
|
|
|
, is_scanning(false)
|
|
|
|
|
{
|
|
|
|
|
atm_orgin_image_remains = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageMatQueue::run()
|
|
|
|
|
{
|
|
|
|
|
if (!m_threadProc) {
|
|
|
|
|
bRun = true;
|
|
|
|
|
m_threadProc.reset(new thread(&ImageMatQueue::proc, this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ImageMatQueue::orginimgcount()
|
|
|
|
|
{
|
|
|
|
|
return atm_orgin_image_remains;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageMatQueue::~ImageMatQueue(void)
|
|
|
|
|
{
|
|
|
|
|
m_rawBuffs.Clear();
|
|
|
|
|
m_imagedata.Clear();
|
|
|
|
|
m_rawBuffs.ShutDown();
|
|
|
|
|
m_imagedata.ShutDown();
|
|
|
|
|
if (m_threadProc) {
|
|
|
|
|
bRun = false;
|
|
|
|
|
m_threadProc->join();
|
|
|
|
|
m_threadProc.reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageMatQueue::pushMat(std::shared_ptr<IDecode> data)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(m_mtxJB);
|
|
|
|
|
m_rawBuffs.Put(data);
|
|
|
|
|
atm_orgin_image_remains++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<unsigned char> ImageMatQueue::popBmpdata()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(m_mtxJB);
|
|
|
|
|
std::vector<unsigned char> retdata = m_imagedata.Take();
|
|
|
|
|
return retdata;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImageMatQueue::valid()
|
|
|
|
|
{
|
|
|
|
|
return m_imagedata.Size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageMatQueue::clear()
|
|
|
|
|
{
|
|
|
|
|
m_rawBuffs.Clear();
|
|
|
|
|
m_imagedata.Clear();
|
|
|
|
|
atm_orgin_image_remains = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageMatQueue::setparam(const GScanCap& param)
|
|
|
|
|
{
|
|
|
|
|
scanParam = param;
|
|
|
|
|
m_iaList.clear();
|
|
|
|
|
|
|
|
|
|
if (scanParam.fillhole.is_fillhole) {
|
|
|
|
|
float ratio = scanParam.fillhole.fillholeratio/100.0;
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageOutHole(200, ratio, 50)));
|
|
|
|
|
} //ȷ<><C8B7><EFBFBD>ܹ<EFBFBD><DCB9><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
bool islongcustomcrop = false;
|
|
|
|
|
if (param.papertype == TwSS::USStatement)
|
|
|
|
|
islongcustomcrop = true;
|
|
|
|
|
CSize fixedSize = papersize.GetPaperSize(param.papertype, 200.0f, param.paperAlign);
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : param.is_autocrop, param.autodescrew, param.fillbackground, cv::Size(fixedSize.cx, fixedSize.cy), true)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (param.is_autodiscradblank_normal || param.is_autodiscradblank_vince) {
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.is_autodiscradblank_normal ? true : false)));
|
|
|
|
|
//m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.areanum,param.devnmax)));
|
|
|
|
|
}
|
|
|
|
|
//if (param.pixtype != 0) //sharpen
|
|
|
|
|
// m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplySharpen()));
|
|
|
|
|
|
|
|
|
|
//filter 0 r 1 g 2 b 3 none enhance color 0 none 1 r 2 g 3 b
|
|
|
|
|
if (param.filter != 3 || param.enhance_color) {
|
|
|
|
|
int channel = 0; //filter none r g b enhance none r g b
|
|
|
|
|
if (param.filter != 3) { channel = param.filter; }
|
|
|
|
|
else { channel = param.enhance_color + 3; }
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyChannel(static_cast<CImageApplyChannel::Channel>(channel))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (param.brightness != 0 || param.contrast != 0 || param.gamma != 1.0) {
|
|
|
|
|
double aa = (254.0 / 2000.0) * param.brightness + 0.5;
|
|
|
|
|
int bright = ceil(aa);//[-127,128] 0.128=256.0/2000.0
|
|
|
|
|
int contrast = (int)(param.contrast * 0.036);//[-36,36] 0.036=72.0/2000.0;
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAdjustColors(bright, contrast, param.gamma)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (param.pixtype == 0) //threshold
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyBWBinaray(CImageApplyBWBinaray::ThresholdType::THRESH_BINARY)));
|
|
|
|
|
|
|
|
|
|
if (param.sharpen) {
|
|
|
|
|
SharpenBlur sb = (SharpenBlur)param.sharpen;
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplySharpen(sb)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (param.resolution_dst != 200.0)
|
|
|
|
|
{
|
|
|
|
|
CImageApplyResize* apply;
|
2020-03-19 13:11:12 +00:00
|
|
|
|
bool islongcustomcrop = false;
|
|
|
|
|
if (param.papertype == TwSS::USStatement)
|
|
|
|
|
islongcustomcrop = true;
|
|
|
|
|
if (param.is_autocrop|| islongcustomcrop) {
|
2020-03-11 01:58:06 +00:00
|
|
|
|
double ratio = param.resolution_dst / 200.0;
|
|
|
|
|
apply = new CImageApplyResize(CImageApplyResize::ResizeType::RATIO, cv::Size(0, 0), ratio, ratio);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
CSize dSize = papersize.GetPaperSize(param.papertype, param.resolution_dst, param.paperAlign);
|
|
|
|
|
apply = new CImageApplyResize(CImageApplyResize::ResizeType::DSIZE, cv::Size(dSize.cx, dSize.cy), 1.0, 1.0);
|
|
|
|
|
}
|
|
|
|
|
m_iaList.push_back(shared_ptr< CImageApply>(apply));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (param.imageRotateDegree != 0.0 || param.is_backrotate180 || param.is_autotext)
|
|
|
|
|
{
|
|
|
|
|
CImageApplyRotation::RotationType type;
|
|
|
|
|
if (param.imageRotateDegree > 89.0f && param.imageRotateDegree < 91.0f)
|
|
|
|
|
type = CImageApplyRotation::RotationType::Rotate_90_clockwise;
|
|
|
|
|
else if (param.imageRotateDegree > 269.0f && param.imageRotateDegree < 271.0f)
|
|
|
|
|
type = CImageApplyRotation::RotationType::Rotate_90_anti_clockwise;
|
|
|
|
|
else if (param.imageRotateDegree > 179.0f && param.imageRotateDegree < 181.0f)
|
|
|
|
|
type = CImageApplyRotation::RotationType::Rotate_180;
|
|
|
|
|
else
|
|
|
|
|
type = CImageApplyRotation::RotationType::Invalid;
|
|
|
|
|
|
|
|
|
|
if (param.is_autotext)
|
|
|
|
|
type = CImageApplyRotation::RotationType::AutoTextOrientation;
|
|
|
|
|
|
|
|
|
|
TCHAR szIniFile[MAX_PATH] = { 0 };
|
|
|
|
|
SHGetSpecialFolderPath(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
|
|
|
|
|
_tcscat(szIniFile, _T("\\twain_32\\HuaGoScan\\tessdata"));
|
|
|
|
|
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);
|
|
|
|
|
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyRotation(type, param.is_backrotate180, param.resolution_dst, chRtn)));
|
|
|
|
|
delete[] chRtn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageMatQueue::EnqueueBmpBuffer(std::vector<unsigned char>& bmpdata)
|
|
|
|
|
{
|
|
|
|
|
//std::lock_guard<std::mutex> lock(m_Locker);
|
|
|
|
|
m_imagedata.Put(bmpdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ImageMatQueue::PaniusCount()
|
|
|
|
|
{
|
|
|
|
|
atm_orgin_image_remains--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ImageMatQueue::empty()
|
|
|
|
|
{
|
|
|
|
|
return atm_orgin_image_remains == 0 && m_imagedata.Size() == 0 && !is_scanning;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int index = 0;
|
|
|
|
|
void ImageMatQueue::proc()
|
|
|
|
|
{
|
|
|
|
|
while (bRun) {
|
|
|
|
|
while (m_imagedata.Size() > 0) {
|
|
|
|
|
this_thread::sleep_for(chrono::milliseconds(1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_rawBuffs.Size() == 0)
|
|
|
|
|
{
|
|
|
|
|
this_thread::sleep_for(chrono::milliseconds(1));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto buffs = m_rawBuffs.Take()->getImageBuffs();
|
|
|
|
|
if (!m_rawBuffs.IsShutDown() && !buffs.empty()) {
|
|
|
|
|
vector<cv::Mat> mats;
|
|
|
|
|
for (auto& buf : buffs) {
|
|
|
|
|
ImreadModes rm;
|
|
|
|
|
|
|
|
|
|
if (scanParam.filter != 3 || scanParam.enhance_color)
|
|
|
|
|
rm = IMREAD_COLOR;
|
|
|
|
|
else
|
|
|
|
|
rm = scanParam.pixtype == 2 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
|
|
|
|
|
|
|
|
|
|
cv::Mat mat = cv::imdecode(*buf, rm);
|
|
|
|
|
if (mat.empty()) {
|
|
|
|
|
fstream fss;
|
|
|
|
|
fss.open("D:\\decodeerror.txt", std::ios::out);
|
|
|
|
|
fss << "decode image data error" << endl;
|
|
|
|
|
fss.close();
|
|
|
|
|
}
|
|
|
|
|
mats.push_back(mat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < m_iaList.size(); j++) {
|
|
|
|
|
m_iaList[j]->apply(mats, scanParam.is_duplex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < mats.size(); i++) {
|
|
|
|
|
if (!scanParam.is_duplex && i == 1) {
|
|
|
|
|
mats[i].release();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!mats[i].empty()) {
|
|
|
|
|
IMat2Bmp idata;
|
|
|
|
|
idata = scanParam.pixtype == 0 ? (IMat2Bmp)Mat2BmpBw(mats[i], scanParam.resolution_dst) : Mat2Bmp(mats[i]);
|
|
|
|
|
auto data = idata.getBmpDataBuffer();
|
|
|
|
|
EnqueueBmpBuffer(data);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
FileTools::write_log("emptyimage.txt", "enqueue image is empty " + std::to_string(index++));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (scanParam.multi_output_red) {
|
|
|
|
|
for (int i = 0; i < mats.size(); i++) {
|
|
|
|
|
ImageMultiOutput m_mlt;
|
|
|
|
|
Mat m_filterMat = m_mlt.GetMultiFilterMat(mats[i], 2);
|
|
|
|
|
if (!m_filterMat.empty()) {
|
|
|
|
|
if (!scanParam.is_duplex && i == 1) {
|
|
|
|
|
mats[i].release();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!m_filterMat.empty()) {
|
|
|
|
|
Mat2Bmp mb(m_filterMat);
|
|
|
|
|
auto data = mb.getBmpDataBuffer();
|
|
|
|
|
EnqueueBmpBuffer(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PaniusCount();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GRawDecode::GRawDecode(std::shared_ptr<std::vector<char>> buff)
|
|
|
|
|
{
|
|
|
|
|
m_buffs.push_back(buff);
|
|
|
|
|
}
|