Search code examples
androidkotlinandroid-jetpack-composeandroid-glidecoil

ImageBitmap to canvas using Glide/Coil


I'm using a @Composable where I need to pass via parameter an ImageBitmap, the problem is that I get the images from the server given an url so I need to load these images, convert them into a Bitmap and then to a ImageBitmap but I'm quite stuck because I don't know how to convert this to an ImageBitmap, this is my @Composable

@ExperimentalComposeUiApi
@Composable
fun MyCanvas(
    myImage: ImageBitmap,
    modifier: Modifier = Modifier,
) {
    Canvas(modifier = modifier
        .size(220.dp)
        .clipToBounds()
        .clip(RoundedCornerShape(size = 16.dp)) {

        ...
        val canvasWidth = size.width.toInt()
        val canvasHeight = size.height.toInt()
        val imageSize = IntSize(width = canvasWidth, height = canvasHeight)

        drawImage(
            image = myImage, dstSize = imageSize
        )
        ...
    }
}

So, when I call this @Composable I need to load the image but not sure how to start with and I need to know what's better either using Glide or Coil.


Solution

  • You don't need ImageBitmap to draw it into Canvas. You can draw painter inside DrawScope. You don't even actually need Canvas function either. androidx.compose.foundation.Canvas is nothing other than Spacer with Modifier.drawBehind

    @Composable
    fun Canvas(modifier: Modifier, onDraw: DrawScope.() -> Unit) =
        Spacer(modifier.drawBehind(onDraw))
    

    And answer to your question is

    @Composable
    private fun MyComposable() {
        val sizeModifier = Modifier
            .fillMaxWidth()
    
        val url =
            "https://avatars3.githubusercontent.com/u/35650605?s=400&u=058086fd5c263f50f2fbe98ed24b5fbb7d437a4e&v=4"
    
        Column(
            modifier =Modifier.fillMaxSize()
        ) {
    
          val painter =  rememberAsyncImagePainter(
                model = url
            )
    
            Canvas(modifier = Modifier
                .clip(RoundedCornerShape(size = 16.dp))
                    .size(220.dp)
                ) {
                    with(painter) {
                        draw(size = size)
                    }
                }
    
        }
    }
    

    And when you apply Modifier.clip() you don't have to apply Modifier.clipToBounds()

    Both are the same thing with clip uses shape extra to clipToBounds

    /**
     * Clip the content to the bounds of a layer defined at this modifier.
     */
    @Stable
    fun Modifier.clipToBounds() = graphicsLayer(clip = true)
    
    /**
     * Clip the content to [shape].
     *
     * @param shape the content will be clipped to this [Shape].
     */
    @Stable
    fun Modifier.clip(shape: Shape) = graphicsLayer(shape = shape, clip = true)