Thursday, 1 November 2018

Is it possible to get the new ImageDecoder class to return Bitmaps, one frame after another, manually?

Background

I'm trying to go over bitmaps of animated GIF&WEBP files manually, so that it would work not just for Views, but on other cases too (such as a live wallpaper).

The problem

Animated GIF/WEBP files are supported only from Android P, using ImageDecoder API (example here) .

For GIF, I wanted to try Glide for the task, but I've failed, so I've tried overcoming this, by using a library that allows to load them (here, solution here). I think it works fine.

For WebP, I thought I've found another library that could work on older Android versions (here, made fork here), but it seems that it can't handle WebP files well in some cases (reported here). I tried to figure out what's the issue and how to solve it, but I didn't succeed.

So, assuming that some day Google will support GIF&WEBP animation for older Android versions via the support library (they wrote it here), I've decided to try to use ImageDecoder for the task.

Thing is, looking in the entire API of ImageDecoder , it's quite restricted in how we should use it. I don't see how I can overcome its limitations.

What I've found

This is how ImageDecoder can be used to show an animated WebP on an ImageView (just a sample, of course, available here) :

class MainActivity : AppCompatActivity() {
    @SuppressLint("StaticFieldLeak")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val source = ImageDecoder.createSource(resources, R.raw.test)
        object : AsyncTask<Void, Void, Drawable?>() {
            override fun doInBackground(vararg params: Void?): Drawable? {
                return try {
                    ImageDecoder.decodeDrawable(source)
                } catch (e: Exception) {
                    null
                }
            }

            override fun onPostExecute(result: Drawable?) {
                super.onPostExecute(result)
                imageView.setImageDrawable(result)
                if (result is AnimatedImageDrawable) {
                    result.start()
                }
            }

        }.execute()

    }
}

I've tried to read all of the documentations of ImageDecoder and AnimatedImageDrawable, and also look at its code, but I don't see how it's possible to manually go over each frame, and have the time that needs to be waited between them.

The questions

  1. Is there a way to use ImageDecoder API to go over each frame manually, getting a Bitmap to draw and knowing how much time it's needed to wait between frames? Any workaround available? Maybe even using AnimatedImageDrawable ?

  2. Is there any way to use ImageDecoder (or a different API/library) to do the same thing on older Android versions? Google wrote it works on a way to use it on older Android versions, but I don't see it being mentioned anywhere (except for the link I've provided). Probably not ready yet... Android P didn't even reach 0.1% of users yet... Maybe Fresco can do it? I've tried to check it there too, but I don't see that it's capable of such a thing either.



from Is it possible to get the new ImageDecoder class to return Bitmaps, one frame after another, manually?

No comments:

Post a Comment