在Android Studio中将图像位图转换为二进制图像

时间:2017-03-28 18:13:59

标签: android performance bitmap type-conversion processing-efficiency

我正在尝试在LED矩阵中显示图像/视频,LED矩阵可以是ON或OFF。所以我需要将任何图像转换为二进制(0/1或真/假)格式,以将值提供给led矩阵。这是使用Android应用程序完成的。

你能建议一种快速有效的方法吗?我知道迭代的方法,即

1)嵌套循环扫描原始位图的高度和宽度

2)从每个Pixel元素获取R,G,B值并使用一些公式将其与阈值进行比较。 (R + G + B> THRESHOLD或灰度公式0.299R + 0.587G + 0.114B> THRESHOLD)

这种方法确实有效。但是,这很慢。转换一个Bitmap大约需要2秒钟。当我尝试转换具有多个帧(和相应的位图)的视频时,即使是10秒的视频也需要太长时间。另一个问题是处理器总是被处理的数据量略微窒息。我删除了#39帧。甚至在对线程进行计算之后也会出错。

必须有更快的方法,因为大多数相机应用程序都有实时图像过滤器。

确切地说,我需要一种方法来获取位图并获得其二进制等效值。

为了节省内存,最好将结果存储在字节流/数组中。否则,布尔/整数变量每个像素占用一个字节。而且这个数字乘以帧中没有像素,没有帧只占用太多内存,特别是如果我尝试使用并行线程来完成它。

希望有人可以帮我解决这个问题。

1 个答案:

答案 0 :(得分:0)

我认为您可以使用颜色矩阵来实现您想要的效果。它比迭代Bitmap更有效。

下面的示例采用位图并将每个可见(alpha!= 0)变为透明(0x0ffffff)以显示下面的视图。每个不可见像素设置为黑色(0xff000000)。我想你可以调整它来解决你的问题:

public Bitmap convertBitmap(Bitmap bitmap) {
    Bitmap output =  Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    Paint colorFilterMatrixPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    colorFilterMatrixPaint.setColorFilter(new ColorMatrixColorFilter(new float[] {
            0, 0, 0, 255, 0,
            0, 0, 0, 255, 0,
            0, 0, 0, 255, 0,
            0, 0, 0, -255, 255
    }));
    canvas.drawBitmap(bitmap, 0, 0, colorFilterMatrixPaint);
    return output;
}

<强>更新 我做了一些调整,使输出成为一个0和1的字节数组(不是位数组,因为这需要对输入的大小或使用我试图避免的if语句进行一些假设)。我正在使用两个传递和ARGB_4444位图,这也可以改进以节省速度和内存消耗,但它看起来很快,大部分工作都是在硬件中完成的:

public Bitmap convertBitmap(Bitmap input) {
    int width = input.getWidth();
    int height = input.getHeight();
    Bitmap firstPass =  Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
    Bitmap secondPass =  Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
    Canvas firstCanvas = new Canvas(firstPass);
    Paint colorFilterMatrixPaint = new Paint();
    colorFilterMatrixPaint.setColorFilter(new ColorMatrixColorFilter(new float[]{
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            1, 1, 1, -1, 0
    }));

    firstCanvas.drawBitmap(input, 0, 0, colorFilterMatrixPaint);

    Canvas secondCanvas = new Canvas(secondPass);
    Paint colorFilterMatrixPaint2 = new Paint();
    colorFilterMatrixPaint2.setColorFilter(new ColorMatrixColorFilter(new float[]{
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            0, 0, 0, 0, 0,
            0, 0, 0, 255, -255
    }));

    secondCanvas.drawBitmap(firstPass, 0, 0, colorFilterMatrixPaint2);

    int pixels[] = new int[width * height];
    byte pixelsMap[] = new byte[width * height];
    secondPass.getPixels(pixels, 0, width, 0, 0, width, height);
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            pixelsMap[(x * y) + y] = (byte) ((pixels[(x * y) + y] >> 24) * -1);
        }
    }
    return secondPass;
}