gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:06:57 24 4
gpt4 key购买 nike

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

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

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com