Open In App

Implement ImageDecoder API in Android

Last Updated : 15 Sep, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

We use a lot of Bitmaps and drawables in Android. Handling bitmap conversions necessitates a significant amount of code, and we frequently encounter the favorite error, the “Out of Memory” exception. The BitmapFactory is used to manipulate Bitmaps, but with Android P, we have ImageDecoder, which allows us to convert images like PNG, JPEG, and so on to Drawables or Bitmaps. We will now go through all the below-mentioned topics in detail: 

  1. Understanding the source and loading Images
  2. Decoding from the Drawable folder
  3. URI Overriding the source’s default settings
  4. Decoding GIFs and WebP Error Handling

Understanding the Source and Image Loading

Before we can decode anything, we must first map the image source. The source is equivalent to the ImageDecoder’s accepted path. We use to create a source

val gfg = ImageDecoder.createSource(file_path_of_your_image)

In this case, generating a source can happen on any thread. However, decoding should be done in the background thread.

imageView.setImageDrawable(your_drawable_file)

We’re using the decodeDrawable method to acquire a drawable, but we’ll use the decodeBitmap function to get a bitmap from the specified source.

val bmp:Bitmap = ImageDecoder.decodeBitmap(your_source_file)

The preceding use-case was to generate a source from a file path and decode it to Drawable or Bitmap. Similarly, we can construct a source from ByteBuffer as follows:

val file = ImageDecoder.createSource(byte_files)

Drawable Folder and URI Decoding

Consider a scenario in which we have PNGs or JPEGs in our project’s drawable folder. Then we can make a source from the resource folder, for example,

val file = ImageDecoder.createSource(resources, R.drawable.gfg_logo)

We’re using ImageDecoder to get the PNG icon ic location from the drawable and create a source for it. Now we may use Drawable or Bitmap to decode the source.

val file: Drawable = ImageDecoder.decodeDrawable(source_file)

SetImageDrawable and setImageBitmap can be used to convert these to ImageView. Similarly, if we have a URI and wish to make a source out of it, we use a content resolver to do so.

val file_source = ImageDecoder.createSource(contentResolver, image_uri)

Finally, if we need to make a source from a file from an asset, we use it.

val file_name = ImageDecoder.createSource(assetManager, some_asset)

Overriding the Source’s Default Settings

We can override the default settings we get from the Image while creating a source. We utilize this to alter the default configuration. We use the onHeaderDecodedListener to add the listener.

Kotlin




val gfgListener: OnHeaderDecodedListener = object : OnHeaderDecodedListener {
    override fun onHeaderDecoded(decoder: ImageDecoder, info: ImageInfo, source: ImageDecoder.Source) {
     // Your logic here.
    }
}
val img_drawable = ImageDecoder.decodeDrawable(your_source, listener)


The listeners can be used for a variety of transformations

The decoder allows us to do transformations, while the information holds all of the original image’s data, such as Mime type, size, and whether or not it is animating, as well as the source. Consider what we would put inside the onHeaderDecoded function if we wanted to resize the image.

decoder.setTargetSize(50,50)

WebP and GIF decoding

If we have GIFs and WebP files, we can load them with all of the frames’ animations and transitions using ImageDecoder alone, without the need for a third-party library. Let’s say we have a Gif file as a source from the assets folder. So, in order to decode it in Drawable and begin the animation

val img_source = ImageDecoder.createSource(assetManager, your_asset_file)

Kotlin




val img_drawable = ImageDecoder.decodeDrawable(img_source)
if (img_source is AnimatedImageDrawable) {
    drawable.start()
}


Error Handling

We may encounter issues while decoding the source. To detect issues, we must set the decoder argument in OnHeaderDecodedListener to setOnPartialImageListener, as seen below.

Kotlin




val gfgListener: OnHeaderDecodedListener = object : OnHeaderDecodedListener {
    override fun onHeaderDecoded(decoder: ImageDecoder, info: ImageInfo, your_source: ImageDecoder.Source) {
        decoder.setOnPartialImageListener {exception->
            Log.d("GfG Decoder",exception.error.toString()))
            true
        }
    }
}


We get the exception here, inside setOnPartialImageListener, and that’s where we can log the error. When we want to log an error, exception.error may return one of the following errors:

We’re returning true in this case, which means the listeners should only see the created image until the exception occurs. If it returns false, however, it will abort the execution and throw an exception.

It’s good to know

We can apply some processing once the image has been loaded, such as adding a custom background, etc.

OnHeaderDecodedListener

We use it for processing in the following ways:

Kotlin




val gfgListener: OnHeaderDecodedListener = object : OnHeaderDecodedListener {
    override fun onHeaderDecoded(decoder: ImageDecoder, info: ImageInfo, source: ImageDecoder.Source) {
        decoder.setPostProcessor { canvas ->
             
        }
    }
}


Here, under setOnProcessor, we obtain the canvas on which we will perform our changes and apply custom effects when the Image has been decoded and loaded. This is how ImageDecoder can be used in your application. To run in your project, you’ll need Android Pie or higher.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads