2012-05-14 9 views
10

Znalazłem brak dobrej dokumentacji w RenderScript, ponieważ to, co wiem, forEach w RS ma wykonać root() dla każdego pojedynczego elementu w przydziale.Przekazywanie tablicy do rsForEach w Rendercript Compute

Próbuję utworzyć bibliotekę dla Renderscript, w której przetwarzanie obrazu, jako punkt wyjścia, osiągnąłem ten great answer. Problem polega jednak na tym, że operacja zamazywania odbywa się na jednym pikselu, a każdy piksel wymaga innej pętli (n z szerokością rozmywania) obliczeń. Chociaż działa w trybie wielordzeniowym, wciąż jest zbyt wolny.

Próbuję zmodyfikować go, aby umożliwić (dwuprzebiegowy) filtr skrzynkowy, ale wymaga to pracy w jednym wierszu lub kolumnie zamiast w komórce. Czy istnieje jakiś sposób, aby poprosić foreach, aby wysłał tablicę do root'a()?

+0

Można mieć 2 skrypty do rozmycia poziomego i pionowego. http://stackoverflow.com/questions/13435561/android-blur-bitmap-instantly –

Odpowiedz

16

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(); 
+0

+100 To jest takie sprytne, nigdy nie pomyślałem o przekazaniu "wskaźników" do sfałszowania go. – xandy

+0

Otrzymuję "brak pasującej funkcji dla wywołania" rsForEach "" dla tego skryptu. dlaczego? Następne wiersze błędu to: "... uwaga: funkcja kandydująca nie jest możliwa: wymaga 3 argumentów, ale 4 zostały dostarczone ... uwaga: funkcja kandydująca nie jest możliwa: wymaga 5 argumentów, ale 4 zostały dostarczone ... Uwaga: Funkcja kandydata nie jest możliwa: wymaga 6 argumentów, ale 4 zostały dostarczone " –

+1

Ta metoda już nie działa, ponieważ" API 20+ zezwala tylko na proste przydziały 1D do użycia z bindem "(Cytat z komunikatu o błędzie). Stąd mBlurRowScript.bind_gInPixels (mInAllocation); zawiedzie. – Searles

Powiązane problemy