#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;
|
}
|