Android Mask Bitmap on Canvas Gen a Black Space

Android Mask bitmap on canvas gen a black space

Here is a solution which helped me to implement masking:

public void draw(Canvas canvas) {
Bitmap original = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.original_image);
Bitmap mask = BitmapFactory.decodeResource(getContext().getResources(),R.drawable.mask_image);

//You can change original image here and draw anything you want to be masked on it.

Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
Canvas tempCanvas = new Canvas(result);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
tempCanvas.drawBitmap(original, 0, 0, null);
tempCanvas.drawBitmap(mask, 0, 0, paint);
paint.setXfermode(null);

//Draw result after performing masking
canvas.drawBitmap(result, 0, 0, new Paint());
}

The mask should be a white image with transparency.

It will work like this:

original image + mask = result image

Android Bitmap Masking (Xfermode) leaves opaque black background behind

It seems that to get the Xfermode done, I need to redirect the drawing to an offscreen bitmap. So adding the following fixed my problem.

canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), q);

But then again, the documentation of saveLayer says to avoid using this method since it is expensive. It is suggested to use a harware layer instead of this method.

Avoid using this method, especially if the bounds provided are large,
or if the CLIP_TO_LAYER_SAVE_FLAG is omitted from the saveFlags
parameter. It is recommended to use a hardware layer on a View to
apply an xfermode, color filter, or alpha, as it will perform much
better than this method.

Hence, intead of saveLayer method, I was able to fix it by adding the following:

setLayerType(LAYER_TYPE_HARDWARE, q);

How to draw on bitmap using another bitmap as mask?

I had to change the masks as described by @Christian. Then, the wanted result could easily be produced:

canvas.drawRect(rect, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
canvas.drawBitmap(mask, 0.0f, 0.0f, paint);

How to Draw a Pattern on Bitmap using canvas

Option 1: Transparent Foreground

If you follow the process described here to merge the two images, you can draw one image onto another. Simply change the opacity of the top-most image as described here. Consider the following example:

Bitmap bitmap = Bitmap.createBitmap(/* width */, /* height */, Config.ARGB_8888);
Paint alpha = new Paint();
alpha.setAlpha(/* alpha */);
Canvas canvas = new Canvas(bitmap);
Bitmap background = BitmapFactory.decodeResource(
getResources(), R.drawable.background);
Bitmap foreground = BitmapFactory.decodeResource(
getResources(), R.drawable.pattern);
canvas.drawBitmap(background, /* xPos */, /* yPos */, null);
canvas.drawBitmap(foreground, /* xPos */, /* yPos */, alpha);

Option 2: Background Masked with Foreground

Alternatively, if you are trying to mask the image, you can consider implementing the solution found here.

Drawing a Bitmap to a Canvas with an alpha gradient

use a ComposeShader, like this:

class V extends View {
Bitmap bitmap;
Paint paint = new Paint();

public V(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.chrome);
Shader shaderA = new LinearGradient(0, 0, bitmap.getWidth(), 0, 0xffffffff, 0x00ffffff, Shader.TileMode.CLAMP);
Shader shaderB = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
paint.setShader(new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SRC_IN));
}

@Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), paint);
}
}


Related Topics



Leave a reply



Submit