#include "stdafx.h" #include "Thread_SaveFullImg.h" static void TightCopy(std::vector& vDst, const BYTE* pSrc, int nWidth, int nHeight, int nStride, int nBpp) { const int nTight = nWidth * nBpp; vDst.resize(size_t(nTight) * nHeight); if (vDst.empty() || nHeight < 1 || nWidth < 1 || nBpp < 1) { g_pLog->DisplayMessage(_T("TightCopy: Invalid parameters, nWidth=%d, nHeight=%d, nBpp=%d"), nWidth, nHeight, nBpp); return; } // Èç¹û nStride µÈÓÚ nTight£¬ËµÃ÷Ô´Êý¾ÝÊǽôÃÜÐд洢 if (nStride == nTight) { memcpy(vDst.data(), pSrc, vDst.size()); return; } // Èç¹û nStride СÓÚ nTight£¬ËµÃ÷Ô´Êý¾Ý²»ÊǽôÃÜÐд洢 if (nStride < nTight) { g_pLog->DisplayMessage(_T("TightCopy: Invalid nStride %d < nTight %d"), nStride, nTight); return; } // Èç¹û nStride ´óÓÚ nTight£¬ÖðÐи´ÖÆ for (int y = 0; y < nHeight; ++y) { memcpy(vDst.data() + size_t(y) * nTight, pSrc + size_t(y) * nStride, nTight); } } CThread_SaveFullImg::CThread_SaveFullImg() { m_bStop = false; } CThread_SaveFullImg::~CThread_SaveFullImg() { StopThread(); } void CThread_SaveFullImg::CreateThread() { if (m_Thread.joinable()) { return; } m_bStop = false; m_Thread = std::thread([this] { ThreadProc(); }); } void CThread_SaveFullImg::StopThread() { { std::lock_guard oLock(m_Mtx); m_bStop = true; } m_Cv.notify_all(); if (m_Thread.joinable()) { m_Thread.join(); } } void CThread_SaveFullImg::Enqueue(SaveImgJob&& oJob) { { std::lock_guard oLock(m_Mtx); m_Q.push(std::move(oJob)); } m_Cv.notify_one(); } size_t CThread_SaveFullImg::GetPendingCount() const { std::lock_guard oLock(m_Mtx); return m_Q.size(); } void CThread_SaveFullImg::ThreadProc() { while (true) { SaveImgJob oJob; { std::unique_lock oLock(m_Mtx); m_Cv.wait(oLock, [this] { return m_bStop || !m_Q.empty(); }); if (m_bStop && m_Q.empty()) { break; } oJob = std::move(m_Q.front()); m_Q.pop(); } try { SaveFullImageModern(oJob); } catch (...) { g_pLog->DisplayMessage(_T("Async save failed: %s"), oJob.strPath.c_str()); } } } BOOL CThread_SaveFullImg::SaveFullImageModern(const SaveImgJob& job) { int iSide = job.nDimension; if (iSide < 0 || iSide > MAX_DIMENSION_COUNT - 1) { g_pLog->DisplayMessage(_T("Save Full Image Fail(%S, %d), invalid side index"), job.strPath.c_str(), job.nDimension); return FALSE; } if (job.vData.empty() || job.nHeight < 100 || job.nWidth < 100 || job.nBpp < 0) { g_pLog->DisplayMessage(_T("Save Full Image Fail(%S, %s, %d, %d)"), job.strPath.c_str(), PANEL_SIDE[iSide], job.nWidth, job.nHeight); return FALSE; } if (job.nStride < job.nWidth * job.nBpp) { g_pLog->DisplayMessage(_T("Save Full Image Fail(%S), stride(%d) < width*bpp(%d)"), job.strPath.c_str(), job.nStride, job.nWidth * job.nBpp); return FALSE; } int nQuality = job.nQuality; if (nQuality < 0) { nQuality = 0; } if (nQuality > 100) { nQuality = 100; } double dTmp = 70 / 100.0; double dRatio = 1.0 - dTmp; dRatio = dRatio - 0.01 < 0.0 ? 1.0 : dRatio; g_pLog->DisplayMessage(_T("Save Full Image Start(%S, %s, %d, %d, %d)"), job.strPath.c_str(), PANEL_SIDE[job.nDimension], job.nStartY, job.nHeight, nQuality); int nStartY = job.nStartY; if (nStartY < 0) { nStartY = 0; } if (nStartY > job.nHeight - 1) { nStartY = job.nHeight - 1; } int cvType; switch (job.nBpp) { case 1: cvType = CV_8UC1; break; case 3: cvType = CV_8UC3; break; default: g_pLog->DisplayMessage(_T("Save Full Image Fail(%S), unsupported nBpp=%d"), job.strPath.c_str(), job.nBpp); return FALSE; } const BYTE* pBase = job.vData.data() + size_t(nStartY) * size_t(job.nStride); const int nHAvail = job.nHeight - nStartY; if (nHAvail < 100) { g_pLog->DisplayMessage(_T("Save Full Image Skip(%S, %s), nHAvail=%d too small"), job.strPath.c_str(), PANEL_SIDE[iSide], nHAvail); return FALSE; } // ԭʼͼÏñÊý¾Ýת cv::Mat cv::Mat origin(nHAvail, job.nWidth, cvType, (void*)pBase, size_t(job.nStride)); // Ëõ·ÅͼÏñ const int nOutW = std::max(1, static_cast(origin.cols * dRatio)); const int nOutH = std::max(1, static_cast(origin.rows * dRatio)); cv::Mat img; if (nOutW == origin.cols && nOutH == origin.rows) { img = origin; } else { cv::resize(origin, img, cv::Size(nOutW, nOutH), 0, 0, cv::INTER_LINEAR); } // ÉèÖà JPEG ѹËõ²ÎÊý std::vector params = { cv::IMWRITE_JPEG_QUALITY, nQuality }; try { if (!cv::imwrite(job.strPath, img, params)) { g_pLog->DisplayMessage(_T("Save Full Image Fail(%S, %s, %d), imwrite failed"), job.strPath.c_str(), PANEL_SIDE[iSide], nStartY); return FALSE; } } catch (...) { g_pLog->DisplayMessage(_T("Save Full Image Fail(%S, %s, %d), exception during imwrite"), job.strPath.c_str(), PANEL_SIDE[iSide], nStartY); return FALSE; } g_pLog->DisplayMessage(_T("Save Full Image Success(%S, %s, %d, %d, %d)"), job.strPath.c_str(), PANEL_SIDE[iSide], nStartY, job.nHeight, nQuality); return TRUE; }