2010-04-17 52 views
11

我想讀取一個矩形區域,或整個屏幕像素。就好像截圖按鈕被按下了一樣。如何讀取屏幕像素?

我該怎麼做?

編輯:工作代碼:

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); 
} 
+1

不要忘記,如果他們幫助你接受的答案。 – Johnsyweb 2010-06-03 14:21:32

+0

我知道,我還沒有這個工作,但 – Newbie 2010-06-03 14:24:44

+0

也許你需要添加更多的信息,如你已經嘗試過什麼和失敗。 – Johnsyweb 2010-06-03 14:26:40

回答

7

與您的代碼開始並省略錯誤檢查...

// 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; 
+0

我爲hCaptureBitmap? – Newbie 2010-06-05 14:46:15

+0

另外,我放在那裏的HDC窗口,我的桌面或我的程序自己的窗口? – Newbie 2010-06-05 15:00:20

+0

看看我的編輯,我更新了我的代碼,它有什麼問題? – Newbie 2010-06-05 15:57:34

6
+0

我如何訪問它在第一個示例函數中複製的內存?我試圖輸出hCaptureBitmap [0]的值,但它崩潰。 – Newbie 2010-04-17 21:15:46

+1

@Newbie:使用'GetDIBits'將設備相關位圖中的像素轉換爲與設備無關的位圖。然後您可以從中訪問像素。或者,您可以創建一個DIB段位圖並將其用於初始捕獲。 – 2010-06-03 14:31:25

+0

函數定義對我來說總是亂碼。這些噸的關鍵字我不知道他們的意思...我不得不穀歌從每個關鍵字遞歸到另一個完全理解它,這將需要幾個星期。所以...我現在有點忙,有其他問題,我現在沒有時間。如果你願意,你可以回答這個問題,並提供一段代碼,然後我可以接受它作爲正確的答案,並感謝。 – Newbie 2010-06-03 14:52:13

2

你與BitBlt的截圖()。鏡頭的大小由nWidth和nHeight參數設置。左上角用nXSrc和nYSrc參數設置。

0

HBITMAP不是一個指針或數組,它是一個由Windows管理的句柄,僅對Windows有意義。您必須要求Windows將像素複製到某處以供使用。

要獲得單個像素值,您可以使用GetPixel而不需要位圖。如果你需要訪問很多像素,這將會很慢。

要將位圖複製到可以訪問的內存,請使用GetDIBits function

2

重讀您的問題,聽起來好像我們可能已經與屏幕截圖切線。如果您只想檢查屏幕上的某些像素,則可以使用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無數次會很慢。

+0

是的,我想讀取一個矩形的像素(或整個屏幕一次,如果它更容易)。我不知道如何使用GetDIBits函數,我無法理解任何參數的條款,我不知道它是如何工作的。 – Newbie 2010-06-04 16:03:35

+0

我得到了你的功能,但我想用更有效的方式讀取多於1個像素。我無法工作這個GetDIBits函數。 – Newbie 2010-06-05 16:45:48

相關問題