我的目标是拥有一个可以捕获游戏画面的程序,然后从代码中读取图片。
我真的是Win API的新手+从未使用过位图,所以即时通讯很困难,即时通讯完全没有。
我必须截屏的代码是(在堆栈溢出时找到它):
HDC hScreenDC = GetDC(NULL);
// and a device context to put it in
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int width = GetDeviceCaps(hScreenDC, HORZRES);
int height = GetDeviceCaps(hScreenDC, VERTRES);
// maybe worth checking these are positive values
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
// get a new bitmap
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
// clean up
DeleteDC(hMemoryDC);
DeleteDC(hScreenDC);
我的想法是将“hBitmap”转换为mat / 2d数组。
我搜索了互联网,找到了下一个解决方案:
步骤1已经完成,我有var“hBitmap”。
对于步骤2,我添加了以下代码:
//Get BITMAP object from HBITMAP
BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
在删除直流之前。
我不知道该怎么做第3步和第4步。
如果有人向我展示,因为我没有找到关于该主题的任何简单指南,我将非常高兴。
如果还有其他更好的解决方案,我也很高兴听到它们。
编辑:试图用“Barmak Shemirani”答案将其保存为.ppm,但它只是显示了4个大方块?
注意:我+ = 4,我知道它的rgba而不是rgb,但是a总是255
码:
using namespace std;
int main()
{
cout << "Hello World!\n";
HDC hScreenDC = GetDC(NULL);
// and a device context to put it in
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int width = GetDeviceCaps(hScreenDC, HORZRES);
int height = GetDeviceCaps(hScreenDC, VERTRES);
// maybe worth checking these are positive values
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, width, height);
// get a new bitmap
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
WORD bpp = 32; //32-bit bitmap
cout << "width=" << width << endl;
cout << "height=" << height << endl;
DWORD size = ((width * bpp + 31) / 32) * 4 * height;
BITMAPINFOHEADER bi = { sizeof(bi) };
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = bpp;
unsigned char* bits = new unsigned char[size];
int result = GetDIBits(hScreenDC, hBitmap, 0, height, bits, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
ofstream img(".ppm");
img << "P3" << endl;
img << 1536 << " " << 864 << endl;
img << "255" << endl;
for (int i = 0; i <= 864; i++) {
for (int j = 0; j < 1536; j+=4) {
int r = bits[i];
int g = bits[i + 1];
int b = bits[i + 2];
img << r << " " << g << " " << b << endl;
}
}
cout << "finished" << endl;
delete[]bits;
// clean up
SelectObject(hMemoryDC, hOldBitmap);//now we can destroy hMemoryDC & hBitmap
DeleteObject(hBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(0, hScreenDC);
}
最佳答案
GetObject(hBitmap...)
将仅填充DIB的bm.bmBits
成员。但是这里我们没有DIB。请改用GetDIBits
。下面的示例读取bits
中的像素以获取32位位图。
WORD bpp = 32; //32-bit bitmap
DWORD size = ((width * bpp + 31) / 32) * 4 * height;
BITMAPINFOHEADER bi = { sizeof(bi) };
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = bpp;
unsigned char* bits = new unsigned char[size];
int result = GetDIBits(hdc, hBitmap, 0, height, bits, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
...
delete[]bits;
此外,您的代码还需要
ReleaseDC(0, hScreenDC)
进行清理,而不是DeleteDC(hScreenDC)
,因为DC是由GetDC
获取的。//cleanup:
SelectObject(hMemoryDC, hOldBitmap);//now we can destroy hMemoryDC & hBitmap
DeleteObject(hBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(0, hScreenDC);
以ppm /非二进制格式保存:
ofstream img("filename.ppm");
img << "P3\n";
img << width << " " << height << "\n";
img << "255\n";
for(int y = height - 1; y >= 0; y--)
{
for(int x = 0; x < width; x ++)
{
int i = (y * width + x) * 4;
int r = bits[i + 2];
int g = bits[i + 1];
int b = bits[i + 0];
img << r << " " << g << " " << b << " ";
}
img << "\n";
}
关于c++ - 位图到mat/2d数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51993412/