简体   繁体   English

如何读取屏幕像素?

[英]How to read the screen pixels?

I want to read a rectangular area, or whole screen pixels. 我想读一个矩形区域,或整个屏幕像素。 As if screenshot button was pressed. 好像按下了屏幕截图按钮。

How i do this? 我怎么做的?

Edit: Working code: 编辑:工作代码:

void CaptureScreen(char *filename)
{
    int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    HWND hDesktopWnd = GetDesktopWindow();
    HDC hDesktopDC = GetDC(hDesktopWnd);
    HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
    HBITMAP hCaptureBitmap = CreateCompatibleBitmap(hDesktopDC, nScreenWidth, nScreenHeight);
    SelectObject(hCaptureDC, hCaptureBitmap); 

    BitBlt(hCaptureDC, 0, 0, nScreenWidth, nScreenHeight, hDesktopDC, 0,0, SRCCOPY|CAPTUREBLT); 

    BITMAPINFO bmi = {0}; 
    bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); 
    bmi.bmiHeader.biWidth = nScreenWidth; 
    bmi.bmiHeader.biHeight = nScreenHeight; 
    bmi.bmiHeader.biPlanes = 1; 
    bmi.bmiHeader.biBitCount = 32; 
    bmi.bmiHeader.biCompression = BI_RGB; 

    RGBQUAD *pPixels = new RGBQUAD[nScreenWidth * nScreenHeight]; 

    GetDIBits(
        hCaptureDC, 
        hCaptureBitmap, 
        0,  
        nScreenHeight,  
        pPixels, 
        &bmi,  
        DIB_RGB_COLORS
    );  

    // write:
    int p;
    int x, y;
    FILE *fp = fopen(filename, "wb");
    for(y = 0; y < nScreenHeight; y++){
        for(x = 0; x < nScreenWidth; x++){
            p = (nScreenHeight-y-1)*nScreenWidth+x; // upside down
            unsigned char r = pPixels[p].rgbRed;
            unsigned char g = pPixels[p].rgbGreen;
            unsigned char b = pPixels[p].rgbBlue;
            fwrite(fp, &r, 1);
            fwrite(fp, &g, 1);
            fwrite(fp, &b, 1);
        }
    }
    fclose(fp);

    delete [] pPixels; 

    ReleaseDC(hDesktopWnd, hDesktopDC);
    DeleteDC(hCaptureDC);
    DeleteObject(hCaptureBitmap);
}

Starting with your code and omitting error checking ... 从您的代码开始并省略错误检查......

// Create a BITMAPINFO specifying the format you want the pixels in.
// To keep this simple, we'll use 32-bits per pixel (the high byte isn't
// used).
BITMAPINFO bmi = {0};
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = nScreenWidth;
bmi.bmiHeader.biHeight = nScreenHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;

// Allocate a buffer to receive the pixel data.
RGBQUAD *pPixels = new RGBQUAD[nScreenWidth * nScreenHeight];

// Call GetDIBits to copy the bits from the device dependent bitmap
// into the buffer allocated above, using the pixel format you
// chose in the BITMAPINFO.
::GetDIBits(hCaptureDC,
            hCaptureBitmap,
            0,  // starting scanline
            nScreenHeight,  // scanlines to copy
            pPixels,  // buffer for your copy of the pixels
            &bmi,  // format you want the data in
            DIB_RGB_COLORS);  // actual pixels, not palette references

// You can now access the raw pixel data in pPixels.  Note that they are
// stored from the bottom scanline to the top, so pPixels[0] is the lower
// left pixel, pPixels[1] is the next pixel to the right,
// pPixels[nScreenWidth] is the first pixel on the second row from the
// bottom, etc.

// Don't forget to free the pixel buffer.
delete [] pPixels;

Rereading your question, it sounds like we may have gotten off on a tangent with the screen capture. 重读你的问题,听起来我们可能已经开始与屏幕截图相切。 If you just want to check some pixels on the screen, you can use GetPixel . 如果您只想检查屏幕上的某些像素,可以使用GetPixel

HDC hdcScreen = ::GetDC(NULL);
COLORREF pixel = ::GetPixel(hdcScreen, x, y);
ReleaseDC(NULL, hdcScreen);
if (pixel != CLR_INVALID) {
  int red = GetRValue(pixel);
  int green = GetGValue(pixel);
  int blue = GetBValue(pixel);
  ...
} else {
  // Error, x and y were outside the clipping region.
}

If you're going to read a lot of pixels, then you're better off with a screen capture and then using GetDIBits . 如果您要读取大量像素,那么最好使用屏幕截图然后使用GetDIBits Calling GetPixel zillions of times will be slow. 调用GetPixel十亿次会很慢。

You make a screenshot with BitBlt(). 你用BitBlt()制作截图。 The size of the shot is set with the nWidth and nHeight arguments. 使用nWidth和nHeight参数设置镜头的大小。 The upper left corner is set with the nXSrc and nYSrc arguments. 左上角设置了nXSrc和nYSrc参数。

You can use the code below to read the screen pixels: 您可以使用下面的代码来读取屏幕像素:

HWND desktop = GetDesktopWindow();
HDC desktopHdc = GetDC(desktop);
COLORREF color = GetPixel(desktopHdc, x, y);

HBITMAP is not a pointer or an array, it is a handle that is managed by Windows and has meaning only to Windows. HBITMAP不是指针或数组,它是由Windows管理的句柄,仅对Windows有意义。 You must ask Windows to copy the pixels somewhere for use. 您必须要求Windows将像素复制到某处以供使用。

To get an individual pixel value, you can use GetPixel without even needing a bitmap. 要获得单个像素值,您可以使用GetPixel ,甚至不需要位图。 This will be slow if you need to access many pixels. 如果您需要访问许多像素,这将很慢。

To copy a bitmap to memory you can access, use the GetDIBits function . 要将位图复制到可以访问的内存,请使用GetDIBits函数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM