web-dev-qa-db-fra.com

Rogner la zone circulaire de bitmap dans Android

J'ai un bitmap et je veux recadrer une région circulaire de ce bitmap. Tous les pixels en dehors du cercle doivent être transparents. Comment puis-je faire ceci?

enter image description here

99
Altaf

Après un long brainstorming, j'ai trouvé la 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;
}
200
Altaf

générer un cercle à partir de 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;
}
39
diesel

@Gene a commenté la réponse ci-dessus en suggérant d'utiliser clipPath comme option pour rogner une image en cercle.

Voici une implémentation propre de ceci:

    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;
    }

Cela pourrait être ajouté à une classe d'utilitaire.

30
HGPB

Vous pouvez rendre votre image circulaire en utilisant RoundedBitmapDrawable

voici le code pour réaliser arrondiImageview:

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);
28
sree

Je pense que cette solution fonctionne mieux avec tout type de rectangle, changez la taille en pixels si vous voulez une image petite ou grande

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;
    }

Cela peut également être fait facilement en XML sans rogner le bitmap réel. Il vous suffit de créer un masque d'image circulaire et de le placer sur votre image réelle. Voici le morceau de code que j'ai utilisé:

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"/>

your_layout.xml (Ignorez "Android: scaleType =" fitXY "" si vous n'en avez pas besoin)

<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:

J'espère que ça pourrait être utile pour quelqu'un !!! :)

10
Ash

vous pouvez utiliser ce code, cela fonctionnera

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;
}
6
anupam sharma

vous pouvez utiliser ce code, cela fonctionnera

 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;
    }
6
user5400869

Maintenant, bonne réponse:

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;
}
1
Master

Je recommande d'ajouter bitmap.recycle() si vous n'en avez plus besoin, cela évitera les erreurs OutOfMemory.

1
badoualy

Basé sur la réponse [Jachumbelechao Unto Mantekilla], ce code fonctionne comme un charme pour ceux qui recherchent une solution Kotlin:

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
}
1
Rodrigo Salinas

Voici la variante de Kotlin utilisant la méthode d'extension

/**
 * 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
    }
}
1
Yuriy Seredyuk

Fonction Kotlin

 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
        }

appelez-le par ce code

 holder.itemFriendImage.setImageBitmap(ImageConverter.getRoundedCornerBitmap(bitmap,600))
1
Samet öztoprak

Pour les personnes qui veulent le centre du rectangle (moi), ajoutez ceci avant de couper:

    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()
        );
    }
} 

Centre de culture Android de Bitmap

1
jobbert

Je pense que la solution la plus simple est de créer un BitmapShader de votre Bitmap, de le transmettre à votre objet Paint, puis d’appeler simplement quelque chose comme canvas.drawCircle (cx, cy, radius, Paint);

par exemple

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

Voici comment https://github.com/hdodenhof/CircleImageView l'a également fait, Vous pouvez lire le code source ici: https://github.com/hdodenhof/CircleImageView /blob/master/circleimageview/src/main/Java/de/hdodenhof/circleimageview/CircleImageView.Java

0
Martin Nowosad
**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);
    }
0
Alok Singh