Java层与 RenderScript 层参数传递
在开发中时常需要将Java层数据传递到RenderScript层来实现参数的传递,例如:高斯模糊中需要我们传递模板(算子)到RenderScript层来实现模糊的功能。下面演示何传递。
RenderScript层首先定义一个变量,如下
rs_allocation inAllocation;
uint32_t nTempMX, nTempMY;
uint32_t nTempW, nTempH;
float fCoef;
float template[256];
在Java层我们就可以通过IDE自动编译生成的代码来传递参数,如下
processScript.set_inAllocation(inAllocation);
System.arraycopy(ntemplate, 0, template, 0, ntemplate.length);
processScript.set_template(template);
processScript.set_nTempH(nTempH);
processScript.set_nTempW(nTempW);
processScript.set_nTempMY(nTempMY);
processScript.set_nTempMX(nTempMX);
processScript.set_fCoef(fCoef);
备注:这里需要注意的是在传递数组类型的时候需要制定Java层和RenderScript层数组的大小,如果他们数组大小不一致会导致异常。如果RenderScript层不显式制定大小,例如float template[],那么它默认的大小为一。
完整示例
下面我用一个高斯模糊的例子来演示参数的传递
Java层代码
// Gauss平滑 1/16
private static final float TEMPLATE_SMOOTH_GAUSS[] =
{1, 2, 1,
2, 4, 2,
1, 2, 1};
private static float template[] = new float[256];
public static Bitmap imTemplate(Context context, Bitmap inBitmap,
float ntemplate[], int nTempH,
int nTempW, int nTempMY,
int nTempMX) {
float weight = 0f;
for (float t : ntemplate) {
weight += t;
}
float fCoef = 1.0f / weight;
// Creates a RS context.
RenderScript mRS = RenderScript.create(context);
// Creates the input Allocation and copies all Bitmap contents into it.
Allocation inAllocation = Allocation.createFromBitmap(mRS, inBitmap);
// Defines the output Type, which will be a RGBA pixel.
// The Allocation will be composed by four unsigned chars (0-255) for each pixel,
// so that R-G-B-A values can be stored.
// It is necessary to use a Type-based approach whenever there is a multi-dimensional sizing (X,Y).
int bitmapWidth = inBitmap.getWidth();
int bitmapHeight = inBitmap.getHeight();
Type.Builder outType = new Type.Builder(mRS, Element.RGBA_8888(mRS)).setX(bitmapWidth).setY(bitmapHeight);
// Creates the output Allocation wherein to store the conversion result.
Allocation outAllocation = Allocation.createTyped(mRS, outType.create(), Allocation.USAGE_SCRIPT);
// Creates the conversion script wrapper.
ScriptC_ImgProcess processScript = new ScriptC_ImgProcess(mRS);
// Binds the inAllocation variable with the actual Allocation.
processScript.set_inAllocation(inAllocation);
System.arraycopy(ntemplate, 0, template, 0, ntemplate.length);
processScript.set_template(template);
processScript.set_nTempH(nTempH);
processScript.set_nTempW(nTempW);
processScript.set_nTempMY(nTempMY);
processScript.set_nTempMX(nTempMX);
processScript.set_fCoef(fCoef);
// Performs the conversion. RS kernel will use outAllocation size for its iterations.
processScript.forEach_imTemplate(outAllocation);
// Creates output Bitmap, matching input one size.
Bitmap outBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, inBitmap.getConfig());
// Copy calculation result to the output Bitmap.
outAllocation.copyTo(outBitmap);
mRS.destroy();
return outBitmap;
}
/**
* 高斯模糊
* @param context
* @param inBitmap
* @return
*/
public static Bitmap gaussSmooth(Context context, Bitmap inBitmap) {
return imTemplate(context, inBitmap, TEMPLATE_SMOOTH_GAUSS, 3, 3, 1, 1);
}
RenderScript代码
// Needed directive for RS to work
#pragma version(1)
// Change java_package_name directive to match your Activity's package path
#pragma rs java_package_name(demo.rs.dong.cn.java_rs_demo)
rs_allocation inAllocation;
uint32_t nTempMX, nTempMY;
uint32_t nTempW, nTempH;
float fCoef;
float template[256];
uchar4 __attribute__((kernel)) imTemplate(uint32_t x, uint32_t y) {
const uint32_t imageWidth = rsAllocationGetDimX(inAllocation);
const uint32_t imageHeight = rsAllocationGetDimY(inAllocation);
uchar4 in = rsGetElementAt_uchar4(inAllocation, x, y);
uchar4 out = in;
//process border
if(x < nTempMX || y < nTempMY || x >= (imageWidth - nTempMX) || y >= (imageHeight - nTempMY)) {
return out;
}
float r = 0 ,g = 0, b = 0;
uint32_t index;
for (uint32_t k = 0; k < nTempH; k++) {
for (uint32_t l = 0; l < nTempW; l++) {
uchar4 value = rsGetElementAt_uchar4(inAllocation, (x + l - nTempMX), (y + k - nTempMY));
//计算加权和
index = k * nTempW + l;
r = r + (float) (value.r * template[index]);
g = g + (float) (value.g * template[index]);
b = b + (float) (value.b * template[index]);
}
}
// 乘以系数
out.r = (uchar) r * fCoef;
out.g = (uchar) g * fCoef;
out.b = (uchar) b * fCoef;
if (out.r > 255) {out.r = 255;};
if (out.g > 255) {out.g = 255;};
if (out.b > 255) {out.b = 255;};
out.a = in.a;
return out;
}