2012-05-14 9 views
10

Encontré que falta una buena documentación en RenderScript, por lo que sé, forEach en RS es ejecutar el directorio raíz() para cada elemento individual en la asignación.Pasando Matriz a rsForEach en Renderscript Compute

Estoy tratando de hacer una biblioteca para Renderscript que procesa la imagen, como punto de partida, llegué a este great answer. Pero el problema es que la operación de desenfoque está en Cada píxel y cada píxel requiere otro ciclo (n con ancho de desenfoque) de cálculo. Aunque se ejecuta en multi-core, todavía es un poco lento.

Estoy tratando de modificarlo para permitir el filtro de cuadro (de dos pasadas), pero eso requiere trabajar en una sola fila o columna en lugar de una celda. Entonces, ¿hay alguna manera de pedirle a foreach que envíe una matriz a root()?

+0

Puede tener 2 guiones de desenfoque horizontal y vertical. http://stackoverflow.com/questions/13435561/android-blur-bitmap-instantly –

Respuesta

16

rsForEach solo puede operar en asignaciones.

Si desea tener la función rsForEach, llame a root() para cada una de las filas de imágenes que debe pasar en una asignación que tenga la misma longitud que el número de filas y luego determine qué fila debe estar operando dentro de root() (de manera similar para operar en cada columna). RenderScript debería dividir el trabajo para que se ejecute con los recursos disponibles (más de una fila se procesa al mismo tiempo en dispositivos multi core).

Una forma de hacerlo es pasando una asignación que proporcione los desplazamientos (dentro del conjunto de datos de imagen) de las filas de la imagen. El argumento v_in dentro de la raíz() será el desplazamiento de la fila. Dado que las asignaciones en las que opera la llamada rsForEach no son los datos de la imagen, no puede escribir la imagen utilizando el argumento v_out y debe vincular la imagen de salida por separado.

Aquí es un poco de RenderScript que muestran esto:

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

Ésta sería la configuración utilizando la siguiente 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 esto es tan inteligente, nunca se pensó en pasar "índices" para falsificarlo. – xandy

+0

Sigo recibiendo "ninguna función coincidente para llamar a 'rsForEach'" para este script. ¿Cómo? Las siguientes líneas del error son: "... nota: la función candidata no es viable: requiere 3 argumentos, pero se proporcionaron 4 ... nota: la función candidata no es viable: requiere 5 argumentos, pero se proporcionaron 4 ... nota: La función candidata no es viable: requiere 6 argumentos, pero se proporcionaron 4 " –

+1

Este método ya no funciona porque" API 20+ solo permite asignar 1D simples para usar con bind "(Cita del mensaje de error). De ahí mBlurRowScript.bind_gInPixels (mInAllocation); falla – Searles

Cuestiones relacionadas