美文网首页Android进阶之路Android开发经验谈Android技术知识
NDK开发系列之——图片亮度、饱和度处理

NDK开发系列之——图片亮度、饱和度处理

作者: 奔跑吧李博 | 来源:发表于2019-08-06 10:04 被阅读42次

    github代码传送门: https://github.com/18380438200/NdkUse

    先上效果图:


    预览图

    java的实现的方法如下:

    public class JavaFilter {
        public static final float brightness = 0.2f;  //亮度
        public static final float contrainst = 0.2f;  //对比度,颜色加深
    
        public static Bitmap getImageBitmap(Bitmap bitmap){
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            Bitmap result = Bitmap.createBitmap(width,height, Bitmap.Config.RGB_565); 
            int a,r,g,b;
            int bab = (int) (255*brightness);
            float ca = 1.0f + contrainst;
            //改变所有像素点的rgb的值
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    int color = bitmap.getPixel(x,y);  //获取color值
                    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);
                    g = gi > 255 ? 255 : (gi<0?0:gi);
                    b = bi > 255 ? 255 : (bi<0?0:bi);
    
                    //扩大对比度,需要白的更白,黑的更黑
                    //128以上加强,128以下再减
                    ri = r - 128;
                    gi = g - 128;
                    bi = b - 128;
    
                    ri = (int) (ri * ca);
                    gi = (int) (gi * ca);
                    bi = (int) (bi * ca);
    
                    ri += 128;
                    gi += 128;
                    bi += 128;
    
                    //边界检测
                    r = ri > 255 ? 255 : (ri<0?0:ri);
                    g = gi > 255 ? 255 : (gi<0?0:gi);
                    b = bi > 255 ? 255 : (bi<0?0:bi);
    
                    result.setPixel(x,y,Color.argb(a,r,g,b));
                }
            }
    
            return result;
        }
    

    Bitmap.createBitmap()

    •createBitmap(Bitmap source, int x, int y, int width, int height):从原位图中指定坐标点(x,y)开始,从中挖取宽width、高height的一块出来,创建新的Bitmap对象。

    •createScaledBitmap(Bitmap source, int dstWidth, int dstHeight, boolean filter):对源位图进行缩放,缩放成指定width、height大小的新位图对象。

    •createBitmap(int width, int height, Bitmap.Config config):创建一个宽width、高height的新位图。
    •createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter):从原位图中指定坐标点(x,y)开始,从中挖取宽width、高height的一块出来,创建新的Bitmap对象。并按Matrix指定的规则进行变换。

    Bitmap.Config.RGB_565理解:Bitmap的内部类
    public enum Config {
    ALPHA_8 (1),
    RGB_565 (3),
    ARGB_4444 (4),
    ARGB_8888 (5),
    RGBA_F16 (6),
    ...
    }
    ALPHA_8就是Alpha由8位组成
    ARGB_4444就是由4个4位组成即16位,
    ARGB_8888就是由4个8位组成即32位,原生的颜色
    RGB_565就是R为5位,G为6位,B为5位共16位
    位数越高,存储的颜色越丰富,图片越清晰

    C实现代码

    extern "C"
    JNIEXPORT jintArray JNICALL
    Java_com_example_apple_ndkconfig_NdkFilter_getNdkBitmap(JNIEnv *env, jobject /* this */,
                                                               jintArray buffer_, jint width,
                                                               jint height) {
        float brightness = 0.2f;  //亮度
        float contrainst = 0.2f;  //对比度,颜色加深
    
        //图像所有颜色值存储在数组中
        jint* source = env->GetIntArrayElements(buffer_,NULL); 
    
        int a,r,g,b;
        int bab = (int) (255 * brightness);
        float ca = 1.0f + contrainst;
        //改变所有像素点的rgb的值
        int x,y;
        for (x = 0; x < width; x++) {
            for (y = 0; y < height; y++) {
                int color = source[width*y + x];  //获取color值
                a = color >> 24;
                r = color >> 16 & 0xFF;
                g = color >> 8 & 0xFF;
                b = color & 0xFF;
    
                //增加亮度(美白)
                int ri = r + bab;
                int gi = g + bab;
                int bi = b + bab;
    
                //边界检测,argb值都在[0-255]范围内
                r = ri > 255 ? 255 : (ri < 0 ? 0 : ri);
                g = gi > 255 ? 255 : (gi < 0 ? 0 : gi);
                b = bi > 255 ? 255 : (bi < 0 ? 0 : bi);
    
                //扩大对比度,需要白的更白,黑的更黑
                //128以上加强,128以下再减
                ri = r - 128;
                gi = g - 128;
                bi = b - 128;
    
                ri = (int) (ri * ca);
                gi = (int) (gi * ca);
                bi = (int) (bi * ca);
    
                ri += 128;
                gi += 128;
                bi += 128;
    
                //再次边界检测
                r = ri > 255 ? 255 : (ri < 0 ? 0 : ri);
                g = gi > 255 ? 255 : (gi < 0 ? 0 : gi);
                b = bi > 255 ? 255 : (bi < 0 ? 0 : bi);
    
                //result.setPixel(x, y, Color.argb(a, r, g, b));
                //jni的argb合成
                source[width * y + x] = a << 24| r << 16 | g << 8 | b;
            }
        }
    
        //处理原理同java,但是获取数据,对象方式不同
        int newSize = width * height;
        //根据数组长度,将source保存到jintArray,资源释放
        jintArray result = env->NewIntArray(newSize);
        env->SetIntArrayRegion(result,0,newSize,source); 
        env->ReleaseIntArrayElements(buffer_, source, 0);
    
        return result;
    }
    
    a = color >> 24;
    r = color >> 16 & 0xFF; 
    g = color >> 8 & 0xFF;
    b = color & 0xFF;
    

    此处,因为color值是32位的int,argb分别占8位,以r = color >> 16 & 0xFF为例,
    右移16位得到高的16位,再 &0xFF,即过程低八位跟1按位与仍得到原值,所以得到对应的r值

    image.png

    更多NDK开发功能,见我该系列下篇博客吧。

    相关文章

      网友评论

        本文标题:NDK开发系列之——图片亮度、饱和度处理

        本文链接:https://www.haomeiwen.com/subject/ozzbdctx.html