2

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.

StuartDTO
  • 783
  • 7
  • 26
  • 72

2 Answers2

6

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)
Thracian
  • 43,021
  • 16
  • 133
  • 222
  • 1
    Heya doc Thrace long time no see – Richard Onslow Roper Nov 18 '22 at 15:39
  • Is there any way to get the size of the views inside canvas? I mean, let's say I have an image and I'm erasing it using `pointerInteropFilter` and I'm trying to find if there's any possibility to check if there's a way to know if the `draw` I did is visible let's say >70% – StuartDTO Nov 18 '22 at 21:46
  • Well I know this is a separated question so I've created a new one let me know if you can help me out https://stackoverflow.com/questions/74496059/get-visibility-canvas-draw-in-compose – StuartDTO Nov 18 '22 at 22:49
  • @StuartDTO this question looks complicated and it's an algorithm question more than it's a Compose question. You might get approximate result if you have a way to differentiate between image pixels from non image pixels by scanning each from before and after erase in a background thread. You should research for an algorithm that is not platform dependent with a search how to detect erased pixels, etc. – Thracian Nov 20 '22 at 12:17
  • @Thracian but it's a Compose question too because what I want is to remove one `draw` that I've done in the `canvas` I mean in the end I want to remove an image from Canvas, could you help me on that? – StuartDTO Nov 22 '22 at 17:05
  • I've updated the question with some ideas @Thracian may you take a look again please? – StuartDTO Nov 25 '22 at 19:11
  • I think i might have found a solution but i need to test it out. I will try it out and post the answer if it works out – Thracian Nov 25 '22 at 19:29
  • Hi @Thracian first of all thank you a lot for your Compose tutorial, I've posted this question here in SO https://stackoverflow.com/questions/76326733/collapsingtoolbar-in-compose-with-button-sticky I was checking you have something with CollapsingToolbar and would be great you have an example like that take a look please – StuartDTO May 25 '23 at 10:21
2

So, obviously, Dr. Thrace has provided you with an optimum solution which he extracted out of his centuries of experience treating the diseased code. You could go with that. However, from the description you provided in the question, it seemed as if majorly all you wanted was just a way to convert a Bitmap to an ImageBitmap object. There's a handy dandy asImageBitmap() extension function available to use with bitmaps now. So, you could just leverage that easy.

Far as Glide vs Coil is concerned, both have popular API methods that I think achieve similar goals/performance. Now, as far as I can remember, Coil was the first to migrate to Compose. I've only used Coil since I required fetching an image from a url and wanted to simply display it, so Coil provided a pretty damn straight forward API for that, rememberCoilPainter() which worked like gravity. Haven't really used the other one but just Google both looking for a comparison. It'll be available absolutely, or just dig through the documentation of both to see which methods are available and design your code structure in your mind while doing so; choose the one that implements easier. The site isn't generally used for taking opinions so I'll leave it there. Nice trick might be - the better the documentation the better the API.

Richard Onslow Roper
  • 5,477
  • 2
  • 11
  • 42