Android 上的 高斯歪曲 依我之见

参考文献

  1. [译]
    RenderScript:不难而高速的图像处理
  2. 图片高斯模糊效果不难优化
  3. 高斯模糊效果完结方案及质量比较
  4. Android:不难可信的动态高斯模糊效果
  5. 教您一分钟已毕动态模糊效果
  6. 怎么?IOS的专利?Android也能流利完毕毛玻璃效果(高斯模糊)效果
  7. Android 高斯模糊总括
  8. Android RenderScript
    不难高效落实图片的高斯模糊效果
  9. [干货]一种高效毛玻璃虚化效果落到实处–Android

前言

iOS 7 开始 Apple 从 拟物化 过渡到了 扁平化
的规划风格,同时也烘托使用了 毛玻璃风格
当做背景效果,不得不说至极惊艳,颇有及时pc上 Windows VistaOS X
Yosemite���
的意味,在那未来,谷歌 也从 Android
L(5.0)
初叶运用了 原质化设计(Material Design) 设计语言,与
Microsoft 的 Metro 那种纯扁平化风格类似很相像,但实际上因为引用了
Z轴 的概念,使其有了阴影和立体感,传达了 响应式交互
的设计意见。说到这边有部分跑题,因为小编对规划美学很感兴趣,所以对那个平台都有点明白一些皮毛。今日就来探究一下怎么在
Android 上已毕高斯模糊效果。

总结

如上就是何许用 法斯特Blur 和 RenderScript 在 Android 上落实和 iOS
一样的高斯模糊效果的简要介绍,就算在质量上不用置疑是 RenderScript
上最好,可是在有的用到处境上 法斯特Blur
耗时会更短,所以大家各取所需,依据实际需求去挑选使用。

贯彻高斯模糊

  • 将主题完成方式 ScriptIntrinsicBlur 封装成工具类。

import android.support.v8.renderscript.*;  // 需要导入v8包,否则无法向下兼容

public class BlurBitmapUtil {

    /***
     * 图片缩放比例 (例如 1/10)
     */
    private static int scaleRatio = 10;

    /**
     * 对图片进行高斯模糊
     *
     * @param context    上下文对象
     * @param image      需要模糊的图片
     * @param blurRadius 模糊半径,由于性能限制,这个值的取值区间为(0至25f)
     * @return 模糊处理后的图片
     */
    public static Bitmap blurBitmap(Context context, Bitmap image, @FloatRange(from = 1, to = 25)
            float blurRadius) {
        // 计算图片缩小后的长宽
        int width = Math.round(image.getWidth() / scaleRatio);
        int height = Math.round(image.getHeight() / scaleRatio);

        // 创建一张缩小后的图片做为渲染的图片
        Bitmap bitmap = Bitmap.createScaledBitmap(image, width, height, false);

        // 创建RenderScript内核对象
        RenderScript rs = RenderScript.create(context);
        // 创建一个模糊效果的RenderScript的工具对象,第二个参数Element相当于一种像素处理的算法,高斯模糊的话用这个就好
        ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

        // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间
        // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去
        Allocation input = Allocation.createFromBitmap(rs, bitmap);
        // 创建相同类型的Allocation对象用来输出
        Type type = input.getType();
        Allocation output = Allocation.createTyped(rs, type);

        // 设置渲染的模糊程度, 25f是最大模糊度
        blurScript.setRadius(blurRadius);
        // 设置blurScript对象的输入内存
        blurScript.setInput(input);
        // 将输出数据保存到输出内存中
        blurScript.forEach(output);
        // 将数据填充到bitmap中
        output.copyTo(bitmap);

        // 销毁它们释放内存
        input.destroy();
        output.destroy();
        blurScript.destroy();
        rs.destroy();
        type.destroy();

        return bitmap;
    }

接纳 RenderScript 增添虚化程度的措施和 法斯特Blur 一样,有二种方法:

  • 外加scaleRatio缩放比,使用更小的bitmap去虚化可以取得更好的模糊效果,而且便于占用内存的回落;

  • 增大blurRadius,可以博得更高水准的虚化,但是会导致虚化时间变长

但因为 RenderScript 的天生优势(低级语言, 运行时机器再一次优化编译,
可以平衡的周转在四个CPU 和
GPU上),所以那里笔者通过增大虚化程度来尝试,缩放比例为
1/10,实际使用时可以根据需要在对虚化程度和缩放比例上选取一个适宜的数值。

  • blurRadius = 5

图片 1

  • blurRadius = 15

图片 2

  • blurRadius = 25

图片 3

由此地点比较图大家可以找出最符合自己的虚化效果。

近日来看,为什么 谷歌(Google) 设置那些25的限定, 原因应该有两个 :

  1. 半径当先25的话耗时就变成了一个瓶颈;
  2. 如若想已毕超越25的混淆效果,可以经过压缩原图,模糊,再推广来达到平等的成效

ReScale

public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) {}

我们可以运用Bitmap的 createScaledBitmap()
方法来展开bitmap的缩放。其中前五个参数很强烈,其中宽高大家得以选择为原图尺寸的1/5;第八个filter是指缩放的效益,filter为true则会赢得一个边缘平滑的bitmap,反之,则会获取边缘锯齿、pixelrelated的bitmap。那里大家要对缩放的图片展开虚化,所以无所谓边缘效果,filter=false。

于是,大家要使用

int scaleRatio = 5;// 缩放比例 此处代表1/5
int blurRadius = 8;// 虚化程度
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originBitmap,
    originBitmap.getWidth() / scaleRatio,
    originBitmap.getHeight() / scaleRatio,
    false);
Bitmap blurBitmap = FastBlur.doBlur(scaledBitmap, blurRadius, true);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageBitmap(blurBitmap);

可以赢得如下效果:

图片 4

图形地址

从图中可以看来,首先可以确定思路是对的;然后,可以见见毛玻璃效果还不是特意的斐然。为了取得如iOS那样的虚化效果,大家有三种方法:

  • 叠加scaleRatio缩放比,使用更小的bitmap去虚化可以取得更好的混淆效果,而且便于占用内存的削减;
  • 增大blurRadius,可以赢得更高水准的虚化,可是会招致CPU尤其intensive

此间作者通过增大缩放比来实验。

  • scaleRatio = 10

图片 5

图表地址

  • scaleRatio = 20

图片 6

图形地址

因而上边相比较图我们可以找出最符合自己的虚化效果。

另一种可能

地点说的2种缓解方案都是从品质和频率出发的产物,但只要自身的须求就是从网络上加载一张图片(比如头像),然后再高斯模糊化当背景,走四次转换成bitma再将其转换成高斯模糊的流水线可能会有一点点烦劳,那里我再提供一种简易便捷的解决方案
—— 基于Glid加载框架去贯彻一键 加载网络图片→高斯模糊化→显示

引入包容包

方式很粗略,只需在build.gradle中进入:

defaultConfig {
        ....
        // 就是这么简单
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }

除此以外由于有的厂商会深度定制Android系统,所以部分必不可少的借助文件会被他们向来去掉,那致使有的型号的设备上调用RenderScriptd的有的方法时会报错。境遇那种包容难点的话,需求丰盛那一个恐怕有失的公文。
实质上也大致,打开android_sdk/build-tools/选择19以上版本/renderscript/lib/packaged咱俩得以望见3个包蕴.so文件的文件夹。

图片 7

so文件

一贯复制那多少个公文加到项目工程的 jniLibs 包下,没有的话去建一个。

图片 8

jniLibs文件夹

设若首次创制 jniLibs 文件夹,还亟需在 build.gradle 的 android{}
中加入:

sourceSets {
        main {
            jniLibs.srcDirs = ['jniLibs']
        }
    }

针对利用的歪曲的同室,须求在混淆中进入:

-keep class android.support.v8.renderscript.** { *; }

Code

连锁代码已上传至Github:BlurView,欢迎Star,Fork。

眼下 Android 上达成高斯模糊效果的章程有:

  • Java :
    FastBlur.java
    ,应用非凡广泛的
    StackBlur
    模糊算法已毕代码,功效最低

  • C++ :二种达成,1:标准高斯模糊算法
    2:均值模糊,效能中等

  • Android :
    RenderScript
    ,用来在 Android
    上编制高质量代码的一种语言(使用C99标准,运行时机器再一次优化编译,
    可以平衡的运行在五个CPU 和
    GPU上,有一个半径范围小于25的限制),成效最高

引入包容包

先是在build.gradle中投入图片框架需求的库和图表工具库:

defaultConfig {
        ....
        compile 'com.yutianran.maven:super-adapter:1.0.0'
        compile 'jp.wasabeef:glide-transformations:2.0.2'
}

再来聊聊 RenderScript

RenderScript 主要 在Android中的对图纸举办处理,RenderScript
选用C99语法举办编辑,首要优势在于品质较高。在 API 11 的时候被投入到
Android
中。同时,谷歌提供了android.support.v8.renderscript协作包,可以落到实处更低版本的非凡。

RenderScript 提供了一个用于落到实处高斯模糊的封装类 ScriptIntrinsicBlur
,因为在 API 17 后才正式适配到 Android
,所以在不利用至极包的景况下只好合营到4.2的设施。不过,我们有格外包啊向下包容不是梦。

准备阶段

概括聊聊 法斯特Blur

因为效益的贯彻是基于 Java 的,所以有必不可少先来打听一下方法怎么着行使。

public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap)

可以看出,使用办法极度不难,传入待虚化的bitmap、虚化程度(一般为8)、是还是不是重用flag,最终回来模糊后的bitmap。

但即使直白把一张大图传入进行虚化,很不难就会爆发OOM内存溢出,这就表示自己只可以虚化小图,那样才能防患内存溢出。可是我并不想换别的图,那么,大家就应有把这张图减少。

毕生大家对图片减弱,必然会拉动很肯定的清晰度的损失,但高斯模糊本身的目标就是要达成模糊的功效,由此实际的功力差距不大,差不离可以忽略。

并且鉴于图片裁减后再举行模糊处理,须求处理的像素点和半径都变小,从而使得模糊处理速度加速。

然后就开写,一行代码即可

Glide.with(this).load(url).bitmapTransform(new BlurTransformation(this,25)).into(imageView);

急需的参数很分别是

  • 上下文对象
  • 图片url
  • 上下文对象,虚化数值
  • imageView控件

图片 9

功用如上,可以看出
glide-transformations
库的虚化效果也是相当没错的,但对图纸本身做的缩放应该不是过多,所以在加载速度上会弱于
法斯特Blur 和 RenderScript ,但作为轻量级图片而言丰硕了。