| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "Thread_SaveFullImg.h" |
| | | |
| | | static void TightCopy(std::vector<BYTE>& 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<std::mutex> 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<std::mutex> oLock(m_Mtx); |
| | | m_Q.push(std::move(oJob)); |
| | | } |
| | | m_Cv.notify_one(); |
| | | } |
| | | |
| | | size_t CThread_SaveFullImg::GetPendingCount() const |
| | | { |
| | | std::lock_guard<std::mutex> oLock(m_Mtx); |
| | | return m_Q.size(); |
| | | } |
| | | |
| | | void CThread_SaveFullImg::ThreadProc() |
| | | { |
| | | while (true) { |
| | | SaveImgJob oJob; { |
| | | std::unique_lock<std::mutex> 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<int>(origin.cols * dRatio)); |
| | | const int nOutH = std::max(1, static_cast<int>(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<int> 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; |
| | | } |