2010-04-17 20 views
11

Desidero leggere un'area rettangolare o pixel di tutto lo schermo. Come se fosse stato premuto il pulsante screenshot.Come leggere i pixel dello schermo?

Come faccio?

Edit: il codice di lavoro:

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

Non dimenticare di accettare risposte se ti aiutano. – Johnsyweb

+0

Lo so, non ho ancora funzionato questo – Newbie

+0

Forse è necessario aggiungere un po 'più di informazioni come quello che hai provato e quello che sta fallendo. – Johnsyweb

risposta

7

A partire con il tuo codice e il controllo degli errori omettendo ...

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

cosa ho messo per hCaptureBitmap? – Newbie

+0

Inoltre, quale finestra HDC ho messo lì, il mio desktop o la mia finestra personale del mio programma? – Newbie

+0

Guarda le mie modifiche, ho aggiornato il mio codice, cosa c'è che non va? – Newbie

6
+0

Come accedere alla memoria copiata nella prima funzione di esempio? Ho provato a mostrare il valore di hCaptureBitmap [0] ma si blocca. – Newbie

+1

@Newbie: utilizzare 'GetDIBits' per ottenere i pixel dalla bitmap dipendente dal dispositivo in una bitmap indipendente dalla periferica. È quindi possibile accedere ai pixel da quello. In alternativa, è possibile creare una bitmap di sezione DIB e utilizzarla per l'acquisizione iniziale. –

+0

la definizione della funzione è totale senza senso per me. ci sono tonnellate di parole chiave non ho idea di cosa significano ... dovrei google ricorsivamente da ogni parola chiave a un altro per capirlo completamente, ci vorranno settimane. quindi ... sono abbastanza occupato ora con altri problemi, non ho tempo per quello ora. Se vuoi, puoi rispondere a questa domanda e offrire un pezzo di codice funzionante, quindi posso semplicemente accettarlo come risposta corretta e essere grato. – Newbie

2

È fare uno screenshot con BitBlt(). La dimensione dello scatto è impostata con gli argomenti nWidth e nHeight. L'angolo in alto a sinistra è impostato con gli argomenti nXSrc e nYSrc.

0

HBITMAP non è un puntatore o un array, è un handle gestito da Windows e che ha significato solo per Windows. Devi chiedere a Windows di copiare i pixel da qualche parte per l'uso.

Per ottenere un valore di singolo pixel, è possibile utilizzare GetPixel senza nemmeno una bitmap. Questo sarà lento se è necessario accedere a molti pixel.

Per copiare una bitmap nella memoria a cui è possibile accedere, utilizzare GetDIBits function.

2

Rileggendo la tua domanda, sembra che siamo riusciti a ottenere una tangente con la cattura dello schermo. Se vuoi solo controllare alcuni pixel sullo schermo, puoi usare 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. 
} 

Se avete intenzione di leggere un sacco di pixel, allora si sta meglio con una cattura dello schermo e quindi utilizzando GetDIBits. Chiamare GetPixel zillioni di volte sarà lento.

+0

sì, voglio leggere un rettangolo di pixel (o schermo intero in una volta se è più facile). Non so come usare la funzione GetDIBits, non ho potuto capire nessuno dei termini per i parametri, non ho idea di come funzioni. – Newbie

+0

Ho ottenuto il funzionamento della funzione, ma mi piacerebbe utilizzare un modo più efficiente per leggere più di 1 pixel. Non riesco a lavorare su questa funzione di GetDIBits. – Newbie

Problemi correlati