Aplique el efecto de escala de grises a la imagen usando NDK (C / C ++) en Android

Quiero aplicar el efecto de escala de grises a la imagen utilizando NDK.

Para eso he buscado en Google pero encontré el mismo resultado que devuelve la imagen de forma algo negativa (esto es lo que creo).

Lo que quiero ::

Por ejemplo ::

Tengo esta imagen original

introduzca la descripción de la imagen aquí

Después de aplicar el efecto de escala de grises debería ser así:

introduzca la descripción de la imagen aquí

Lo que he intentado ::

Quiero lograr esta funcionalidad utilizando NDK, de modo que haya creado una función en el archivo .cpp

JNIEXPORT void JNICALL Java_com_example_ndksampleproject_MainActivity_jniConvertToGray(JNIEnv * env, jobject obj, jobject bitmapcolor,jobject bitmapgray) { AndroidBitmapInfo infocolor; void* pixelscolor; AndroidBitmapInfo infogray; 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); } LOGI("unlocking pixels height = %d",infocolor.height); // 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("unlocking pixels"); AndroidBitmap_unlockPixels(env, bitmapcolor); AndroidBitmap_unlockPixels(env, bitmapgray); } 

La función anterior me devuelve el resultado como este:

introduzca la descripción de la imagen aquí

Este efecto parece algo negativo de la imagen.

Déjame saber si necesitas algo de mi lado. Por favor, ayúdame a resolver este problema, ya que me he mantenido en esto por muchas horas.

Muchas gracias de antemano…

EDITAR ::

Sugerencia de floppy12 ::

 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] = (255-0.3 * line[x].red) + (255-0.59 * line[x].green) + (255-0.11*line[x].blue)/3; } pixelscolor = (char *)pixelscolor + infocolor.stride; pixelsgray = (char *) pixelsgray + infogray.stride; } 

Salida ::

introduzca la descripción de la imagen aquí

EDITAR 2 ::

He hecho algunas modificaciones simples a la imagen y me devuelve la imagen que quería pero la imagen perdió su brillo.

Estos son los cambios que he hecho en la función nativa ..

 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] = ((255-0.3 * line[x].red) + (255-0.59 * line[x].green) + (255-0.11*line[x].blue))/3; } pixelscolor = (char *)pixelscolor + infocolor.stride; pixelsgray = (char *) pixelsgray + infogray.stride; } 

Resultado (la imagen está en escala de grises pero pierde su brillo) ::

introduzca la descripción de la imagen aquí

Para obtener una imagen en escala de grises, cada píxel debe tener la misma cantidad de rojo, verde y azul.

Tal vez use el componente rojo y afecte a verde y azul en su cálculo de línea gris

o use la fórmula (R + G + B) / 3 = Gris

Las imágenes negativas se obtienen normalmente desplazando cada componente:

NegR = 255 – grayR

y así

Así que podrías intentar calcular grayscal [x] = (255 – 0.3 * línea [x]) + …

Editar para brillo: para obtener un mejor brillo, intente agregar una cantidad fija a su cálculo en escala de grises:

 G += Bness; 

Aquí parece que Bness debería ser negativo siempre que vayas de 255 (negro) a 0 (blanco) por alguna extraña razón. Desea poner un límite inferior para no pasar de 0 a su valor de escala, luego intente:

 G = max(0, G+Bness); 

Recomiendo algo como Bness = -25

Editar el brillo de la implementación:

 // Declare a global variable for your brightness - outside your class static uint8_t bness = -25; // In your grayscale computation function for y... for x... grayscale[x] = ( (255-0.3*line[x].red) + ..... ) /3 ; int16_t gBright = grayscale[x] + bness; grayscale[x] = MAX( 0, gBright );