Scale a Bitmap in an Android application

This tutorial explains how to scale (resize) a bitmap while maintaining the aspect ratio in an Android application using Kotlin.

January 25, 2021 - 3 minute read -
Android Tutorial Kotlin

Resizing an image is a piece of functionality that’s common to many applications, however the code needed to achieve this with the Android SDK isn’t readily apparent.

The obvious method you may arrive at is this:

Bitmap.createScaledBitmap(source, width, height, filter)

However, this assumes know exactly what height and width we want the target image to be, or you’ll end up with a stretched bitmap.

The following code can be used to re-size a bitmap, ensuring neither of its dimensions exceed the provided values and also maintaining the aspect ratio:

fun resizeBitmap(image: Bitmap, maxHeight: Int, maxWidth: Int): Bitmap {

        checkMainThread()

        if (maxHeight > 0 && maxWidth > 0) {

            val sourceWidth: Int = image.width
            val sourceHeight: Int = image.height

            var targetWidth = maxWidth
            var targetHeight = maxHeight

            val sourceRatio = sourceWidth.toFloat() / sourceHeight.toFloat()
            val targetRatio = maxWidth.toFloat() / maxHeight.toFloat()

            if (targetRatio > sourceRatio) {
                targetWidth = (maxHeight.toFloat() * sourceRatio).toInt()
            } else {
                targetHeight = (maxWidth.toFloat() / sourceRatio).toInt()
            }

            return Bitmap.createScaledBitmap(
                image, targetWidth, targetHeight, true
            )

        } else {
            throw RuntimeException()
        }
    }

What’s happening here?

  • If either the maximum height or maximum width are 0, throw a RuntimeException as we obviously cannot resize a bitmap to have 0 pixels in either dimension.

  • The larger dimension of the target bitmap size is going to match either maxWidth or maxHeight, the second dimension will be scaled proportionally.

  • A new bitmap is created using createScaledBitmap with the correct targetWidth and targetHeight.

Usage

Since this functionality would typically be used throughout the entire application, I would suggest creating a utility class for it:

object ImageScalingUtility {

    fun resizeBitmap(image: Bitmap, maxHeight: Int, maxWidth: Int): Bitmap {
        ...
    }
    
}

The utility can then be used like this:

val scaledImage = ImageScalingUtility.resizeBitmap(
    source, 
    MAX_THUMBNAIL_HEIGHT, 
    MAX_THUMBNAIL_WIDTH
)
    
companion object {
        
    private const val MAX_THUMBNAIL_HEIGHT = 256
    private const val MAX_THUMBNAIL_WIDTH = 256
        
}