우선 비트맵 두개를 비교한다는 것이 XOR 연산을 통하여 보는 것보다. 영상처리의 Subtraction을 이용하는 것이 더욱 속도도 빠르고, 정확한 결과를 얻을 수 있을 것 같습니다.
우선 두개의 비트맵 또는 이미지 파일의 원본 버퍼를 읽어서, (두개의 사이즈가 같다고 가정하고) Subtraction을 수행합니다. 간단한 코드를 예제로 해보겠습니다.
void Subtraction(int nWidth, nHeight, void* pSrcA, void* pSrcB, /*out*/void *pDst)
{
for(register int y = 0; y < nHeight; ++y)
for(register int x = 0; x < nWidth; ++x)
pDst[y * nWidth + x] = pSrcA[y * nWidth + x] - pSrcB[y * nWidth + x];
}
nWidth, nHeight는 영상의 크기를 나타내며, pSrcA와 pSrcB는 원본 비트맵의 버퍼입니다.
결과는 pDst에 저장되며, pDst를 버퍼로하는 비트맵을 만들어서 화면에 출력하게 되면, A 영상과 B 영상의 차이점을 확인할 수가 있습니다.
위 소스는 테스트되지 않았습니다.
/*
> Function: CheckBmp
> Parameters:
szFileName: 비트맵 파일명
rRect: 캡쳐할 영역
*/
BOOL CheckBmp(LPTSTR szFileName, CRect &rRect)
{
int x,y;
int dx,dy;
CDC memDC;
CDC ScreenDC;
CBitmap m_Bitmap;
CPalette m_Pal;
x = rRect.TopLeft().x;
y = rRect.TopLeft().y;
dx = rRect.Width();
dy = rRect.Height();
ScreenDC.CreateDC("DISPLAY", NULL, NULL, NULL); //스크린 DC를 얻는다.
memDC.CreateCompatibleDC(&ScreenDC); //스크린 DC와 호환되는 DC 를 만든다
m_Bitmap.CreateCompatibleBitmap(&ScreenDC, dx, dy); //스크린 DC와 호환되는 비트맵을 만든다.
CBitmap* pOldBitmap = memDC.SelectObject(&m_Bitmap);
memDC.StretchBlt(0, 0, dx, dy, &ScreenDC, x, y, dx, dy, SRCCOPY);
//현재 해상도가 256칼라 이하라면 팔레트 추가
if( ScreenDC.GetDeviceCaps(RASTERCAPS) & RC_PALETTE ) {
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = GetSystemPaletteEntries(
ScreenDC,
0,
255,
pLP->palPalEntry );
// Create the palette
m_Pal.CreatePalette( pLP );
delete[] pLP;
}
memDC.SelectObject(pOldBitmap);
HANDLE hDIB = DDBToDIB(m_Bitmap, BI_RGB, &m_Pal);
ScreenDC.DeleteDC();
if (hDIB == NULL) {
return FALSE;
}
if ( TRUE == CompDIB(szFileName, hDIB) ) { //이미지 비교
GlobalFree(hDIB);
return TRUE;
} else {
GlobalFree(hDIB);
return FALSE;
}
}
// 주어진 파일명의 비트맵과 동일한 비트맵인가를 비교.
BOOL CompDIB(LPTSTR szFileName, HANDLE hDIB)
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
unsigned char *pBuf;
long lBmpSize;
if (!hDIB)
return FALSE;
CFile file;
if (!file.Open(szFileName, CFile::modeRead)) return FALSE;
lpbi = (LPBITMAPINFOHEADER)hDIB;
// 한 픽셀당 비트수를 왼쪽으로 1 이동 (shift)
int nColors = 1 << lpbi->biBitCount;
lBmpSize = GlobalSize(hDIB);
if(lBmpSize <= BMP_FRONT_GARBAGE_SIZE) {
return FALSE;
}
// Fill in the fields of the file header ( Bitmap file header )
hdr.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
hdr.bfSize = lBmpSize + sizeof(hdr); // 비트맵 파일의 전체 크기
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// 파일에서 비트맵 데이터가 있는 위치
hdr.bfOffBits = (DWORD) (sizeof(hdr)) + lpbi->biSize;
//준비
pBuf = (unsigned char *)malloc(lBmpSize-BMP_FRONT_GARBAGE_SIZE); //대충 큼직하게
file.Seek(sizeof(hdr)+BMP_FRONT_GARBAGE_SIZE, CFile::begin); //헤더랑 파레트는 뛴다.
file.Read(pBuf, lBmpSize- BMP_FRONT_GARBAGE_SIZE );
//DIB header and the bits 비교
if ( 0 != memcmp(pBuf, (char *)lpbi+BMP_FRONT_GARBAGE_SIZE, lBmpSize- BMP_FRONT_GARBAGE_SIZE ) ) {
free(pBuf);
file.Close();
return FALSE;
}
free(pBuf);
file.Close();
return TRUE;
}
Designed by sketchbooks.co.kr / sketchbook5 board skin
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5