2010-04-17 15 views
11

Quiero leer un área rectangular o píxeles de pantalla completa. Como si se hubiera presionado el botón de captura de pantalla.¿Cómo leer los píxeles de la pantalla?

¿Cómo hago esto?

Editar: Código de Trabajo:

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

No se olvide de aceptar respuestas si te ayudan. – Johnsyweb

+0

Lo sé, todavía no lo he hecho funcionar – Newbie

+0

Quizás necesite agregar un poco más de información, como lo que ha intentado y lo que está fallando. – Johnsyweb

Respuesta

7

A partir de su código de comprobación de errores y omitiendo ...

// 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

¿qué puse para hCaptureBitmap? – Newbie

+0

Además, ¿qué ventana HDC puse allí, mi escritorio o la ventana de mi programa? – Newbie

+0

Mira mis ediciones, actualicé mi código, ¿qué tiene de malo? – Newbie

6
+0

¿Cómo accedo a la memoria que copió en la primera función de ejemplo? intenté generar el valor de hCaptureBitmap [0] pero se bloquea. – Newbie

+1

@Newbie: use 'GetDIBits' para obtener los píxeles del mapa de bits dependiente del dispositivo en un mapa de bits independiente del dispositivo. A continuación, puede acceder a los píxeles de eso. Alternativamente, puede crear un mapa de bits de sección DIB y usarlo para la captura inicial. –

+0

la definición de la función es un galimatías total para mí. Hay toneladas de palabras clave que no tengo idea de lo que significan ... Tendría que google recursivamente de cada palabra clave a otra para comprenderlo por completo, eso tomará semanas. entonces ... ahora estoy ocupado con otros problemas, no tengo tiempo para eso ahora. Si lo desea, puede responder a esta pregunta y ofrecer un código de trabajo, luego puedo aceptarlo como la respuesta correcta y estar agradecido. – Newbie

2

De hacer una captura de pantalla con BitBlt(). El tamaño de la toma se establece con los argumentos nWidth y nHeight. La esquina superior izquierda se establece con los argumentos nXSrc y nYSrc.

0

HBITMAP no es un puntero o una matriz, es un identificador que es administrado por Windows y solo tiene significado para Windows. Debe pedirle a Windows que copie los píxeles en algún lugar para usarlos.

Para obtener un valor de píxel individual, puede usar GetPixel sin necesidad de un mapa de bits. Esto será lento si necesita acceder a muchos píxeles.

Para copiar un mapa de bits en la memoria a la que puede acceder, use el GetDIBits function.

2

Al volver a leer su pregunta, parece que hemos logrado una tangente con la captura de pantalla. Si solo desea verificar algunos píxeles en la pantalla, puede usar 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. 
} 

Si usted va a leer una gran cantidad de píxeles, entonces usted está mejor con una captura de pantalla y luego usando GetDIBits. Llamar al GetPixel trillones de veces será lento.

+0

Sí, quiero leer un rectángulo de píxeles (o toda la pantalla a la vez si es más fácil). No sé cómo usar esa función GetDIBits, no pude entender ninguno de los términos para los parámetros, no tengo idea de cómo funciona. – Newbie

+0

Tengo su función para trabajar, pero me gustaría utilizar una forma más eficiente para leer más de 1 píxel. No puedo trabajar en esta función GetDIBits. – Newbie

Cuestiones relacionadas