c++ - 如何比较 C++ 中两个位图屏幕截图的字节与字节

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

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

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

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

在输入中保存数据以了解要分析的屏幕部分,在输出中返回函数发现变化的最大矩形的数据。为了更好的说明问题,最后看到if构造:

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

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

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

谢谢

弗朗切斯科

附言。变量声明放在它们引用的 block 旁边只是为了使这个问题更加清晰。

编辑:

我像这样重写了它,它似乎可以工作 :) 谢谢大家,但是任何更正都是值得赞赏的

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

最佳答案

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

关于c++ - 如何比较 C++ 中两个位图屏幕截图的字节与字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6243233/

相关文章:

c# - 如何在单个存储过程中从多个表中获取数据?

algorithm - 有哪些字符串相似度算法?

C++ 分数混合比较运算符错误

string - 空格/制表符/换行符不敏感比较

c++ - 无向加权稀疏图的所有对最短路径长度

c++ - 了解构造函数的一些具体情况

c# - 使用emgu CV写视频报错"System.AccessViolationException was unhandled"

c++ - 使用来自函数的数据初始化 C++ const 成员 (MPI_comm_size/rank)

C++ 嵌套 for 循环

c++ - 无法分配大小为 0 的常量数组