Android Bitmap Circle And Draw Border [duplicate] - android
What i have:: I have a Imageview for which i am making image as a circle using picassso
What i what to do:: I want to add a black border for rounded image using my current implementation, how to achieve this without using third party library
Picasso.with(this)
.load("http://i.imgur.com/DvpvklR.png")
.transform(new RoundedTransformation(50, 4))
.resize(100, 100)
.centerCrop().into(imageView1);
RoundedTransformation.java
// 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";
}
}
EDIT
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();
}
Paint paint1 = new Paint();
paint1.setColor(Color.RED);
paint1.setStyle(Style.STROKE);
paint1.setAntiAlias(true);
paint1.setStrokeWidth(2);
canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint1);
return output;
}
#Override
public String key() {
return "rounded";
}
}
Final transformation class, thanks to blackbelt
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.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint);
if (source != output) {
source.recycle();
}
Paint paint1 = new Paint();
paint1.setColor(Color.RED);
paint1.setStyle(Style.STROKE);
paint1.setAntiAlias(true);
paint1.setStrokeWidth(2);
canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint1);
return output;
}
#Override
public String key() {
return "rounded";
}
}
you can use drawCircle with another Paint object. For instance:
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint);
Also, instead of using a drawRoundRect to draw a circle, you can use drawCircle
Answers of BlackBelt and Devrath are great. And if you are looking for a Kotlin version of this class, here it is:
class RoundedBorderTransform(private val radius: Int, private val margin: Int) : com.squareup.picasso.Transformation {
override fun transform(source: Bitmap?): Bitmap {
val paint = Paint()
paint.isAntiAlias = true
paint.shader = BitmapShader(source!!, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
val output = Bitmap.createBitmap(source.width, source.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
canvas.drawCircle((source.width - margin) / 2f, (source.height - margin) / 2f, radius - 2f, paint)
if (source != output) {
source.recycle()
}
val borderPaint = Paint()
borderPaint.color = Color.RED
borderPaint.style = Paint.Style.STROKE
borderPaint.isAntiAlias = true
borderPaint.strokeWidth = 2f
canvas.drawCircle((source.width - margin) / 2f, (source.height - margin) / 2f, radius - 2f, borderPaint)
return output
}
override fun key(): String {
return "roundedBorder"
}
}
This is solution for circle and rectangle shapes. Also it's useful not only for Picasso usage, but for general android Canvas-tasks.
I've created them very voluminous and detailed only for yours understanding of processes, shorten as you want.
But I want to clarify a main problem that many people faced with.
In android there no possibilities to create inner or outer border - only centered:
And this is the reason why you receive border elements cut off like these:
So there only a single way to recalculate position of border: in case of
circle you have to decrease circle radius by HALF OF BORDER WIDTH
rectangle you have to 1) shift border lines "inside" by HALF OF BORDER WIDTH; 2) decrease corner radius by HALF OF BORDER WIDTH
These actions will provide you an expected results:
If you're need only code for you border - pick only correspondent drawBorder() method.
Here is an example for empty Fragment with two images:
ViewsCroppingAndBorderingTestFragment.kt
class ViewsCroppingAndBorderingTestFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_test_views_cropping_and_bordering, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val urlCircle = "https://images-na.ssl-images-amazon.com/images/I/71zLQIfmTlL._AC_SX466_.jpg"
val urlRectRounded = "https://www.gardendesign.com/pictures/images/675x529Max/site_3/helianthus-yellow-flower-pixabay_11863.jpg"
val ivCircle = view.findViewById<ImageView>(R.id.ivCircle)
val ivRectRounded = view.findViewById<ImageView>(R.id.ivRectRounded)
val trCircle = CircleTransformation()
val trRectRounded = RectRoundedTransformation()
Picasso.get().load(urlCircle).transform(trCircle).into(ivCircle)
Picasso.get().load(urlRectRounded).transform(trRectRounded).into(ivRectRounded)
}
class CircleTransformation() : Transformation {
override fun transform(source: Bitmap): Bitmap {
val size = Math.min(source.width, source.height)
val x = (source.width - size) / 2
val y = (source.height - size) / 2
val w = size
val h = size
val squaredBitmap = Bitmap.createBitmap(source, x, y, w, h)
if (squaredBitmap != source) {
source.recycle()
}
val bitmap = Bitmap.createBitmap(w, h, source.config)
val canvas = Canvas(bitmap)
// >> Draw original rectangle image
// val paint = Paint(Paint.ANTI_ALIAS_FLAG)
// canvas.drawBitmap(squaredBitmap, 0F, 0F, paint)
val rImage = w / 2f
cropWithCircle(squaredBitmap, canvas, rImage)
squaredBitmap.recycle()
drawBorder(canvas, rImage)
return bitmap
}
private fun cropWithCircle(bitmapSource: Bitmap, canvas: Canvas, rImage: Float) {
val shader = BitmapShader(bitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.shader = shader
paint.isAntiAlias = true
val xCenter = rImage
val yCenter = rImage
canvas.drawCircle(xCenter, yCenter, rImage, paint)
}
private fun drawBorder(canvas: Canvas, rImage: Float) {
val borderWidth = 30F
val paintBorder = Paint()
paintBorder.strokeWidth = borderWidth
paintBorder.style = Paint.Style.STROKE
paintBorder.color = Color.GREEN
paintBorder.isAntiAlias = true
val cCenter = rImage
val yCenter = rImage
// ANDROID'S BORDER IS ALWAYS CENTERED.
// So have to reduce radius by half of border's width
val rBorder = rImage - borderWidth / 2
canvas.drawCircle(cCenter, yCenter, rBorder, paintBorder)
}
override fun key(): String {
return "circle"
}
}
class RectRoundedTransformation() : Transformation {
override fun transform(source: Bitmap): Bitmap {
val x = 0
val y = 0
val w = source.width
val h = source.height
val squaredBitmap = Bitmap.createBitmap(source, x, y, w, h)
if (squaredBitmap != source) {
source.recycle()
}
val bitmap = Bitmap.createBitmap(w, h, source.config)
val canvas = Canvas(bitmap)
// >> Draw original rectangle image
// val paint = Paint(Paint.ANTI_ALIAS_FLAG)
// canvas.drawBitmap(squaredBitmap, 0F, 0F, paint)
val rCorner = 80F
cropCorners(squaredBitmap, canvas, rCorner)
squaredBitmap.recycle()
drawBorder(canvas, rCorner)
return bitmap
}
private fun cropCorners(bitmapSource: Bitmap, canvas: Canvas, rCorner: Float) {
val width = canvas.width
val height = canvas.height
val maskBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
val maskCanvas = Canvas(maskBitmap)
val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG)
val maskRect = RectF(0F, 0F, width.toFloat(), height.toFloat())
// 1. draw base rect
maskCanvas.drawRect(maskRect, maskPaint)
// 2. cut off inner rounded rect, leave corners
maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
maskCanvas.drawRoundRect(maskRect, rCorner, rCorner, maskPaint)
// 3. draw original rectangle image
val paintSource = Paint(Paint.ANTI_ALIAS_FLAG)
canvas.drawBitmap(bitmapSource, 0f, 0f, paintSource)
// 4.cut off corners
val paintCropped = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
paintCropped!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
canvas.drawBitmap(maskBitmap!!, 0f, 0f, paintCropped)
}
private fun drawBorder(canvas: Canvas, rCorner: Float) {
val borderWidth = 30F
val paintBorder = Paint()
paintBorder.strokeWidth = borderWidth
paintBorder.style = Paint.Style.STROKE
paintBorder.color = Color.RED
paintBorder.isAntiAlias = true
// // ANDROID'S BORDER IS ALWAYS CENTERED.
// // So have to shift every side by half of border's width
val rectLeft = 0 + borderWidth / 2
val rectTop = 0 + borderWidth / 2
val rectRight = canvas.width.toFloat() - borderWidth / 2
val rectBottom = canvas.height.toFloat() - borderWidth / 2
val rectF = RectF(rectLeft, rectTop, rectRight, rectBottom)
// // So have to corner reduce radius by half of border's width
val rectRCorner = rCorner - borderWidth / 2
canvas.drawRoundRect(rectF, rectRCorner, rectRCorner, paintBorder)
}
override fun key(): String {
return "rectRounded"
}
}
}
fragment_test_views_cropping_and_bordering.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/temp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="200dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:background="#android:color/darker_gray">
<ImageView
android:id="#+id/ivCircle"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_margin="10dp"/>
<ImageView
android:id="#+id/ivRectRounded"
android:layout_width="200dp"
android:layout_height="160dp"
android:layout_margin="10dp"/>
</LinearLayout>
Related
Draw rounded button instead of rectangular in Android
I'm developing a function to draw a rounded button in my android application. The problem is that the final results is rectangular instead of something rounded on the corners. What am I missing? fun draw(canvas: Canvas?) { canvas?.let { if (strokeColor != -1) { shaderBorderPaint.color = strokeColor shaderBorderPaint.shader = null } else { shaderBorderPaint.shader = shaderFactory.resize(it.width, it.height) } val cornerRadius = 8f val halfStrokeSize: Float = shaderBorderPaint.strokeWidth / 2 val rect = RectF(halfStrokeSize, it.height - halfStrokeSize, it.width - halfStrokeSize, halfStrokeSize) it.drawRoundRect(rect, cornerRadius, cornerRadius, shaderBorderPaint) } }
Try this instead. val corners = floatArrayOf( 80f, 80f, // Top left radius in px 80f, 80f, // Top right radius in px 0f, 0f, // Bottom right radius in px 0f, 0f // Bottom left radius in px ) val path = Path() path.addRoundRect(rect, corners, Path.Direction.CW) canvas.drawPath(path, mPaint) or this, public static void makeRoundCorner(int bgcolor,int radius,View v,int strokeWidth,int strokeColor) { GradientDrawable gdDefault = new GradientDrawable(); gdDefault.setColor(bgcolor); gdDefault.setCornerRadius(radius); gdDefault.setStroke(strokeWidth, strokeColor); v.setBackgroundDrawable(gdDefault); }
because val cornerRadius = 8f. try to set cornerRadius = heightRect / 2
How to set bitmap in center in kotlin
How i can set bitmap image in center it is not in center .Here is my code and screen.I tried so much but I failed to solves this fun onDraw(c: Canvas, rectF: RectF, pos: Int) { val p = Paint() p.color = color c.drawRect(rectF, p) p.color = Color.WHITE p.textSize - textSize.toFloat() var r = Rect() val cHeight = rectF.height() val cWidth = rectF.width() p.textAlign = Paint.Align.RIGHT p.getTextBounds(text, 0, text.length, r) var x = 0f var y = 0f if (imageResId == 0) { x = cWidth / 2f - r.width() / 2f - r.left.toFloat() y = cHeight / 2f + r.height() / 2f - r.bottom.toFloat() c.drawText(text, rectF.left + x, rectF.top + y, p) } else { val d = ContextCompat.getDrawable(context, imageResId) val bitmap = drawableToBitmap(d!!) c.drawBitmap( bitmap, (rectF.left + rectF.right) / 2, (rectF.top + rectF.bottom) / 2, p ) } clickRegion = rectF this.pos = pos } Here is image link that is produce error enter link description here private fun drawableToBitmap(d: Drawable?): Bitmap { if (d is BitmapDrawable) return d.bitmap val bitmap = Bitmap.createBitmap(d!!.intrinsicWidth, d.intrinsicHeight, Bitmap.Config.ARGB_8888) var canvas = Canvas(bitmap) d.setBounds(0, 0, canvas.width, canvas.height) d.draw(canvas) return bitmap }
You can see that your drawables are all in center and draw from there, all you do are right, you just only need a simply offset with: Subtract the half of the drawable's width & height from the start position Red to Green Code Snippet c.drawBitmap( bitmap, (rectF.left + rectF.right) / 2, (rectF.top + rectF.bottom) / 2, p ) To c.drawBitmap( bitmap, (rectF.left + rectF.right - bitmap.width) / 2, (rectF.top + rectF.bottom - bitmap.height) / 2, p )
Draw line with shadow
Right now i draw line without shadow: override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { val dividerStart = parent.paddingStart val dividerEnd = parent.width - parent.paddingEnd val endIndex = parent.adapter?.itemCount ?: 0 for (index in 0 until endIndex) { val currentChild = parent.getChildAt(index) if (needDrawBottomDelimiter(parent, currentChild)) { val topOfCurrentView = currentChild.top val startX = dividerStart.toFloat() val topY = topOfCurrentView.toFloat() - rectHeight val endX = dividerEnd.toFloat() val bottomY = topOfCurrentView.toFloat() canvas.drawRect(startX, topY, endX, bottomY, spacePaint) canvas.drawLine(startX, bottomY, endX, bottomY, dividerPaint) } } } I know what can help me shader, but doesn't know how i can use it here. Let me know how to use shader here.
In your layout you can do: <View android:layout_width="match_parent" android:layout_height="0.5dp" android:elevation="5dp" android:background="#color/colorBlack" />
You just try the below method: Paint paint; paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setShadowLayer(12, 0, 0, Color.YELLOW); // Important for certain APIs setLayerType(LAYER_TYPE_SOFTWARE, paint); #Override protected void onDraw(Canvas canvas) { canvas.drawRect(20, 20, 100, 100, paint); }
I solved problem with comment deepak kumar dividerPaint.setShadowLayer(12F, 0F, 0F, Color.YELLOW) setLayerType(parent, LAYER_TYPE_SOFTWARE, dividerPaint)
Draw with canvas
How to use canvas to draw a selected field of transparent color with blue background? In official documentation i find smth like this . But there is still a question of how to implement it. Also for example, i tried to draw line: private fun someFun(canvas: Canvas, parent: RecyclerView) { val radius: Float = parent.context.resources.getDimension(R.dimen.dimen_12) val paint = Paint() paint.color = ContextCompat.getColor(parent.context, R.color.primary) paint.style = Paint.Style.FILL val path = Path() path.moveTo(0f, 0f) path.lineTo(0f, radius) path.arcTo(RectF(0f, 0f, radius * 2, radius * 2), 270f, -90f) path.close() canvas.drawPath(path, paint) } And get smth like this:
Decided to the next way: private fun drawRoundedCorners(canvas: Canvas, parent: RecyclerView) { val radius: Float = parent.context.resources.getDimension(R.dimen.dimen_12) val paint = Paint() paint.color = ContextCompat.getColor(parent.context, R.color.primary) paint.style = Paint.Style.FILL val path = Path() path.moveTo(0f, 0f) path.lineTo(150f, 0f) path.arcTo(RectF(0f, 0f, radius * 2, radius * 2), 270f, -90f) path.moveTo(parent.width.toFloat(), 0f) path.lineTo(parent.width.toFloat(), 0f) path.arcTo(RectF(parent.width.toFloat() - radius * 2, 0f, parent.width.toFloat(), radius * 2), 270f, 90f) path.close() canvas.drawPath(path, paint) }
Adding borders for image rounded image android
What i have:: I have a Imageview for which i am making image as a circle using picassso What i what to do:: I want to add a black border for rounded image using my current implementation, how to achieve this without using third party library Picasso.with(this) .load("http://i.imgur.com/DvpvklR.png") .transform(new RoundedTransformation(50, 4)) .resize(100, 100) .centerCrop().into(imageView1); RoundedTransformation.java // 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"; } } EDIT 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(); } Paint paint1 = new Paint(); paint1.setColor(Color.RED); paint1.setStyle(Style.STROKE); paint1.setAntiAlias(true); paint1.setStrokeWidth(2); canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint1); return output; } #Override public String key() { return "rounded"; } }
Final transformation class, thanks to blackbelt 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.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint); if (source != output) { source.recycle(); } Paint paint1 = new Paint(); paint1.setColor(Color.RED); paint1.setStyle(Style.STROKE); paint1.setAntiAlias(true); paint1.setStrokeWidth(2); canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint1); return output; } #Override public String key() { return "rounded"; } }
you can use drawCircle with another Paint object. For instance: Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStyle(Style.STROKE); paint.setAntiAlias(true); paint.setStrokeWidth(2); canvas.drawCircle((source.getWidth() - margin)/2, (source.getHeight() - margin)/2, radius-2, paint); Also, instead of using a drawRoundRect to draw a circle, you can use drawCircle
Answers of BlackBelt and Devrath are great. And if you are looking for a Kotlin version of this class, here it is: class RoundedBorderTransform(private val radius: Int, private val margin: Int) : com.squareup.picasso.Transformation { override fun transform(source: Bitmap?): Bitmap { val paint = Paint() paint.isAntiAlias = true paint.shader = BitmapShader(source!!, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) val output = Bitmap.createBitmap(source.width, source.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(output) canvas.drawCircle((source.width - margin) / 2f, (source.height - margin) / 2f, radius - 2f, paint) if (source != output) { source.recycle() } val borderPaint = Paint() borderPaint.color = Color.RED borderPaint.style = Paint.Style.STROKE borderPaint.isAntiAlias = true borderPaint.strokeWidth = 2f canvas.drawCircle((source.width - margin) / 2f, (source.height - margin) / 2f, radius - 2f, borderPaint) return output } override fun key(): String { return "roundedBorder" } }
This is solution for circle and rectangle shapes. Also it's useful not only for Picasso usage, but for general android Canvas-tasks. I've created them very voluminous and detailed only for yours understanding of processes, shorten as you want. But I want to clarify a main problem that many people faced with. In android there no possibilities to create inner or outer border - only centered: And this is the reason why you receive border elements cut off like these: So there only a single way to recalculate position of border: in case of circle you have to decrease circle radius by HALF OF BORDER WIDTH rectangle you have to 1) shift border lines "inside" by HALF OF BORDER WIDTH; 2) decrease corner radius by HALF OF BORDER WIDTH These actions will provide you an expected results: If you're need only code for you border - pick only correspondent drawBorder() method. Here is an example for empty Fragment with two images: ViewsCroppingAndBorderingTestFragment.kt class ViewsCroppingAndBorderingTestFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_test_views_cropping_and_bordering, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val urlCircle = "https://images-na.ssl-images-amazon.com/images/I/71zLQIfmTlL._AC_SX466_.jpg" val urlRectRounded = "https://www.gardendesign.com/pictures/images/675x529Max/site_3/helianthus-yellow-flower-pixabay_11863.jpg" val ivCircle = view.findViewById<ImageView>(R.id.ivCircle) val ivRectRounded = view.findViewById<ImageView>(R.id.ivRectRounded) val trCircle = CircleTransformation() val trRectRounded = RectRoundedTransformation() Picasso.get().load(urlCircle).transform(trCircle).into(ivCircle) Picasso.get().load(urlRectRounded).transform(trRectRounded).into(ivRectRounded) } class CircleTransformation() : Transformation { override fun transform(source: Bitmap): Bitmap { val size = Math.min(source.width, source.height) val x = (source.width - size) / 2 val y = (source.height - size) / 2 val w = size val h = size val squaredBitmap = Bitmap.createBitmap(source, x, y, w, h) if (squaredBitmap != source) { source.recycle() } val bitmap = Bitmap.createBitmap(w, h, source.config) val canvas = Canvas(bitmap) // >> Draw original rectangle image // val paint = Paint(Paint.ANTI_ALIAS_FLAG) // canvas.drawBitmap(squaredBitmap, 0F, 0F, paint) val rImage = w / 2f cropWithCircle(squaredBitmap, canvas, rImage) squaredBitmap.recycle() drawBorder(canvas, rImage) return bitmap } private fun cropWithCircle(bitmapSource: Bitmap, canvas: Canvas, rImage: Float) { val shader = BitmapShader(bitmapSource, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) val paint = Paint(Paint.ANTI_ALIAS_FLAG) paint.shader = shader paint.isAntiAlias = true val xCenter = rImage val yCenter = rImage canvas.drawCircle(xCenter, yCenter, rImage, paint) } private fun drawBorder(canvas: Canvas, rImage: Float) { val borderWidth = 30F val paintBorder = Paint() paintBorder.strokeWidth = borderWidth paintBorder.style = Paint.Style.STROKE paintBorder.color = Color.GREEN paintBorder.isAntiAlias = true val cCenter = rImage val yCenter = rImage // ANDROID'S BORDER IS ALWAYS CENTERED. // So have to reduce radius by half of border's width val rBorder = rImage - borderWidth / 2 canvas.drawCircle(cCenter, yCenter, rBorder, paintBorder) } override fun key(): String { return "circle" } } class RectRoundedTransformation() : Transformation { override fun transform(source: Bitmap): Bitmap { val x = 0 val y = 0 val w = source.width val h = source.height val squaredBitmap = Bitmap.createBitmap(source, x, y, w, h) if (squaredBitmap != source) { source.recycle() } val bitmap = Bitmap.createBitmap(w, h, source.config) val canvas = Canvas(bitmap) // >> Draw original rectangle image // val paint = Paint(Paint.ANTI_ALIAS_FLAG) // canvas.drawBitmap(squaredBitmap, 0F, 0F, paint) val rCorner = 80F cropCorners(squaredBitmap, canvas, rCorner) squaredBitmap.recycle() drawBorder(canvas, rCorner) return bitmap } private fun cropCorners(bitmapSource: Bitmap, canvas: Canvas, rCorner: Float) { val width = canvas.width val height = canvas.height val maskBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8) val maskCanvas = Canvas(maskBitmap) val maskPaint = Paint(Paint.ANTI_ALIAS_FLAG) val maskRect = RectF(0F, 0F, width.toFloat(), height.toFloat()) // 1. draw base rect maskCanvas.drawRect(maskRect, maskPaint) // 2. cut off inner rounded rect, leave corners maskPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) maskCanvas.drawRoundRect(maskRect, rCorner, rCorner, maskPaint) // 3. draw original rectangle image val paintSource = Paint(Paint.ANTI_ALIAS_FLAG) canvas.drawBitmap(bitmapSource, 0f, 0f, paintSource) // 4.cut off corners val paintCropped = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG) paintCropped!!.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) canvas.drawBitmap(maskBitmap!!, 0f, 0f, paintCropped) } private fun drawBorder(canvas: Canvas, rCorner: Float) { val borderWidth = 30F val paintBorder = Paint() paintBorder.strokeWidth = borderWidth paintBorder.style = Paint.Style.STROKE paintBorder.color = Color.RED paintBorder.isAntiAlias = true // // ANDROID'S BORDER IS ALWAYS CENTERED. // // So have to shift every side by half of border's width val rectLeft = 0 + borderWidth / 2 val rectTop = 0 + borderWidth / 2 val rectRight = canvas.width.toFloat() - borderWidth / 2 val rectBottom = canvas.height.toFloat() - borderWidth / 2 val rectF = RectF(rectLeft, rectTop, rectRight, rectBottom) // // So have to corner reduce radius by half of border's width val rectRCorner = rCorner - borderWidth / 2 canvas.drawRoundRect(rectF, rectRCorner, rectRCorner, paintBorder) } override fun key(): String { return "rectRounded" } } } fragment_test_views_cropping_and_bordering.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/temp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="200dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:background="#android:color/darker_gray"> <ImageView android:id="#+id/ivCircle" android:layout_width="150dp" android:layout_height="150dp" android:layout_margin="10dp"/> <ImageView android:id="#+id/ivRectRounded" android:layout_width="200dp" android:layout_height="160dp" android:layout_margin="10dp"/> </LinearLayout>