Picassoで円形に切り取った画像に枠線を付ける


はじめに

Picassoで画像を円形に切り取るのは Picasso で角丸なImageを描画するなどで紹介されていますが、更に切り取った画像に枠線を付けたいことがあったので調べたメモです。

今回使ったライブラリのバージョンは下記です、適宜読み替えて下さい。

  • com.squareup.picasso:picasso:2.71828

実装

巷に出回っているCircleTransformにもう少し手を加える形で実現できました。

BorderedCircleTransform.kt
import android.graphics.*
import com.squareup.picasso.Transformation

class BorderedCircleTransform(
    private val borderColor: Int,
    private val borderSize: Int
) : Transformation {

    override fun transform(source: Bitmap?): Bitmap? {
        source ?: return null

        val size = Math.min(
            source.width,
            source.height
        )

        val x = (source.width - size) / 2
        val y = (source.height - size) / 2

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

        if (squaredBitmap != source) {
            source.recycle()
        }

        val bitmap = Bitmap.createBitmap(
            size,
            size,
            source.config
        )

        val canvas = Canvas(bitmap)
        val paint = Paint().apply {
            shader = BitmapShader(
                squaredBitmap,
                Shader.TileMode.CLAMP,
                Shader.TileMode.CLAMP
            )
            isAntiAlias = true
        }

        val r = size / 2f
        Canvas(bitmap).drawCircle(
            r,
            r,
            r,
            paint
        )

        val paintBg = Paint().apply {
            color = borderColor
            isAntiAlias = true
        }

        canvas.drawCircle(
            r,
            r,
            r,
            paintBg
        )

        canvas.drawCircle(
            r,
            r,
            r - borderSize,
            paint
        )

        squaredBitmap.recycle()

        return bitmap
    }

    override fun key(): String = "bordered_circle"
}

呼び出し時にborderの色と太さを指定できます。

        Picasso.get()
            .load(URL)
            .transform(
                BorderedCircleTransform(
                    borderColor = Color.RED,
                    borderSize = 4
                )
            )
            .into(image_view_bordered_circle)

文字色を赤、太さを4で指定するとこんな感じ。

おわりに

早くImageViewのプロパティでサクッと円形や枠線をつけることが出来る時代が来て欲しいですね。