Преобразовать растровое изображение в GrayScale в Android - PullRequest
51 голосов
/ 30 июля 2010

Я новичок в этом сайте и задаю вопрос об Android.

Есть ли способ конвертировать растровое изображение в градации серого?Я знаю, как нарисовать растровое изображение в градациях серого (используя операции холста: http://www.mail-archive.com/android-developers@googlegroups.com/msg38890.html), но мне действительно нужно фактическое растровое изображение серого цветаили, по крайней мере, что-то, что может быть позже преобразовано в растровое изображение).Нужно ли реализовывать это вручную (пиксель за пикселем)?

Я много искал, но так и не смог найти.Кто-нибудь знает простой / эффективный способ сделать это?

Большое спасибо!

Ответы [ 5 ]

143 голосов
/ 02 августа 2010

ОН, да, это так.Я использовал это неправильно, спасибо, что указал мне это.(Извините за бесполезный вопрос) Вот код конца (в значительной степени основанный на связанном), так как он может кому-то помочь:

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

Любые замечания или комментарии по нему очень приветствуются.

Спасибо

17 голосов
/ 18 апреля 2015

Если вы собираетесь показать это растровое изображение на ImageView.Затем вместо преобразования растрового изображения в шкалу серого можно попробовать следующий код:

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

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

Для справки

14 голосов
/ 30 июля 2010

Разве это не то, что делает код, на который вы ссылаетесь? Он принимает цветное растровое изображение («bmp»), создает дублированный растровое изображение («bm»), а затем рисует цветное растровое изображение в «bm», используя фильтр, чтобы превратить его в оттенки серого. С этого момента вы можете использовать «bm» как фактическое растровое изображение в градациях серого и делать с ним все, что вы хотите.

Вам нужно немного подправить семпл (он использует жестко закодированные размеры, вы можете просто клонировать размер оригинального растрового изображения), но в остальном он кажется готовым к использованию. в зависимости от того, что вы хотите.

12 голосов
/ 11 октября 2011

Я хотел бы отметить, что при таком подходе должен быть принят во внимание один важный аспект.Битовые карты на Android хранятся в NativeHeap.Просто «создавая растровые изображения», вы в конечном итоге забьете память, получив OutOfMemoryException (OOM).

Поэтому растровое изображение всегда должно быть .recycled().

0 голосов
/ 20 апреля 2019

Вот более эффективный способ, который я сделал для поддержки всех версий 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
    }
...