IN THE END OF THE QUESTION MY LAST EDIT
Hi all, I have to implement a function that compares two shots of a portion of the screen in order to know if there are differences/variations. I wrote something like the following code but I can't manage it to work. In the code COORDINATES_RECT is a struct
typedef struct _COORDINATES_RECT {
int x;
int y;
int sizeX;
int sizeY;
} COORDINATES_RECT;
that in input holds data to know which is the portion of the screen to analyze, and in output returns the data of the biggest rectangle in which the function found variations. To better explain the problem, I saw that if construct in the end:
if(lpbitmap1[(i*bmpScreen1.bmWidth)+j] != lpbitmap2[(i*bmpScreen1.bmWidth)+j])
never get executed. I don't know if it is the right way to compare two bitmaps (converted into char arrays). I googled and searched in msdn but with no result. Full code follows:
void testBitmapVariations(COORDINATES_RECT *c)
{
HDC hdcScreen = GetDC(NULL);
HDC hdcMemDC1 = CreateCompatibleDC(hdcScreen);
HDC hdcMemDC2 = CreateCompatibleDC(hdcScreen);
HBITMAP hBmpScreen1 = NULL;
HBITMAP hBmpScreen2 = NULL;
BITMAP bmpScreen1;
BITMAP bmpScreen2;
if(!hdcMemDC1 || !hdcMemDC2)
{
MessageBox(NULL,L"CreateCompatibleDC failed", L"Failed", MB_OK);
ReleaseDC(NULL, hdcMemDC1);
ReleaseDC(NULL, hdcMemDC2);
return;
}
hBmpScreen1 = CreateCompatibleBitmap(hdcMemDC1, c->sizeX, c->sizeY);
hBmpScreen2 = CreateCompatibleBitmap(hdcMemDC2, c->sizeX, c->sizeY);
SelectObject(hdcMemDC1,hBmpScreen1);
if(!BitBlt(hdcMemDC1,
0,0,
c->sizeX, c->sizeY,
hdcScreen,
c->x,c->y,
SRCCOPY))
{
MessageBox(NULL,L"BitBlt failed", L"Failed", MB_OK);
ReleaseDC(NULL, hdcMemDC1);
ReleaseDC(NULL, hdcMemDC2);
return;
}
GetObject(hBmpScreen1,sizeof(BITMAP),&bmpScreen1);
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen1.bmWidth;
bi.biHeight = bmpScreen1.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = ((bmpScreen1.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen1.bmHeight;
// Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that
// call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc
// have greater overhead than HeapAlloc.
char *lpbitmap1 = (char *)malloc(dwBmpSize);
// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbitmap1.
GetDIBits(hdcScreen, hBmpScreen1, 0,
(UINT)bmpScreen1.bmHeight,
lpbitmap1,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);
Sleep(200);
SelectObject(hdcMemDC2,hBmpScreen2);
if(!BitBlt(hdcMemDC2,
0,0,
c->sizeX, c->sizeY,
hdcScreen,
c->x,c->y,
SRCCOPY))
{
MessageBox(NULL,L"BitBlt failed", L"Failed", MB_OK);
ReleaseDC(NULL, hdcMemDC1);
ReleaseDC(NULL, hdcMemDC2);
return;
}
GetObject(hBmpScreen2,sizeof(BITMAP),&bmpScreen2);
char *lpbitmap2 = (char *)malloc(dwBmpSize);
// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbitmap2.
GetDIBits(hdcScreen, hBmpScreen2, 0,
(UINT)bmpScreen2.bmHeight,
lpbitmap2,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);
int i, j, minX = bmpScreen1.bmWidth, minY = bmpScreen1.bmHeight, maxX = 0, maxY = 0;
bool changed = false;
for(i = 0; i < bmpScreen1.bmHeight; i++)
{
for(j = 0; j < bmpScreen1.bmWidth; j++)
{
// I don't know why this if never get executed
if(lpbitmap1[(i*bmpScreen1.bmWidth)+j] != lpbitmap2[(i*bmpScreen1.bmWidth)+j])
{
changed = true;
if(i < minY)
minY = i;
if(i > maxY)
maxY = i;
if(j < minX)
minX = j;
if(j > maxY)
maxY = j;
}
}
}
if(changed)
{
c->x = minX;
c->y = minY;
c->sizeX = maxX - minX;
c->sizeY = maxY - minY;
}
else
{
c->sizeX = 0;
c->sizeY = 0;
}
//Frees from the heap
free(lpbitmap1);
free(lpbitmap2);
ReleaseDC(NULL, hdcMemDC1);
ReleaseDC(NULL, hdcMemDC2);
}
Thanks
Francesco
Ps. Variables declarations are put next to the block they refers to only to achieve more clarity in this question..
EDIT:
I rewrote it like this and it seems to work :) Thanks to all, however any correction is appreciated
void testBitmapVar(COORDINATES_RECT *c)
{
HDC screenDC = GetDC(0),
memDC = CreateCompatibleDC(screenDC);
HBITMAP hBm = CreateCompatibleBitmap(screenDC, c->sizeX, c->sizeY),
oldHBm;
BITMAP bm;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
UINT *pixels = (UINT*) malloc ((c->sizeX*c->sizeY) * sizeof(UINT));
std::ostringstream ss;
std::wstring str;
int i, j, minX, maxX, minY, maxY;
if(!pixels)
{
c->sizeX = 0;
c->sizeY = 0;
return;
}
memset(pixels, 0, (c->sizeX*c->sizeY) * sizeof(UINT));
oldHBm = (HBITMAP) SelectObject(memDC, hBm);
// copies to bitmap
BitBlt(memDC, 0, 0, c->sizeX, c->sizeY, screenDC, c->x, c->y, SRCCOPY);
Sleep(500);
BitBlt(memDC, 0, 0, c->sizeX, c->sizeY, screenDC, c->x, c->y, SRCINVERT);
GetObject(hBm, sizeof(BITMAP), &bm);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
GetDIBits(memDC, hBm, 0,
(UINT)bm.bmHeight,
pixels,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);
for(i = 0, minY = c->sizeY, maxY = -1; i < c->sizeY; i++)
{
for(j = 0, minX = c->sizeX, maxX = -1; j < c->sizeX; j++)
{
if(pixels[(i*c->sizeX)+j])
{
if(i < minY)
minY = i;
if(i > maxY)
maxY = i;
if(j < minX)
minX = j;
if(j > maxX)
maxX = j;
}
}
}
if(maxX != -1 && maxY != -1)
{
c->x = minX;
c->y = minY;
c->sizeX = maxX - minX;
c->sizeY = maxY - minY;
}
else
{
c->sizeX = 0;
c->sizeY = 0;
}
free(pixels);
SelectObject(memDC, oldHBm);
DeleteObject(hBm);
ReleaseDC(0, screenDC);
DeleteDC(memDC);
}