I'm grabbing a portion of the screen and scanning through the pixels for a certain color range.
I looked at MSDN's Capturing an Image example and know how to use the functions.
I can get the bits into an array, but I'm not sure how to do it in such a way that I can loop through it as I would an image. A pseudo-example (which I'm sure is way off):
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];
}
}
That's basically what I want to do, so if red, blue, and green is a certain color, I'll know what coordinate it's at (x, y) in the image.
I just don't know how to use GetDIBits in such a way, and how to setup the array appropriately to be able to accomplish this.
Some surprise from MSDN:
so, colors are in BGR order in memory after GetDIBits()
Apart from the good answers already given, here's an example of how to get a simple array structure to walk on. (You can use e.g. Goz' code for the iteration.)
GetDIBits reference @ MSDN
You have to select
DIB_RGB_COLORS
as flag foruUsage
and set up theBITMAPINFO
structure and theBITMAPINFOHEADER
structure it contains. When you setbiClrUsed
andbiClrImportant
to zero, there is "no" color table, so you can read the pixels of the bitmap you get fromGetDIBits
as a sequence of RGB values. Using32
as bit count (biBitCount
) sets up the data structure according to MSDN:Since a MS
LONG
is exactly 32 bit long (the size of aDWORD
), you do not have to pay attention to padding (as described in the Remarks section).Code:
It's not so easy. Your algorithm will depend on the colour depth of the image. If it's 256 or less you won't have pixel colours, but indeces into a palette of colours. 16-bit pixels could be RGB555 or RGB565, 24-bit images will be RGB888, and 32-bit images will be RGBA or ARGB. You'll need the BITMAPINFOHEADER to find out.
Once you find out, the pixel data will just be an array of size width * height * (BitsPerPixel / 8)
In the link you post you create a 32-bit bitmap so I'll assume you are reading from a 32-bit bitmap (This assumption may be incorrect).
Therefore changing your loop to the following should work:
Things to bear in mind:
1.Arrays are 0 based in C/C++
2. You were stepping 3 pixels horizontally and vertically each time. Which meant you aren't visiting every pixel.
3. A bitmap is usually organised such that there are "height" spans of "width" pixels. Therefore you should step through each pixel in a span and then move to the next span.
4. As already pointed out make sure you aare reading pixels correctly. in 16-bit mode its more complex
GetDIBits
returns a one-dimensional array of values. For a bitmap that's M pixels wide by N pixels tall and uses 24-bit color, the first (M*3) bytes will be the first row of pixels. That can be followed by some padding bytes. It depends on the BITMAPINFOHEADER. There is usually padding to make the width a multiple of 4 bytes. So if your bitmap is 33 pixels wide, there will actually be (36*3) bytes per row.This "pixels plus padding" is called the "stride". For RGB bitmaps, you can calculate stride with:
stride = (biWidth * (biBitCount / 8) + 3) & ~3
, wherebiWidth
andbiBitCount
are taken from the BITMAPINFOHEADER.I'm not sure how you want to traverse the array. If you want to go pixel-by-pixel from top left to lower right (assuming this is a top-down bitmap):