I started my android app using png files for objects that required alpha, but I quickly realized that the space required was simply too much. So, I wrote a program that took a png with alpha and created a b&w alpha mask png file and a jpeg. This gives me a tremendous amount of space savings, but the speed is not great.
The following is the code in my Android app which combines the jpg image (the origImgId in the code) and the png mask (the alphaImgId in the code).
It works, but it’s not fast. I already cache the result and I’m working on code which will load these images in the menu screen before the game starts, but it would be nice if there was a way to speed this up.
Does anyone have any suggestions? Note that I modified the code slightly so as to make it easily understandable. In the game this is actually a sprite which loads the image on demand and caches the result. Here you just see the code for loading the images and applying the alpha.
public class BitmapDrawableAlpha
{
public BitmapDrawableAlpha(int origImgId, int alphaImgId) {
this.origImgId = origImgId;
this.alphaImgId = alphaImgId;
}
protected BitmapDrawable loadDrawable(Activity a) {
Drawable d = a.getResources().getDrawable(origImgId);
Drawable da = a.getResources().getDrawable(alphaImgId);
Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(),d.getIntrinsicHeight(),Bitmap.Config.ARGB_8888);
{
Canvas c = new Canvas(b);
d.setBounds(0,0,d.getIntrinsicWidth()-1,d.getIntrinsicHeight()-1);
d.draw(c);
}
Bitmap ba = Bitmap.createBitmap(d.getIntrinsicWidth(),d.getIntrinsicHeight(),Bitmap.Config.ARGB_8888);
{
Canvas c = new Canvas(ba);
da.setBounds(0,0,d.getIntrinsicWidth()-1,d.getIntrinsicHeight()-1);
da.draw(c);
}
applyAlpha(b,ba);
return new BitmapDrawable(b);
}
/** Apply alpha to the specified bitmap b. */
public static void applyAlpha(Bitmap b, Bitmap bAlpha) {
int w = b.getWidth();
int h = b.getHeight();
for(int y=0; y < h; ++y) {
for(int x=0; x < w; ++x) {
int pixel = b.getPixel(x,y);
int finalPixel = Color.argb(Color.alpha(bAlpha.getPixel(x,y)), Color.red(pixel), Color.green(pixel), Color.blue(pixel));
b.setPixel(x,y,finalPixel);
}
}
}
private int origImgId;
private int alphaImgId;
}
If you are going to be manipulating every multiple pixels you could call getPixels() and setPixels() to get them all at once. This will prevent additional method calls and memory references in your loop.
Another thing you could do is do the pixel addition with bitwise or instead of the helper methods. Preventing method calls should increase efficiency:
That being said the process you are trying to undertake is fairly simple, I can’t imagine these will provide a huge performance boost. From this point the only suggestion I can provide would be to goto a native implementation with the NDK.
EDIT: Also since a Bitmap doesn’t have to be mutable to use
getPixels()orgetPixel()you can get the alpha bitmap with BitmapFactory.decodeResource():