twain3/device/ImageMatQueue.cpp

437 lines
13 KiB
C++
Raw Permalink Normal View History

#include "ImageMatQueue.h"
#include "ImageApplyHeaders.h"
#include "GScan.h"
#include "filetools.h"
#include "common.h"
#include "Global.h"
#include <iostream>
#ifdef WIN32
#include <Windows.h>
#include <shlobj.h>
#include <tchar.h>
#endif // WIN32
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));
}
}
ImageMatQueue::~ImageMatQueue(void)
{
if (m_rawBuffs.Size() > 0) {
m_rawBuffs.Clear();
m_rawBuffs.ShutDown();
}
if (m_imagedata.Size() > 0) {
m_imagedata.Clear();
m_imagedata.ShutDown();
}
if (m_threadProc.get()) {
bRun = false;
this_thread::sleep_for(chrono::milliseconds(200));
if (m_threadProc->joinable()) {
m_threadProc->join();
m_threadProc.reset();
}
}
}
void ImageMatQueue::pushMat(std::shared_ptr<IDecode> data)
{
m_rawBuffs.Put(data);
atm_orgin_image_remains++;
}
MatEx ImageMatQueue::popimage()
{
auto ret = m_imagedata.Take();
return ret;
}
void ImageMatQueue::get_image_front_info(ImageInfo* info)
{
auto tempMat = m_imagedata.Take();
info->Width = tempMat.mat.cols;
info->Height = tempMat.mat.rows;
info->bpp = tempMat.Bpp;
}
bool ImageMatQueue::valid()
{
return m_imagedata.Size();
}
void ImageMatQueue::clear()
{
m_rawBuffs.Clear();
m_imagedata.Clear();
atm_orgin_image_remains = 0;
}
void ImageMatQueue::setparam(GScanCap& param)
{
scanParam = param;
m_iaList.clear();
#ifndef _NOT_USE
if (param.imageProcess.fillHole.enable) {
float scale = param.imageProcess.fillHole.ratio / 100.0;
m_iaList.push_back(shared_ptr<CImageApply>(new CImageOutHole(90, scale, 80.0f)));
}
#endif // _NOT_USE
bool autocrop = param.paperSize== TwSS::None;
/*pixtype 0 colcor; 1 gray; 2 bw*/
SIZE temp_Size = papersize.GetPaperSize(param.paperSize, 200,param.paperAlign);
cv::Size cvSize(temp_Size.cx, temp_Size.cy);
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(param.imageProcess.autoCrop,
param.hardwareParam.skewDetection.enable,
param.imageProcess.fillBlackRect,
cvSize,true,
param.imageProcess.isfillcolor)));
if (param.scanSide.discardBlank|| param.scanSide.discardBlankVince) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyDiscardBlank()));
}
if (param.resolution != param.resolution_native)
{
CImageApplyResize::ResizeType resizeType;
double ratio = 1.0;
SIZE reSize = papersize.GetPaperSize(param.paperSize, param.resolution, param.paperAlign);
cv::Size cvSize(reSize.cx, reSize.cy);
if (param.imageProcess.autoCrop || param.cropRect.enable) {
resizeType = CImageApplyResize::ResizeType::RATIO;
ratio = param.resolution/ param.resolution_native;
}
else {
resizeType = CImageApplyResize::ResizeType::DSIZE;
}
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyResize(resizeType,
cvSize,
ratio,
ratio)));
}
if (param.cropRect.enable &&!param.imageProcess.autoCrop) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyCustomCrop(cv::Rect(param.cropRect.x, param.cropRect.y,param.cropRect.width, param.cropRect.height))));
}
if ((param.imageProcess.filter != ColorFilter::FILTER_NONE) && (param.pixelType != ColorMode::RGB)) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyChannel((CImageApplyChannel::channel)(param.imageProcess.filter))));
}
if (param.imageProcess.customGamma.enable) {
if (param.imageProcess.customGamma.tableLength == 256)
{
uchar table[256];
memcpy(table, param.imageProcess.customGamma.table, 256);
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyCustomGamma(table, param.imageProcess.customGamma.tableLength)));
}
else
{
uchar table[768];
memcpy(table, param.imageProcess.customGamma.table, 768);
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyCustomGamma(table, param.imageProcess.customGamma.tableLength)));
}
}
else {
if (param.imageProcess.brightness != 128 ||
param.imageProcess.contrast != 4 ||
(param.imageProcess.gamma <(1.0f-1e-2)) || (param.imageProcess.gamma> (1.0f+1e-2))) {
int temp_contrast=(param.imageProcess.contrast-4)*12;
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyAdjustColors(param.imageProcess.brightness-128, temp_contrast, param.imageProcess.gamma)));
}
}
if ((param.pixelType == 2) && param.imageProcess.answerSheetFilterRed) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyHSVCorrect(CImageApplyHSVCorrect::Red_Removal)));
}
if (param.imageProcess.refuseInflow) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyRefuseInflow()));
}
if ((param.imageProcess.colorCorrection) && (param.pixelType != ColorMode::BlackWhite)) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyAutoContrast()));
}
if (param.scanSide.fold) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyConcatenation(CImageApplyConcatenation::horizontal, cv::Scalar(255, 255, 255))));
}
if ((param.imageProcess.orentation!=0) ||param.imageProcess.backRotate180 )
{
CImageApplyRotation::RotationType rotatetype = (CImageApplyRotation::RotationType)param.imageProcess.orentation;
if (param.imageProcess.orentation==Orentation::AUTOTEXT_DETECT)
rotatetype = CImageApplyRotation::RotationType::AutoTextOrientation;
#ifdef WIN32
#ifndef _NOT_USE
WCHAR szIniFile[MAX_PATH] = { 0 };
SHGetSpecialFolderPathW(NULL, szIniFile, CSIDL_WINDOWS, TRUE);
wcscat(szIniFile, L"\\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(rotatetype,param.imageProcess.backRotate180, param.resolution, chRtn)));
delete[] chRtn;
#endif //_NOT_USE
#else // WIN32
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyRotation(rotatetype, param.imageProcess.backRotate180, param.resolution, "/opt/apps/com.huagaochina.huagoscan/files/doc/HuaGoScan")));
#endif
}
if (param.imageProcess.textureRemove) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyTextureRemoval()));
}
if (param.imageProcess.sharpenType!=0) {
CImageApplyFilter::FilterMode sharpenType = (CImageApplyFilter::FilterMode)param.imageProcess.sharpenType;
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyFilter(sharpenType)));
}
if (param.pixelType == ColorMode::BlackWhite)//黑白图像
{
CImageApplyBWBinaray::ThresholdType thrtype;
if (param.imageProcess.errorExtention) {
thrtype = CImageApplyBWBinaray::ThresholdType::ERROR_DIFFUSION;
}
else {
thrtype = CImageApplyBWBinaray::ThresholdType::THRESH_BINARY;
}
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyBWBinaray(thrtype)));
if (param.imageProcess.nosieDetach) {
m_iaList.push_back(shared_ptr < CImageApply >(new CImageApplyDetachNoise()));
}
}
m_multiprc_list.clear();
if (param.imageProcess.multiOutFilterRed && (param.pixelType == ColorMode::RGB)) {
m_multiprc_list.push_back(shared_ptr<IMulti>(new ImageMultiOutputRed(2)));
}
if (param.multiOutput != -1) {
m_multiprc_list.push_back(shared_ptr<IMulti>(new IMageMulti(param.multiOutput)));
}
//if (param.imageProcess.splitImage) {
// m_multiprc_list.push_back(shared_ptr<IMulti>(new CImageApplySplit(param.multiOutput,param.imageProcess.splitImage, param.imageProcess.multiOutFilterRed,param.pixelType)));
//}
}
void ImageMatQueue::EnqueueMat(cv::Mat& mat) {
//m_imagedata.Put(mat);
}
void ImageMatQueue::EnqueueMatOutPut(MatEx& matoutput)
{
m_imagedata.Put(matoutput);
}
void ImageMatQueue::PaniusCount()
{
atm_orgin_image_remains--;
}
bool ImageMatQueue::empty()
{
return atm_orgin_image_remains == 0 && m_imagedata.Size() == 0 && !is_scanning;
}
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.imageProcess.filter != ColorFilter::FILTER_NONE)|| scanParam.imageProcess.multiOutFilterRed) {
rm = IMREAD_COLOR;
}
else{
rm = scanParam.pixelType == 2 ? IMREAD_COLOR : IMREAD_GRAYSCALE;
}
cv::Mat mat;
if (mode == 0){
mat = cv::imdecode(*buf, rm);
mats.push_back(mat);
}
else
{
mat = cv::imdecode(*buf, rm);
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 (mode == 1)
{
if ((scanParam.imageProcess.orentation != 0) && scanParam.imageProcess.orentation != 2) {
cv::flip(front, front, 0);
cv::flip(front, front, 1);
}
}
mats.push_back(back);
mats.push_back(front);
}
}
//if (scanParam.scanSide.switchFrontBack)
//{
// cv::Mat f = mats[0];
// mats[0] = mats[1];
// mats[1] = f;
//}
if (scanParam.scanSide.fold) {
cv::flip(mats[0], mats[0], 1);
cv::flip(mats[0], mats[0], 0);
}
for (int j = 0; j < m_iaList.size(); j++) {
m_iaList[j]->apply(mats, scanParam.scanSide.duplex);
}
vector< cv::Mat> matall;
for (int i = 0; i < mats.size(); i++) {
if ((!scanParam.scanSide.duplex) && (i == 1))
break;
bool multiout_red, multi_type, msplit;
multiout_red = scanParam.imageProcess.multiOutFilterRed;
multi_type = scanParam.multiOutput != -1;
msplit = scanParam.imageProcess.splitImage;
if (multiout_red || multi_type || msplit)
{
vector < cv::Mat > retmats;
for (int j = 0; j < m_multiprc_list.size(); j++) {
if (!mats[i].empty())
retmats = m_multiprc_list[j]->apply(mats[i]);
}
int colormode = 1;
if (scanParam.imageProcess.filter == ColorFilter::FILTER_NONE)
colormode = scanParam.pixelType;
CImageApplySplit isp(scanParam.multiOutput, msplit, multiout_red, colormode);
if (!retmats.size())//如果没有多流,只有拆分
{
auto matexs = isp.SplitMats(mats, scanParam.scanSide.duplex);
for (auto &matex : matexs)
EnqueueMatOutPut(matex);
break;
}
else
{
auto matexs = isp.SplitMats(retmats,scanParam.imageProcess.splitImage);
for (auto &matex : matexs)
EnqueueMatOutPut(matex);
}
}
else {
if (!mats[i].empty()) {
int bpp = scanParam.pixelType == ColorMode::BlackWhite ? 1 : (scanParam.pixelType == ColorMode::Gray ? 8 : 24);
if (scanParam.imageProcess.filter != ColorFilter::FILTER_NONE) { bpp = 8; }
MatEx out(mats[i], bpp);
EnqueueMatOutPut(out);
}
}
}
PaniusCount();
}
}
}
void ImageMatQueue::EnqueueCheck(bool multiout_red, int s, std::vector<cv::Mat>& retmats)
{
if (multiout_red) {
int bpp = s == 0 ? 24 : 8;
MatEx out(retmats[s], bpp);//第一张一定是24位彩色图
EnqueueMatOutPut(out);
}
else {
int bpp = -1;
/*switch ((Multi_output)scanParam.ImageProcessParam.MultiOutputType)
{
case All:
if (s == 0) bpp = 24;
else if (s == 1) bpp = 8;
else bpp = 1;
break;
case ColorGray:
if (s == 0) bpp = 24;
else if (s == 1) bpp = 8;
break;
case ColorBw:
if (s == 0) bpp = 24;
else if (s == 1) bpp = 1;
break;
case GrayBw:
if (s == 0) bpp = 8;
else if (s == 1) bpp = 1;
break;
default:
break;
}*/
if (bpp != -1)
{
MatEx out(retmats[s], bpp);//第一张一定是24位彩色图
EnqueueMatOutPut(out);
}
}
}
GRawDecode::GRawDecode(std::shared_ptr<std::vector<char>> buff)
{
m_buffs.push_back(buff);
}