Convert a Bitmap to GrayScale in Android

拟墨画扇 提交于 2019-11-26 14:17:23

Isn't that exactly what the code you're linking to does? It takes a color bitmap ("bmp"), creates a duplicate bitmap ("bm"), and then draws the color bitmap into "bm" using the filter to turn it into grayscale. From that point on, you can use "bm" as an actual grayscale bitmap and do whatever you want to do with it.

You'd need to tweak the sample a bit (it's using hard-coded sizes, you may want to just clone the size of the original bitmap), but other than that, this seems to be as ready-to-use as it gets, depending on what you want.

OH, yes, it does. I was using it wrong, thanks for pointing it out to me. (Sorry for the useless question) Here is the end code (heavily based on the one linked) since it may help someone:

public Bitmap toGrayscale(Bitmap bmpOriginal)
{        
    int width, height;
    height = bmpOriginal.getHeight();
    width = bmpOriginal.getWidth();    

    Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bmpGrayscale);
    Paint paint = new Paint();
    ColorMatrix cm = new ColorMatrix();
    cm.setSaturation(0);
    ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
    paint.setColorFilter(f);
    c.drawBitmap(bmpOriginal, 0, 0, paint);
    return bmpGrayscale;
}

Any remarks or comments on it are very welcome.

Thanks

E Player Plus

If you are going to show that Bitmap on ImageView. Then Instead of converting Bitmap to Gray Scale, you can try below code:

ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);

ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
imageview.setColorFilter(filter);

For reference

Code-Monkey

I'd like to mention that with this approach one important aspect must be taken in account. BitMap's on Android are stored in the NativeHeap. By just "creating bitmaps", you'll eventually clog the memory, getting an OutOfMemoryException (OOM).

Therefor, the bitmap must always be .recycled().

Here's a more efficient way, which I've made to support all versions of Android:

    //    https://xjaphx.wordpress.com/2011/06/21/image-processing-grayscale-image-on-the-fly/
    @JvmStatic
    fun getGrayscaledBitmapFallback(src: Bitmap, redVal: Float = 0.299f, greenVal: Float = 0.587f, blueVal: Float = 0.114f): Bitmap {
        // create output bitmap
        val bmOut = Bitmap.createBitmap(src.width, src.height, src.config)
        // pixel information
        var A: Int
        var R: Int
        var G: Int
        var B: Int
        var pixel: Int
        // get image size
        val width = src.width
        val height = src.height
        // scan through every single pixel
        for (x in 0 until width) {
            for (y in 0 until height) {
                // get one pixel color
                pixel = src.getPixel(x, y)
                // retrieve color of all channels
                A = Color.alpha(pixel)
                R = Color.red(pixel)
                G = Color.green(pixel)
                B = Color.blue(pixel)
                // take conversion up to one single value
                B = (redVal * R + greenVal * G + blueVal * B).toInt()
                G = B
                R = G
                // set new pixel color to output bitmap
                bmOut.setPixel(x, y, Color.argb(A, R, G, B))
            }
        }
        // return final image
        return bmOut
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @JvmStatic
    fun getGrayscaledBitmap(context: Context, src: Bitmap): Bitmap {
//        https://gist.github.com/imminent/cf4ab750104aa286fa08
//        https://en.wikipedia.org/wiki/Grayscale
        val redVal = 0.299f
        val greenVal = 0.587f
        val blueVal = 0.114f
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
            return getGrayscaledBitmapFallback(src, redVal, greenVal, blueVal)
        val render = RenderScript.create(context)
        val matrix = Matrix4f(floatArrayOf(-redVal, -redVal, -redVal, 1.0f, -greenVal, -greenVal, -greenVal, 1.0f, -blueVal, -blueVal, -blueVal, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
        val result = src.copy(src.config, true)
        val input = Allocation.createFromBitmap(render, src, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT)
        val output = Allocation.createTyped(render, input.type)
        // Inverts and do grayscale to the image
        @Suppress("DEPRECATION")
        val inverter =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
                    ScriptIntrinsicColorMatrix.create(render)
                else
                    ScriptIntrinsicColorMatrix.create(render, Element.U8_4(render))
        inverter.setColorMatrix(matrix)
        inverter.forEach(input, output)
        output.copyTo(result)
        src.recycle()
        render.destroy()
        return result
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!