技术调研,可以给一些优缺点的对比.,目前主流实现毛玻璃效果(高斯模糊)分大致三种方法:
一 利用RenderScript接口
利用现有Android结构,通过RenderScript调用底层接口实现高斯模糊计算.
// Remix Blur
private void blur(Bitmap bkg, View view) {
…
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();
}
说明 :
这种方法直接利用Android系统提供的机制, 从代码实现上是最简单也相对高效的实现. 在此过程中遇到的很现实的问题是: 1. 当模糊半径 (radius)变大后会直接出现计算性能问题. 2. ScriptIntrinsicBlur脚本模糊半径不能大于25. 因此, 直接使用ScriptIntrinsicBlur不能得到模糊程度较高的图片.
考虑到高斯模糊是计算周边像素平均值,在模糊程度很高的情况下,逐点计算平均值从显示效果上优势并不明显.可以通过将图片压缩成小图,计算小图的高斯模糊, 再将小图放大的方法来模拟大半径高斯模糊的效果.
二 在低版本Android中通过Java实现高斯模糊
可以参考如下代码实现
/paveldudka/blurring/blob/master/app/src/main/java/com/paveldudka/util/FastBlur.java
这种方式通过在Java层中直接实现高斯模糊算法.在大模糊半径和大图片情况下,性能会出现问题.基本目前只作为对低版本Android客户端的兼容性方案使用.
三 通过OpenGL直接实现
没有具体实践过, 可以参考muzei壁纸的实现, 无论从效果和实时性来讲都是最好的. 但需要根据需求来看是否真的有这样的实时性要求. 这种方式从显示效果上会优于第一种方法,甚至可以达到渐变的效果.但这些计算都是以耗电作为代价的. 作为Launcher这种系统级别的应用, 在显示效果差异并不明显的情况下, 建议综合考虑耗电量, 以及内存和计算性能的消耗. 》
其中一个关键技巧是: 先压缩原图大小再高斯. 这样能够大大减少高斯计算量, 提高性能.
Android StackBlur 图片模糊效果工具类
这个问题要分两部分来看。
第一是
模糊算法,主要目前有两种方案:
(1)借助Renderscript做高斯模糊,这个本质上是做了个卷积计算。
(2)用jni实现StackBlur 算法对图片进行模糊处理,这个可以看下源码,相较于高斯模糊,计算量小了很多。
两种方案都可以进行对Bitmap对象的模糊处理,但当模糊半径增大时,StackBlur能够保持较好的性能,且不受Renderscript半径25px的限制。这两种方案都可以通过对原图进行压缩采样方式优化。至于模糊结果,可以看实际效果,个人认为均可满足需求。
第二是
使用场景,同样分为两种:
(1)非实时处理:比如说用做背景虚化,这种场合下对性能要求不是太苛刻,只要保证在非主线程处理好图片,之后填充即可。上面两种方案都可满足需求。
下面是stackblur的一个android实现
/kikoso/android-stackblur
(2)实时处理:比如说需要在滚动的ListView或者ScrollView上添加毛玻璃遮罩。由于待虚化的Bitmap不是固定不变的,这就需要我们逐帧处理。这个时候半径如果大的话,Renderscript会出现明显的卡顿,而StackBlur方案在中高端机器上会有不错的表现。
下面是一个比较好的开源的android实现,使用起来比较简单
/harism/android_anndblur
其原理是自定义容器控件,通过重绘的方式获取自身原本要绘制的bitmap纹理,然后实时处理并填充到自身的背景中,能保证基本的流畅度。注意会除了模糊处理,还会引发多余的绘制操作。铁定会拖慢UI的流畅度。
对于实时毛玻璃效果,建议还是多做测试,毕竟耗费计算资源,甚至可以监控fps设置阈值对特效进行开关。
给一个图片,质量压缩到很小,然后方大,然后对这个图片进行blur,blur网上有很多方法,都可以用。压缩到很小后,放大然后blur,速度非常快。