twain3.0/huagao/Device/ImageMatQueue.cpp

367 lines
12 KiB
C++
Raw 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 "StdAfx.h"
#include "ImageMatQueue.h"
#include "PublicFunc.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
#include "filetools.h"
#include <math.h>
#include "StopWatch.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)
{
#ifdef G200
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);
buff.reset();
#else // G200
m_buffs.push_back(buff);
#endif
}
ImageMatQueue::ImageMatQueue(void)
: bRun(false)
, is_scanning(false)
,fx(1.001)
,fy(1.007)
{
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;
}
void ImageMatQueue::updatefixratio(float& hratio, float& vratio)
{
if (hratio > 0.80f && hratio < 1.2f && vratio >0.80f && vratio < 1.2f) {
this->fx = hratio;
this->fy = vratio;
}
else
{
writelog("error horizental or vertical ratio");
}
}
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)
{
m_rawBuffs.Put(data);
atm_orgin_image_remains++;
}
std::shared_ptr<std::vector<unsigned char>> ImageMatQueue::popBmpdata()
{
return m_imagedata.Take();
}
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;
//scanParam.is_duplex = 0;
//scanParam.imageRotateDegree = 90.0f;
#ifdef DEBUG
string outinfo = "autodescrew : " + to_string(scanParam.autodescrew) + "\n brightness : " + to_string(scanParam.brightness) + "\n contrast " + to_string(scanParam.contrast) + "\n enhance_color : " + to_string(scanParam.enhance_color) + "\n en_fold: " + to_string(scanParam.en_fold)
+ "\n fillbackground : " + to_string(scanParam.fillbackground) + "\n is_fillhole : " + to_string(scanParam.fillhole.is_fillhole) + "\n fillholeratio : " + to_string(scanParam.fillhole.fillholeratio) + "\n filter : " + to_string(scanParam.filter) + "\n gamma : " + to_string(scanParam.gamma)
+ "\n imageRotateDegree : " + to_string(scanParam.imageRotateDegree) + "\n is_autocrop : " + to_string(scanParam.is_autocrop) + "\n is_autodiscradblank_normal : " + to_string(scanParam.is_autodiscradblank_normal) + "\n is_autodiscradblank_vince : " + to_string(scanParam.is_autodiscradblank_vince)
+ "\n is_autotext : " + to_string(scanParam.is_autotext) + "\n is_backrotate180 : " + to_string(scanParam.is_backrotate180) + "\n is_duplex : " + to_string(scanParam.is_duplex) + "\n is_switchfrontback : " + to_string(scanParam.is_switchfrontback) + "\n multi_output_red : " + to_string(scanParam.multi_output_red)
+ "\n paperAlign : " + to_string(scanParam.paperAlign) + "\n papertype : " + to_string(scanParam.papertype) + "\n resolution_dst : " + to_string(scanParam.resolution_dst) + "\n scannum : " + to_string(scanParam.scannum) + "\n sharpen : " + to_string(scanParam.sharpen)+
"\n Pixtype : "+to_string(scanParam.pixtype);
FileTools::write_log("D:\\2.txt", outinfo);
#endif // DEBUG
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 = param.papertype == TwSS::USStatement;
//bool isautocrop = param.papertype == TwSS::None;
CSize fixedSize;
#ifdef REAL300DPI
fixedSize = papersize.GetPaperSize(param.papertype, param.resolution_dst > 240.0f ? 300.0f : 200.0f, param.paperAlign);
#else // REAL300DPI
fixedSize = papersize.GetPaperSize(param.papertype, 200.0f, param.paperAlign);
#endif
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()));
//m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.areanum,param.devnmax)));
}
//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)));
}
//<2F><><EFBFBD><EFBFBD><E2BFA8><EFBFBD><EFBFBD>
if (scanParam.hsvcorrect)
{
m_iaList.push_back(shared_ptr<CImageApplyHSVCorrect>(new CImageApplyHSVCorrect(CImageApplyHSVCorrect::CorrectOption::Red_Removal)));
}
//<2F><><EFBFBD><EFBFBD>
if (param.sharpen) {
SharpenBlur sb = (SharpenBlur)param.sharpen;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplySharpen(sb)));
}
//<2F><>ֵ<EFBFBD><D6B5>
if (param.pixtype == 0) //threshold
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyBWBinaray(CImageApplyBWBinaray::ThresholdType::THRESH_BINARY)));
if (param.resolution_dst != param.resolution_native)
{
CImageApplyResize* apply;
bool islongcustomcrop = false;
if (param.papertype == TwSS::USStatement)
islongcustomcrop = true;
if (param.is_autocrop || islongcustomcrop) {
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 (scanParam.en_fold)
{
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyConcatenation(CImageApplyConcatenation::horizontal)));
}
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::shared_ptr<std::vector<unsigned char>> bmpdata)
{
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;
}
bool ImageMatQueue::queuesempty()
{
return atm_orgin_image_remains == 0 && m_imagedata.Size() == 0;
}
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 || scanParam.hsvcorrect)
rm = IMREAD_COLOR;
else
rm = scanParam.pixtype == 2 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
try
{
//StopWatch sw;
cv::Mat mat = cv::imdecode(*buf, rm);
//double epl= sw.elapsed_ms();
//FileTools::write_log("1.txt", to_string(epl)+" img index"+to_string(++index));
buf.reset();
if (mat.empty()) {
writelog("decode image data error");
}
#ifdef G200
resize(mat, mat, cv::Size(), fx, fy);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD>
mats.push_back(mat);
mat.release();
#else // G200
//resize(mat, mat, cv::Size(), 1.001, 1.0070);//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1>ƥ<EFBFBD><C6A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׶<EFBFBD>
//cv::imwrite("D:\\bb\\"+to_string(++index)+".jpg", mat);
mats.push_back(mat);
Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows));
Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
if (scanParam.imageRotateDegree != 0.0&&scanParam.imageRotateDegree!=180.0) {
cv::flip(front, front, 0);
cv::flip(front, front, 1);
}
mats.push_back(front);
mats.push_back(back);
#endif
}
catch (const std::exception& e)
{
writelog(e.what());
}
}
buffs.clear();
if (scanParam.is_switchfrontback)
swap(mats[0], mats[1]);
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;
if (scanParam.pixtype == 1 && scanParam.hsvcorrect)
if (mats[i].channels() == 3)
cvtColor(mats[i], mats[i], cv::COLOR_BGR2GRAY);
idata = scanParam.pixtype == 0 ? (IMat2Bmp)Mat2BmpBw(mats[i], scanParam.resolution_dst) : Mat2Bmp(mats[i], scanParam.resolution_dst);
auto data = idata.getBmpDataBuffer();
EnqueueBmpBuffer(data);
}
else
{
writelog("enqueue image is empty " + std::to_string(index++));
}
}
//FileTools::write_log("E:\\Users\\huago\\Desktop\\2.txt", "image output time eplsed: " + std::to_string(sw.elapsed_ms()));
if (scanParam.multi_output_red) {
for (int i = 0; i < mats.size(); i++) {
if (!mats[i].empty()) {
ImageMultiOutput m_mlt;
Mat ret = m_mlt.GetMultiFilterMat(mats[i], 2);
mats[i].release();
if (!ret.empty()) {
if (!scanParam.is_duplex && i == 1) {
ret.release();
break;
}
Mat2Bmp mb(ret, scanParam.resolution_dst);
auto data = mb.getBmpDataBuffer();
ret.release();
EnqueueBmpBuffer(data);
}
}
}
}
mats.clear();
PaniusCount();
}
}
}
GRawDecode::GRawDecode(std::shared_ptr<std::vector<char>> buff)
{
m_buffs.push_back(buff);
}