Domanda

Sto prendere una porzione dello schermo e la scansione attraverso i pixel per una certa gamma di colori.

di MSDN cattura di un'immagine esempio e saper utilizzare le funzioni.

posso ottenere i bit in un array, ma non sono sicuro come farlo in modo tale che un posso ciclo attraverso di essa come vorrei un'immagine. Una pseudo-example (che sono sicuro che è lontano):

for ( x = 1; x <= Image.Width; x += 3 )
{
    for ( y = 1; y <= Image.Height; y += 3 )
    {
        red = lpPixels[x];
        green = lpPixels[x + 1];
        blue = lpPixels[x + 2];
    }
}

Questo è fondamentalmente ciò che voglio fare, quindi, se rosso, blu e verde è un certo colore, saprò cosa coordinamento è al (x, y) nell'immagine.

Ho appena non so come utilizzare GetDIBits in tal modo, e come impostare la matrice in modo appropriato per essere in grado di raggiungere questo obiettivo.

È stato utile?

Soluzione

A parte le buone risposte già date, ecco un esempio di come per ottenere una semplice struttura a matrice su cui camminare. (Si può usare ad esempio Goz' codice per l'iterazione.)

GetDIBits riferimento @ MSDN

È necessario selezionare DIB_RGB_COLORS come bandiera per la uUsage e impostare il struttura BITMAPINFO e la struttura BITMAPINFOHEADER essa contiene. Quando si imposta biClrUsed e biClrImportant a zero, non v'è "no" tabella dei colori, in modo da poter leggere i pixel del bitmap si ottiene da GetDIBits come una sequenza di valori RGB. Utilizzando 32 come numero di bit (biBitCount) imposta la struttura dati secondo MSDN:

  

La bitmap ha un massimo di 2 ^ 32 colori. Se il membro biCompression della BITMAPINFOHEADER è BI_RGB, il membro bmiColors di BITMAPINFO è NULL. Ogni DWORD nell'array bitmap rappresenta le intensità relative rispettivamente blu, verde e rosso,, per un pixel. Il byte alto in ogni DWORD non viene utilizzato.

Dal momento che un LONG MS è esattamente a 32 bit lungo (delle dimensioni di un DWORD), non si deve prestare attenzione a imbottitura (come descritto nella Note sezione ).

Codice:

HDC hdcSource = NULL; // the source device context
HBITMAP hSource = NULL; // the bitmap selected into the device context

BITMAPINFO MyBMInfo = {0};
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);

// Get the BITMAPINFO structure from the bitmap
if(0 == GetDIBits(hdcSource, hSource, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS))
{
    // error handling
}

// create the pixel buffer
BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

// We'll change the received BITMAPINFOHEADER to request the data in a
// 32 bit RGB format (and not upside-down) so that we can iterate over
// the pixels easily. 

// requesting a 32 bit image means that no stride/padding will be necessary,
// although it always contains an (possibly unused) alpha channel
MyBMInfo.bmiHeader.biBitCount = 32;
MyBMInfo.bmiHeader.biCompression = BI_RGB;  // no compression -> easier to use
// correct the bottom-up ordering of lines (abs is in cstdblib and stdlib.h)
MyBMInfo.bmiHeader.biHeight = abs(MyBMInfo.bmiHeader.biHeight);

// Call GetDIBits a second time, this time to (format and) store the actual
// bitmap data (the "pixels") in the buffer lpPixels
if(0 == GetDIBits(hdcSource, hSource, 0, MyBMInfo.bmiHeader.biHeight,
                  lpPixels, &MyBMInfo, DIB_RGB_COLORS))
{
    // error handling
}
// clean up: deselect bitmap from device context, close handles, delete buffer

Altri suggerimenti

GetDIBits restituisce un array monodimensionale di valori. Per una bitmap che è M pixel di larghezza per N pixel di altezza e utilizza colori a 24 bit, il primo (M * 3) byte sarà la prima fila di pixel. Che può essere seguito da alcuni byte di riempimento. Dipende dalla BITMAPINFOHEADER. Di solito c'è imbottitura per rendere la larghezza di un multiplo di 4 byte. Così, se il bitmap è largo 33 pixel, ci sarà effettivamente (36 * 3) byte per riga.

Questa "pixel più padding" è chiamato il "passo". Per le bitmap RGB, è possibile calcolare stride con:. stride = (biWidth * (biBitCount / 8) + 3) & ~3, dove biWidth e biBitCount sono presi dal BITMAPINFOHEADER

Non sono sicuro di come si desidera attraversare l'array. Se si vuole andare pixel-by-pixel da sinistra in alto a basso a destra (sempre che sia una bitmap top-down):

for (row = 0; row < Image.Height; ++row)
{
    int rowBase = row*stride;
    for (col = 0; col < Image.Width; ++col)
    {
        red = lpPixels[rowBase + col];
        // etc.
    }
}

Non è così facile. Il vostro algoritmo dipenderà dalla profondità del colore dell'immagine. Se si tratta di 256 o meno non avrà i colori dei pixel, ma indici in una tavolozza di colori. pixel a 16 bit potrebbero essere RGB555 o RGB565, immagini a 24 bit saranno RGB888, e immagini a 32 bit saranno RGBA o ARGB. Avrete bisogno del BITMAPINFOHEADER per scoprirlo.

Una volta a scoprire, i dati dei pixel sarà solo un array di larghezza di dimensioni * altezza * (BitsPerPixel / 8)

In questo link si crea un post che a 32-bit bitmap quindi darò per scontato che si sta leggendo da una a 32 bit bitmap (Questa ipotesi potrebbe non essere corretta).

Quindi cambiare il vostro ciclo per il seguente dovrebbe funzionare:

char* pCurrPixel = (char*)lpPixels;
for ( y = 0; y < Image.Height; y++ )
{
    for ( x = 0; x < Image.Width; x++ )
    {
        red = pCurrPixel[0];
        green = pCurrPixel[1];
        blue = pCurrPixel[2];

        pCurrPixel += 4;
    }
}

Cose da tenere a mente:

1.Arrays sono 0 con sede in C / C ++
 2. Ha entrando 3 pixel in orizzontale e in verticale ogni volta. Il che significava che non sta visitando ogni pixel.
 3. Una bitmap è solitamente organizzato in modo tale che ci sono campate "altezza" pixel "larghezza". Pertanto si dovrebbe passare da ogni pixel in un arco e poi passare al successivo arco.
 4. Come già sottolineato assicuratevi di Aare lettura pixel correttamente. in modalità a 16 bit sua
più complesso

una certa sorpresa da MSDN:

  

La tabella è costituita da una matrice di strutture di dati RGBQUAD. (La tavola   per il formato BITMAPCOREINFO è costruito con i dati RGBTRIPLE   struttura.) rosso, verde e blu byte sono in ordine inverso (rosso   swap posizione con il blu) dalla convenzione di Windows.

così, i colori sono in ordine BGR in memoria dopo GetDIBits ()

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top