ColorMatrix滤镜处理
方法很简单,直接新建一个bitmap去操作即可
public static Bitmap opencv(Bitmap bitmap){
Bitmap dst= Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(),bitmap.getConfig());
Canvas canvas=new Canvas(dst);
Paint paint=new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
ColorMatrix colorMatrix=new ColorMatrix();
//饱和 0->灰度图
colorMatrix.setSaturation(0);
paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
canvas.drawBitmap(bitmap,0,0,paint);
return dst;
}
效果图(第一张是原图,第二张是效果图)
![](https://img.haomeiwen.com/i9387746/10c29b5c880ff92a.png)
矩阵乘法运算
参考百科:https://baike.sogou.com/v7527881.htm?fromTitle=%E7%9F%A9%E9%99%A3%E4%B9%98%E6%B3%95
![](https://img.haomeiwen.com/i9387746/1f95ac0da2ced5e7.png)
setSaturation源码分析
public void setSaturation(float sat) {
reset();
float[] m = mArray;
final float invSat = 1 - sat;
final float R = 0.213f * invSat;
final float G = 0.715f * invSat;
final float B = 0.072f * invSat;
m[0] = R + sat; m[1] = G; m[2] = B;
m[5] = R; m[6] = G + sat; m[7] = B;
m[10] = R; m[11] = G; m[12] = B + sat;
}
reset源码中我们可以看注释
![](https://img.haomeiwen.com/i9387746/5daa5395ede25c1c.png)
[ 1 0 0 0 0 - red vector
0 1 0 0 0 - green vector
0 0 1 0 0 - blue vector
0 0 0 1 0 ] - alpha vector
我们可以看到这个矩阵实际代表的是原图,回到setSaturation的源码,刚才我们传的值是0,所以我们把相关值,带进去之后会发现,灰图矩阵实际是
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
0.213f,0.715f,0.072f,0,0,
0.213f,0.715f,0.072f,0,0,
0.213f,0.715f,0.072f,0,0,
0,0,0,1,0,
});
扩展
- 底片效果
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
-1,0,0,0,255,
0,-1,0,0,255,
0,0,-1,0,255,
0,0,0,1,0,
});
总结:适合做色彩滤镜,但是无法做高斯模糊
Java Bitmap获取像素操作
public static Bitmap gary(Bitmap bitmap) {
Bitmap dst = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
//java层像素操作
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
//第二个参数偏移量
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
for (int i = 0; i < pixels.length; i++) {
int pixel = pixels[I];
int a = (pixel >> 24) & 0xff;
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = pixel & 0xff;
// f=.0.213f*r+0.715f*g+0.072f*b;
//灰度
//int gery = (int) (0.213f * r + 0.715f * g + 0.072f * b);
//黑白
int gery = (a + r + g) / 3 > 125 ? 125 : 0;
pixels[i] = (a << 24) | (gery << 16) | (gery << 8) | gery;
}
dst.setPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
return dst;
}
Native层像素操作
ava_com_peakmain_mall_ndk_MainActivity_gray(JNIEnv *env, jobject instance,
jobject bitmap) {
AndroidBitmapInfo info;
int res = AndroidBitmap_getInfo(env, bitmap, &info);
if (res != 0) {
return -1;
}
void *addrPtr;
AndroidBitmap_lockPixels(env, bitmap, &addrPtr);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
for (int i = 0; i < info.width * info.height; ++i) {
//+i移动指针
uint32_t *pixel_p = reinterpret_cast<uint32_t *>(addrPtr) + I;
uint32_t pixel = *pixel_p;
int a = (pixel >> 24) & 0xff;
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = pixel & 0xff;
// f = 0.213f * r + 0.715f * g + 0.072f * b
int gery = (int) (0.213f * r + 0.715f * g + 0.072f * b);
//重新设置回去
*pixel_p = (a << 24) | (gery << 16) | (gery << 8) | gery;
}
} else if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
for (int i = 0; i < info.width * info.height; ++i) {
uint16_t *pixel_p = reinterpret_cast<uint16_t *>(addrPtr) + I;
uint16_t pixel = *pixel_p;
//5 0001 1111->1f
//6 0011 1111->3f
int r = ((pixel >> 11) & 0x1f) << 3;//8->5
int g = ((pixel >> 5) & 0x3f) << 2;//8->6
int b = (pixel & 0x1f) << 3;//8->5
// f = 0.213f * r + 0.715f * g + 0.072f * b
int gery = (int) (0.213f * r + 0.715f * g + 0.072f * b);
//重新设置回去
*pixel_p = ((gery >> 3) << 11) | ((gery >> 2) << 5) | (gery >> 3);
}
}
AndroidBitmap_unlockPixels(env, bitmap);
return 1;
}
MainActivity层调用
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
//最好的是ARGB8888 32位
options.inPreferredConfig = Bitmap.Config.RGB_565;
// RGB_565比ARGB_8888小1 倍
// ARGB_8888 -> RGB 565 RGB 5位R 6位G 5位B 565是16位
Bitmap src = BitmapFactory.decodeResource(getResources(), R.mipmap.copy, options);
gray(src);
ImageView imageView2 = findViewById(R.id.image_2);
imageView2.setImageBitmap(src);
}
public native int gray(Bitmap bitmap);
效果图
![](https://img.haomeiwen.com/i9387746/019122dd0c106472.png)
网友评论