Convert bitmap to Grayscale

Viewed 1362

In my application i want to upload an image to server but i want to convert it to gray scale before i do that.< br /> So i found a function that takes a bitmap and returns a bitmap as Gray scale.

fun getGrayScale(src: Bitmap): Bitmap {

        //Custom color matrix to convert to GrayScale
        val matrix = floatArrayOf(
            0.3f,
            0.59f,
            0.11f,
            0f,
            0f,
            0.3f,
            0.59f,
            0.11f,
            0f,
            0f,
            0.3f,
            0.59f,
            0.11f,
            0f,
            0f,
            0f,
            0f,
            0f,
            1f,
            0f
        )

        val dest = Bitmap.createBitmap(src.width, src.height, Bitmap.Config.RGB_565)

        val canvas = Canvas(dest)
        val paint = Paint()
        val filter = ColorMatrixColorFilter(matrix)
        paint.colorFilter = filter
        canvas.drawBitmap(src, 0.toFloat(), 0.toFloat(), paint)

        return dest
    }

That runs successfully but NOT in Android 10, in which i get the following exception

java.util.concurrent.ExecutionException: java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps
        at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
        at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
        at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:298)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.lang.IllegalArgumentException: Software rendering doesn't support hardware bitmaps
        at android.graphics.BaseCanvas.onHwBitmapInSwMode(BaseCanvas.java:632)
        at android.graphics.BaseCanvas.throwIfHwBitmapInSwMode(BaseCanvas.java:639)
        at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:73)
        at android.graphics.BaseCanvas.drawBitmap(BaseCanvas.java:113)
        at android.graphics.Canvas.drawBitmap(Canvas.java:1540)
        at com.example.utilities.ImageUtils.getGrayScale(ImageUtils.kt:64)
        at com.example.utilities.FileUtils.imageRefactor(FileUtils.kt:98)
        at com.example.workmanager.FileSplitterWorker.doWork(FileSplitterWorker.kt:54)
        at androidx.work.CoroutineWorker$startWork$1.invokeSuspend(CoroutineWorker.kt:68)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)

I have tried to add hardwareAccelerated as true in my manifest but same happens. Can i do this with Glide, or with another way?

1 Answers

In Android O they have introduced new Bitmap.Config the Bitmap.Config.HARDWARE which is an actual optimization when it comes to draw the Bitmap to the screen. So since you are using Software rendering that is why you get the error.

Try this:

fun getGrayScaleBitmap(original: Bitmap): Bitmap {
    // You have to make the Bitmap mutable when changing the config because there will be a crash
    // That only mutable Bitmap's should be allowed to change config.
    val bmp = original.copy(Bitmap.Config.ARGB_8888, true)
    val bmpGrayscale = Bitmap.createBitmap(bmp.width, bmp.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bmpGrayscale)
    val paint = Paint()
    val colorMatrix = ColorMatrix()
    colorMatrix.setSaturation(0f)
    val colorMatrixFilter = ColorMatrixColorFilter(colorMatrix)
    paint.colorFilter = colorMatrixFilter
    canvas.drawBitmap(bmp, 0F, 0F, paint)
    return bmpGrayscale
}

This will replace the Bitmap.Config from Bitmap.Config.HARDWARE to Bitmap.Config.ARGB_8888.

Hope it helps!!!

Related