Android Kotlin: How to invert colors of a Bitmap

Inverting Bitmap Colors in Android with Kotlin

This code demonstrates how to invert the colors of a Bitmap image in an Android application written in Kotlin. It achieves this by loading an image from the application's assets, creating a new bitmap with inverted colors, and displaying both the original and inverted versions in separate ImageViews.

Breakdown of the Code:

  1. MainActivity.kt:

    • This file defines the main activity of the application.
    • In the onCreate method, the code retrieves references to two ImageViews from the layout (imageView and imageView2).
    • It then loads a bitmap image named "flower103.jpg" from the assets folder using the assetsToBitmap extension function.
    • If the image is loaded successfully, it sets the original bitmap to the first ImageView and attempts to invert its colors using the invertColors extension function.
    • The inverted bitmap is then set to the second ImageView if it's created successfully.
  2. assetsToBitmap:

    • This extension function takes a filename as input and tries to open the corresponding file from the assets folder.
    • If successful, it decodes the file into a Bitmap object and returns it. Otherwise, it catches the exception and prints an error message.
  3. invertColors:

    • This extension function takes a Bitmap object as input and creates a new Bitmap with the same dimensions.
    • It defines a ColorMatrix object with negative values for red, green, and blue components, effectively inverting the colors.
    • A Paint object is then created and assigned a ColorMatrixColorFilter using the inverted color matrix.
    • Finally, the original bitmap is drawn onto the new bitmap with the inverted color filter applied, resulting in an inverted version of the image.
  4. activity_main.xml:

    • This file defines the layout of the main activity screen.
    • It uses a ConstraintLayout to position two ImageViews and two TextViews.
    • The first ImageView and TextView display the original bitmap and its label, respectively.
    • The second ImageView and TextView display the inverted bitmap and its label.

Summary

This code provides a clear and concise approach to inverting the colors of a Bitmap image in an Android app using Kotlin. It leverages extension functions for cleaner code and utilizes the ColorMatrix class for efficient color manipulation. The use of separate ImageViews allows for a visual comparison between the original and inverted versions of the image.


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 original bitmap to first image view
            imageView.setImageBitmap(this)

            // set inverted colors bitmap to second image view
            invertColors()?.apply {
                imageView2.setImageBitmap(this)
            }
        }
    }
}


// extension function to get a 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 invert bitmap colors
fun Bitmap.invertColors(): Bitmap? {
    val bitmap = Bitmap.createBitmap(
        width,
        height,
        Bitmap.Config.ARGB_8888
    )

    val matrixInvert = ColorMatrix().apply {
        set(
            floatArrayOf(
                -1.0f, 0.0f, 0.0f, 0.0f, 255.0f,
                0.0f, -1.0f, 0.0f, 0.0f, 255.0f,
                0.0f, 0.0f, -1.0f, 0.0f, 255.0f,
                0.0f, 0.0f, 0.0f, 1.0f, 0.0f
            )
        )
    }

    val paint = Paint()
    ColorMatrixColorFilter(matrixInvert).apply {
        paint.colorFilter = this
    }

    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="Inverted Colors Bitmap"
        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