web-dev-qa-db-de.com

Konvertieren Sie eine Bitmap in GrayScale in Android

Ich bin neu auf dieser Website und habe eine Frage zu Android.

Gibt es eine Möglichkeit, eine Bitmap in Graustufen umzuwandeln? Ich weiß, wie man eine Graustufen-Bitmap zeichnet (mithilfe von Zeichenbereichsoperationen: http://www.mail-archive.com/[email protected]/msg38890.html ), aber ich brauche wirklich die aktuelle Bitmap in grauen Farben (oder zumindest etwas, das später in eine Bitmap umgewandelt werden könnte). Muss ich es von Hand implementieren (pixelweise Operationen)?

Ich habe viel gesucht und konnte immer noch nicht finden. Kennt jemand einen einfachen/effizienten Weg, dies zu tun?

Danke vielmals!

53
leparlon

Ist das nicht genau der Code, mit dem Sie verknüpfen? Es wird eine Farbbitmap ("bmp") verwendet, eine doppelte Bitmap ("bm") erstellt und die Farbbitmap mit dem Filter in "bm" gezeichnet, um sie in Graustufen umzuwandeln. Ab diesem Zeitpunkt können Sie "bm" als tatsächliche Graustufen-Bitmap verwenden und damit tun, was Sie wollen.

Sie müssten das Beispiel ein wenig optimieren (es verwendet fest codierte Größen, Sie möchten möglicherweise nur die Größe der ursprünglichen Bitmap klonen), aber ansonsten scheint dies so einsatzbereit zu sein, wie es nur geht , je nachdem was du willst.

14
EboMike

Oh ja, das tut es. Ich habe es falsch benutzt, danke, dass du mich darauf hingewiesen hast. (Entschuldigung für die nutzlose Frage) Hier ist der Endcode (der stark auf dem verknüpften Code basiert), da er möglicherweise jemandem hilft:

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

Anmerkungen oder Kommentare dazu sind sehr willkommen.

Vielen Dank

144
leparlon

Wenn Sie diese Bitmap auf ImageView anzeigen möchten. Anstatt Bitmap in Graustufen zu konvertieren, können Sie folgenden Code versuchen:

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

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

als Referenz

18
E Player Plus

Ich möchte erwähnen, dass bei diesem Ansatz ein wichtiger Aspekt berücksichtigt werden muss. BitMaps auf Android sind im NativeHeap gespeichert. Durch einfaches "Erstellen von Bitmaps" wird der Speicher möglicherweise verstopft und es wird ein OutOfMemoryException (OOM) angezeigt.

Daher muss die Bitmap immer .recycled() sein.

13
Code-Monkey

Hier ist eine effizientere Methode, mit der ich alle Android-Versionen unterstützt habe:

    //    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