如何使用Renderscript找到2个位图之间的区别?

时间:2018-01-08 07:46:38

标签: android renderscript android-renderscript

我有2个完全相同大小的位图,我想找到两者之间最小的变化区域。这是Kotlin相当于我正在做的事情:

var minX = Int.MAX_VALUE
var minY = Int.MAX_VALUE
var maxX = 0
var maxY = 0

for (i in 0 until cols) {
    for (j in 0 until rows) {
        if (bitmapOne.getPixel(i, j) != bitmapTwo.getPixel(i, j)) {
            if (i < minX) minX = i
            if (i > maxX) maxX = i
            if (j < minY) minY = j
            if (j > maxY) maxY = j
        }
    }
}

我只需要保持最小变化区域的四个矩形点。基于我所做的一些测试,Renderscript位图迭代速度更快,所以我也在尝试学习Renderscript并移植这个Kotlin代码。

我面临的问题是我无法将2位图作为分配传递 到任何映射内核。文档说

  

“如果您需要比内核更多的输入或输出分配,   那些对象应该绑定到rs_allocation脚本全局和   通过rsGetElementAt_type()从内核或可调用函数访问   或rsSetElementAt_type()。“

但是这方面没有足够的例子。

第二个问题是如何获得返回类型,因为没有内核具有返回类型 - 我到目前为止看到的输入/输出分配示例都是相同的维度。但我需要一个不同的维度作为输出(只是一个Int4)。

在浏览reduce内核文档时,似乎他们也无法一起处理2个分配。

到目前为止,我的理解可能是错的。非常感谢能帮助我开始的任何帮助。

1 个答案:

答案 0 :(得分:2)

脚本全局变量肯定有助于解决您的情况。本质上,它们是Java / Kotlin方可以访问设置或获取的脚本变量。如果您只能使用Android 7+,则可以将其作为还原内核(而不是映射内核)。基本上,没有“输出”分配。

这是通过映射内核快速编写的。我没有尝试或编译过这个,所以你可能需要调整它。假设你有两个Bitmap个对象并且它们的大小/格式相同(这里没有错误处理以保持简短),并且正在使用Activity,你可以这样设置:< / p>

//  You should only create the Rendescript context and script one
//  time in the lifetime of your Activity.  It is an expensive op.
Renderscript rs = Renderscript.create(this);
ScriptC_diffBitmap script = new ScriptC_diffBitmap(rs);

Allocation inAlloc1 =
    Allocation.createFromBitmap(rs,
                                bitmap1,
                                Allocation.MipmapControl.MIPMAP_NONE,
                                Allocation.USAGE_SCRIPT);
Allocation inAlloc2 =
    Allocation.createFromBitmap(rs,
                                bitmap2,
                                Allocation.MipmapControl.MIPMAP_NONE,
                                Allocation.USAGE_SCRIPT);
Allocation outAlloc = Allocation.createTyped(rs,
                                             inAlloc2.getType());
script.set_maxX(0);
script.set_maxY(0);
script.set_minX(Int.MAX_VALUE);
script.set_minY(Int.MAX_VALUE);
script.set_inBitmap1(inAlloc1);
script.foreach_root(inAlloc2, outAlloc);

//  Get back the min/max values and do whatever you need
minX = script.get_minX();
minY = script.get_minY();
maxX = script.get_maxX();
maxY = script.get_mayY();

支持此功能的Rendescript代码(再次使用映射内核),名为diffBitmap.rs

#pragma version(1)
#pragma rs java_package_name(com.example.DiffBitmap)

int32_t minX;
int32_t minY;
int32_t maxX;
int32_t maxY;
rs_allocation inBitmap1;

uchar4 RS_KERNEL root(uchar4 inBitmap2Point, uint32_t x, uint32_t y)
{
    uchar4 inBitmap1Point = rsGetElementAt_uchar4(inBitmap1, x, y);

    if ((inBitmap1Point.r != inBitmap2Point.r) ||
        (inBitmap1Point.g != inBitmap2Point.g) ||
        (inBitmap1Point.b != inBitmap2Point.b) ||
        (inBitmap1Point.a != inBitmap2Point.a))
    {
        if (x < minX) minX = x;
        if (x > maxX) maxX = x;
        if (y < minY) minY = y;
        if (y > maxY) maxY = y;
    }

    //  Since we have to return an output, just return bitmap1
    return inBitmap1Point;
}