#include "StdAfx.h"
|
#include "ImageMerger.h"
|
#include "CHImageControls/CHImageProcess.h"
|
|
|
CImageMerger::CImageMerger(int nThreadCount, IImageMerger2Parent* pIIM2P) : CWorkThreadPools(nThreadCount), m_pIIM2P(pIIM2P)
|
{
|
m_strImagePath = _T("");
|
m_nCameraType = -1;
|
m_nCameraCount = 0;
|
m_nScanCount = 0;
|
m_nRotationType = MergeRotationType_None;
|
m_dMergeScale = 1.0;
|
|
m_nMergeImageCount = 0;
|
m_nMergedImageCount = 0;
|
}
|
|
CImageMerger::~CImageMerger(void)
|
{
|
}
|
|
void CImageMerger::SetIIM2P( IImageMerger2Parent* pIIM2P )
|
{
|
m_csMergeImage.Lock();
|
m_pIIM2P = pIIM2P;
|
m_csMergeImage.Unlock();
|
}
|
|
void CImageMerger::WorkThreadProcess( PVOID pParameter )
|
{
|
if (m_pIIM2P==NULL) return;
|
if (pParameter==NULL) return;
|
CMergeThreadData* pThreadData = static_cast<CMergeThreadData*>(pParameter);
|
|
// load image
|
CString strLoadFilename = m_strImagePath + pThreadData->m_strImageFile;
|
|
CCHImageData sourceImage;
|
if (sourceImage.LoadImage(strLoadFilename)==FALSE)
|
{
|
return;
|
}
|
|
// check channels
|
int nSourceChannels = sourceImage.GetChannels();
|
int nTargetChannels = m_MergeImage.GetChannels();
|
if (nTargetChannels != nSourceChannels)
|
{
|
return;
|
}
|
|
// image flip
|
CCHImageData *pFlipImage = &sourceImage;
|
CCHImageData flipeImage;
|
switch(pThreadData->m_nFlipType)
|
{
|
case MergeFlipType_Vertical:
|
if (CCHImageProcess::ImageFlip(&sourceImage, &flipeImage, CHImageControls::FlipTypeVert)==1)
|
{
|
pFlipImage = &flipeImage;
|
}
|
else pFlipImage = NULL;
|
break;
|
|
case MergeFlipType_Horizontal:
|
if (CCHImageProcess::ImageFlip(&sourceImage, &flipeImage, CHImageControls::FlipTypeHoriz)==1)
|
{
|
pFlipImage = &flipeImage;
|
}
|
else pFlipImage = NULL;
|
break;
|
}
|
|
if (pFlipImage==NULL)
|
{
|
return;
|
}
|
|
// image rotation
|
CCHImageData *pRotationImage = pFlipImage;
|
CCHImageData rotationImage;
|
switch(pThreadData->m_nRotationType)
|
{
|
case MergeRotationType_Left: // left
|
if (CCHImageProcess::ImageRotate(pRotationImage, &rotationImage, CHImageControls::RotateTypeLeft)==1)
|
{
|
pRotationImage = &rotationImage;
|
}
|
else pRotationImage = NULL;
|
break;
|
|
case MergeRotationType_Right: // right
|
if (CCHImageProcess::ImageRotate(pRotationImage, &rotationImage, CHImageControls::RotateTypeRight)==1)
|
{
|
pRotationImage = &rotationImage;
|
}
|
else pRotationImage = NULL;
|
break;
|
}
|
|
if (pRotationImage==NULL)
|
{
|
return;
|
}
|
|
// ¿øº» À̹ÌÁö ¹öÆÛ ½ÃÀÛ À§Ä¡
|
int nSourceStep = pRotationImage->GetWidthStep();
|
char* pSourceBuffer = pRotationImage->GetImageBuffer() + (pThreadData->m_nSourcePosY * nSourceStep) + (pThreadData->m_nSourcePosX * nSourceChannels);
|
|
// Ÿ°Ù À̹ÌÁö ¹öÆÛ ½ÃÀÛ À§Ä¡
|
int nTargetStep = m_MergeImage.GetWidthStep();
|
char* pTargetBuffer = m_MergeImage.GetImageBuffer() + (pThreadData->m_nTargetPosY * nTargetStep) + (pThreadData->m_nTargetPosX * nTargetChannels);
|
|
// À̹ÌÁö ¹öÆÛ º¹»ç
|
for (int nIdx=0; nIdx<pThreadData->m_nTargetHeight; nIdx++)
|
{
|
memcpy(pTargetBuffer, pSourceBuffer, sizeof(char)*(pThreadData->m_nSourceWidth*nSourceChannels));
|
pSourceBuffer = pSourceBuffer + nSourceStep;
|
pTargetBuffer = pTargetBuffer + nTargetStep;
|
}
|
|
m_csMergeImage.Lock();
|
m_nMergedImageCount++;
|
if (m_nMergedImageCount>=m_nMergeImageCount)
|
{
|
m_pIIM2P->IIM2P_SetMergeComplete(m_nCameraType, m_nMergedImageCount);
|
}
|
m_csMergeImage.Unlock();
|
}
|
|
BOOL CImageMerger::CalculateThreadData_None(int nCameraWidth, int nGlassHeight, CMergeThreadData* pThreadData)
|
{
|
if (m_pIIM2P==NULL) return FALSE;
|
if (pThreadData==NULL) return FALSE;
|
|
int nMarginLeft = 0;
|
int nMarginRight = 0;
|
if (m_pIIM2P->IIM2P_GetCameraMarginPixel(m_nCameraType, pThreadData->m_nCameraIndex, pThreadData->m_nScanIndex, nMarginLeft, nMarginRight)==FALSE)
|
{
|
return FALSE;
|
}
|
|
int nGlassStart = 0;
|
if (m_pIIM2P->IIM2P_GetGlassStartPixel(m_nCameraType, pThreadData->m_nCameraIndex, pThreadData->m_nScanIndex, nGlassStart)==FALSE)
|
{
|
return FALSE;
|
}
|
|
pThreadData->m_nFlipType = (pThreadData->m_nScanIndex%2==0) ? MergeFlipType_None: MergeFlipType_Vertical; // ¿ª¹æÇâÀϽà flip
|
|
pThreadData->m_nSourcePosX = (int)((nMarginLeft * m_dMergeScale) + 0.5);
|
pThreadData->m_nSourceWidth = (int)(((nCameraWidth - nMarginLeft - nMarginRight) * m_dMergeScale) + 0.5);
|
|
pThreadData->m_nSourcePosY = (int)((nGlassStart * m_dMergeScale) + 0.5);
|
pThreadData->m_nSourceHeight = (int)((nGlassHeight * m_dMergeScale) + 0.5);
|
|
return TRUE;
|
}
|
|
BOOL CImageMerger::CalculateThreadData_Right(int nCameraWidth, int nGlassHeight, CMergeThreadData* pThreadData)
|
{
|
int nMarginLeft = 0;
|
int nMarginRight = 0;
|
if (m_pIIM2P->IIM2P_GetCameraMarginPixel(m_nCameraType, pThreadData->m_nCameraIndex, pThreadData->m_nScanIndex, nMarginLeft, nMarginRight)==FALSE)
|
{
|
return FALSE;
|
}
|
|
int nGlassStart = 0;
|
if (m_pIIM2P->IIM2P_GetGlassStartPixel(m_nCameraType, pThreadData->m_nCameraIndex, pThreadData->m_nScanIndex, nGlassStart)==FALSE)
|
{
|
return FALSE;
|
}
|
|
pThreadData->m_nFlipType = (pThreadData->m_nScanIndex%2==0) ? MergeFlipType_None: MergeFlipType_Vertical; // ¿ª¹æÇâÀϽà flip
|
|
pThreadData->m_nSourcePosX = (int)((nGlassStart * m_dMergeScale) + 0.5);
|
pThreadData->m_nSourceWidth = (int)((nGlassHeight * m_dMergeScale) + 0.5);
|
|
pThreadData->m_nSourcePosY = (int)((nMarginLeft * m_dMergeScale) + 0.5);
|
pThreadData->m_nSourceHeight = (int)(((nCameraWidth - nMarginLeft - nMarginRight) * m_dMergeScale) + 0.5);
|
|
return TRUE;
|
}
|
|
BOOL CImageMerger::CalculateThreadData_Left(int nCameraWidth, int nGlassHeight, CMergeThreadData* pThreadData)
|
{
|
int nMarginLeft = 0;
|
int nMarginRight = 0;
|
if (m_pIIM2P->IIM2P_GetCameraMarginPixel(m_nCameraType, pThreadData->m_nCameraIndex, pThreadData->m_nScanIndex, nMarginLeft, nMarginRight)==FALSE)
|
{
|
return FALSE;
|
}
|
|
int nGlassStart = 0;
|
if (m_pIIM2P->IIM2P_GetGlassStartPixel(m_nCameraType, pThreadData->m_nCameraIndex, pThreadData->m_nScanIndex, nGlassStart)==FALSE)
|
{
|
return FALSE;
|
}
|
|
pThreadData->m_nFlipType = (pThreadData->m_nScanIndex%2==0) ? MergeFlipType_None: MergeFlipType_Vertical; // ¿ª¹æÇâÀϽà flip
|
|
pThreadData->m_nSourcePosX = (int)((nGlassStart * m_dMergeScale) + 0.5);
|
pThreadData->m_nSourceWidth = (int)((nGlassHeight * m_dMergeScale) + 0.5);
|
|
pThreadData->m_nSourcePosY = (int)((nMarginRight * m_dMergeScale) + 0.5);
|
pThreadData->m_nSourceHeight = (int)(((nCameraWidth - nMarginLeft - nMarginRight) * m_dMergeScale) + 0.5);
|
|
return TRUE;
|
}
|
|
int CImageMerger::SetMergeData( int nCameraType, int nCameraCount, int nScanCount, const CString& strImagePath, int nRotationType, int nMergeChannels, double dMergeScale )
|
{
|
if (m_pIIM2P==NULL) return 0;
|
|
m_csMergeImage.Lock();
|
|
m_nMergeImageCount = 0;
|
m_nMergedImageCount = 0;
|
m_nCameraType = nCameraType;
|
m_nCameraCount = nCameraCount;
|
m_nScanCount = nScanCount;
|
m_strImagePath = strImagePath;
|
m_nRotationType = nRotationType;
|
m_dMergeScale = dMergeScale;
|
|
int nCameraWidth = m_pIIM2P->IIM2P_GetCameraWidthPixel(m_nCameraType);
|
int nGlassHeight = m_pIIM2P->IIM2P_GetGlassHeightPixel(m_nCameraType);
|
|
int nTotalMergeWidth = (m_nRotationType==MergeRotationType_None) ? 0: nGlassHeight;
|
int nTotalMergeHeight = (m_nRotationType==MergeRotationType_None) ? nGlassHeight: 0;
|
|
VectorMergeThreadData vecThreadData;
|
|
for (int nCameraIdx=0; nCameraIdx<m_nCameraCount; nCameraIdx++)
|
{
|
for (int nScanIdx=0; nScanIdx<m_nScanCount; nScanIdx++)
|
{
|
CMergeThreadData *pThreadData = new CMergeThreadData(this);
|
if (pThreadData==NULL) continue;
|
|
// set thread data
|
pThreadData->m_nCameraIndex = nCameraIdx;
|
pThreadData->m_nScanIndex = nScanIdx;
|
pThreadData->m_nRotationType = m_nRotationType;
|
|
// set source image pos
|
BOOL bResult = FALSE;
|
switch(pThreadData->m_nRotationType)
|
{
|
case MergeRotationType_None: // none
|
bResult = CalculateThreadData_None(nCameraWidth, nGlassHeight, pThreadData);
|
break;
|
|
case MergeRotationType_Left: // left
|
bResult = CalculateThreadData_Left(nCameraWidth, nGlassHeight, pThreadData);
|
break;
|
|
case MergeRotationType_Right: // right
|
bResult = CalculateThreadData_Right(nCameraWidth, nGlassHeight, pThreadData);
|
break;
|
}
|
|
if (bResult==FALSE)
|
{
|
delete pThreadData;
|
continue;
|
}
|
|
// set image file name
|
pThreadData->m_strImageFile.Format(_T("\\%d_%d.jpg"), nCameraIdx, nScanIdx);
|
|
// set target image size
|
pThreadData->m_nTargetWidth = pThreadData->m_nSourceWidth;
|
pThreadData->m_nTargetHeight = pThreadData->m_nSourceHeight;
|
|
// set target image pos
|
switch(pThreadData->m_nRotationType)
|
{
|
case MergeRotationType_None: // none
|
pThreadData->m_nTargetPosX = nTotalMergeWidth;
|
pThreadData->m_nTargetPosY = 0;
|
break;
|
|
case MergeRotationType_Left: // left
|
pThreadData->m_nTargetPosX = 0;
|
pThreadData->m_nTargetPosY = nTotalMergeHeight;
|
break;
|
|
case MergeRotationType_Right: // right
|
pThreadData->m_nTargetPosX = 0;
|
pThreadData->m_nTargetPosY = nTotalMergeHeight;
|
break;
|
}
|
|
// add merge pos
|
if (pThreadData->m_nRotationType==MergeRotationType_None)
|
{
|
nTotalMergeWidth += pThreadData->m_nTargetWidth;
|
}
|
else
|
{
|
nTotalMergeHeight += pThreadData->m_nTargetHeight;
|
}
|
|
vecThreadData.push_back(pThreadData);
|
|
m_nMergeImageCount++;
|
}
|
}
|
|
// create merge image
|
if (m_MergeImage.CreateImage(nTotalMergeWidth, nTotalMergeHeight, 8, nMergeChannels)==FALSE)
|
{
|
m_csMergeImage.Unlock();
|
return 0;
|
}
|
m_csMergeImage.Unlock();
|
|
|
for (VectorMergeThreadDataIt it=vecThreadData.begin(); it!=vecThreadData.end(); it++)
|
{
|
CMergeThreadData *pThreadData = *it;
|
|
if (pThreadData->m_nRotationType==MergeRotationType_Left)
|
{
|
pThreadData->m_nTargetPosY = nTotalMergeHeight - (pThreadData->m_nTargetPosY + pThreadData->m_nTargetHeight);
|
}
|
|
if (CreateWorkThread(pThreadData)==FALSE)
|
{
|
continue;
|
}
|
}
|
|
return m_nMergeImageCount;
|
}
|
|
BOOL CImageMerger::SaveImage( const CString& strFilename, int nQuality )
|
{
|
return m_MergeImage.SaveImage(strFilename, nQuality);
|
}
|