我有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个分配。
到目前为止,我的理解可能是错的。非常感谢能帮助我开始的任何帮助。
答案 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;
}