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

Question: Not worth to use QOI decoding over PNG decoding on Android? #3

Open
AndroidDeveloperLB opened this issue Apr 2, 2022 · 8 comments

Comments

@AndroidDeveloperLB
Copy link

AndroidDeveloperLB commented Apr 2, 2022

Whether I use QOIUtil.readFile vs BitmapFactory.decodeFile of Android, or I use QOIUtil.readImage vs BitmapFactory.decodeStream , it seems that Android's implementation is faster to parse PNG files over QOI:

From inputStream of the resource (files are within the app) :
QOI took 84 ms
PNG took 25 ms

From a file outside the app:
QOI took 36 ms
PNG took 30 ms

And that's before getting Bitmap instance out of the QOIImage instance, which I don't understand how to do.

Tested on Pixel 4 with Android API 32 on the "wikipedia_008" image files, from here (got from here) :
https://qoiformat.org/qoi_test_images.zip

See attached project:

My Application.zip

How could it be?
Is there anything that can be improved in the implementation?
And how do you convert the output of the function to a working Bitmap instance?

@saharNooby
Copy link
Owner

it seems that Android's implementation is faster to parse PNG files over QOI

I don't know exactly, but most probably Android's PNG decoder is a native library, whereas qoi-java decoder is a Java library. To get expected performance boost from using QOI, it would make more sense to use original C library or one of its optimized implementations like in Rust.

Note that I've compared qoi-java with Java AWT PNG parser, and it mostly does make sense, because AWT's PNG parser is mostly written in Java.

Is there anything that can be improved in the implementation?

Java implementation of QOI is already optimized well (although I have some ideas, but implementing them will not give much performance boost). To decode even faster, as I've said above, you need to use native libraries.

Most performant version of QOI decoder should be written in a native language (C/Rust/etc.) and output an int array, suitable to be passed into Bitmap#createBitmap.

And how do you convert the output of the function to a working Bitmap instance?

You need to get RGB(A) values from a QOIImage and set pixels on a Bitmap: https://stackoverflow.com/a/59788350

@AndroidDeveloperLB
Copy link
Author

AndroidDeveloperLB commented Apr 3, 2022

Have you tested it using C library instead of Java (on Android) that you say it's faster?
If so, can you please share the code you've used? Maybe it's better to have a library for Android based on this, instead.
How did you measure?

As I remember, on new Android versions, the ART makes Java/Kotlin as good as C/C++ in terms of performance, usually.
Here:
https://source.android.com/devices/tech/dalvik/jit-compiler
They also keep improving Java/Kotlin performance on every version of Android.
So I don't think it's a valid argument anymore (on new Android versions).

Have you tested the conversion to Android's Bitmap object?

@saharNooby
Copy link
Owner

saharNooby commented Apr 3, 2022

Have you tested it using C library instead of Java (on Android) that you say it's faster?

No, I just guess -- I assume that C is faster than Java, but of course I can't argue for or against it because no becnhmarks were done.

Have you tested the conversion to Android's Bitmap object?

No -- I'm not an Android developer and do not have Android development environment set up, so I can't do benchmarks/tests. But the conversion is so simple that I do not think anything needs to be tested here -- you can just try.

@AndroidDeveloperLB
Copy link
Author

AndroidDeveloperLB commented Apr 3, 2022

I see.

Can you please try to have a sample that runs on Java, but uses the C/C++ library you talked about?
You can compare what you did here to this one of using C/C++ on a PC instead of Android.
I'm sure that Java on PC got improved in speed too, and not just what Google did on Android.

As for the conversion from QOIImage to Bitmap, this worked for me:

fun convertQoiImageToBitmap(qoiImage: QOIImage): Bitmap {
    val width = qoiImage.width
    val height = qoiImage.height
    val bytes = qoiImage.pixelData
    val hasAlpha = qoiImage.channels == 4
    val pixels = IntArray(if (hasAlpha) bytes.size / 4 else bytes.size / 3)
    var j = 0
    for (i in pixels.indices) {
        val red: Int = bytes[j++].toInt() and 0xff
        val green: Int = bytes[j++].toInt() and 0xff
        val blue: Int = bytes[j++].toInt() and 0xff
        val alpha: Int = if (hasAlpha) bytes[j++].toInt() and 0xff else 0xff
        val pixel = alpha shl 24 or (red shl 16) or (green shl 8) or blue
        pixels[i] = pixel
    }
    val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height)
    return bitmap
}

Now I calculated including the conversion to Bitmap.
Somehow for the same input files the time taken has changed (probably some app was/is running in the background, or something) :

From inputStream of the resource (files are within the app) :
QOI took 61 ms
PNG took 31 ms

From a file outside the app:
QOI took 38 ms
PNG took 27 ms

Still slower than PNG, of course.

Attached here:

My Application.zip

@saharNooby
Copy link
Owner

Can you please try to have a sample that runs on Java, but uses the C/C++ library you talked about?

Probably I can, using JNI/JNR (although there will be overhead, it would be interesting to see). But I can not say for now when I will have time to do it.

@AndroidDeveloperLB
Copy link
Author

Can you please create a Java JNI wrapper and see if it performs better than what you did here?

@saharNooby
Copy link
Owner

Can you please create a Java JNI wrapper and see if it performs better than what you did here?

Yea, I can, it's just that I'm busy with my job and don't know when I will have time to work on QOI.

@AndroidDeveloperLB
Copy link
Author

OK thanks. I'm just curious. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants