Android: improving conversion speed of grayscale bitmap to monochromatic

92 views Asked by At

How can I improve the speed of the following process of conversion?

For grayscale bitmap of 384x524 pixels, this takes around 2,1 seconds on the target device.

fun convertToMonochromatic(bitmap: Bitmap): Bitmap {
    val result = Bitmap.createBitmap(bitmap.width, bitmap.height, bitmap.config)

    for (row in 0 until bitmap.height) {
        for (col in 0 until bitmap.width) {
            val hsv = FloatArray(3)
            Color.colorToHSV(bitmap.getPixel(col, row), hsv)

            if (hsv[2] > 0.7f) {
                result.setPixel(col, row, Color.WHITE)
            } else {
                result.setPixel(col, row, Color.BLACK)
            }
        }
    }

    return result
}

Is there some "mass operation", transforming all the pixels at once directly based on the HSV and the Value particulary

1

There are 1 answers

1
Ariczek On BEST ANSWER

Using this access, to iterate the pixels one by one, it seems the main time consuming part is the colorToHSV function. It computes more info, than the needed Value.

Description of the transform https://www.rapidtables.com/convert/color/rgb-to-hsv.html

After the following adjustion, the needed time for the given size, is reduced from 2,1 seconds to 0,1 second.

    fun convertToMonochromatic(bitmap: Bitmap): Bitmap {
        val result = Bitmap.createBitmap(bitmap.width, bitmap.height, bitmap.config)

        val size = bitmap.width * bitmap.height
        val input = IntArray(size)
        val output = IntArray(size)

        bitmap.getPixels(input, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)

        var current = 0
        input.forEach {

            val red = it shr 16 and 0xFF
            val green = it shr 8 and 0xFF
            val blue = it and 0xFF

            val max = maxOf(red, green, blue)
            if (max > 175) {
                output[current++] = Color.WHITE
            } else {
                output[current++] = Color.BLACK
            }
        }

        result.setPixels(output, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)

        return result
    }