Masking(crop) image in frame

AndroidImageBitmapMaskingPorter Duff

Android Problem Overview


Having a rich UI application in which I want to show image with complex shape like this

enter image description here

Now what I want is to crop my image as per Mask image, Actually image is coming dynamic and can be imported from Camera or Gallery(square or rectangle shape) and I want that image to fit in my layout frame like above

So just wondering that how do I have achieve this? Any idea /hint welcome

Background frame
enter image description here
Mask
enter image description here

Like this

Android Solutions


Solution 1 - Android

Finally got the solution while changing mask image and using of Xfermode with Bitmap

Mask

enter image description here

 ImageView mImageView= (ImageView)findViewById(R.id.imageview_id);
 Bitmap original = BitmapFactory.decodeResource(getResources(),R.drawable.content_image);
 Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.mask);
 Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), 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(original, 0, 0, null);
 mCanvas.drawBitmap(mask, 0, 0, paint);
 paint.setXfermode(null);
 mImageView.setImageBitmap(result);
 mImageView.setScaleType(ScaleType.CENTER);
 mImageView.setBackgroundResource(R.drawable.background_frame);

see output

enter image description here

Source can be found here

Solution 2 - Android

It's even easier using the Picasso library and a custom Transformation:

MaskTransformation.java:

 * ORIGINAL:
 * Copyright (C) 2015 Wasabeef
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.monori.example.utilities;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;

import com.squareup.picasso.Transformation;

public class MaskTransformation implements Transformation {

    private static Paint mMaskingPaint = new Paint();
    private Context mContext;
    private int mMaskId;

    static {
        mMaskingPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    }

    /**
     * @param maskId If you change the mask file, please also rename the mask file, or Glide will get
     * the cache with the old mask. Because getId() return the same values if using the
     * same make file name. If you have a good idea please tell us, thanks.
     */
    public MaskTransformation(Context context, int maskId) {
        mContext = context.getApplicationContext();
        mMaskId = maskId;
    }

    @Override public Bitmap transform(Bitmap source) {
        int width = source.getWidth();
        int height = source.getHeight();

        Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        Drawable mask = getMaskDrawable(mContext, mMaskId);

        Canvas canvas = new Canvas(result);
        mask.setBounds(0, 0, width, height);
        mask.draw(canvas);
        canvas.drawBitmap(source, 0, 0, mMaskingPaint);

        source.recycle();

        return result;
    }

    @Override public String key() {
        return "MaskTransformation(maskId=" + mContext.getResources().getResourceEntryName(mMaskId)
                + ")";
    }

    public Drawable getMaskDrawable(Context context, int maskId) {
        Drawable drawable = ContextCompat.getDrawable(context, maskId);

        if (drawable == null) {
            throw new IllegalArgumentException("maskId is invalid");
        }

        return drawable;
    }
}

Then simply defining it in a line:

Picasso.with(context)
                    .load(imageUrl)
                    .transform(new MaskTransformation(context, _maskDrawableId))
                    .placeholder(R.drawable.drawableId)
                    .into(imageView);

Solution 3 - Android

	 final ImageView mImageView = (ImageView) findViewById(R.id.image);
	 mImageView.setBackgroundResource(R.drawable.user_outer_circle_icon);
	 

	 mImageView.setOnClickListener(new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			

			if(b){
				 mImageView.setBackgroundResource(R.drawable.profil_circle);
				 
				 Bitmap original = BitmapFactory.decodeResource(getResources(),R.drawable.doge);
				 
				 Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.mask_white);
				 
				 Bitmap mask1 = BitmapFactory.decodeResource(getResources(),R.drawable.pencil_bg);
				 
				 original = Bitmap.createScaledBitmap(original, mask.getWidth(),mask.getHeight(), true);
				 
				 Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),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(original, 0, 0, null);
				 mCanvas.drawBitmap(mask, 0, 0, paint);
				 mCanvas.drawBitmap(mask1, 0, 0, null);
				 Bitmap mask2 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_pencil);
				 mCanvas.drawBitmap(mask2, 0, 0, null);
				 mImageView.setImageBitmap(result);
				 mImageView.setScaleType(ScaleType.FIT_XY);
				 
				 b=false;
			 }else{
				 ImageView mImageView = (ImageView) findViewById(R.id.image);
				 Bitmap original = BitmapFactory.decodeResource(getResources(),
				 R.drawable.doge);
				 
				 Bitmap mask = BitmapFactory.decodeResource(getResources(),
				 R.drawable.mask_white);
				 
				 original = Bitmap.createScaledBitmap(original, mask.getWidth(),
				 mask.getHeight(), true);
				 
				 Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),
				 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(original, 0, 0, null);
				 mCanvas.drawBitmap(mask, 0, 0, paint);
				 paint.setXfermode(null);
				 mImageView.setImageBitmap(result);
				 mImageView.setScaleType(ScaleType.FIT_XY);
				// mImageView.setBackgroundResource(R.drawable.user_outer_circle_icon);
				 b= true;

				 
			 }
			
			
		}
	});

Solution 4 - Android

This example masks his child element (Imageview) with the mask "animation_mask"

<com.christophesmet.android.views.maskableframelayout.MaskableFrameLayout
android:id="@+id/frm_mask_animated"
android:layout_width="100dp"
app:porterduffxfermode="DST_IN"
app:mask="@drawable/animation_mask"
android:layout_height="100dp">

<ImageView android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:scaleType="centerCrop"
           android:src="@drawable/unicorn"/>

check this git link

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMohammed Azharuddin ShaikhView Question on Stackoverflow
Solution 1 - AndroidMohammed Azharuddin ShaikhView Answer on Stackoverflow
Solution 2 - AndroidanthonymonoriView Answer on Stackoverflow
Solution 3 - AndroidPrashantView Answer on Stackoverflow
Solution 4 - AndroidLalliView Answer on Stackoverflow