NDK处理图片:通过对比度达到美黑效果

前言

  • 这里主要还是学习ndk开发,这个对比度的算法,原理上也不是很清晰,通过本篇文章,主要了解到ndk简单开发的流程,图片处理的基本原理。
  • 学习来源:爱奇艺视频搜索:Android开发NDK图片处理,有个一个半小时的视频的,他的开发环境是eclipse。目前我用过的环境是android studio2.2的,开发环境的搭建可以看我之前的文章。

程序步骤

  • AS2.2创建一个支持C++的工程,自动生成了Jni文件夹和一些配置文件。
  • 先看项目的配置文件,build.gradle中:
 externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
  • 这里是要执行这个cmake的文件,再看CMakeLists.txt
add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/native-lib.cpp
             src/main/cpp/ndk_handle_pics.cpp )
  • 这里加载一个名为 native-lib 的动态库,文件中的内容有src/main/cpp/native-lib.cpp, src/main/cpp/ndk_handle_pics.cpp
    这两个文件。
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
  • 这里 就是将 log-lib 连接到我们的 native-lib动态库中

  • 图片是我随便在网上找到的一张图片的,图片里面的处理前跟处理后跟我这里的处理没有什么关系,这里搜索磨皮效果的时候找到的图片,这是别人的对比图。我先上我没处理过之前的图片的
    这里写图片描述

  • 以上主要是介绍配置文件的作用,核心代码如下:

  • 这里是用java来处理图片的代码
                  long start_time = System.currentTimeMillis();

                //核心:获取到bitmap的ARGB,来用它做 对比度 的处理
                //定义一个亮度和对比度 这个对比度的算法是别人来做的
                float brightness = 0.2f;
                float constract = 0.2f;
                int width = mBitmap.getWidth();
                int height = mBitmap.getHeight();
                Bitmap bitmap = Bitmap.createBitmap(width , height , Bitmap.Config.RGB_565);
                //开始来处理
                int a , r , g , b ;
                //调黑的亮度
                int bab  = (int) (255 * brightness);
                //对比度
                float ca = 1.0f + constract;
                //再调高一点而已
                ca *= ca;
                int cab = (int) (ca * 65536) + 1 ;

                //开始每一个点来做处理的
                for(int x = 0 ; x < width ; x++){
                    for(int y = 0 ; y < height ; y++){
                        //获取到每个像素点的颜色值
                        int color = mBitmap.getPixel(x, y);
                        a = Color.alpha(color);
                        r = Color.red(color);
                        g = Color.green(color);
                        b = Color.blue(color);
                        //然后减去一个亮度
                        int ri = r - bab;
                        int gi = g - bab;
                        int bi = b - bab;
                        //重新进行一下赋值
                        r = (ri > 255)?255:(ri < 0 ? 0 : ri);
                        b = (bi > 255)?255:(bi < 0 ? 0 : bi);
                        g = (gi > 255)?255:(gi < 0 ? 0 : gi);

                        //对比变化度,主要看大于还是小于0
                        ri = r - 128;
                        gi = g - 128;
                        bi = b - 128;

                        //ri = (ri * cab)/65536 等价于 ri = (ri * cab)>>16;
                        ri = (ri * cab)/65536;
                        gi = (gi * cab)/65536;
                        bi = (bi * cab)/65536;

                        //加回来
                        ri += 128;
                        gi += 128;
                        bi += 128;

                        //重新进行一下赋值
                        r = (ri > 255)?255:(ri < 0 ? 0 : ri);
                        b = (bi > 255)?255:(bi < 0 ? 0 : bi);
                        g = (gi > 255)?255:(gi < 0 ? 0 : gi);

                        //以前的这些算法原理不是很清晰,不过是这样算的
                        //一个argb的像素点已经改变了  那么现在要进行的是赋值
                        bitmap.setPixel(x,y,Color.argb(a , r ,g , b));
                    }
                }

                long end_time = System.currentTimeMillis();
                mIv_pic.setImageBitmap(bitmap);
  • 处理时间如下这里写图片描述

  • ndk处理代码基本类似 如下:

  jint *pics = env->GetIntArrayElements(pics_, NULL);
    int newSize=width * height;
    float brightness = 0.2f;
    float constract = 0.2f;
    //开始来处理
    int a , r , g , b ;
    //调黑的亮度
    int bab  = (int) (255 * brightness);
    //对比度
    float ca = 1.0f + constract;
    //再调高一点而已
    ca *= ca;
    int cab = (int) (ca * 65536) + 1 ;

    //开始每一个点来做处理的
    int x,y;
    for(x = 0 ; x < width ; x++){
        for(y = 0 ; y < height ; y++){
            //获取到每个像素点的颜色值 这个算法 与运算 其实 你到java中Color.alpha(color)的这个跟进去 其实就是这里面的方法
            int color = pics[y * width + x ];
            //这个& 0xFF可以看做是只取8bit的数据 (二进制的) argb每个只占用了一个Byte的数据,要把其他位置 归0
            a = (color >> 24) & 0xFF;
            r = (color >> 16) & 0xFF;
            g = (color >> 8) & 0xFF;
            b = color & 0xFF;
            //然后减去一个亮度
            int ri = r - bab;
            int gi = g - bab;
            int bi = b - bab;
            //重新进行一下赋值
            r = (ri > 255)?255:(ri < 0 ? 0 : ri);
            b = (bi > 255)?255:(bi < 0 ? 0 : bi);
            g = (gi > 255)?255:(gi < 0 ? 0 : gi);

            //对比变化度,主要看大于还是小于0
            ri = r - 128;
            gi = g - 128;
            bi = b - 128;

            //ri = (ri * cab)/65536 等价于 ri = (ri * cab)>>16;
            ri = (ri * cab)/65536;
            gi = (gi * cab)/65536;
            bi = (bi * cab)/65536;

            //加回来
            ri += 128;
            gi += 128;
            bi += 128;

            //重新进行一下赋值
            r = (ri > 255)?255:(ri < 0 ? 0 : ri);
            b = (bi > 255)?255:(bi < 0 ? 0 : bi);
            g = (gi > 255)?255:(gi < 0 ? 0 : gi);

            //以前的这些算法原理不是很清晰,不过是这样算的
            //一个argb的像素点已经改变了  那么现在要进行的是赋值 这里 的赋值也看java的里面是如何进行赋值的
            //Color.argb(a , r ,g , b)中是这么来进行运算的return (alpha << 24) | (red << 16) | (green << 8) | blue;
            //透明度一般不变化  就直接用0xFF
            pics[y * width + x] = (0xFF << 24) | (r << 16) | (g << 8) | b;
        }
    }

    jintArray it = (*env).NewIntArray(newSize);
    (*env).SetIntArrayRegion(it,0,newSize,pics);

    env->ReleaseIntArrayElements(pics_, pics, 0);
  • 处理时间如下:
    这里写图片描述
  • 由此可见,处理的时间差距还是挺大的。
  • 其实图片在内存中就是一连串的数组的,如果是argb的像素模式存在的话,每个像素点占用1个int的大小,argb每个占用一个byte即8bit的数据量大小,所以很多颜色的调试都是0-255(2^8)范围内来调试的。调整这些argb就可以来调整图片。

    项目下载地址

  • csdn:http://download.csdn.net/detail/the_name_for_yu/9747911

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值