views:

1822

answers:

3

I would like to change an image I loaded to have round corners.

Any hints, tutorials, best practices you know of?

+2  A: 

How about creating a NinePatchDrawable image that has just rounded corners and has a transparent body. Overlay your image with an appropriately re-sized version of your NinePatchDrawable.

Navin
Very good idea, but what if my rounded-corners image is placed over a gradient background? Would this still work?
iamkoa
I agree that this is the less hack-ish way to achieve this. You can simply put the image and the image frame into a FrameLayout (in this order) and you're done.
Matthias
+4  A: 

For a more controlled method draw a rounded rectangle and mask it onto your image using the porter-duff Xfer mode of the paint.

First setup the Xfer paint and the rounded bitmap:

Bitmap myCoolBitmap = ... ; // <-- Your bitmap you want rounded    
int w = myCoolBitmap.getWidth(), h = myCoolBitmap.getHeight();

// We have to make sure our rounded corners have an alpha channel in most cases
Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(rounder);    

// We're going to apply this paint eventually using a porter-duff xfer mode.
// This will allow us to only overwrite certain pixels. RED is arbitrary. This
// could be any color that was fully opaque (alpha = 255)
Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.RED);

// We're just reusing xferPaint to paint a normal looking rounded box, the 20.f
// is the amount we're rounding by.
canvas.drawRoundRect(new RectF(0,0,w,h), 20.0f, 20.0f, xferPaint);     

// Now we apply the 'magic sauce' to the paint  
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

Now apply this bitmap ontop of your image:

canvas.drawBitmap(myCoolBitmap, 0,0, null);
canvas.drawBitmap(rounder, 0, 0, xferPaint);

Note: this is not the same canvas as before, it is a canvas to whatever buffer you're drawing to.

Ralphleon
Wow, very nice! My only concern with this method is speed - if I was applying this technique to nine images at a time, would the app chug?
iamkoa
I use this technique in a high performance graphics situation -- and haven't seen any issue with it (even after profiling)! Just make sure to save the xferPaint and the rounder bitmap as a field in your class, creating a bitmap is slow, but drawing it is reasonably fast.
Ralphleon
It would be great if you could edit some explanations about the parameters you are using into your post. The sample code looks nice but understanding it is not that easy if you haven't worked with this classes already.
Janusz
Good point! I added some more comments.
Ralphleon
A: 

try this!

public class BitmapUtils {
private static final int ROUND_DIPS = 10;

public static Bitmap getRoundedCornerBitmap(Context context, 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());
    final RectF rectF = new RectF(rect);
    final float roundPx = convertDipsToPixels(context, ROUND_DIPS);

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

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

    return output;
}

public static int convertDipsToPixels(Context context, int dips) {
    final float scale = context.getResources().getDisplayMetrics().density;
    return (int) (dips * scale + 0.5f);
}

}

shiami