pixel color detection

Started by
8 comments, last by tadobie 19 years, 6 months ago
Can anyone tell me, or direct me to an article that can explain how to detect a particular color in a direct draw surface. I want to do some collision detection based on color.
Don't mug ya self!
Advertisement
Lock the surface, then with the array it gives you, find the pixel you want.

//Declare and Zero the structDDSURFACEDESC2 sd = { sizeof ( sd ) };//if you set this rect, then you//only lock the area inside itLPRECT rct = NULL;lpsrf->Lock(rct, &sd, DDLOCK_WAIT | DDLOCK_READONLY, NULL);//pitch is the number of bytes in each rowDWORD pitch = sd.lPitch;LPDWORD pixels = (LPDWORD)(sd.lpSurface);int x = 25, int y = 25;//since it only gives you a 1 dimensional array//you need to specify the pixel in an odd manner.//Of course, there are much more efficient ways of//accessing these values, such as a lookup table,//but this is the math you need. bpp is bits per pixelDWORD color = pixels[x * (bpp/8) + (y*pitch)];//you must remember to unlock the surface before continuinglpsrf->Unlock(rct);


You dont want to lock your surface too many times in one frame, however, because its slow.

You would have to loop through your entire surface to detect a particular color and where it lies.
I've been looking for the same info.

What I basically want to do is to check for a single point (the "attack point" in a fist, for example), and test for that being inside the RECT of another surface (actually, the ideal thing to do is to test if it's in contact with the surface minus the transparent colour). How would I adapt this part to test for that kind of collision?

int x = 25, int y = 25;//since it only gives you a 1 dimensional array//you need to specify the pixel in an odd manner.//Of course, there are much more efficient ways of//accessing these values, such as a lookup table,//but this is the math you need. bpp is bits per pixelDWORD color = pixels[x * (bpp/8) + (y*pitch)];


I also have trouble seeing what those x and y values are used for, and how they are set... Are they widths and heights, or what?
Eskil
I'm also a little confused by this section:

int x = 25, int y = 25;DWORD color = pixels[x * (bpp/8) + (y*pitch)];	


Firstly are the int's just arbitary values or are they specific to the mathematical solution?

Could you please explain this part a little further?
I'm not sure if the index in the pixels array points to an entire pixel meaning you traverse through the array one index (ie. one pixel) at a time to see the colour of each pixel.
If so could I simply do something like this to test if the RECT in question contains a particular pixel colour?
	DWORD colour = pixels[0];	i = 0;		while(colour != NULL)	{		colour = pixels;		if(colour == MY_COLOUR)		{			Surface->Unlock(rct);			return true;		}				i++;	}

Don't mug ya self!
You shouldn't do that. There might be padding that just happened to contain your colour. Plus, testing color against NULL is bad. NULL (aka, 0) is almost always black. If there's no black in the image, it will crash because it will keep reading into no man's land.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
what do you suggest then if I just want to test a RECT for the presence of a certain colour?
Don't mug ya self!
I have adjusted my code to avoid the "NULL" indicator and now have this:

LPDWORD pixels = (LPDWORD)(sd.lpSurface);DWORD colour = pixels[0];for(int i=0;i<sizeof(pixels);i++){		colour = pixels;	if(colour == COL_COLLISION)	{		Attacker->UnlockSurface(rct);		return true;	}}


IT CRASHES and BURNS!
I'm obviously screwing up somewhere.
I'm still not sure if the index in the pixels array points to an entire pixel meaning you traverse through the array one index (ie. one pixel) at a time to see the colour of each pixel.
I'm also not sure if the "sizeof" function is the right way to go.

Can anyone help on this?
Don't mug ya self!
Yes, the values for x and y are arbitrary. Sorry I didn't mention that.

as for the confusion around the issue of:

DWORD color = pixels[x * (bpp/8) + (y*pitch)];

if your image is laid out like this:

|0 |1 |2 |3 |4 |
|5 |6 |7 |8 |9 |
|10|11|12|13|14|

(where each space is a pixel)

in this 1D array, it is actually stored like this:

|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|

so to get the value at (2, 2), (using coordinates), we would have to multiply the y value by the width and add the x value.

thus (x + w*y), which is 2 + 2*5 = 12 (lies at space (2, 2))

this works in 8 bit mode fine, but when in other modes, you need to multiply x by bpp/8 because bpp/8 = the number of bytes per pixel. It just means that you only want to index every (bpp/8)'th byte.
Try doing a loop like this:
(completely ignores my last post's explanation)

This way actually accesses each scanline's x value, then
at the end it increments the scanline to the next one.

LPWORD ptr = (LPDWORD)(sd.lpSurface);DWORD color;register int x=0;register int y=0;bool collision=false;do {	do	{                color = ptr[x];                if (color == COL_COLLISION)                {                     collision = true;                     break;                }                x++;	} while (x < width);        //heres where we move to the next scanline	ptr += pitch;	x = 0;	y++;} while (y < height);srf->unlock()return collision;


This way is like 10000 times better that the other way.

[Edited by - squicklid on October 18, 2004 2:14:03 AM]
COOL,
A couple of questions:
1)What type should MY_COLOR be and how should it be used to represent a particular color eg. RGB(1, 1, 1)

2) I am only locking a RECT within a surface and only want to test within that. How is pitch effected ie. does the pitch that is returned represent the pitch of the whole surface or just the locked portion?

3) Would width and height be rect.right and rect.bottom in the case of testing a part of the surface

Thanks for the help on this so far SQUICKLID and friends :)
Don't mug ya self!

This topic is closed to new replies.

Advertisement