如何在c ++中比较两个位图截图的字节到字节

时间:2011-06-05 13:31:23

标签: c++ visual-studio-2010 comparison bitmap msdn

在问题的最后我的最后编辑

大家好, 我必须实现一个功能,比较屏幕的一部分的两个镜头,以便知道是否存在差异/变化。我写了类似下面的代码,但我无法管理它。在代码中COORDINATES_RECT是一个结构

typedef struct _COORDINATES_RECT {
int     x;
int     y;
int     sizeX;
int     sizeY;
} COORDINATES_RECT; 

在输入中保存数据以了解哪个是要分析的屏幕部分,并在输出中返回函数发现变化的最大矩形的数据。为了更好地解释这个问题,我看到如果构造到底:

if(lpbitmap1[(i*bmpScreen1.bmWidth)+j] != lpbitmap2[(i*bmpScreen1.bmWidth)+j])

永远不会被执行。我不知道它是否是比较两个位图(转换为char数组)的正确方法。我用msogle搜索并搜索但没有结果。 完整代码如下:

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

由于

弗朗西斯

聚苯乙烯。变量声明放在它们引用的块旁边,只是为了在这个问题中更清晰。

编辑:

我像这样重写了它似乎工作:)感谢所有,但是任何更正都值得赞赏

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

2 个答案:

答案 0 :(得分:4)

不要完全自己比较两个位图,而是考虑使用BitBlt使用SRCINVERT运算符将它们组合在一起,将两者进行XOR运算,因此相同的部分将显示为零,并且所有非零区域将是差异。

答案 1 :(得分:0)

gc5,谢谢!我将添加我的2bit:

您应将bi定义为:

BITMAPINFO bi;
memset(&bi, 0, sizeof(BITMAPINFO));
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = bm.bmWidth;
bi.bmiHeader.biHeight = bm.bmHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;

,然后无需定义类型:

GetDIBits(memDC, hBm, 0, (UINT)bm.bmHeight, pixels, &bi, DIB_RGB_COLORS);