compose-multiplatform icon indicating copy to clipboard operation
compose-multiplatform copied to clipboard

Impossible to create a custom ImageBitmap and draw it on a canvas

Open kirill-grouchnikov opened this issue 5 years ago • 4 comments

The code in ImageBitmap.asDesktopBitmap is called in DesktopCanvas.drawImage. This path expects the ImageBitmap to be a very specific - and private! - implementation of the interface, namely DesktopImageBitmap. And that implementation can only be used with org.jetbrains.skija.Bitmap class.

How can a desktop Compose app create its own ImageBitmap as a dynamically generated entity? Specifically, I'm looking to port some code that generates noise-based texture at runtime based on certain parameters. That code populates an IntArray where every entry packs ARGB channels of the specific pixel. Then I have a custom implementation of the ImageBitmap interface (much as DesktopImageBitmap is) that returns the relevant subset of the pixels in readPixels. But that implementation of the Compose interface is not accepted at runtime by the DesktopCanvas.drawImage.

kirill-grouchnikov avatar Nov 17 '20 05:11 kirill-grouchnikov

The full stacktrace that starts in DrawScope.drawImage:

Exception in thread "AWT-EventQueue-0 @coroutine#1" java.lang.UnsupportedOperationException: Unable to obtain org.jetbrains.skija.Image
	at androidx.compose.ui.graphics.DesktopImageAssetKt.asDesktopBitmap(DesktopImageAsset.kt:92)
	at androidx.compose.ui.graphics.DesktopCanvas.drawImage-uwcbMjI(DesktopCanvas.kt:167)
	at androidx.compose.ui.graphics.drawscope.CanvasDrawScope.drawImage-JUiai_k(CanvasDrawScope.kt:202)
	at androidx.compose.ui.node.LayoutNodeDrawScope.drawImage-JUiai_k(LayoutNode.kt:1426)
	at androidx.compose.ui.graphics.drawscope.DrawScope$DefaultImpls.drawImage-JUiai_k$default(DrawScope.kt:429)

kirill-grouchnikov avatar Nov 17 '20 05:11 kirill-grouchnikov

Isn't it a dup of https://github.com/JetBrains/compose-jb/issues/111?

olonho avatar Nov 17 '20 20:11 olonho

This one is different. See https://issuetracker.google.com/issues/173490304 which was filed on Compose as well.

Right now I can "reach" into the backing array of ints / bytes like this:

        val result = ImageBitmap(width = width, height = height)
        val skijaBitmap = result.asDesktopBitmap()
        skijaBitmap.installPixels(
            ImageInfo.makeS32(width, height, ColorAlphaType.UNPREMUL),
            byteDstBuffer, 4L * width
        )

But it's not a cross-platform / compose "pure" solution

kirill-grouchnikov avatar Nov 17 '20 20:11 kirill-grouchnikov

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

okushnikov avatar Aug 26 '24 17:08 okushnikov