mirror of http://192.168.1.51:8099/lmh188/twain3
437 lines
13 KiB
C++
437 lines
13 KiB
C++
#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);
|
|
} |