近期接触到了图像模糊处理,用了一些办法可以实现但交互效果不好;在Github上找到的,试了一些办法,觉得还是以下方法 比较靠谱,大致分为两种,一种是RenderScript 、一种是国外提供的一种---高斯算法。上代码,来看看
首先来看看android系统自带的图像模糊处理方法,该方法ScriptIntrinsicBlur只支持API17以上,当让也可以通过Renderscript 的support lib降低版本处理,这里不做过多的解释了。使用该方法是需要先调用下View的addOnPreDrawListener方法预加载,
image.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
image.getViewTreeObserver().removeOnPreDrawListener(this);
image.buildDrawingCache();
Bitmap bmp = image.getDrawingCache();
blur(bmp, text);
return true;
}
});
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
private void blur(Bitmap bkg, View view) {
long startMs = System.currentTimeMillis();
float radius = 20;
Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()),
(int) (view.getMeasuredHeight()), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.translate(-view.getLeft(), -view.getTop());
canvas.drawBitmap(bkg, 0, 0, null);
RenderScript rs = RenderScript.create(getActivity());
Allocation overlayAlloc = Allocation.createFromBitmap(rs, overlay);
ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, overlayAlloc.getElement());
blur.setInput(overlayAlloc);
blur.setRadius(radius);
blur.forEach(overlayAlloc);
overlayAlloc.copyTo(overlay);
view.setBackground(new BitmapDrawable(getResources(), overlay));
rs.destroy();
重点说一下 第二中方法,FastBlur其实也就是对图片的像素处理,看看代码,刚开始对这些处理不太理解,找了些资料了解下
private void blur(Bitmap bkg, View view) {
long startMs = System.currentTimeMillis();
float scaleFactor = 1;
float radius = 20;
if (downScale.isChecked()) {
scaleFactor = 8;
radius = 2;
}
}
提供了需要缩小的等级,在代码中我把bitmap的尺寸缩小到原图的1/8。因为这个bitmap在模糊处理时会先被缩小然后再放大,所以在我的模糊算法中就不用radius这个参数了,所以把它设成2
Bitmap overlay = Bitmap.createBitmap((int) (view.getMeasuredWidth()/scaleFactor),
(int) (view.getMeasuredHeight()/scaleFactor), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(overlay);
canvas.translate(-view.getLeft()/scaleFactor, -view.getTop()/scaleFactor);
canvas.scale(1 / scaleFactor, 1 / scaleFactor);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
Paint提供了FILTER_BITMAP_FLAG标示,这样的话在处理bitmap缩放的时候,就可以达到双缓冲的效果,模糊处理的过程就更加顺畅了</span>
canvas.drawBitmap(bkg, 0, 0, paint);
overlay = FastBlur.doBlur(overlay, (int)radius, true);
view.setBackground(new BitmapDrawable(getResources(), overlay))
总结下:Android中渲染一帧的时间应该不超过16ms(60fps),但如果在UI线程中做模糊处理就会让帧率降到了17fps。即便是放到了async中也不会快多少,交互不是很好,
而,FastBlur的原理则是 ,先压缩图片后模糊然后放大图片,这样以来速度得到了很好的提升。
GitHub