Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pixel perfect collision with Config.ALPHA_8

Tags:

java

android

I've found this code of pixel perfect collision checking and used it in my code:

public boolean isCollisionDetected(
    Bitmap bitmap1, int x1, int y1,
    Bitmap bitmap2, int x2, int y2
) {
    Rect bounds1 = new Rect(
        x1, y1, x1 + bitmap1.getWidth(), y1 + bitmap1.getHeight()
    );
    Rect bounds2 = new Rect(
        x2, y2, x2 + bitmap2.getWidth(), y2 + bitmap2.getHeight()
    );

    if (Rect.intersects(bounds1, bounds2)) {
        Rect collisionBounds = getCollisionBounds(bounds1, bounds2);
        for (int i = collisionBounds.left; i < collisionBounds.right; i++) {
            for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) {
                int bitmap1Pixel = bitmap1.getPixel(i - x1, j - y1);
                int bitmap2Pixel = bitmap2.getPixel(i - x2, j - y2);
                if (isFilled(bitmap1Pixel) && isFilled(bitmap2Pixel)) {
                    return true;
                }
            }
        }
    }
    return false;
}

private Rect getCollisionBounds(Rect rect1, Rect rect2) {
    int left = (int) Math.max(rect1.left, rect2.left);
    int top = (int) Math.max(rect1.top, rect2.top);
    int right = (int) Math.min(rect1.right, rect2.right);
    int bottom = (int) Math.min(rect1.bottom, rect2.bottom);
    return new Rect(left, top, right, bottom);
}

private boolean isFilled(int pixel) {
    return pixel != Color.TRANSPARENT;
}

And it worked perfectly, no problems what so ever. That until I set the images into Bitmap.Config.ALPHA_8 using this code (because of RAM problems):

private Bitmap convert(Bitmap bitmap, Bitmap.Config config) {
    Bitmap convertedBitmap = 
        Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), config);
    Canvas canvas = new Canvas(convertedBitmap);
    Paint paint = new Paint();
    paint.setColor(Color.BLACK);
    canvas.drawBitmap(bitmap, 0, 0, paint);
    return convertedBitmap;
}

Why Nothing won't happen, it does go inside isCollisionDetected, I've checked with logs! But it won't detect collision... Can anyone provide working function for checking pixel perfect collision of Bitmap with Bitmap.Config.ALPHA_8?

like image 832
SpoocyCrep Avatar asked Oct 19 '22 16:10

SpoocyCrep


1 Answers

Calling getPixel() on a Bitmap with ALPHA_8 configuration will always return zero. This seems to be a bug.

You can work around this problem by storing the pixels of each Bitmap as a byte array:

byte[] pixelData = getPixels(convert(bitmap, Bitmap.Config.ALPHA_8));

...

public byte[] getPixels(Bitmap bmp) {
    int bytes = bmp.getRowBytes() * bmp.getHeight();
    ByteBuffer buffer = ByteBuffer.allocate(bytes);
    bmp.copyPixelsToBuffer(buffer);
    return buffer.array();
}

You will need to modify your collision detection function a little:

public boolean isCollisionDetected(
    byte[] pixels1, Bitmap bitmap1, int x1, int y1,
    byte[] pixels2, Bitmap bitmap2, int x2, int y2
) {
    Rect bounds1 = new Rect(
        x1, y1, x1 + bitmap1.getWidth(), y1 + bitmap1.getHeight()
    );
    Rect bounds2 = new Rect(
        x2, y2, x2 + bitmap2.getWidth(), y2 + bitmap2.getHeight()
    );

    if (Rect.intersects(bounds1, bounds2)) {
        Rect collisionBounds = getCollisionBounds(bounds1, bounds2);
        for (int i = collisionBounds.left; i < collisionBounds.right; i++) {
            for (int j = collisionBounds.top; j < collisionBounds.bottom; j++) {
                byte bitmap1Pixel = pixels1[((j - y1) * width1) + (i - x1)];
                byte bitmap2Pixel = pixels2[((j - y2) * width2) + (i - x2)];
                if (isFilled(bitmap1Pixel) && isFilled(bitmap2Pixel)) {
                    return true;
                }
            }
        }
    }
    return false;
}
like image 183
Harry Silver Avatar answered Oct 22 '22 08:10

Harry Silver