Picking up on <https://github.com/JetBrains/skiko/...
# compose-desktop
s
Picking up on https://github.com/JetBrains/skiko/issues/853 I find this an interesting idea. Reading images at a smaller size using sampling should speed up thumbnail creation. Can someone answer the question if SKIA has or has not sampling support? I don't find a clear answer to that. 🤔
j
https://saket.github.io/telephoto/ Would check out this library, not sure if works on desktop or not 🙂
s
Thanks, Joel. This is actually the lib I got that sub-sampling idea from. 😉 It's interesting for my photo app to replace the current hero photo zooming as soon as it gets full multiplatform support.
🎉 1
k
Based on playing with it a little bit, it looks like Skia doesn’t support arbitrary scaling for arbitrary codecs - https://chromium.googlesource.com/skia/+/83988edfd3256dc822b961362aad7fbc3e0cdabc/src/codec/SkCodec.cpp#369
👍 1
And even for webp, requesting to load a scaled down version doesn’t result in significantly faster performance
s
Ok, that's interesting.
k
Copy code
val filename = Paths.get("/my/big.webp").normalize().toAbsolutePath()
        .toString()
    println("Filename = $filename")
    val time0 = System.nanoTime()
    val codec = Codec.makeFromData(Data.makeFromFileName(filename))
    val time1 = System.nanoTime()
    println("Making codec took " + (time1 - time0) + " ns")

    val time2 = System.nanoTime()
    val pixels = codec.readPixels()
    val time3 = System.nanoTime()
    println("Reading ${pixels.width}x${pixels.height} pixels took " + (time3 - time2) + " ns")

    val imageInfo = ImageInfo(
        width = codec.width / 8, height = codec.height / 8,
        colorType = codec.colorType,
        alphaType = codec.alphaType
    )
    val bitmap = Bitmap()
    bitmap.setImageInfo(imageInfo)
    bitmap.allocPixels()
    val time4 = System.nanoTime()
    val pixelsSmall = codec.readPixels(bitmap)
    val time5 = System.nanoTime()
    println("Reading ${bitmap.width}x${bitmap.height} pixels took " + (time5 - time4) + " ns")
👍 1
Copy code
Making codec took 266628708 ns
Reading 2560x1150 pixels took 115026375 ns
Reading 320x143 pixels took 86284709 ns
s
Sounds like something is off with SKIA here, because inSampleSize on Android does for JPG a nice job. Even Apple recommends their equivalent of that in WWDC videos.
k
How is the performance? Asking for a 10% scaling results in 0.1x loading time?
s
I didn't measure exact numbers. I only remember after switching to that it was way faster.
k
I tried the above with a JPEG, and it only worked for half the scale. Anything under that returned
kInvalidScale
1
s
🤔
k
Maybe there’s another way to load downscaled images in Skia
s
I hope there is.
k
I’d recommend asking on the skia mailing list, and based on the answer(s), look up the matching Skiko bindings
👍 1
s
I assume you refer to https://groups.google.com/g/skia-discuss. Wow, never used Google groups, but usability is horrible. I just wrote my post twice, because the first time it looked like it wasn't saved or something. The second time I saw the toast showing up for only one(!) second saying "posted, but not yet approved". And there is no obvious way to see my not approved post. Horrible UX. 🙄 I will link one of my posts once approved here.
> I tried the above with a JPEG, and it only worked for half the scale. Anything under that returned
kInvalidScale
Some of my test images even don't work with that. There seem to be some (undocumented?) restrictions to this. It's a bit of magic. Hopefully someone on the mailing list can explain the rules. Thanks for your code snippet. I learned something new about SKIA today. 🙂
k
Next time I wouldn’t mention Skiko at all, since if there are Skia APIs that have not been exposed through Skiko, adding those bindings would be pretty straightforward.
👍 1
s
To be honest I’m not really expecting an answer there. I see many unanswered questions and rather low activity in that mailing list. Maybe with the inception of Impeller some people might have lost interest in SKIA. 🤔
s
fwiw I was exploring ImageIO for sampling images on the JVM: https://stackoverflow.com/a/15149382/2511884
https://kotlinlang.slack.com/archives/C01D6HTPATV/p1706537324615659?thread_ts=1706520992.241859&amp;cid=C01D6HTPATV I wonder if it's because the sampling factor can only be multiples of 2, just like android?
k
It didn’t work for 4 or 8
s
ah okay
s
Apparently there is a dedicated method to calculate the valid sizes for the desired scale factor. I created an issue to add this to the binding. https://github.com/JetBrains/skiko/issues/861
googlesource.com is a mess compared to GitHub. It's very hard to navigate and fine something there. 🙄 I just look if I can find the actual implementation of that method-
By googling it I find that a lot of other image libraries also use libjpeg
jpeg_calc_output_dimensions()
to calculate the correct dimensions. Seems to involve quite some magic to determine that.
k
I’d suggest making a PR if you want to see it in Skiko sooner rather than later.
They’re pretty receptive to PRs
s
That will be a challenge ^^ Never did anything with JNI so far.
k
It’s pretty much copy paste of what other bindings are doing, one for common and one for JS or something along those lines. And then add test coverage. That’s what I did to add shaders a year or so ago.
When you build a local copy of Skiko, you can deploy it to local Maven, and then test in your app that the bindings work.
These four files is where you’d make your changes
s
Ok, thanks for your guidance.