Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use an alternative implementation of Image.toBitmap for web target #917

Merged
merged 3 commits into from Nov 30, 2023

Conversation

eymar
Copy link
Collaborator

@eymar eymar commented Nov 28, 2023

Bitmap.makeFromImage is faster than canvas.drawImage on web:

With canvas.drawImage:
First call: 44ms; Second call: 14ms; Third call: 16ms; (for 256x256 PNG image)

With Bitmap.makeFromImage:
First call: 9.92ms; Second call: 1.88ms; Third call: 1.63ms; (for 256x256 PNG image)

Please see a comment in the code for more details.

`Bitmap.makeFromImage` is faster on web than `canvas.drawImage`
@eymar
Copy link
Collaborator Author

eymar commented Nov 28, 2023

Here is how this can be tested in skiko:
+ this snippet can be helpful in the future to investigate further.

val imageBase64 = "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"


@OptIn(ExperimentalEncodingApi::class)
val img = Base64.decode(imageBase64).let {
    Image.makeFromEncoded(it)
}

internal fun test() {
    val time = measureTime {
        repeat(1) {
            img.alternativeToBitmap()
        }
    }.inWholeMilliseconds

    println("Time = $time ms")
}

private fun Image.alternativeToBitmap(): Bitmap {
    val bitmap = Bitmap.makeFromImage(this)
    bitmap.setImmutable()
    return bitmap
}

private fun Image.defaultToBitmap(): Bitmap {
    val bitmap = Bitmap()
    bitmap.allocPixels(ImageInfo.makeN32(width, height, ColorAlphaType.PREMUL))
    val canvas = org.jetbrains.skia.Canvas(bitmap)
    canvas.drawImage(this, 0f, 0f)
    bitmap.setImmutable()
    return bitmap
}

Copy link

@dima-avdeev-jb dima-avdeev-jb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

…dx/compose/ui/graphics/Actuals.skikoExcludingWeb.kt
…dx/compose/ui/graphics/Actuals.skikoExcludingWeb.kt

Co-authored-by: Igor Demin <igordmn@users.noreply.github.com>
@eymar eymar merged commit 9f3a4e3 into jb-main Nov 30, 2023
1 check failed
@eymar eymar deleted the ok/improve_image_to_bitmap branch November 30, 2023 10:14
eymar added a commit that referenced this pull request Dec 1, 2023
)

`Bitmap.makeFromImage` is faster than `canvas.drawImage` on web:

With `canvas.drawImage`:
First call: 44ms; Second call: 14ms; Third call: 16ms; (for 256x256 PNG
image)


With `Bitmap.makeFromImage`:
First call: 9.92ms; Second call: 1.88ms; Third call: 1.63ms; (for
256x256 PNG image)

Please see a comment in the code for more details.

---------

Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
Co-authored-by: Igor Demin <igordmn@users.noreply.github.com>
eymar added a commit that referenced this pull request Dec 5, 2023
)

`Bitmap.makeFromImage` is faster than `canvas.drawImage` on web:

With `canvas.drawImage`:
First call: 44ms; Second call: 14ms; Third call: 16ms; (for 256x256 PNG
image)


With `Bitmap.makeFromImage`:
First call: 9.92ms; Second call: 1.88ms; Third call: 1.63ms; (for
256x256 PNG image)

Please see a comment in the code for more details.

---------

Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
Co-authored-by: Igor Demin <igordmn@users.noreply.github.com>
mazunin-v-jb pushed a commit that referenced this pull request Dec 7, 2023
)

`Bitmap.makeFromImage` is faster than `canvas.drawImage` on web:

With `canvas.drawImage`:
First call: 44ms; Second call: 14ms; Third call: 16ms; (for 256x256 PNG
image)


With `Bitmap.makeFromImage`:
First call: 9.92ms; Second call: 1.88ms; Third call: 1.63ms; (for
256x256 PNG image)

Please see a comment in the code for more details.

---------

Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
Co-authored-by: Igor Demin <igordmn@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants