安卓项目实战之:基于StackBlur封装的好用的高斯模糊组件

前言

基于 Android StackBlur 开源库做的二次封装。封装的目的在于,方便外部使用。StackBlur开源库只是提供了基础的功能,在实际的开发中,产品的需求是各种各样的,这样就导致每次使用时,都需要自己额外处理很多东西写一些代码。而一旦新的项目又需要接入高斯模糊了,又得重新写相似的逻辑,重复写很多相同的代码,所以在基于传统开源库以及实际项目的通用需求上进行了二次封装,这样需要的时候直接添加依赖即可。

GitHub地址:https://github.com/woshidasusu/base-module/tree/master/blur

高斯模糊的原理简介

首先我们要知道“高斯模糊”是图片模糊处理众多算法中的的一种,它将正态分布(又名”高斯分布”)用于图像处理,本质上是一种“数据平滑技术”,可以应用于多种场合,而图像处理刚好是其在实际应用中的一个完美案例。

所谓”模糊”,可以理解成每一个像素都取以自己为圆心半径为R的周边范围内的所有像素的平均值:
在这里插入图片描述
上图中,2是中间点,周边点都是1。
在这里插入图片描述
“中间点”取”周围点”的平均值,就会变成1。在数值上,这是一种”平滑化”。在图形上,就相当于产生”模糊”效果,”中间点”失去细节。
在这里插入图片描述
显然,计算平均值时,取值范围越大,模糊半径越大,图像就越模糊。从数值角度看,就是数值越平滑。
既然每个点都要取周边像素的平均值,那么应该如何合理分配权重呢?很显然高斯模糊算法采用正态分布作为权重的分配模式。

由此可见高斯模糊是要遍历所有像素点,对每个像素点都重新计算。这自然是一个耗时的工作,所以只有掌握了基本原理,我们要优化时也才有方向去优化。

目前流行的四种高斯模糊方式性能对比

大神的开源库中提供了三种高斯模糊方式,而我在 Blankj 的 AndroidUtilCode 开源库中发现了另外一种,所以我将他们都整合起来,一共有四种:

1,Google 官方提供的 RenderScript 方式 (RSBlur)
2,C 编写的高斯算法 blur.c 方式 (NativeBlur)
3,Java 编写的高斯算法方式1(JavaBlur)
4,Java 编写的高斯算法方式2(StackBlur)

关于四种之间的详细对比结果请查看原作者文章:https://www.jianshu.com/p/6064a14d86a3

高斯模糊的优化

优化点总结为以下三个:
1,选择不同的高斯模糊方式,
2,通过 scale 对原图先缩小,再模糊,最后再放大方式
3,优化高斯模糊算法

最后一点就不考虑了,毕竟难度太大。那么,其实就剩下两种,要么是从高斯模糊的方案上选择,要么从待模糊的图片上做手脚。

虽然有四种高斯模糊方案,但每种都有各自优缺点:
1,RSBlur 在低端机上可能无法兼容,
2,NativeBlur 需要生成对应 CPU 架构的 so 文件支持
3,JavaBlur 和 StackBlur 耗时会较长

优化的考虑点大体上这几种:

大体上,使用 NativeBlur 或者 RSBlur 即可,如果出现一些问题,那么此时可考虑切到 JavaBlur 或 StackBlur 方案,但记得结合 scale 方式优化处理。
如果高斯模糊的图片有实时性要求,要求模糊得同步进行处理,主线程后续的工作需要等待高斯模糊后才能够处理的话,那么尽量选择 scale 方式进行优化,减少耗时。
如果对实时性没要求,但对图片模糊程度有要求,那其实,只要后台异步去进行高斯模糊即可,此时 scale 可不用缩小太多,而利用 radius 来控制模糊效果,以达到理想的要求。
如果两者都有要求,那就自行尝试寻找折中点吧。

最后说一点,因为已经封装成组件库了,RSBlur 也是引入的 support 包,so 文件也打包好了,那么使用这两种方案足够满足绝大部分场景了,所以,没有特意指定,组件默认的方案为 RSBlur。

二次封装针对的项目需求点

要能够对当前页面(Activity)截图后,进行模糊
要能够对 drawable 资源图片进行模糊、或者对指定 View 的视图进行模糊
模糊完成后,要能够自动以淡入的动画方式显示在指定的控件上
存在这种需求场景:对当前界面截图、并且模糊,模糊后的图片展示的时机可能在其他界面,因此需要支持缓存功能,可以根据指定 cacheKey 值获取缓存
当然,可以根据各种配置使用高斯模糊,当不指定配置时,有默认配置

总结一下,其实封装要做的事也就是要实现:

截图、缓存、淡入动画、默认配置
可以的话,组件最好可以达到,其他人在不看文档,不看源码前提下,以最少的成本接入直接上手使用。

如何使用

1,添加依赖

compile 'com.dasu.image:blur:0.0.6'

2,使用很简单直接利用 AndroidStudio 的代码提示功能,你只需要了解组件的入口是 DBlur 即可,至于后续怎么使用,全靠 AndroidStudio 来提示,跟着 AndroidStudio 走就行,如下图:
在这里插入图片描述
当敲完 DBlur. 时,会弹出代码提示框,入口很少就两个,看命名也能猜到作用:getCacheBitmap() 明显是用来取缓存的,那么要高斯模糊自然是另外一个入口 source(),这个方法有多个重载函数,看参数,其实也能知道,这就对应着要模糊的图片的不同来源类型,如:

1,直接传入 Bitmap 对其进行模糊

2,传入 Activity/View,内部会对这个界面/控件进行截图后再模糊

3,传入 resId,对 drawable 资源图片进行模糊

那么,可能想问了,哪里进行高斯模糊配置,哪里设置同步或异步,哪里注册回调等等。别急,既然只给你开了一个入口,那么就跟着入口走下去,自然会一步步引导你走到最后。如:
在这里插入图片描述
第一步、第二步该做什么,我都给你规定好了,你也只能按照步骤一步步来。想要设置高斯模糊配置,你得先指定图片来源,才能进入第二步,在这里,可以进行的配置也都给你列出来了,想要哪个,直接设置即可。

如:

1,mode(),modeRs(),modeNative() 等等类似 mode 开头的方法,用于指定要使用哪种高斯模糊方案,一共四种,每种内部都有提供对应的常量标志,但如果你不知道哪里找,那么直接调用 modeXXX 方法即可。

2,radius() 用于设置高斯模糊计算的半径,内部默认为 4。

3,sampling() 用于设置对原图的缩小比例,内部默认为 8,即默认先缩小 8 倍,再模糊,最后再放大。

4,cache() 用于设置缓存此次模糊后的图片,没有调用默认不缓存。

5,animAlpha() 用于设置使用淡入动画,需要结合 intoTarget() 使用,否则不生效。

6,intoTarget() 用于设置模糊完成后,自动显示到指定控件上。

另外,看每个方法返回的类名,其实这个过程都是在设置配置项,如果有对 Builder 模式了解的话,应该清楚,这个大多用来解决构造函数参数过多的场景,最后一般都会有一个 build() 或者 create() 类型的方法。参考的是 Android 源码中 AlertDialog。

也就是说,要进入下一个步骤,需要调用 build() 方法,如:
在这里插入图片描述
显然,已经到最后一个步骤了,这里就是发起高斯模糊工作的地方了。

1,doBlur() 会指定此次高斯模糊工作异步进行,所以需要注册回调的在这里传入。
2,doBlurSync() 指定高斯模糊同步进行,模糊后的 Bitmap 直接返回。

至此,接入结束。

下面再来看下GitHub上给出的使用的示例代码:

//使用默认配置,最短调用链
Bitmap bitmap = DBlur.source(MainActivity.this).build().doBlurSync();

//同步模糊,将imageView控制的视图进行模糊,完成后自动显示到 imageView1 控件上,以淡入动画方式
DBlur.source(imageView).intoTarget(imageView1).animAlpha().build().doBlurSync();

//异步模糊,将drawable资源文件中的图片以 NATIVE 方式进行模糊,注册回调,完成时手动显示到 imageView1 控件上
DBlur.source(this, R.drawable.background).mode(BlurConfig.MODE_NATIVE).build()
      .doBlur(new OnBlurListener() {
            @Override
            public void onBlurSuccess(Bitmap bitmap) {
                imageView1.setImageBitmap(bitmap);
            }

            @Override
            public void onBlurFailed() {
                //do something
            }});

猜你喜欢

转载自blog.csdn.net/gpf1320253667/article/details/84873222