Android : alpha masking 8-bit bitmaps (png-8)

on Saturday, July 5, 2014


I've been trying to figure out how to effectively use png-8 files as bitmaps when rendering simple 2d animations in Android.


Static background tiles haven't been a problem thus far; all I had to do was set Bitmap.Config.Alpha_8, and the images load properly and display as intended via canvas.drawBitmap().


The problem is when drawing animation sprites. I realized that Android would not support 8-bit PNG files with alpha channel, so I attempted to solve the problem by setting the border pixels in my sprite bitmaps to an obnoxious shade of pink that I wouldn't use in any of my sprites anyway (not sure of the 8-bit code for this shade of pink, have yet to dig it up). This leaves me with 255 colors for the actual sprites, which is fine with me. I resolved to draw each bitmap to the screen by extracting color data pixel-by-pixel and then setting up an if test to see if the color matched my shade of pink. If it did, I simply wouldn't draw it. The end result would be the intended animation sprite minus the pink border pixels. I wouldn't have any real transparencies, but I decided I could do without those.


Sadly, I have yet to find a way to do that.


bitmap.getPixel() is throwing nullpointer exceptions whenever I use it to extract color data from any of my ALPHA_8 bitmaps if I call the method from within my View's onDraw method (I'm using a simple View here). If I try calling bitmap.getPixels() from the constructor, it produces an array full of 0s (though it does not throw an exception).


The only other thing I can think to do would be to dump the contents of the bitmap into a ByteBuffer via bitmap.copyPixelsToBuffer() in the constructor, feed that data into my if statement (to ignore color codes for the pink border pixels) in onDraw, and then dynamically convert the 8-bit color codes into 32-bit color codes which I would then feed to bitmap.drawPoint() along with the relevant x,y coordinates where I'd need the individual pixels to be on the screen. If the 8-bit to 32-bit conversions aren't too slow, I could probably get away with it, but I'd honestly rather use bitmap.getPixel() or bitmap.getPixels() if possible. Having to set up a separate ByteBuffer for every animation sprite I intend to use in a view sort of negates the memory savings advantage from using a png-8 file instead of png-24 + alpha channel. At that point, it would be better to just throw in the towel and switch to png-24 + alpha.


I've also looked at applying alpha masks, and frankly I don't like what I see there.


So, any advice on how I can solve this problem?


0 comments:

Post a Comment