为了编写有效的代码,您应该使用最简单的数据类型。对于Renderscript来说更是如此,其中相同的计算在内核中重复了这么多次。现在,我想编写一个非常简单的内核,它将(颜色)位图作为输入并生成一个int []数组作为输出:
#pragma version(1)
#pragma rs java_package_name(com.example.xxx)
#pragma rs_fp_relaxed
uint __attribute__((kernel)) grauInt(uchar4 in) {
uint gr= (uint) (0.21*in.r + 0.72*in.g + 0.07*in.b);
return gr;
}
Java方面:
int[] data1 = new int[width*height];
ScriptC_gray graysc;
graysc=new ScriptC_gray(rs);
Type.Builder TypeOut = new Type.Builder(rs, Element.U32(rs));
TypeOut.setX(width).setY(height);
Allocation outAlloc = Allocation.createTyped(rs, TypeOut.create());
Allocation inAlloc = Allocation.createFromBitmap(rs, bmpfoto1, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
graysc.forEach_grauInt(inAlloc,outAlloc);
outAlloc.copyTo(data1);
对于600k像素的位图,我的三星S5(5.0)需要40毫秒,而我的三星Tab2(4.2)需要180毫秒。现在我试着优化。由于输出实际上是一个8位无符号整数(0-255),我尝试了以下内容:
uchar __attribute__((kernel)) grauInt(uchar4 in) {
uchar gr= 0.2125*in.r + 0.7154*in.g + 0.0721*in.b;
return gr;
}
并在Java中将第4行更改为:
Type.Builder TypeOut = new Type.Builder(rs, Element.U8(rs));
但是,这会产生错误“32位整数源与分配类型UNSIGNED_8不匹配”。我对此的解释是forEach_grauInt(inAlloc,outAlloc)语句在输入和输出端需要相同的Element-type。因此,我尝试“断开”in-out-out-Allocation并将输入分配(bitmap)视为全局变量bmpAllocIn,如下所示:
#pragma version(1)
#pragma rs java_package_name(com.example.dani.oldgauss)
#pragma rs_fp_relaxed
rs_allocation bmpAllocIn;
int32_t width;
int32_t height;
uchar __attribute__((kernel)) grauInt(uint32_t x, uint32_t y) {
uchar4 c=rsGetElementAt_uchar4(bmpAllocIn, x, y);
uchar gr= (uchar) 0.2125*c.r + 0.7154*c.g + 0.0721*c.b;
return gr;
}
使用Java方:
int[] data1 = new int[width*height];
ScriptC_gray graysc;
graysc=new ScriptC_gray(rs);
graysc.set_bmpAllocIn(Allocation.createFromBitmap(rs,bmpfoto1));
Type.Builder TypeOut = new Type.Builder(rs, Element.U8(rs));
TypeOut.setX(width).setY(height);
Allocation outAlloc = Allocation.createTyped(rs, TypeOut.create());
graysc.forEach_grauInt(outAlloc);
outAlloc.copyTo(data1);
现在令人惊讶的是我再次收到相同的错误消息:“32位整数源与分配类型UNSIGNED_8不匹配”。这个我无法理解。我在这做错了什么?
答案 0 :(得分:1)
原因是
int[] data1 = new int[width * height];
线。您正在尝试使用它创建的数组作为copyTo()的目标,并抛出异常。将其更改为
byte[] data1 = new byte[width * height];
一切都会好的。 BTW,输入和输出分配可以是不同类型的。
作为旁注,您还可以完全消除RS过滤器的浮点计算,它将提高某些体系结构的性能。