How to crop circular area from bitmap in Android

AndroidAndroid LayoutUser InterfaceGraphics

Android Problem Overview


I have a bitmap and I want to crop a circular region from this bitmap. All pixels outside the circle should be transparent. How can I do this?

enter image description here

Android Solutions


Solution 1 - Android

After long brainstorming I have found the solution

public Bitmap getCroppedBitmap(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());

	paint.setAntiAlias(true);
	canvas.drawARGB(0, 0, 0, 0);
	paint.setColor(color);
	// canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
	canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
			bitmap.getWidth() / 2, paint);
	paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
	canvas.drawBitmap(bitmap, rect, rect, paint);
	//Bitmap _bmp = Bitmap.createScaledBitmap(output, 60, 60, false);
	//return _bmp;
	return output;
}

Solution 2 - Android

to generate Circle from rectangles

public static Bitmap getCircularBitmap(Bitmap bitmap) {
	Bitmap output;

	if (bitmap.getWidth() > bitmap.getHeight()) {
		output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Config.ARGB_8888);
	} else {
		output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), 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());

	float r = 0;

	if (bitmap.getWidth() > bitmap.getHeight()) {
		r = bitmap.getHeight() / 2;
	} else {
		r = bitmap.getWidth() / 2;
	}

	paint.setAntiAlias(true);
	canvas.drawARGB(0, 0, 0, 0);
	paint.setColor(color);
	canvas.drawCircle(r, r, r, paint);
	paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
	canvas.drawBitmap(bitmap, rect, rect, paint);
	return output;
}

Solution 3 - Android

You Can make your imageview circular using RoundedBitmapDrawable

here is the code for achieving roundedImageview:

ImageView profilePic=(ImageView)findViewById(R.id.user_image);

//get bitmap of the image
Bitmap imageBitmap=BitmapFactory.decodeResource(getResources(),  R.drawable.large_icon);
RoundedBitmapDrawable roundedBitmapDrawable=RoundedBitmapDrawableFactory.create(getResources(), imageBitmap);

//setting radius
roundedBitmapDrawable.setCornerRadius(50.0f);
roundedBitmapDrawable.setAntiAlias(true);
profilePic.setImageDrawable(roundedBitmapDrawable);

Solution 4 - Android

@Gene made a comment on the answer above that suggested using clipPath as an option for cropping an image as a circle.

The following is a clean implementation of this:

    public static Bitmap GetBitmapClippedCircle(Bitmap bitmap) {
        
        final int width = bitmap.getWidth();
        final int height = bitmap.getHeight();
        final Bitmap outputBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        
        final Path path = new Path();
        path.addCircle(
                  (float)(width / 2)
                , (float)(height / 2)
                , (float) Math.min(width, (height / 2))
                , Path.Direction.CCW);

        final Canvas canvas = new Canvas(outputBitmap);
        canvas.clipPath(path);
        canvas.drawBitmap(bitmap, 0, 0, null);
        return outputBitmap;
    }

This could be added to a utility class.

Solution 5 - Android

I think this solution works better with any type of rectangle, change the pixel size if you want image small or large :

public static Bitmap getCircleBitmap(Bitmap bm) {

		int sice = Math.min((bm.getWidth()), (bm.getHeight()));

		Bitmap bitmap = ThumbnailUtils.extractThumbnail(bm, sice, sice);

		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);

		Canvas canvas = new Canvas(output);

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

		paint.setAntiAlias(true);
		paint.setDither(true);
		paint.setFilterBitmap(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);
		canvas.drawOval(rectF, paint);

		paint.setColor(Color.BLUE);
		paint.setStyle(Paint.Style.STROKE);
		paint.setStrokeWidth((float) 4);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);

		return output;
	}

Solution 6 - Android

This can be easlity done in xml as well without cropping the actual bitmap, You just need to create a circular image mask and place over your actual image. Here is the piece of code which i used:

circle.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
    <gradient android:startColor="#00FFFFFF" android:endColor="#00FFFFFF"
        android:angle="270"/>
     <stroke android:width="10dp" android:color="#FFAAAAAA"/>
</shape>

your_layout.xml (Ignore "android:scaleType="fitXY"" if you don't need it)

<RelativeLayout

        android:id="@+id/icon_layout"
        android:layout_width="@dimen/icon_mask"
        android:layout_height="@dimen/icon_mask"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

        <ImageView
            android:id="@+id/icon"
            android:layout_width="@dimen/icon"
            android:layout_height="@dimen/icon"
            android:layout_centerInParent="true"
            android:scaleType="fitXY" >
        </ImageView>

        <ImageView
            android:id="@+id/icon_mask"
            android:layout_width="@dimen/icon_mask"
            android:layout_height="@dimen/icon_mask"
            android:layout_centerInParent="true"
            android:background="@drawable/circle"
            android:scaleType="fitXY" >
        </ImageView>
    </RelativeLayout>

dimen.xml


<dimen name="icon">36dp</dimen>
<dimen name="icon_mask">55dp</dimen>

enter image description here

OutPut Image View:

Hope, It might be useful for someone!!! :)

Solution 7 - Android

you can use this code, it will work

 private Bitmap getCircleBitmap(Bitmap bitmap) {
        final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(output);

        final int color = Color.RED;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

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

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

        bitmap.recycle();

        return output;
    }

Solution 8 - Android

you can use this code, it will work

public Bitmap getRoundedShape(Bitmap scaleBitmapImage) {
	int targetWidth = 110;
	int targetHeight = 110;
	Bitmap targetBitmap = Bitmap.createBitmap(targetWidth, 
			targetHeight,Bitmap.Config.ARGB_8888);

	Canvas canvas = new Canvas(targetBitmap);
	Path path = new Path();
	path.addCircle(((float) targetWidth - 1) / 2,
			((float) targetHeight - 1) / 2,
			(Math.min(((float) targetWidth), 
					((float) targetHeight)) / 2),
					Path.Direction.CCW);

	canvas.clipPath(path);
	Bitmap sourceBitmap = scaleBitmapImage;
	canvas.drawBitmap(sourceBitmap, 
			new Rect(0, 0, sourceBitmap.getWidth(),
					sourceBitmap.getHeight()), 
					new Rect(0, 0, targetWidth, targetHeight), new Paint(Paint.FILTER_BITMAP_FLAG));
	return targetBitmap;
}

Solution 9 - Android

I believe the easiest solution is to create a BitmapShader of your Bitmap, pass it to your paint object and then simply call something like canvas.drawCircle(cx, cy, radius, paint);

for example

Paint p = new Paint();
p.setShader(new BitmapShader(myBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getHeight() / 2, p);

This is how https://github.com/hdodenhof/CircleImageView also has done it, you can read the source code here: https://github.com/hdodenhof/CircleImageView/blob/master/circleimageview/src/main/java/de/hdodenhof/circleimageview/CircleImageView.java

Solution 10 - Android

I recommend adding bitmap.recycle() if you don't need it anymore, it will prevent OutOfMemory error.

Solution 11 - Android

Here is Kotlin variant using extension method

/**
 * Creates new circular bitmap based on original one.
 */
fun Bitmap.getCircularBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap {
    // circle configuration
    val circlePaint = Paint().apply { isAntiAlias = true }
    val circleRadius = Math.max(width, height) / 2f

    // output bitmap
    val outputBitmapPaint = Paint(circlePaint).apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN) }
    val outputBounds = Rect(0, 0, width, height)
    val output = Bitmap.createBitmap(width, height, config)

    return Canvas(output).run {
        drawCircle(circleRadius, circleRadius, circleRadius, circlePaint)
        drawBitmap(this@getCircularBitmap, outputBounds, outputBounds, outputBitmapPaint)
        output
    }
}

Solution 12 - Android

For peaple who want the center of the rectangle (me), add this before cutting:

    public static Bitmap cropBitmapToBlock(Bitmap bitmap) {
    if (bitmap.getWidth() >= bitmap.getHeight()){
        return Bitmap.createBitmap(
                bitmap,
                bitmap.getWidth()/2 - bitmap.getHeight()/2,
                0,
                bitmap.getHeight(),
                bitmap.getHeight()
        );
    }else{
        return Bitmap.createBitmap(
                bitmap,
                0,
                bitmap.getHeight()/2 - bitmap.getWidth()/2,
                bitmap.getWidth(),
                bitmap.getWidth()
        );
    }
} 

https://stackoverflow.com/questions/6908604/android-crop-center-of-bitmap

Solution 13 - Android

Based on [Jachumbelechao Unto Mantekilla] answer, this code works like a charm for people looking for a Kotlin solution:

fun cropCircleFromBitmap(originalBitmap: Bitmap): Bitmap {
    val size = Math.min(originalBitmap.width, originalBitmap.height)
    val bitmap = ThumbnailUtils.extractThumbnail(originalBitmap, size, size)
    var output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(output)
    val paint = Paint()
    val rect = Rect(0, 0, bitmap.width, bitmap.height)
    val rectF = RectF(rect)
    paint.isAntiAlias = true
    paint.isDither = true
    paint.isFilterBitmap = true
    canvas.drawARGB(0, 0, 0, 0)
    paint.color = 0xffff0000.toInt()
    canvas.drawOval(rectF, paint)
    paint.color = Color.BLUE
    paint.style = Paint.Style.STROKE
    paint.strokeWidth = 4f
    paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
    canvas.drawBitmap(bitmap, rect, rect, paint)
    return output
}

Solution 14 - Android

Now, Right answer:

private Bitmap getCroppedBitmap(Bitmap bitmap, Integer cx, Integer cy, Integer radius) {
    int diam = radius << 1;
    Bitmap targetBitmap = Bitmap.createBitmap(diam, diam, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(targetBitmap);
    final int color = 0xff424242;
    final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawCircle(radius, radius, radius, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(bitmap, -cx+radius, -cy+radius, paint);
    return targetBitmap;
}

Solution 15 - Android

Kotin Fucntion

 fun getRoundedCornerBitmap(bitmap: Bitmap, pixels: Int): Bitmap {
            val output = Bitmap.createBitmap(bitmap.width, bitmap.height, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(output)

            val color = -0xbdbdbe
            val paint = Paint()
            val rect = Rect(0, 0, bitmap.width, bitmap.height)
            val rectF = RectF(rect)
            val roundPx = pixels.toFloat()

            paint.isAntiAlias = true
            canvas.drawARGB(0, 0, 0, 0)
            paint.color = color
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint)

            paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
            canvas.drawBitmap(bitmap, rect, rect, paint)

            return output
        }

call it by this code

 holder.itemFriendImage.setImageBitmap(ImageConverter.getRoundedCornerBitmap(bitmap,600))

Solution 16 - Android

**Jst Add this to your image Id and get the circuler image.**

 imgUserProfile.setImageBitmap(getCircularCenterCropBitmap(bitmap, (int) (150 * denisty)));

Method:-

public void Bitmap getCircularCenterCropBitmap(Bitmap originalBmp, int diameter) {
        Bitmap resizedBmp = BitmapUtils.getScaledCroppedBitmap(originalBmp, diameter, diameter);
        return BitmapUtils.getRoundedCircularBitmap(resizedBmp, diameter / 2);
    }

Solution 17 - Android

For kotlin:

private fun getCircularBitmap(bitmap: Bitmap): Bitmap? {
        val output = Bitmap.createBitmap(
            bitmap.width,
            bitmap.height, Bitmap.Config.ARGB_8888
        )
        val canvas = Canvas(output)
        val color = -0xbdbdbe
        val paint = Paint()
        val rect = Rect(0, 0, bitmap.width, bitmap.height)
        paint.isAntiAlias = true
        canvas.drawARGB(0, 0, 0, 0)
        paint.color = color
        canvas.drawCircle(
            (bitmap.width / 2).toFloat(), (bitmap.height / 2).toFloat(), (
                    bitmap.width / 2).toFloat(), paint
        )
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        canvas.drawBitmap(bitmap, rect, rect, paint)
        return output
    }

Solution 18 - Android

kotlin, put it in Ext.kt

 private fun Bitmap.getCircledBitmap(): Bitmap {
    val output = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(output)
    val paint = Paint()
    val rect = Rect(0, 0, this.width, this.height)
    paint.isAntiAlias = true
    canvas.drawARGB(0, 0, 0, 0)
    canvas.drawCircle(this.width / 2f, this.height / 2f, this.width / 2f, paint)
    paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    canvas.drawBitmap(this, rect, rect, paint)
    return output
}

Solution 19 - Android

Not sure this is a programming question but...

The easiest solution would be to make the outside area transparent in the source bitmap. Otherwise, you'll have to calculate which pixels are outside of the circle, and set the alpha accordingly (alpha = 0 for full transparency).

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
QuestionAltafView Question on Stackoverflow
Solution 1 - AndroidAltafView Answer on Stackoverflow
Solution 2 - AndroiddieselView Answer on Stackoverflow
Solution 3 - Androidsree_sgView Answer on Stackoverflow
Solution 4 - AndroidHGPBView Answer on Stackoverflow
Solution 5 - AndroidJachumbelechao Unto MantekillaView Answer on Stackoverflow
Solution 6 - AndroidAshView Answer on Stackoverflow
Solution 7 - Androiduser5400869View Answer on Stackoverflow
Solution 8 - Androidanupam sharmaView Answer on Stackoverflow
Solution 9 - AndroidMartin NowosadView Answer on Stackoverflow
Solution 10 - AndroidbadoualyView Answer on Stackoverflow
Solution 11 - AndroidYuriy SeredyukView Answer on Stackoverflow
Solution 12 - AndroidjobbertView Answer on Stackoverflow
Solution 13 - AndroidRodrigo SalinasView Answer on Stackoverflow
Solution 14 - AndroidMasterView Answer on Stackoverflow
Solution 15 - AndroidSamet ÖZTOPRAKView Answer on Stackoverflow
Solution 16 - AndroidAlok SinghView Answer on Stackoverflow
Solution 17 - AndroidJamil Hasnine TamimView Answer on Stackoverflow
Solution 18 - AndroidPhạm Quang LinhView Answer on Stackoverflow
Solution 19 - AndroidMandisaWView Answer on Stackoverflow