Android 图片Android JNI程序员

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

2017-12-08  本文已影响55人  奔跑吧李博

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开发功能,见我该系列下篇博客吧。

上一篇下一篇

猜你喜欢

热点阅读