2011-10-01 26 views
6

Estoy tratando de convertir una imagen a escala de grises a través de una función nativa, usando un código tomado de Android en Acción (2nd ed. También puede verlo here). Desafortunadamente, el objeto de mapa de bits devuelto, en lugar de la escala de grises, termina vacío.Procesamiento de mapa de bits nativo y ALPHA_8

Así es como me carga la imagen (.png):

Bitmap original = BitmapFactory.decodeResource(this.getResources(), R.drawable.sample, options); 

Hay una serie de condiciones de seguridad que pasa el mapa de bits (por favor, consulte más abajo). Esta es la definición nativa función en Java:

public native void convertToGray(Bitmap bitmapIn,Bitmap bitmapOut); 

y la llamada:

// Grayscale bitmap (initially empty)  
Bitmap gray = Bitmap.createBitmap(original.getWidth(),original.getHeight(),Config.ALPHA_8); 
// Native function call 
convertToGray(original,gray); 

y aquí está la función:

JNIEXPORT void JNICALL Java_com_example_Preprocessor_convertToGray(JNIEnv * env, jobject obj, jobject bitmapcolor,jobject bitmapgray) 
{ 
    AndroidBitmapInfo infocolor; 
    AndroidBitmapInfo infogray; 
    void* pixelscolor; 
    void* pixelsgray; 
    int ret; 
    int y; 
    int x;  

    LOGI("convertToGray"); 
    if ((ret = AndroidBitmap_getInfo(env, bitmapcolor, &infocolor)) < 0) { 
     LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); 
     return; 
    }  

    if ((ret = AndroidBitmap_getInfo(env, bitmapgray, &infogray)) < 0) { 
     LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); 
     return; 
    } 

    LOGI("color image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infocolor.width,infocolor.height,infocolor.stride,infocolor.format,infocolor.flags); 
    if (infocolor.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { 
     LOGE("Bitmap format is not RGBA_8888 !"); 
     return; 
    } 

    LOGI("gray image :: width is %d; height is %d; stride is %d; format is %d;flags is %d",infogray.width,infogray.height,infogray.stride,infogray.format,infogray.flags); 
    if (infogray.format != ANDROID_BITMAP_FORMAT_A_8) { 
     LOGE("Bitmap format is not A_8 !"); 
     return; 
    } 

    if ((ret = AndroidBitmap_lockPixels(env, bitmapcolor, &pixelscolor)) < 0) { 
     LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); 
    } 

    if ((ret = AndroidBitmap_lockPixels(env, bitmapgray, &pixelsgray)) < 0) { 
     LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret); 
    } 

    // modify pixels with image processing algorithm 
    for (y=0;y<infocolor.height;y++) { 
     argb * line = (argb *) pixelscolor; 
     uint8_t * grayline = (uint8_t *) pixelsgray; 
     for (x=0;x<infocolor.width;x++) { 
      grayline[x] = 0.3 * line[x].red + 0.59 * line[x].green + 0.11*line[x].blue; 
     } 

     pixelscolor = (char *)pixelscolor + infocolor.stride; 
     pixelsgray = (char *) pixelsgray + infogray.stride; 
    } 

    LOGI("Done! Unlocking pixels..."); 
    AndroidBitmap_unlockPixels(env, bitmapcolor); 
    AndroidBitmap_unlockPixels(env, bitmapgray); 
} 

El mapa de bits de color se transmite correctamente, y la parte de procesamiento de el código parece estar funcionando bien, pero bitmapgray permanece vacío. Creo que me estoy perdiendo algo crucial aquí.

Entorno de prueba: emulador, v2.2. Con esta versión, la función funciona cuando se llama al código nativo desde el hilo principal . En un emulador 2.3, la función no funciona independientemente del hilo que llama al código C, o la forma en que se carga el mapa de bits. Android NDK: 4b & 6b.

ACTUALIZACIÓN # 1: Encontrará el código fuente completo here.

ACTUALIZACIÓN # 2: RGB_565 en lugar de ALPHA_8 da algunos resultados. Parece que ni siquiera setPixels() en Java funciona para ALPHA_8, y estoy teniendo problemas para encontrar información sobre este tipo de configuración. Cualquier tipo de ayuda sería muy apreciada.

+0

¿Usted ha considerado que intenta utilizar un ByteBuffer como salida? Si eso funciona, entonces podríamos estar más seguros de que hay algo mal con AndroidBitmap ... ¿También están 'bitmapIn',' bitmapOrig' y 'original' el mismo objeto? –

+0

Soy completamente nuevo en JNI, así que no, no lo he probado. Le daré una oportunidad y luego informaré. Todavía estaría agradecido por algunos consejos o indicaciones que podrían acelerar el proceso. Y sí, bitmapIn = bitmapOrig = original (lo siento por los dos últimos, debería haberlo aclarado, haberlo solucionado). –

+0

@SamuelAudet: Bien, probé [este] (http://imrannazar.com/Augmented-Reality-with-the-Android-NDK:-Part-2). El resultado es un mapa de bits * casi * en blanco (una superficie blanca con artefactos negros (puntos negros al azar)). ¿Alguien más sería tan amable de dar una oportunidad? –

Respuesta

1

Tuve un problema similar. Antes que nada, utilicé el formato RGBA_8888 de Android para infogray en lugar de A_8 (el mapa de bits original se creó usando el formato ARGB_8888). Entonces si utiliza ARGB estructura de grayline en lugar de uint_8, puede rellenar los píxeles de esta manera:

for (y = 0; y < infocolor.height; ++y) { 
     argb* line = (argb*) pixelscolor; 
     argb* grayline = (argb*) pixelsgray; 
     for (x = 0; x < infocolor.width; ++x) {   
      grayline[x].red = grayline[x].green = grayline[x].blue = 0.3 * line[x].red + 0.59 * line[x].green + 0.11 * line[x].blue; 
     } 
     pixelscolor = (char*)pixelscolor + infocolor.stride; 
     pixelsgray = (char*)pixelsgray + infogray.stride; 
    } 
+0

Bueno, da algunos resultados, pero la imagen de salida es azulada. Esperaba usar A_8 para ahorrar algo de memoria (me gustaría probar algún procesamiento de imágenes en tiempo real). –

1

tuve los mismos problemas. No intenté hacer que ALPHA_8 funcionara pero el uso de ARGB_8888 soluciona el problema.

Por cierto, en respuesta al comentario de @ white_pawn (lo siento, no puedo responder a los comentarios)

La estructura ARGB en IBM's ejemplo está en orden incorrecto. en mis emuladores o teléfono, convirtiéndolo en RGBA resuelve el problema (esta es probablemente la razón por la cual su imagen se ve azul porque usa alpa para azul). Aunque no estoy seguro de si este orden depende del hardware.

typedef struct 
{ 
    uint8_t red; 
    uint8_t green; 
    uint8_t blue; 
    uint8_t alpha; 
} argb; 
0

Tuve el mismo problema y encontré lo que salió mal!Cuando se utiliza APHA_8 es necesario cambiar el fondo a #FFFFFFFF,

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:background="#ffffffff"> 
Cuestiones relacionadas