Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rounded Corner Image Transformation for square's Picasso
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
// enables hardware accelerated rounded corners
// original idea here : http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
public class RoundedTransformation implements com.squareup.picasso.Transformation {
private final int radius;
private final int margin; // dp
// radius is corner radii in dp
// margin is the board in dp
public RoundedTransformation(final int radius, final int margin) {
this.radius = radius;
this.margin = margin;
}
@Override
public Bitmap transform(final Bitmap source) {
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint);
if (source != output) {
source.recycle();
}
return output;
}
@Override
public String key() {
return "rounded";
}
}
@JakeWharton

This comment has been minimized.

Copy link

JakeWharton commented Jul 8, 2014

Keys must be unique for a configuration of a transformation!

Should be:

    @Override
    public String key() {
        return "rounded(radius=" + radius + ", margin=" + margin + ")";
    }

Even better if you pre-compute this string once in the constructor.

@broakenmedia

This comment has been minimized.

Copy link

broakenmedia commented Jul 17, 2014

@JakeWharton

And what happens if you dont set it? Surely it's not unique the radius and margin as it's often the same for every image?

@Naderkunbhar

This comment has been minimized.

Copy link

Naderkunbhar commented Sep 15, 2014

Android picasso in Gridview Adaptor Transformer is not applying,please tell me what is problem
package com.example.picasso_transform;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

///Nader
public class Adopter_Feeds extends BaseAdapter {
ArrayList data;

Context mContext;

private Picasso pic;

private LayoutInflater mInflater;

public Adopter_Feeds(Context product_List, ArrayList<Image> data) {
    super();
    this.data = data;
    this.mContext = product_List;
    this.mInflater = (LayoutInflater) product_List
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    pic = PicassoBigCache.INSTANCE.getPicassoBigCache(mContext);
}

public int dpToPx(int dp) {
    DisplayMetrics displayMetrics = mContext.getResources()
            .getDisplayMetrics();
    int px = Math.round(dp
            * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
    return px;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null)
        convertView = mInflater.inflate(R.layout.feed_layout, null);
    ImageView Feed_Image = (ImageView) convertView
            .findViewById(R.id.Feed_Image);
    pic.load(data.get(position).imgPath)
            .transform(new Round_Corners(dpToPx(8), dpToPx(8)))
            .into(Feed_Image);

    return convertView;
}

public float convertDipToPx(float dip) {
    DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
    return dip * dm.density; // dm.density gives the scaling factor

}

void setFonts(TextView text, String font) {
    Typeface tf = Typeface.createFromAsset(mContext.getAssets(), "fonts/"
            + font);
    text.setTypeface(tf);
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return data.size();
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public long getItemId(int position) {
    // TODO Auto-generated method stub
    return 0;
}

void showAlert(String Title, String Message) {
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
    alertDialog.setTitle(Title);
    alertDialog.setCancelable(false);
    alertDialog.setMessage("" + Message);
    alertDialog.setPositiveButton("Ok",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                }
            });
    AlertDialog alert = alertDialog.create();
    alert.show();
}

}

package com.example.picasso_transform;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;

import com.squareup.picasso.Transformation;

public class Round_Corners implements Transformation {
private int Round;

Round_Corners(int margin, int Round) {
    this.Round = Round;

}

@Override
public String key() {
    return "Round" + Round;
}

@Override
public Bitmap transform(Bitmap arg0) {
    // TODO Auto-generated method stub
    return getRoundedTopLeftCornerBitmap(arg0);
}

public Bitmap getRoundedTopLeftCornerBitmap(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 Px = Round;

    final Rect bottomRect = new Rect(0, bitmap.getHeight() / 2,
            bitmap.getWidth(), bitmap.getHeight());

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawRoundRect(rectF, Px, Px, paint);
    // Fill in upper right corner
    // canvas.drawRect(topRightRect, paint);
    // Fill in bottom corners
    canvas.drawRect(bottomRect, paint);

    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, paint);
    if (bitmap != output) {
        bitmap.recycle();
    }
    return output;
}

}

@Naderkunbhar

This comment has been minimized.

Copy link

Naderkunbhar commented Sep 15, 2014

is ther any problem in my code

@miao1007

This comment has been minimized.

Copy link

miao1007 commented Oct 5, 2014

thanks,.work fine on my listview

@rsablania

This comment has been minimized.

Copy link

rsablania commented Oct 27, 2014

Only rounds the upper 2 corners of my imageview @Naderkunbhar

@ashokcs

This comment has been minimized.

Copy link

ashokcs commented Jan 7, 2015

Getting exception when trying to make round transformation of 102 X 103 pix resolution image.
Please help me with this.

java.lang.RuntimeException: Transformation rounded(radius=0, margin=0) crashed with exception.
at com.squareup.picasso.BitmapHunter$3.run(BitmapHunter.java:370)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.graphics.Bitmap.createBitmap(Bitmap.java:903)
at android.graphics.Bitmap.createBitmap(Bitmap.java:880)
at android.graphics.Bitmap.createBitmap(Bitmap.java:847)
at com.company.app.ui.RoundedTransformation.transform(RoundedTransformation.java:45)
at com.squareup.picasso.BitmapHunter.applyCustomTransformations(BitmapHunter.java:365)
at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:174)
at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:111)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:408)

@cbeyls

This comment has been minimized.

Copy link

cbeyls commented Jul 29, 2015

    if (source != output) {
        source.recycle();
    }

Source is always different from output. Otherwise this code would not even work.

@crackcode007

This comment has been minimized.

Copy link

crackcode007 commented Nov 3, 2015

its working only with wrap_content image view not with given height and width

@Mark-Mark-Mark

This comment has been minimized.

Copy link

Mark-Mark-Mark commented Jan 6, 2016

@ashokcs where you able to solve your crash?
I'm having the same problem:

Fatal Exception: java.lang.RuntimeException: Transformation rounded(radius=12, margin=0) crashed with exception.
       at com.squareup.picasso.BitmapHunter$3.run(BitmapHunter.java:434)
       at android.os.Handler.handleCallback(Handler.java:808)
       at android.os.Handler.dispatchMessage(Handler.java:103)
       at android.os.Looper.loop(Looper.java:193)
       at android.app.ActivityThread.main(ActivityThread.java:5299)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
       at dalvik.system.NativeStart.main(NativeStart.java)
Caused by java.lang.NullPointerException
       at android.graphics.Canvas.(Canvas.java:136)
       at MY_FOO_APP.util.RoundedTransformation.transform(RoundedTransformation.java:30)
       at com.squareup.picasso.BitmapHunter.applyCustomTransformations(BitmapHunter.java:429)
       at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:238)
       at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:159)
       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
       at java.util.concurrent.FutureTask.run(FutureTask.java:237)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:848)
       at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:411)
@abdul-martinez

This comment has been minimized.

Copy link

abdul-martinez commented Apr 21, 2016

@1492Mark @ashokcs have you solved this crash? I'm having crashes with the same @1492Mark stack trace.

@amardeshbd

This comment has been minimized.

Copy link

amardeshbd commented Jul 25, 2016

If anybody is looking for option to apply rounded corner to only top and bottom corners individually, check following gist

https://gist.github.com/amardeshbd/06b491d4adb568b1b226a20d4953a180

@mensly

This comment has been minimized.

Copy link

mensly commented Feb 9, 2017

Thanks for this! Here's my slight modification to convert to Kotlin and have appropriate defaults without needing to know the radius beforehand. Used to show pretty images in push notifications!

class RoundedTransformation(private val radius: Float? = null, private val margin: Float = 0f) : Transformation {
    override fun transform(source: Bitmap): Bitmap {
        val paint = Paint().apply {
            isAntiAlias = true
            shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
        }
        val output = Bitmap.createBitmap(source.width, source.height, Config.ARGB_8888)
        Canvas(output).drawRoundRect(margin, margin, source.width - margin, source.height - margin,
                radius ?: source.width.toFloat() / 2, radius ?: source.height.toFloat() / 2,
                paint)
        if (source != output) {
            source.recycle()
        }
        return output
    }

    override fun key(): String {
        return "rounded(radius=$radius, margin=$margin)"
    }
}
@VincentMasselis

This comment has been minimized.

Copy link

VincentMasselis commented Jul 11, 2017

Thanks @mensly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.