Подтвердить что ты не робот

Преобразование растрового изображения в GrayScale в Android

Я новичок на этом сайте, и у меня есть вопрос об Android.

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Спасибо

Ответ 3

Если вы собираетесь показать, что Bitmap на ImageView. Затем вместо преобразования Bitmap в Gray Scale вы можете попробовать выполнить код ниже:

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

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

Для справки

Ответ 4

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

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

Ответ 5

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