Masking(crop) image in frame
Solution 1
Finally got the solution while changing mask image and using of Xfermode
with Bitmap
Mask
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
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;
}
}
});
Related videos on Youtube
Mohammed Azharuddin Shaikh
[email protected] Skills: React Native, JavaScript, TypeScript, Android, BLE, OpenCV, MLKit, ArCore, Firebase, Playcanvas.
Updated on July 05, 2022Comments
-
Mohammed Azharuddin Shaikh almost 2 years
Having a rich UI application in which I want to show image with complex shape like this
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
Mask
Like this
-
zeitgeist almost 2 yearsCan this be done efficiently on GPU with renderscript?
-
-
Dory about 11 yearshello @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 about 11 years@Nidhi you can create scaled bitmap for the same.
-
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 over 10 yearsthanks @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 over 10 yearsTo 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 about 10 years@hotveryspicy very thanks for the code. I want to know how to do this (image masking) with animation.
-
zionpi over 8 yearsDoes this cause OOM?
-
Rushi M Thakker over 6 yearsSelected bitmap is not scaled to imageview's height and width
-
vikrant arankalle over 6 yearsI am using same code but unable to focus on object in image please help
-
jake oliver almost 6 years@AzharShaikh how can i do this with camera?
-
Ashish Kakadiya over 4 years@AzharShaikh I want masking for multiple images in single layout