Как сделать blur на бекграунде Canvas?

Есть вот такая иконка

введите сюда описание изображения

она рисуется вот так:

    @Composable
    private fun IconWithCircleBackground(
        @DrawableRes res: Int,
        modifier: Modifier = Modifier,
        radius: Dp = 16.dp,
        strokeColor: Color = ColorTokens.grey_10,
        strokeWidth: Dp = 1.dp,
        backgroundColor: Color = Color.Black,
        backgroundAlpha: Float = 0.7f
    ) {
        Box(modifier = modifier.size(radius)) {
            Canvas(modifier = Modifier.size(radius)) {
                drawCircle(
                    color = backgroundColor.copy(alpha = backgroundAlpha),
                    radius = radius.toPx() - strokeWidth.toPx() / 2
                )

                drawCircle(
                    color = strokeColor,
                    radius = radius.toPx(),
                    style = Stroke(width = strokeWidth.toPx())
                )
            }

            Image(
                painter = painterResource(id = res),
                contentDescription = stringResource(id = ...)
            )
        }
    }

То есть есть Canvas на кортором отрисовывается первый слой как бекграунд в форме окружности заполненый черным цветом (+ альфа), и вторым слоем отрисовывается белая линия как граница и в центре располагается иконка.

Нужно сделать первый слой (черный бекграунд), чтоб он был blur. Вопрос - как можно применить blur тут?


Ответы (2 шт):

Автор решения: Style-7

Размытие на основе RenderScript, радиусом задается глубина размытия:

    Bitmap bm_out = Bitmap.createBitmap( bm_in );
    RenderScript rs = RenderScript.create(context);
    ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
    Allocation alloc_in = Allocation.createFromBitmap(rs, bm_in);
    Allocation alloc_out = Allocation.createFromBitmap(rs, bm_out );
    theIntrinsic.setRadius( radius );
    theIntrinsic.setInput(alloc_in);
    theIntrinsic.forEach(alloc_out);
    alloc_out.copyTo( bm_out );

Более примитивный вариант - это просто уменьшить исходный Bitmap раз в 8-16 а потом "растянуть" его на canvas.

→ Ссылка
Автор решения: Sirop4ik

В итоге я сделал это так (спойлер - блюр не помог мне сделать то что я хотел, то что я хотел это все же гласморфик, но может кому то пригодится)

    @Composable
    private fun IconWithCircleBackground(
        @DrawableRes res: Int,
        modifier: Modifier = Modifier,
        radius: Dp = 32.dp,
        strokeColor: Color = ColorTokens.grey_10,
        strokeWidth: Dp = 2.dp,
        backgroundColor: Color = Color.Black,
        backgroundAlpha: Float = 0.8f
    ) {
        Box(
            modifier = modifier
                .size(radius)
                .clip(CircleShape)
        ) {
            // Background
            Image(
                modifier = modifier
                    .fillMaxSize()
                    .blur(radius = 10.dp)
                ,
                bitmap = coloredBitmap(color = backgroundColor, alpha = backgroundAlpha).asImageBitmap(),
                contentDescription = null
            )

            // Stroke
            Canvas(modifier = Modifier.matchParentSize()) {
                drawCircle(
                    color = strokeColor,
                    radius = size.minDimension / 2,
                    style = Stroke(width = strokeWidth.toPx())
                )
            }

            Image(
                modifier = Modifier.align(Alignment.Center),
                painter = painterResource(id = res),
                contentDescription = stringResource(id = ...)
            )
        }
    }

Идея в том, что есть такой модифаер blur(radius = 10.dp), но его нельзя применить для drawCircle, поэтому я создаю битмап, вставляю его в Image и на Image уже применяю blur через модифаер.

→ Ссылка