web-dev-qa-db-fra.com

Convertir un bitmap en GrayScale en Android

Je suis nouveau sur ce site et je viens avec une question sur Android.

Existe-t-il un moyen de convertir un bitmap en niveaux de gris? Je sais comment dessiner un bitmap en niveaux de gris (en utilisant les opérations de canevas: http://www.mail-archive.com/[email protected]/msg38890.html ) mais j'ai vraiment besoin du réel bitmap en couleurs grises (ou au moins quelque chose qui pourrait être converti en bitmap plus tard). Dois-je l'implémenter à la main (opérations pixel par pixel)?

J'ai beaucoup cherché et je n'ai toujours pas trouvé. Quelqu'un sait-il comment le faire facilement et efficacement?

Merci beaucoup!

53
leparlon

N'est-ce pas exactement ce que fait le code auquel vous créez un lien? Il prend un bitmap couleur ("bmp"), crée un bitmap en double ("bm"), puis dessine le bitmap couleur en "bm" à l'aide du filtre pour le transformer en niveaux de gris. À partir de ce moment, vous pouvez utiliser "bm" comme un bitmap en niveaux de gris et faire ce que vous voulez en faire.

Vous auriez besoin de modifier un peu l'échantillon (il utilise des tailles codées en dur, vous voudrez peut-être simplement cloner la taille du bitmap d'origine), mais à part cela, cela semble être aussi prêt à l'emploi que possible , selon ce que vous voulez.

14
EboMike

OH, oui, c'est vrai. Je l'utilisais mal, merci de me l'avoir signalé. (Désolé pour la question inutile) Voici le code de fin (fortement basé sur celui lié) car il peut aider quelqu'un:

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;
}

Toutes remarques ou commentaires à ce sujet sont les bienvenus.

Merci

144
leparlon

Si vous allez montrer ce Bitmap sur ImageView. Au lieu de convertir Bitmap en niveaux de gris, vous pouvez essayer le code ci-dessous:

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

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

Pour référence

18
E Player Plus

Je voudrais mentionner qu'avec cette approche, un aspect important doit être pris en compte. BitMap est activé Android sont stockés dans le NativeHeap. En créant simplement des bitmaps, vous finirez par obstruer la mémoire, obtenant un OutOfMemoryException (OOM).

Pour cela, le bitmap doit toujours être .recycled().

13
Code-Monkey

Voici un moyen plus efficace, que j'ai conçu pour prendre en charge toutes les versions d'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
    }
0
android developer