NDK开发系列之——图片亮度、饱和度处理
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值
更多NDK开发功能,见我该系列下篇博客吧。