#include "ImageMatQueue.h" #include "ImageApplyHeaders.h" #include "GScan.h" #include "filetools.h" #include "common.h" #include "Global.h" #include #ifdef WIN32 #include #include #include #endif // WIN32 using namespace cv; using namespace std; #define DECODE_COLOR_BGR 1 #define DECODE_GRAY 6 G200Decode::G200Decode(std::shared_ptr> 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> buffB(new std::vector(buff->size())); std::shared_ptr> buffF(new std::vector(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 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(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(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(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(new ImageMultiOutputRed(2))); } if (param.multiOutput != -1) { m_multiprc_list.push_back(shared_ptr(new IMageMulti(param.multiOutput))); } //if (param.imageProcess.splitImage) { // m_multiprc_list.push_back(shared_ptr(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 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& 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> buff) { m_buffs.push_back(buff); }