Transform an avatar into a Circular One

This blog article will illustrate us about how to convert an image into a circular shape. We will go through the process of converting a conventional image to a circular cropped one. Nowadays circular images are more preferred than normal ones as they provide us with more finesse and it seriously looks good to the eye. Just for example, see WhatsApp! How would it have looked if the user image would have been in a square conventional shape!

Converting an image into a circular one is quite easy and we at Open Event Android have used a sort of a simple algorithm to convert it. Let us head straight to the code.

We will use the Picasso library to load an image. The library provides us with a transform function which takes input of type of transform we want to do.

The fetching of image code:-

Picasso.get()

       .load(image_url)

       .placeholder(R.drawable.ic_person_black_24dp)

       .transform(CircleTransform())

       .into(rootView.avatar)

As you can see, we are passing a CircleTransform class. Let’s get onto the CircleTransform class then.

It contains methods which are overridden. The first one is where the magic happens. The second one just returns the key value of “circle”.

@Override

public Bitmap transform(Bitmap source) { … }

@Override

public String key() {

   return “circle”;

}

The below code is present in the first method.

int size = Math.min(source.getWidth(), source.getHeight());

int x = (source.getWidth() – size) / 2;

int y = (source.getHeight() – size) / 2;

Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);

if (!squaredBitmap.equals(source)) {

   source.recycle();

}

We initially proceed by declaring a size variable which gets the minimum of the height and width. This is due to the fact that a circle can have only one radius!

We head onto creating a bitmap. Basically we create a new bitmap using the source. The coordinates of starting and ending pixels are provided by x and y. The next two fields are actually width and height, which is size in both cases. ( We want a perfect Circle )

As we have a new bitmap, we can now remove the Bitmap source from memory by calling the recycle function.

Bitmap.Config config = source.getConfig() != null ? source.getConfig() : Bitmap.Config.ARGB_8888;

Bitmap bitmap = Bitmap.createBitmap(size, size, config);

We now create a config variable which fetches the config of the original source. If the source is null, it takes the value of ARGB_8888 which basically means the colour of the bitmap should have four channels Alpha, Red, Green, Blue. Thus a new bitmap is created using that config.

Now we are going to draw on the bitmap. The bitmap has been only configured, but it still is empty. So we create a Canvas and a Paint object ( Basically we are going to paint the squared bitmap on the bitmap! )

Canvas canvas = new Canvas(bitmap);

Paint paint = new Paint();

BitmapShader shader = new BitmapShader(squaredBitmap,

       BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);

paint.setShader(shader);

paint.setAntiAlias(true);

We observe that we use a shader to shade the bitmap. So we create a new BitmapShader object with a squaredBitmap as one of its inputs. The Shader.TileMode.CLAMP constant defines that the edge corners should be used to fill the extra space.

We then set the shader to the setShader method of Paint. Setting antiAlias to true will smooth out edges of what is being drawn. Thus our painting tools are ready.

float r = size / 2f;

canvas.drawCircle(r, r, r, paint);

squaredBitmap.recycle();

return bitmap;

Thus we are using the canvas to paint the bitmap as a circle. The variable r specifies the radius of the circle. .drawCircle is a function which helps us in drawing out a perfect circle. The masterpiece is made using paint.

As the drawing has already been done, we don’t need squaredBitmap to be in memory anymore. Finally we return the Bitmap bitmap. Final Code:-

public class CircleTransform implements Transformation {

   @Override

   public Bitmap transform(Bitmap source) {

       int size = Math.min(source.getWidth(), source.getHeight());

       int x = (source.getWidth() – size) / 2;

       int y = (source.getHeight() – size) / 2;

       Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);

       if (!squaredBitmap.equals(source)) {

           source.recycle();

       }

       Bitmap.Config config = source.getConfig() != null ? source.getConfig() :      Bitmap.Config.ARGB_8888;

       Bitmap bitmap = Bitmap.createBitmap(size, size, config);

       Canvas canvas = new Canvas(bitmap);

       Paint paint = new Paint();

       BitmapShader shader = new BitmapShader(squaredBitmap,

               BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);

       paint.setShader(shader);

       paint.setAntiAlias(true);

       float r = size / 2f;

       canvas.drawCircle(r, r, r, paint);

       squaredBitmap.recycle();

       return bitmap;

   }

   @Override

   public String key() {

       return “circle”;

   }

}

That’s all is required to have a perfectly circular image!

References

Tags: GSoC18, FOSSASIA, Open Event, Android, CircularTransform