如何将屏幕图像放入内存缓冲区?

时间:2013-09-17 19:47:36

标签: c++ image winapi screen

我一直在寻找一种纯粹的WIN32方法,将屏幕的图像数据放入缓冲区,以便稍后分析图像中的对象......可悲的是,我还没有找到任何内容。我现在愿意接受可以进行“打印屏幕”的库/类的建议,但我仍然可以访问它的内存缓冲区。

任何帮助表示感谢。

编辑:我忘了提到我将继续捕捉屏幕,因此操作速度非常重要。也许有人为此知道一个好的图书馆?

2 个答案:

答案 0 :(得分:1)

// get screen DC and memory DC to copy to
HDC hScreenDC = GetDC(0);
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);

// create a DIB to hold the image
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = GetDeviceCaps(hScreenDC, HORZRES);
bmi.bmiHeader.biHeight = -GetDeviceCaps(hScreenDC, VERTRES);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
LPVOID pBits;
HBITMAP hBitmap = CreateDIBSection(hMemoryDC, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);

// select new bitmap into memory DC
HGDIOBJ hOldBitmap = SelectObject(hMemoryDC, hBitmap);

// copy from the screen to memory
BitBlt(hMemoryDC, 0, 0, bmi.bmiHeader.biWidth, -bmi.bmiHeader.biHeight, hScreenDC, 0, 0, SRCCOPY);

// clean up
SelectObject(hMemoryDC, hOldBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(0, hScreenDC);

// the image data is now in pBits in 32-bpp format
// free this when finished using DeleteObject(hBitmap);

答案 1 :(得分:1)

有多种方法(您可以使用DirectX),但最简单和最简单的方法是使用GDI。

    // GetDC(0) will return screen device context
    HDC hScreenDC = GetDC(0);
    // Create compatible device context which will store the copied image
    HDC hMyDC= CreateCompatibleDC(hScreenDC );

    // Get screen properties
    int iScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int iScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    int iBpi= GetDeviceCaps(hScreenDC ,BITSPIXEL);

    // Fill BITMAPINFO struct
    BITMAPINFO info;
    info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    info.bmiHeader.biWidth = iScreenWidth;
    info.bmiHeader.biHeight = iScreenHeight ;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount  = iBpi;
    info.bmiHeader.biCompression = BI_RGB;

    // Create bitmap, getting pointer to raw data (this is the important part)
    void *data;
    hBitmap = CreateDIBSection(hMyDC,&info,DIB_RGB_COLORS,(void**)&data,0,0);
    // Select it into your DC
    SelectObject(hMyDC,hBitmap);

    // Copy image from screen
    BitBlt(hMyDC, 0, 0, iScreenWidth, iScreenHeight, hScreenDC , 0, 0, SRCCOPY);

    // Remember to eventually free resources, etc.

我这样做已经有一段时间了,所以我可能会遗忘一些东西,但这就是它的要点。一句警告:这不快;当屏幕移动很多时,捕获一帧可能需要50ms或更长时间。它基本上相当于按下PrintScreen键。