【问题标题】:C++ screen capture - how to read the bitmap?C++ 屏幕截图 - 如何读取位图?
【发布时间】:2018-05-15 21:50:49
【问题描述】:

我希望程序(用 c++ 编写)从屏幕上读取像素,但我得到的响应似乎很混乱,变量 start 表示鼠标的位置。正确的方法是什么? 我使用了 GetPixel() 效果很好,但我需要一个完整的位图来提高效率。代码如下:

#include <Windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;

int nScreenWidth;
int nScreenHeight;

HBITMAP GetScreenBmp(HDC hdc) {
    HDC hCaptureDC  = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap);
    BOOL bOK = BitBlt(hCaptureDC,0,0,nScreenWidth, nScreenHeight, hdc,0,0,SRCCOPY|CAPTUREBLT);

    SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
    DeleteDC(hCaptureDC);
    return hBitmap;
}

int main() {
    nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    HBITMAP hBitmap;

    int times = 0;
    while (!GetAsyncKeyState(VK_SPACE) && times<1000)
    {
        times++;

        POINT p;
        GetCursorPos(&p);

        HDC hdc = GetDC(0);

        hBitmap = GetScreenBmp(hdc);

        BITMAPINFO MyBMInfo = {0};
        MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

        if(0 == GetDIBits(hdc, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
            cout << "error" << endl;
        }

        BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

        MyBMInfo.bmiHeader.biCompression = BI_RGB;

        if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
            cout << "error2" << endl;
        }
        //**HERE** - position is wrong?
        int start = (p.y*nScreenWidth+p.x)*4;
        for(int i = start; i < start + 4; i+=4)
        {
            cout << "R:" << (int)lpPixels[i+2] << " G:" << (int)lpPixels[i+1] << " B:" << (int)lpPixels[i] << endl;
        }

        ReleaseDC(NULL, hdc);
        delete[] lpPixels;

        Sleep(1000);
    }
    DeleteObject(hBitmap);

    return 0;
}

【问题讨论】:

  • “看起来很乱”是什么意思?你遇到了什么问题?
  • 我给了你尝试的代码 - 我得到了错误的 RGB 值,这不是我现在鼠标下的值。
  • 您可以在实际问题中尽可能明确地描述您的问题。 “凌乱”并没有削减它,您的代码也无法编译,它在某处缺少大括号。
  • @RetiredNinja 对不起,我没有经验 - 这是我在这里的第一篇文章,无论如何我修复了括号,它现在可以编译;)
  • 与您的问题无关,在 C++ 中几乎不需要使用运算符 newdelete。请改用std::vector&lt;BYTE&gt;

标签: c++ winapi bitmap screen capture


【解决方案1】:

你强制压缩为BI_RGB,你不妨设置前6个值并只调用一次GetDIBits。由于位图高度从下到上开始,您必须为BITMAPINFOHEADER 提供负高度,否则从下到上读取。

确保该过程可识别 DPI。最简单的方式(但不是首选方式)是致电SetProcessDPIAware()。对于每个hBitmap 分配调用DeleteObject(hBitmap)

int main()
{
    SetProcessDPIAware();
    int width = GetSystemMetrics(SM_CXSCREEN);
    int height = GetSystemMetrics(SM_CYSCREEN);
    while(!GetAsyncKeyState(VK_SPACE))
    {
        HDC hdc = GetDC(0);
        POINT p;
        GetCursorPos(&p);

        HDC memdc = CreateCompatibleDC(hdc);
        HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width, height);
        HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
        BitBlt(memdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY | CAPTUREBLT);
        SelectObject(memdc, oldbmp);
        DeleteDC(memdc);

        //use GetPixel for testing
        COLORREF c = GetPixel(hdc, p.x, p.y);
        printf("%02X%02X%02X\n", GetRValue(c), GetGValue(c), GetBValue(c));

        BITMAPINFO bi = { 0 };
        bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
        bi.bmiHeader.biWidth = width;
        bi.bmiHeader.biHeight = -height;
        bi.bmiHeader.biBitCount = 32; //32-bit bitmap
        bi.bmiHeader.biPlanes = 1;
        bi.bmiHeader.biCompression = BI_RGB;

        //allocate 4 bytes per pixel for 32-bit
        BYTE* lpPixels = new BYTE[height * width * 4]; 
        if(0 != GetDIBits(hdc, hbitmap, 0, height, lpPixels,
            &bi, DIB_RGB_COLORS))
        {
            int i = (p.y * width + p.x) * 4;
            printf("%02X%02X%02X\n\n", 
                        lpPixels[i + 2], lpPixels[i + 1], lpPixels[i + 0]);
        }
        DeleteObject(hbitmap);
        ReleaseDC(NULL, hdc);
        delete[] lpPixels;
        Sleep(1000);
    }
    return 0;
}

【讨论】:

  • 我什至不能赞成你的回答,但谢谢你,它有效;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
相关资源
最近更新 更多