jni与bitmap

来源:互联网 发布:佳明官网下载软件 编辑:程序博客网 时间:2024/06/05 19:01

说明

        本文c代码来自于ndk demo。主要演示在ndk中如何操作bitmap对象,改变bitmap中的某些像素值。利用该功能再结合相应的算法,可实现将图片置灰等功能。

颜色

        除了常用的rgb8888外,还有rgb565模式。

        rgb565:用16位表示一个颜色,从高位到低位如下:R R R R R G G G G G G B B B B B。因此在该种模式下红色为0xf800,绿色为0x7e0,蓝色为0x1f。

基础

        第一步:要导入#include <android/bitmap.h>头文件。

        第二步:在ldLibs的值中加入"jnigraphics"。如下:

ndk {            moduleName "ImageJniUtils"          //生成的so名字            ldLibs "log","jnigraphics"          //可以使用log与graphics            abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无        }

方法

        AndroidBitmap_getInfo:获取一个AndroidBitmapInfo的结构体对象。利用该对象可以获取bitmap的format,height,width等信息。只有在该方法返回值>0的时才代表该方法执行成功。

        AndroidBitmap_lockPixels:用于获取bitmap像素数组的地址。bitmap的每一个像素值都是一个int数值,它们存储在一个数组中(Bitmap#getPixels()会将这些数值存储到指定的数组中)。获取地址后就可以对每一个像素进行操作了。

        AndroidBitmap_unlockPixels:与上面一个方法相反,它是释放地址。

示例

示例一:基本使用

void*              pixels;    if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);        return;    }    if (info.format != ANDROID_BITMAP_FORMAT_RGB_565) {        LOGE("Bitmap format is not RGB_565 !");        return;    }    if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {//此时pixels便指向了像素数组的首地址        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);    }    /* Now fill the values with a nice little plasma */    fill_plasma(&info, pixels, time_ms );    AndroidBitmap_unlockPixels(env, bitmap);
对于pixels的使用如下(来自于置灰demo):
                void *pixel = ((uint16_t *)pixels) + y * info.width + x;                  uint16_t v = *(uint16_t *)pixel;  //ARGB_565共16位,所以使用unit16_t                r = RGB565_R(v);  //获取对应的r通道值                g = RGB565_G(v);  //获取对应的g通道值                b = RGB565_B(v);  //获取对应的b通道值int gray = (r * 38 + g * 75 + b * 15) >> 7;  //将获取到的三通道值改变                *((uint16_t *)pixel) = MAKE_RGB565(gray, gray, gray);  //将改变后的值存储到原来的位置,这样就改变了这个位置上的像素值

示例二,微信红包图片

        先将要保留的范围内的像素值单独存储,等图片模糊后再将范围内的像素值恢复。模糊代码的来源。如下:
int Edge(int x, int y, int radius, int centerX, int centerY) {    return sqrt((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY)) < radius &&           abs(y - centerY) <= radius && abs(x - centerX) <= radius;}JNIEXPORT void JNICALL Java_com_baigle_image_ImageUtils_blur(JNIEnv *env, jobject obj,                                                             jobject bitmap, jint width,                                                             jint height) {    AndroidBitmapInfo info;    void *pixels;    int ret;    if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);        return;    }    if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);        return;    }    int centerX = info.width / 2;    int centerY = info.height / 3;    int shortP = info.width > info.height ? info.height : info.width;    int radius = shortP / 8;//确定保留半径    int x, y = centerY - radius;    void *dst = malloc((2 * radius + 1) * (2 * radius + 1) * sizeof(int));    for (; y <= centerY + radius; y++) {//保留像素值        for (x = centerX - radius; x <= centerX + radius; x++) {            if (Edge(x, y, radius, centerX, centerY)){                *((int *) dst + (y - centerY + radius) * (2 * radius + 1) + x - centerX +                  radius) = *((int *) pixels + y * info.width + x);            }        }    }    blur((int *) pixels, info.width, info.height, 100);//调用模糊方法进行模糊    for (y = centerY - radius; y <= centerY + radius; y++) {//还原保留区域内的像素值        for (x = centerX - radius; x <= centerX + radius; x++) {            if (Edge(x, y, radius, centerX, centerY))                *((int *) pixels + y * info.width + x) = *((int *) dst + (y - centerY + radius) *                                                                         (2 * radius + 1) + x -                                                           centerX + radius);        }    }    free(dst);    AndroidBitmap_unlockPixels(env, bitmap);}
        在使用图片时,将图片转换成ARGB_8888。如下:
            mBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.xxxxxxx);            mBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888,false);





0 0
原创粉丝点击