Android Kotlin: Bitmap to grayscale

This is an Android Kotlin code that demonstrates how to convert a Bitmap image to grayscale.

The code first retrieves a Bitmap from the app's assets directory using the assetsToBitmap extension function. This function takes the filename of the image as input and returns a Bitmap object.

Next, the code creates a new Bitmap object with the same dimensions and configuration as the original Bitmap. A new ColorMatrix is then created and its saturation is set to 0, effectively converting the image to grayscale. A ColorMatrixColorFilter is created using the modified ColorMatrix and applied to a new Paint object.

Finally, a new Canvas is created on the grayscale Bitmap and the original Bitmap is drawn onto it using the Paint object with the grayscale filter. The resulting grayscale Bitmap is then set to the second ImageView.

Here's a breakdown of the code:

MainActivity.kt

  1. Import statements: The code imports necessary classes from the Android graphics library, including Activity, Context, Bitmap, BitmapFactory, Canvas, Paint, ColorMatrix, and ColorMatrixColorFilter.

  2. assetsToBitmap extension function: This function takes a filename as input and attempts to open a stream from the app's assets directory. If successful, it decodes the stream into a Bitmap object and returns it. Otherwise, it catches any IOException that may occur and prints an error message.

  3. onCreate method: This method is called when the activity is first created. Here's a step-by-step explanation of what happens inside this method:

    • Sets the layout of the activity using setContentView.
    • Finds the two ImageViews and two TextViews from the layout using findViewById.
    • Calls the assetsToBitmap function to load the image from the assets directory.
    • If the bitmap is loaded successfully, it sets the original Bitmap to the first ImageView using setImageBitmap.
    • Calls the toGrayscale extension function on the original Bitmap to convert it to grayscale.
    • If the grayscale conversion is successful, it sets the grayscale Bitmap to the second ImageView using setImageBitmap.

activity_main.xml

This file defines the layout of the activity. It contains two ImageViews to display the original and grayscale bitmaps, and two TextViews to label them.

Summary

This code demonstrates a straightforward approach to converting a Bitmap image to grayscale in Android using Kotlin. The code effectively utilizes extension functions to improve readability and maintainability.


MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.content.Context
import android.graphics.*
import android.os.Bundle
import android.widget.*
import java.io.IOException


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

        // get the widgets reference from XML layout
        val imageView = findViewById<ImageView>(R.id.imageView)
        val imageView2 = findViewById<ImageView>(R.id.imageView2)

        // get the bitmap from assets
        val bitmap = assetsToBitmap("flower103.jpg")

        bitmap?.apply {
            // set bitmap to first image view
            imageView.setImageBitmap(this)

            // convert bitmap to grayscale bitmap
            toGrayscale()?.apply {
                imageView2.setImageBitmap(this)
            }
        }
    }
}


// extension function to get bitmap from assets
fun Context.assetsToBitmap(fileName:String):Bitmap?{
    return try {
        val stream = assets.open(fileName)
        BitmapFactory.decodeStream(stream)
    } catch (e: IOException) {
        e.printStackTrace()
        null
    }
}


// extension function to convert bitmap to grayscale
fun Bitmap.toGrayscale():Bitmap?{
    val bitmap = Bitmap.createBitmap(
        width,
        height,
        Bitmap.Config.ARGB_8888
    )

    val matrix = ColorMatrix().apply {
        setSaturation(0f)
    }
    val filter = ColorMatrixColorFilter(matrix)

    val paint = Paint().apply {
        colorFilter = filter
    }

    Canvas(bitmap).drawBitmap(this, 0f, 0f, paint)
    return bitmap
}
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootLayout"
    android:background="#DCDCDC"
    android:padding="24dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="250dp"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Original Bitmap"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/imageView"
        app:layout_constraintTop_toBottomOf="@+id/imageView" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="0dp"
        android:layout_height="250dp"
        android:layout_marginTop="24dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Bitmap To Grayscale"
        app:layout_constraintEnd_toEndOf="@+id/imageView2"
        app:layout_constraintStart_toStartOf="@+id/imageView2"
        app:layout_constraintTop_toBottomOf="@+id/imageView2" />

</androidx.constraintlayout.widget.ConstraintLayout>
More android kotlin tutorials