twain3.0/huagao/Device/ImageMatQueue.cpp

347 lines
10 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;
}
float ImageMatQueue::getdpi()
{
return scanParam.resolution_dst;
}
void ImageMatQueue::updatefixratio(float& hratio, float& vratio)
{
if (hratio > 0.80f && hratio < 1.2f && vratio >0.80f && vratio < 1.2f) {
fx = hratio;
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;
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;
#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(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 != 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 / param.resolution_native;
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::vector<unsigned char>& bmpdata)
{
//std::lock_guard<std::mutex> lock(m_Locker);
//m_imagedata.Put(bmpdata);
}
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;
}
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;
int k = 0;
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;
try
{
cv::Mat mat = cv::imdecode(*buf, rm);
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>
Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows));
Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows));
mats.push_back(front);
mats.push_back(back);
#endif
}
catch (const std::exception& e)
{
writelog(e.what());
}
}
buffs.clear();
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], scanParam.resolution_dst);
auto data = idata.getBmpDataBuffer();
//mats[i].release();
EnqueueBmpBuffer(data);
}
else
{
writelog("enqueue image is empty " + std::to_string(index++));
}
}
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);
}