Masking(crop) image in frame

48,790

Solution 1

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

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

     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;


             }


        }
    });
Share:
48,790

Related videos on Youtube

Mohammed Azharuddin Shaikh
Author by

Mohammed Azharuddin Shaikh

[email protected] Skills: React Native, JavaScript, TypeScript, Android, BLE, OpenCV, MLKit, ArCore, Firebase, Playcanvas.

Updated on July 05, 2022

Comments

  • Mohammed Azharuddin Shaikh
    Mohammed Azharuddin Shaikh almost 2 years

    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

    • zeitgeist
      zeitgeist almost 2 years
      Can this be done efficiently on GPU with renderscript?
  • Dory
    Dory about 11 years
    hello @hotveryspicy,thanks for example code,it helped a lot. I am facing some problem,some little hint will go long way for me. I want to cut the bitmap in some polygon shape drawn. My bitmap cuts in polygon shape but the content of cropped bitmap is taken from the top left i.e. 0,0 of original bitmap. And I want the content below where the polygon is drawn.
  • Mohammed Azharuddin Shaikh
    Mohammed Azharuddin Shaikh about 11 years
    @Nidhi you can create scaled bitmap for the same.
  • Dory
    Dory about 11 years
    @hotveryspicy thankyou for the reply. Actually I want to do same thing given in here. stackoverflow.com/questions/15969028/…. My problem is cropped bitmap is crop from top left i.e 0,0. Not form the path which i specified. I have also put code. Please guide me where i am going wrong.
  • I'm a frog dragon
    I'm a frog dragon over 10 years
    thanks @hotveryspicy, for anyone that need it, I made a simple fork that can help scale the image to the mask's size: github.com/worker8/MaskImage/tree/master
  • Miguel
    Miguel over 10 years
    To scale the mask to fit the image, i use this line: Bitmap resized = Bitmap.createScaledBitmap(mask, original.getWidth(), original.getHeight(), true); And the use the mCanvas.drawBitmap(original, 0, 0, null); mCanvas.drawBitmap(resized, 0, 0, paint);
  • maddy d
    maddy d about 10 years
    @hotveryspicy very thanks for the code. I want to know how to do this (image masking) with animation.
  • zionpi
    zionpi over 8 years
    Does this cause OOM?
  • Rushi M Thakker
    Rushi M Thakker over 6 years
    Selected bitmap is not scaled to imageview's height and width
  • vikrant arankalle
    vikrant arankalle over 6 years
    I am using same code but unable to focus on object in image please help
  • jake oliver
    jake oliver almost 6 years
    @AzharShaikh how can i do this with camera?
  • Ashish Kakadiya
    Ashish Kakadiya over 4 years
    @AzharShaikh I want masking for multiple images in single layout