2012-05-14 5 views
10

Ho trovato che manca una buona documentazione in RenderScript, per quello che so, forEach in RS è eseguire il root() per ogni singolo elemento nell'assegnazione.Passing Array to rsForEach in Renderscript Compute

Sto cercando di creare una libreria per Renderscript che esegue l'elaborazione delle immagini, come punto di partenza, ho raggiunto questo great answer. Ma il problema è che l'operazione di sfocatura è su Ogni pixel e ogni pixel richiede un altro ciclo (n con larghezza di sfocatura) di calcolo. Sebbene funzioni su multi-core, è ancora un po 'troppo lento.

Sto tentando di modificarlo per consentire il filtro di casella (due passaggi), ma che richiede il lavoro su una singola riga o colonna anziché cella. Quindi, c'è un modo per chiedere a foreach di inviare un array a root()?

+0

Si possono avere 2 script per sfocatura orizzontale e verticale. http://stackoverflow.com/questions/13435561/android-blur-bitmap-instantly –

risposta

16

rsForEach può funzionare solo su Allocations.

Se si desidera avere la funzione rsForEach, chiamare root() per ciascuna delle righe di immagine che si devono passare in un'allocazione di dimensioni pari alla stessa lunghezza del numero di righe e quindi calcolare quale riga si deve operare su root() (analogamente per operare su ogni colonna). RenderScript dovrebbe quindi dividere il lavoro da eseguire sulle risorse disponibili (più di una riga viene elaborata contemporaneamente su dispositivi multi-core).

Un modo per farlo è passare un'allocazione che fornisce gli offset (all'interno dell'array di dati immagine) delle righe dell'immagine. L'argomento v_in all'interno di root() sarà quindi l'offset della riga. Poiché le allocazioni su cui sta operando la chiamata rsForEach non sono i dati dell'immagine, non è possibile scrivere l'immagine utilizzando l'argomento v_out ed è necessario associare l'immagine di output separatamente.

Ecco alcune RenderScript che mostrano questo:

#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); 
} 

Questo sarebbe l'installazione utilizzando il seguente 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 questo è così intelligente, mai pensato di passare "indici" per simularlo. – xandy

+0

Continuo a ricevere "nessuna funzione di corrispondenza per la chiamata a 'rsForEach'" per questo script. come mai? Le seguenti righe sull'errore sono: "... nota: la funzione candidata non è valida: richiede 3 argomenti, ma 4 sono stati forniti ... nota: la funzione candidata non è valida: richiede 5 argomenti, ma 4 sono stati forniti ... nota: funzione candidata non valida: richiede 6 argomenti, ma 4 sono forniti " –

+1

Questo metodo non funziona più poiché" API 20+ consente solo l'uso di allocazioni 1D semplici con bind "(citazione dal messaggio di errore). Quindi mBlurRowScript.bind_gInPixels (mInAllocation); non riesce. – Searles