How to apply a custom image mask with borders?

1.4k Views Asked by At

So I have the following image to be used as a mask:

enter image description here

Now I want to apply this mask to images so that the image will fill the inner white space but will not fill the borders, keeping it as it is. However, when I use the code below, the image takes the inner white space plus the border.

public static Bitmap applyMask(Bitmap scaledBitmap, Bitmap mask) {
    Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas mCanvas = new Canvas(result);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
    mCanvas.drawBitmap(scaledBitmap, 0, 0, null);
    mCanvas.drawBitmap(mask, 0, 0, paint);
    paint.setXfermode(null);
    return result;
}

So is there any way to make the image fill only the white space? How can I keep the mask borders intact?

Thanks in advance.

2

There are 2 best solutions below

1
On

I had to download your image to see the transparent areas. They are on the outside of your shape (which is why DST_IN is the mode that works for this).

What the DST_IN mode does is erases any pixels already on the canvas where the pixels in the mask are transparent. So whether it's the dark border or the white inside, those pixels all have alpha > 0, so they mask the canvas just the same. Those pixels outside the shape have alpha == 0, so they erase the canvas pixels.

Since the final bitmap is the size of your mask, as I see it you have two options:

  • OPTION 1: If you can put the background color in the mask image:

    Change your mask image so that the transparent pixels are inside the shape, and the pixels outside the shape are your background color. Then use SRC_OVER as your xfer mode. The background color outside the border, plus the black border will overwrite the existing pixels in this mode, and since the inner pixels are transparent, the middle part of the image will come through the way you want.

  • OPTION 2: If you have to specify the background color in the app so you can't put it in the mask image:

    For this you'll need two mask images, the one you have and a copy with the inside pixels transparent as well, so you are left with the border. Draw with your mask image the way you are doing right now using DST_IN, then draw the image with just the border using SRC_OVER to draw the border on top of your masked image.

0
On

Here you have an example of what you want and you can adapt it to your case:

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
  Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
      bitmap.getHeight(), Config.ARGB_8888);
  Canvas canvas = new Canvas(output);

  final int color = 0xff424242;
  final Paint paint = new Paint();
  final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
  final RectF rectF = new RectF(rect);
  final float roundPx = 12;

  paint.setAntiAlias(true);
  canvas.drawARGB(0, 0, 0, 0);
  paint.setColor(color);
  canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

  paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
  canvas.drawBitmap(bitmap, rect, rect, paint);

  return output;
}

I've found it here. Hope it helps! :)