15

長方形の領域、または画面全体のピクセルを読み取りたい。スクリーンショットボタンが押されたかのように。

どうすればいいですか?

編集:作業コード:

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);
}
4

5 に答える 5

12

コードから始めて、エラーチェックを省略します...

// 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;
于 2010-06-05T02:51:09.627 に答える
3

質問を読み直してみると、スクリーンキャプチャとの関係がうまくいかなかったようです。画面上のいくつかのピクセルを確認したいだけの場合は、を使用できます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のは遅くなります。

于 2010-06-03T21:54:03.510 に答える
2

BitBlt()を使用してスクリーンショットを作成します。ショットのサイズは、nWidth引数とnHeight引数で設定されます。左上隅には、nXSrc引数とnYSrc引数が設定されています。

于 2010-04-17T21:02:53.047 に答える
1

以下のコードを使用して、画面のピクセルを読み取ることができます。

HWND desktop = GetDesktopWindow();
HDC desktopHdc = GetDC(desktop);
COLORREF color = GetPixel(desktopHdc, x, y);
于 2018-09-05T15:59:21.147 に答える
0

HBITMAPはポインターや配列ではなく、Windowsによって管理されるハンドルであり、Windowsに対してのみ意味があります。使用するためにピクセルをどこかにコピーするようにWindowsに依頼する必要があります。

個々のピクセル値を取得するには、ビットマップを必要とせずにGetPixelを使用できます。多くのピクセルにアクセスする必要がある場合、これは遅くなります。

アクセス可能なメモリにビットマップをコピーするには、GetDIBits関数を使用します。

于 2010-06-03T14:57:56.103 に答える