#include "StdAfx.h" #include "ImageMatQueue.h" #include "PublicFunc.h" #include "ImageProcess/ImageApplyHeaders.h" #include "ImageMultiOutput.h" #include "filetools.h" #include #include "StopWatch.h" #include "ImageProcess/ImageApplyUV.h" using namespace cv; using namespace std; #define DECODE_COLOR_BGR 1 #define DECODE_GRAY 6 G200Decode::G200Decode(std::shared_ptr> buff) { m_buffs.push_back(buff); } 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 data) { m_rawBuffs.Put(data); atm_orgin_image_remains++; } std::shared_ptr> 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(new CImageOutHole(200, ratio, 50))); } //确保能够获取正反两面图 { 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(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(new CImageApplyDiscardBlank(param.is_autodiscradblank_normal ? true : false))); //m_iaList.push_back(shared_ptr(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(new CImageApplyChannel(static_cast(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(new CImageApplyAdjustColors(bright, contrast, param.gamma))); } if (param.sharpen) { SharpenBlur sb = (SharpenBlur)param.sharpen; m_iaList.push_back(shared_ptr(new CImageApplySharpen(sb))); } if (param.pixtype == 0) //threshold m_iaList.push_back(shared_ptr(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 / 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(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); #ifdef MAKEHUAGAO _tcscat(szIniFile, _T("\\twain_32\\HuaGoScan\\tessdata")); #else defined MAKERTW _tcscat(szIniFile, _T("\\twain_32\\RighTWayScan\\tessdata")); #endif // MAKEHUGO 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(type, param.is_backrotate180, param.resolution_dst, chRtn))); delete[] chRtn; } } void ImageMatQueue::EnqueueBmpBuffer(std::vector& bmpdata) { //std::lock_guard lock(m_Locker); //m_imagedata.Put(bmpdata); } void ImageMatQueue::EnqueueBmpBuffer(std::shared_ptr> bmpdata) { m_imagedata.Put(bmpdata); } void ImageMatQueue::PaniusCount(bool enableuv) { enableuv? atm_orgin_image_remains-=2: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(); vector>> uvbuffers; if (scanParam.en_uv) uvbuffers = m_rawBuffs.Take()->getImageBuffs(); if (!m_rawBuffs.IsShutDown() && !buffs.empty()) { vector mats; for (auto& buf : buffs) { ImreadModes rm = IMREAD_COLOR;//全部按照彩色解压 if (scanParam.pixtype == 0) rm = ImreadModes::IMREAD_GRAYSCALE; try { cv::Mat mat = cv::imdecode(*buf, rm); buf.reset(); //cv::imwrite("D:\\error\\org" + to_string(++index) + ".jpg", mat); if (mat.empty()) { writelog("decode image data error"); } 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(scanParam.is_switchfrontback?front:back ); mats.push_back(scanParam.is_switchfrontback? back:front); front.release(); back.release(); } catch (const std::exception& e) { writelog(e.what()); } } buffs.clear(); for (auto& buf : uvbuffers) { ImreadModes rm = IMREAD_COLOR;//全部按照彩色解压 if (scanParam.pixtype == 0) rm = ImreadModes::IMREAD_GRAYSCALE; try { cv::Mat mat = cv::imdecode(*buf, rm); buf.reset(); if (mat.empty()) { writelog("decode image data error"); } Mat front = mat(Rect(0, 0, mat.cols / 2, mat.rows)); Mat back = mat(Rect(mat.cols / 2, 0, mat.cols / 2, mat.rows)); m_uvMats.push_back(scanParam.is_switchfrontback ? front : back); m_uvMats.push_back(scanParam.is_switchfrontback ? back : front); front.release(); back.release(); } catch (const std::exception& e) { writelog(e.what()); } } uvbuffers.clear(); std::vector rects; std::vector angleResults; bool isDesaskew = false; for (int j = 0; j < m_iaList.size(); j++) { m_iaList[j]->apply(mats, scanParam.is_duplex); CImageApply* ptr = m_iaList[j].get(); if (typeid(*ptr) == typeid(CImageApplyAutoCrop)) { rects = dynamic_cast(ptr)->rotatedROIs(); isDesaskew = dynamic_cast(ptr)->isDesaskew(); } else if (typeid(*ptr) == typeid(CImageApplyRotation)) angleResults = dynamic_cast(ptr)->angleResults(); } if (!m_uvMats.empty()) { //拼接原图和UV图 for (int j = 0; j < mats.size(); j++) { if (!scanParam.is_duplex && j == 1) { mats[j].release(); break; } cv::Mat mergeOrgin_UV = ImageApplyUV::Apply(mats[j], m_uvMats[j], rects[j], isDesaskew, angleResults.size() > 0 ? angleResults[j] : 0); //cv::imwrite("D:/0.bmp", mergeOrgin_UV); if (!mergeOrgin_UV.empty()) mats[j] = mergeOrgin_UV; } m_uvMats.clear(); } if (scanParam.en_fold) { CImageApplyConcatenation Concatenation; if(scanParam.en_uv) Concatenation= CImageApplyConcatenation(CImageApplyConcatenation::vertical); else Concatenation = CImageApplyConcatenation(CImageApplyConcatenation::horizontal); Concatenation.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()) { if (scanParam.pixtype == 1 && mats[i].channels() == 3)//gray cv::cvtColor(mats[i], mats[i], COLOR_BGR2GRAY); IMat2Bmp idata; idata = scanParam.pixtype == 0 ? (IMat2Bmp)Mat2BmpBw(mats[i], scanParam.resolution_dst) : Mat2Bmp(mats[i], scanParam.resolution_dst); auto data = idata.getBmpDataBuffer(); CStdioFile file; 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(scanParam.en_uv==1); } } } GRawDecode::GRawDecode(std::shared_ptr> buff) { m_buffs.push_back(buff); }