rsForEach może działać tylko po alokacjach.
Jeśli chcesz mieć funkcję rsForEach wywołaj root() dla każdego z wierszy obrazu, musisz przejść w przydziale, który ma taką samą długość, jak liczba wierszy, a następnie sprawdź, który wiersz powinieneś działa na wewnętrznym root() (podobnie do działania w każdej kolumnie). RenderScript powinien następnie podzielić pracę, aby działała na dostępnych zasobach (więcej niż jeden wiersz jest przetwarzany w tym samym czasie na urządzeniach wielordzeniowych).
Jednym ze sposobów, w jaki można to zrobić, jest przekazanie alokacji, która daje przesunięcia (w obrębie tablicy danych obrazu) wierszy obrazu. Argument v_in wewnątrz root() będzie wtedy przesunięciem wiersza. Ponieważ alokacja, w której działa wywołanie rsForEach, nie jest danymi obrazu, nie można zapisać obrazu za pomocą argumentu v_out i należy powiązać obraz wyjściowy oddzielnie.
Oto RenderScript które pokazują to:
#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, 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);
}
Byłoby to konfiguracja za pomocą następującego 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();
Można mieć 2 skrypty do rozmycia poziomego i pionowego. http://stackoverflow.com/questions/13435561/android-blur-bitmap-instantly –