Getting area from Image

In my game I use png's to represent my objects.

Now I want to get the area of the opaque part of the image.

I don't want to use the whole image as a bounding box since it contains lots of transparent pixels in it.

public Area getOpaqueArea(Image src){

// Insert your code here please :)

}

Thanks

[472 byte] By [namnet] at [2007-9-30 12:37:34]
# 1

I'm guessing you are going to use these for collision detection. Using many Areas is pretty slow if you are trying to use them in real time. However, you can try using something like these [url http://www.scottshaver2000.com/ImageFunctions.java]ImageFunctions[/url] which make masks and compare them.

If you still want to use Area, the mask generator may help you get a list of points that make up the opaque part of the image. Run a convex hull algorithm on the points and you can get a useful approximation that would probably have decent performance.

Hope these help!

-JBoeing

jboeing at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...
# 2

what I would do is use the mask generator, but still rely on bounding box collision checking or radius vs distance checking, and if they return true, THEN you do the Area collision checking. So you really only ever call for the Area collision method if you're pretty sure there's going to be a collision.

Malohkan at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...
# 3

Thank you jboeing for a great reply. I was planning to predefine all the areas but I now see that Area have

no setLocation method, nor does Shape. And since my objects will be moving that might be a problem.

Anyway I went with this solution:

public static Area getOpaqueArea(Image src) {

// 1) Grab pixels

int width = src.getWidth(null);

int height = src.getHeight(null);

int pixels[][] = grabPixels(src);

// 2) Place the opaque pixels in a polygon

Polygon poly = new Polygon();

for (int y = 0; y < height; y++) // y coordinate

{

for (int x = 0; x < width; x++) // x coordinate

{

if (pixels[y][x] != TRANSPARENT) {

poly.addPoint(x,y);

}

}

}

// 3) Return a new area that represents the polygon

return new Area(poly);

}

I don't think my algorithm is very good since it adds all opaque points to the polygon when it would be

enough just to add the outer borders.

namnet at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...
# 4

Your area will have a lot of points. This is why Malohkan suggested using the bounding boxes for quick tests before you use the more complicated areas.

If you want to simplify your Area objects, look into making a convex hull of the points. A convex hull is the smallest convex polygon that contains a collection of points. So unless your area has alot of concavities, it will make a nice approximation. for collision tests.

jboeing at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...
# 5

You might also want to look into a technique called "collision maps". For each sprite you create an array that represent it's opaque pixels, and check against those for collisions. If the memory they might take is an issue you can sacrifice memory for performance by using bitmaps: since the values in collision maps are only 0s and 1s you can represent them with bits instead of bytes or ints. Another way to save memory is to create scaled down collision maps, where each value represents squares of 4 pixels (or 9, etc.), and you can make those into bitmaps if you want too. If you still do bounding rectangle checks as a first step and only do collision map checks for objects that pass the bounding rectangle test, you could incorporate this method and still keep reasonable performance.

shmoove

shmoove at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...
# 6

Yes, I am doing bounding circle collision tests as the first step.

Convex hulls sounds promesing, but if it isn't enough changing the code like this:

if ( pixels[x][y] != TRANSPARENT && !poly.contains(x,y) ) {

poly.addPoint(x,y);

}

then could someone show me the correct way? I made a quick google search and found some info about convex hulls but there was no code available.

shmoove, are those collision maps you are talking about the same as jboeings pixel masks?

namnet at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...
# 7

I'm not familiar with his pixel maps, but it sounds like the same thing.

From the looks of it you are getting the pixels to create your areas anyway, so using the Area object is just unnecessary overhead as far as I can tell. Instead you could just save an array (or bitmap like I said) that contains the opaque pixels and check directly against that for pixel level collision.

shmoove

shmoove at 2007-7-4 16:30:40 > top of Java-index,Other Topics,Java Game Development...