在Android中使用NDK(C / C ++)将灰度效果应用于Image

时间:2014-04-07 14:27:18

标签: android c++ bitmap android-ndk grayscale

我想使用NDK将灰度效果应用于图像。

因为我已经google了很多但是发现相同的结果会使图像有点像负面(这就是我所相信的)。

我想要什么::

例如::

我有这张原始图片

enter image description here

应用灰度效果后应该像::

enter image description here

我尝试了什么::

我想使用NDK实现此功能,因此我在.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);
}

上面的函数返回结果如下::

enter image description here

此效果看起来像图像的负片。

如果你需要我身边的任何东西,请告诉我。 请帮助我解决这个问题,因为我已经坚持了好几个小时。

非常感谢提前......

编辑::

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

输出::

enter image description here

编辑2 ::

我对图像做了一些简单的修改,然后它返回了我想要的图像,但图像却失去了亮度。

这是我在原生函数中所做的更改..

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

结果(图像灰度但失去亮度)::

enter image description here

1 个答案:

答案 0 :(得分:1)

要获得灰度图像,每个像素应具有相同数量的红色,绿色和蓝色

也许使用红色组件并在grayline计算中将其影响为绿色和蓝色

或使用公式(R + G + B)/ 3 =灰色

通常通过移动每个组件来获得负像:

NegR = 255 - grayR

等等

所以你可以尝试计算灰度[x] =(255 - 0.3 * line [x])+ ...

编辑亮度: 要获得更好的亮度,请尝试在灰度计算中添加固定量:

G += Bness;

只要你出于某种奇怪的原因从255(黑色)变为0(白色),Bness似乎应该是负数。你想为你的grascale值设置一个不低于0的下限,然后尝试:

G = max(0, G+Bness);

我推荐像Bness = -25

这样的东西

编辑实施亮度:

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