Appliquer un effet de niveaux de gris à l’image à l’aide de NDK (C / C ++) sous Android

Je souhaite appliquer l’effet Niveaux de gris à une image à l’aide de NDK.

Pour cela, j’ai beaucoup cherché sur Google mais j’ai trouvé le même résultat qui renvoie l’image en quelque sorte comme négatif (c’est ce que je crois).

Ce que je veux ::

Par exemple ::

J’ai cette image originale

entrez la description de l'image ici

Après avoir appliqué l’effet de niveaux de gris, cela devrait ressembler à ceci:

entrez la description de l'image ici

Ce que j’ai essayé ::

Je souhaite obtenir cette fonctionnalité à l’aide de NDK, de sorte que j’ai créé une fonction dans un fichier .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 fonction ci-dessus me renvoie le résultat comme ceci ::

entrez la description de l'image ici

Cet effet ressemble à quelque chose comme le négatif de l’image.

Faites-moi savoir si vous avez besoin de quelque chose de mon côté .. S’il vous plaît, aidez-moi à résoudre ce problème car je suis coincé dans cette affaire depuis de nombreuses heures.

Merci d’avance…

MODIFIER ::

Suggestion 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; } 

Sortie ::

entrez la description de l'image ici

EDIT 2 ::

J’ai fait quelques modifications simples à l’image et elle me renvoie l’image que je voulais mais l’image a perdu sa luminosité.

Ce sont les changements que j’ai apportés dans la fonction native ..

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

Résultat (l’image est en niveaux de gris mais perd de sa luminosité) ::

entrez la description de l'image ici

Pour obtenir une image en niveaux de gris, chaque pixel doit avoir la même quantité de rouge, de vert et de bleu.

Peut-être utiliser la composante rouge et l’affecter au vert et au bleu dans votre calcul de la ligne de gris

ou utilisez la formule (R + G + B) / 3 = Gris

Les images négatives sont normalement obtenues en décalant chaque composant:

NegR = 255 – greyR

etc

Donc, vous pouvez essayer de calculer grayscal [x] = (255 – 0.3 * ligne [x]) + …

Modifier la luminosité: pour obtenir une meilleure luminosité, essayez d’append un montant fixe à votre calcul en niveaux de gris:

 G += Bness; 

Ici, il semble que Bness devrait être négatif aussi longtemps que vous passez de 255 (noir) à 0 (blanc) pour une raison étrange. Vous voulez fixer une limite inférieure à 0 pour votre valeur grascale, puis essayez:

 G = max(0, G+Bness); 

Je recommande quelque chose comme Bness = -25

Modifier la luminosité de la mise en œuvre:

 // 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 );