我发现在RenderScript中缺少良好的文档,对于我所知道的,每个RS都是为分配中的每个单独的项执行root().
我正在为一个图像处理的Renderscript做一个库,作为起点,我达到了这个great answer.但问题是模糊操作是在每个像素和每个像素需要另一个循环(n与模糊宽度)计算.虽然运行在多核,但还是有点太慢了.
我试图修改它以允许(两遍)框过滤器,但这需要在单行或列而不是单元格上工作.那么有什么办法可以让foreach将数组发送给root()吗?
解决方法
rsForEach只能在分配上操作.
如果要让rsForEach函数调用每个图像行的root(),必须在一个Allocation中传递一个大小与行数相同的长度,然后计算出应该在哪个行上运行root()(类似于在每列上操作).然后,RenderScript应该将工作分配到可用资源上运行(在多核设备上同时处理多行).
您可以通过传递给予图像行中的偏移(在图像数据数组中)的分配来实现. root()中的v_in参数就是行偏移量.由于rsForEach调用正在运行的分配不是映像数据,您无法使用v_out参数写入映像,并且必须单独绑定输出映像.
这里有一些RenderScript显示:
#pragma version(1) #pragma rs java_package_name(com.android.example.hellocompute) rs_allocation gIn; rs_allocation gOut; rs_script gScript; int mImageWidth; const uchar4 *gInPixels; uchar4 *gOutPixels; void init() { } static const int kBlurWidth = 20; // // This is called per row. // The row indices are passed in as v_in or you could also use the x argument and multiply it by image width. // void root(const int32_t *v_in,int32_t *v_out,const void *usrData,uint32_t x,uint32_t y) { float3 blur[kBlurWidth]; float3 cur_colour = {0.0f,0.0f,0.0f}; for ( int i = 0; i < kBlurWidth; i++) { float3 init_colour = {0.0f,0.0f}; blur[i] = init_colour; } int32_t row_index = *v_in; int blur_index = 0; for ( int i = 0; i < mImageWidth; i++) { float4 pixel_colour = rsUnpackColor8888(gInPixels[i + row_index]); cur_colour -= blur[blur_index]; blur[blur_index] = pixel_colour.rgb; cur_colour += blur[blur_index]; blur_index += 1; if ( blur_index >= kBlurWidth) { blur_index = 0; } gOutPixels[i + row_index] = rsPackColorTo8888(cur_colour/(float)kBlurWidth); //gOutPixels[i + row_index] = rsPackColorTo8888(pixel_colour); } } void filter() { rsDebug("Number of rows:",rsAllocationGetDimX(gIn)); rsForEach(gScript,gIn,gOut,NULL); }
这将使用以下Java进行设置:
mBlurRowScript = new ScriptC_blur_row(mRS,getResources(),R.raw.blur_row); int row_width = mBitmapIn.getWidth(); // // Create an allocation that indexes each row. // int num_rows = mBitmapIn.getHeight(); int[] row_indices = new int[num_rows]; for ( int i = 0; i < num_rows; i++) { row_indices[i] = i * row_width; } Allocation row_indices_alloc = Allocation.createSized( mRS,Element.I32(mRS),num_rows,Allocation.USAGE_SCRIPT); row_indices_alloc.copyFrom(row_indices); // // The image data has to be bound to the pointers within the RenderScript so it can be accessed // from the root() function. // mBlurRowScript.bind_gInPixels(mInAllocation); mBlurRowScript.bind_gOutPixels(mOutAllocation); // Pass in the image width mBlurRowScript.set_mImageWidth(row_width); // // Pass in the row indices Allocation as the input. It is also passed in as the output though the output is not used. // mBlurRowScript.set_gIn(row_indices_alloc); mBlurRowScript.set_gOut(row_indices_alloc); mBlurRowScript.set_gScript(mBlurRowScript); mBlurRowScript.invoke_filter();