In our application we need to apply mask to some icons to make them semitransparent. The original images are in RGB format i.e. without alpha channel. To apply mask we need add alpha channel to original images. Before Android 2.0 we did this like:

Bitmap dest = src.copy(Bitmap.Config.ARGB_8888, true);

When we run our application on Android 2.1 device we noticed that the destination bitmap is created but without alpha channel. After applying mask, pixels that should be semitransparent become black.

The getPixel() method returns different value than was set by setPixel() method.

So, how to add alpha channel to RGB bitmap?

There are three ways:

First:

Use ARGB_4444 format:

Bitmap dest = src.copy(Bitmap.Config.ARGB_4444, true);

In this case the alpha channel will be added, but you will lose the quality of image

Second:

Create empty bitmap with dimensions of original image and ARGB_8888 format:

int width =  src.getWidth();
int height = src.getHeight();
Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

Copy pixels from source bitmap to the int array:

int[] pixels = new int[width * height];
src.getPixels(pixels, 0, width, 0, 0, width, height);

And set these pixels to destination bitmap:

dest.setPixels(pixels, 0, width, 0, 0, width, height);

The alpha channel will be added without losing image quality. But this way is too slow ~ 5027ms average for 1000 bitmaps

Third: (Thanks to Cyril Mottier post)

First of all you need to create mask image which you want to apply to the icon and put it in to the resources.

Then you need to create Paint object and set xfermode to it:

paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

And draw source bitmap and mask on canvas:

canvas.drawBitmap(src, 0, 0, null);
canvas.drawBitmap(icon, 0, 0, paint);

This way requires to have mask image (you can’t modify source bitmap on the fly), but it is fast (~ 2659ms average for 1000 bitmaps) and without quality loss