#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(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; nIdxm_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; nCameraIdxm_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); }