Handling Images (Bitmap Processing, Glide/Picasso Libraries) in Android Development


Handling images efficiently is crucial for Android applications, as they can consume a lot of memory and processing power. In this article, we will explore different ways of handling images in Android using Bitmap processing and popular image loading libraries such as Glide and Picasso.

Bitmap Processing in Android

Android provides the Bitmap class to represent images. You can create and manipulate bitmaps in your Android app. However, since large images can be memory-intensive, it’s important to process and scale them appropriately.

Loading an Image into a Bitmap

To load an image into a bitmap, you can use the BitmapFactory class. Here's how you can load a bitmap from a file:

    import android.graphics.Bitmap
    import android.graphics.BitmapFactory
    import android.os.Bundle
    import android.widget.ImageView
    import androidx.appcompat.app.AppCompatActivity
    import java.io.File

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val imageView: ImageView = findViewById(R.id.imageView)

            val file = File("/path/to/your/image.jpg")
            val bitmap: Bitmap = BitmapFactory.decodeFile(file.absolutePath)

            imageView.setImageBitmap(bitmap)
        }
    }
        

In this example, we load an image from a file into a Bitmap object and then display it in an ImageView.

Scaling a Bitmap

When working with large images, it’s important to scale them to avoid consuming too much memory. You can scale a bitmap before loading it into an ImageView.

    fun getScaledBitmap(path: String, reqWidth: Int, reqHeight: Int): Bitmap {
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        BitmapFactory.decodeFile(path, options)

        var inSampleSize = 1
        if (options.outHeight > reqHeight || options.outWidth > reqWidth) {
            val halfHeight = options.outHeight / 2
            val halfWidth = options.outWidth / 2
            while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
                inSampleSize *= 2
            }
        }

        options.inSampleSize = inSampleSize
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeFile(path, options)
    }
        

This function loads a bitmap and scales it to the required width and height using the inSampleSize option.

Using Glide for Efficient Image Loading

Glide is a powerful image loading and caching library for Android. It provides an efficient way to load images from the web or local storage and also handles caching automatically.

Adding Glide to Your Project

To use Glide in your Android project, first add the Glide dependency in your build.gradle file:

    dependencies {
        implementation 'com.github.bumptech.glide:glide:4.11.0'
        annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
    }
        

Using Glide to Load an Image

Here's how you can use Glide to load an image from a URL into an ImageView:

    import com.bumptech.glide.Glide
    import android.os.Bundle
    import android.widget.ImageView
    import androidx.appcompat.app.AppCompatActivity

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val imageView: ImageView = findViewById(R.id.imageView)

            Glide.with(this)
                .load("https://example.com/image.jpg")
                .into(imageView)
        }
    }
        

Glide automatically handles downloading and caching the image, reducing the need for manual management of image loading and memory usage.

Glide with Placeholders and Error Handling

Glide allows you to display placeholder images while the image is loading and handle errors if the image fails to load.

    Glide.with(this)
        .load("https://example.com/image.jpg")
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.error_image)
        .into(imageView)
        

In this example, a placeholder image is shown while the image is being loaded, and an error image is shown if the loading fails.

Using Picasso for Image Loading

Picasso is another popular image loading library for Android. It provides simple and powerful functionality to load images with caching, transformations, and more.

Adding Picasso to Your Project

To use Picasso in your Android project, add the Picasso dependency in your build.gradle file:

    dependencies {
        implementation 'com.squareup.picasso:picasso:2.71828'
    }
        

Using Picasso to Load an Image

Here's how you can use Picasso to load an image into an ImageView:

    import com.squareup.picasso.Picasso
    import android.os.Bundle
    import android.widget.ImageView
    import androidx.appcompat.app.AppCompatActivity

    class MainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)

            val imageView: ImageView = findViewById(R.id.imageView)

            Picasso.get()
                .load("https://example.com/image.jpg")
                .into(imageView)
        }
    }
        

Just like Glide, Picasso simplifies the image loading process and handles caching and error handling.

Picasso with Placeholders and Error Handling

Picasso also supports displaying placeholder images while loading and error images if something goes wrong.

    Picasso.get()
        .load("https://example.com/image.jpg")
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.error_image)
        .into(imageView)
        

Bitmap Manipulation and Transformations

Both Glide and Picasso support image transformations, which can be used to resize, crop, or apply other visual effects to an image.

Example: Applying a Circle Transformation with Glide

    import com.bumptech.glide.load.resource.bitmap.CircleCrop

    Glide.with(this)
        .load("https://example.com/image.jpg")
        .transform(CircleCrop())
        .into(imageView)
        

Example: Applying a Circle Transformation with Picasso

    import com.squareup.picasso.Transformation

    val transformation: Transformation = object : Transformation {
        override fun transform(source: Bitmap): Bitmap {
            val result = Bitmap.createBitmap(source.width, source.height, source.config)
            val canvas = Canvas(result)
            val paint = Paint()
            paint.isAntiAlias = true
            canvas.drawCircle(source.width / 2f, source.height / 2f, source.width / 2f, paint)
            return result
        }

        override fun key(): String {
            return "circle"
        }
    }

    Picasso.get()
        .load("https://example.com/image.jpg")
        .transform(transformation)
        .into(imageView)
        

Conclusion

Efficient image handling is critical in Android development, especially for performance and memory management. You can either work with the Bitmap class for direct manipulation or use popular libraries like Glide and Picasso to simplify image loading, caching, and transformations. Both Glide and Picasso provide robust solutions for working with images, offering features like automatic caching, placeholder images, error handling, and easy integration for displaying images in ImageView widgets.





Advertisement