我想读取一个矩形区域,或整个屏幕像素。 就好像截图button被按下了一样。
我如何做到这一点?
编辑:工作代码:
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); }
从您的代码开始,并省略错误检查…
// 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;
从这里开始捕捉屏幕的各种方法
你用BitBlt()做一个截图。 镜头的大小由nWidth和nHeight参数设置。 左上角用nXSrc和nYSrc参数设置。
重读你的问题,听起来好像我们可能已经与屏幕截图切线了。 如果您只想检查屏幕上的某些像素,则可以使用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. }
如果你要读取很多像素,那么最好用屏幕截图,然后使用GetDIBits
。 调用GetPixel
无数次将是缓慢的。
HBITMAP不是一个指针或数组,它是一个由Windows管理的句柄,仅对Windows有意义。 您必须要求Windows将像素复制到某处以供使用。
为了获得一个单独的像素值,你可以使用GetPixel而不需要一个位图。 如果你需要访问许多像素,这将是缓慢的。
要将位图复制到内存中,可以使用GetDIBits函数 。