c++ - 位图到mat/2d数组

标签 c++ opencv bitmap

我的目标是拥有一个可以捕获游戏画面的程序,然后从代码中读取图片。

我真的是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数组。
我搜索了互联网,找到了下一个解决方案:
  • 将图像加载到HBITMAP句柄中。
  • 从HBITMAP获取BITMAP对象。
  • 创建一个DWORD数组以从BITMAP加载bmBits。
  • 将DWORD数组保存到RGB结构矩阵中。

  • 步骤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/

    相关文章:

    c - 在不同平台上流式传输桌面以提高速度

    c++ - 3D网格投影到2D平面

    c++ - SetCheck用于多个按钮或使用转换字符串来定义

    c++ - 当我执行C++程序时如何设置VSCode屏幕不会立即消失

    c++ - opencv 内存位置异常

    android - 位图回收错误,没有位图回收调用

    c++ - 多个文件困难的模板

    javascript - JavaScript 的 OpenFrameworks 替代品

    c# - 如何获取数组中处于一定范围内的数字数量?

    c - 无法显示CUDA C结果