Is there a way to retrieve the color value of a pixel within a texture at a given x,y position?
How to get pixel color within texture?
(10 posts) (8 voices)-
Posted 2 years ago #
-
Theres a lengthy discussion on the old google groups about collision detection, one possible way (which I'm actually using) is a collision mask image that uses the pixel values to define different collision areas.
Ernesto covers this method in his very helpful post:
http://groups.google.com/group/cocos2d-iphone-discuss/browse_thread/thread/f6e734e00d863f5e/41768952a1bcca0e?lnk=gst&q=image+mask#41768952a1bcca0eShould hopefully be what you need.
Posted 2 years ago # -
I just figured out how to do this for the purpose of using alpha value to do collision detection using a non-rectangle sized image... By grabbing one byte you can get the rgb color value. It should be reasonably efficient because it just uses a 1px drawing context. When you call CGContextDrawImage it fills the rawData array with the bitmap values that it drew as a side effect.
Weird! But after a lot of research and random groveling through the CG API, this is the best I could come up with.
I wish I had found this post and the above answer a few weeks ago. I just skimmed it and I assume it works fine too. I'm just posting this for fun, and in case someone has comments on which approach is better... :)
Here's the basic idea:
// figure out if the touch overlaps the graphic
// has to be an integer for CGRectMake
int tx = (int) touchPoint.x;
int ty = (int) touchPoint.y;// handData is a UIImage created from a texture
// UIImage *handData;
// handData = [[UIImage alloc]initWithContentsOfFile:fullpath];// You also have to translate the touch x,y to the context of the image/texture.
// 0,0 for this next step is the upper left corner of the texture
// In my app I just hardcoded this as CGRectMake(tx-90,320-ty,1,1) which is lame but works. :)CGImageRef handRef = CGImageCreateWithImageInRect([handData CGImage], CGRectMake(tx,ty,1,1));
unsigned char *rawData = malloc(4);
CGContextRef context = CGBitmapContextCreate(
rawData,
CGImageGetWidth(handRef),
CGImageGetHeight(handRef),
// same as 1,1,
CGImageGetBitsPerComponent(handRef),
CGImageGetBytesPerRow(handRef),
CGImageGetColorSpace(handRef),
kCGImageAlphaPremultipliedLast
);
CGContextDrawImage(context, CGRectMake(0,0,1,1), handRef);
NSLog(@"rgba values at touch point %i %i = %u %u %u %u", tx, ty, rawData[0], rawData[1], rawData[2], rawData[3]);// do something with the raw data
CGContextRelease(context);
free (rawData);Posted 2 years ago # -
You can use glReadPixels to get the value of a pixel (or pixels) in the frame buffer. Not exactly what was asked but it may be useful.
Byte pixelColor[4]; glReadPixels(x,y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixelColor[0]); NSLog(@"%d %d %d",pixelColor[0],pixelColor[1],pixelColor[2]);Posted 2 years ago # -
Hi!
I was trying to do collision check pixel by pixel by using method described here:
http://groups.google.com/group/cocos2d-iphone-discuss/browse_thread/thread/f6e734e00d863f5e/41768952a1bcca0e?lnk=gst&q=image+mask#41768952a1bcca0eI had no problems with code but it doesn't work correctly for me. I looked at rgba values (they seem to be in reversed order - abgr) and it looks like value for alpha channel is always greater than 0. The problem is that my sprite has a lot of transparent pixels and I don't know what to do now. Can somebody explain me what have I done wrong?
I used code like this:
- (void) createCollisionMap: (NSString*) path { NSArray * filename; filename = [path componentsSeparatedByString: @"."]; UIImage *collisionImage = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource: [filename objectAtIndex:0] ofType:[filename objectAtIndex:1]]]; width = (int)collisionImage.size.width; height = (int)collisionImage.size.height; collisionMap = (unsigned char *)malloc( width * height ); memset( collisionMap, 0, width * height ); CFDataRef imageData = CGDataProviderCopyData( CGImageGetDataProvider ( collisionImage.CGImage ) ); UInt32 * pixels = (UInt32*)CFDataGetBytePtr( imageData ); for(int j = 0; j < (width * height); j++ ){ NSLog(@"%.X", pixels[j]); //trace hexes if ( pixels[j] & 0xff000000 ) collisionMap[j] = 1; } CFRelease( imageData ); }Posted 2 years ago # -
Hey. It was stupid issue, program was loading old file. I was using dummy file at first and after changing it to real sprite xCode was still using old file. Clearing project helped.
Posted 2 years ago # -
Hey Biposz I have a quick question.
In your code why do you not use the bitwise operator "|=" in the IF statement nested in the FOR loop? I'm just curious because on the old forum in Ernesto's code he uses it.
Ernesto's Code:
if ( pixels[j] & 0xff000000 ) collisionMap[j] |= 1;Your Code:
if ( pixels[j] & 0xff000000 ) collisionMap[j] = 1;Posted 2 years ago # -
Hi!
I don't use it because I don't know why I really should. collisionMap is memset with zeros so 0 | 1 is always 1. I suppose it could be faster than normal "=" operator but I don't really know. My collision map is small and I generate it only once before my game starts so I decided not to use it.
Posted 2 years ago # -
Hi, I have read through this a few times now and tried to implement this code. I can get it to compile and run but i'm struggling with how to implement this is part of my game.
Basically im looking to have a collision layer and a sprite layer, the collision layer will have single colour images detecting collision using the code above and the sprite layer will have the image representation that the player will see.
I need to be able to position these directly on top of each other and move them together in unison. Is that possible using this code? How would I implement this as I cannot see how I can position these 2 elements on screen, and move with a setPosition method for example.
Please let me know if this isnt clear.
Any help is much appreciated.
Posted 2 years ago # -
any new solution about this question?
I wondering this also.
Posted 10 months ago #
Reply
You must log in to post.