Android利用RenderScript实现毛玻璃模糊效果示例

RenderScript 介绍

在开始之前,先看下 RenderScript 的官方介绍

RenderScript is a framework for running computationally intensive tasks at high performance on Android. RenderScript is primarily oriented for use with data-parallel computation, although serial workloads can benefit as well. The RenderScript runtime parallelizes work across processors available on a device, such as multi-core CPUs and GPUs. This allows you to focus on expressing algorithms rather than scheduling work. RenderScript is especially useful for applications performing image processing, computational photography, or computer vision.

大致意思就是说 RenderScript 是 Android 平台上为了计算密集型任务的一中高性能框架,并且RenderScript 尤其对图像的处理特别有用。另外,RenderScript 之所以效率高是因为其底层是 C 实现的。

使用 RenderScript Support Library

为了可以兼容到更早的版本,我们直接使用 android.support.v8.renderscript(支持API level 9+)包下的,而不使用android.renderscript(支持API level 11+)

以 Android Studio 为例,打开你的 app 的 build.gradle 文件,在 android 的 defaultConfig 结点添加两句:

renderscriptTargetApi 18
renderscriptSupportModeEnabled true

其中 renderscriptTargetApi 的值官方说的是从 11 到最新的 API Level 都可以

这样我们等下导包就可以导 v8 内的了。

模糊背景

局部模糊

先上一张我们要实现的效果图:

这里可以看到实现的是局部模糊,在图片的正中间有一个 TextView,TextView 的背景部分做了模糊处理。

先大致说下模糊的主要步骤(完全模糊步骤一样):

  1. 首先取出 TextView 在 ImageView 正上方处的那一块背景
  2. 然后对取出的那一块背景做模糊处理
  3. 最后把模糊处理后的背景再设为 TextView 的背景

这样,就可以达到我们图片中的局部模糊效果,具体的过程在代码中有详细的注释。

下面先贴上布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:padding="20dp">

 <FrameLayout
  android:layout_width="300dp"
  android:layout_height="300dp"
  android:layout_centerInParent="true">

  <ImageView
   android:id="@+id/image"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:scaleType="centerCrop"
   android:src="@drawable/img"/>

  <TextView
   android:id="@+id/text"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center"
   android:text="Melody"
   android:textColor="@android:color/white"
   android:textSize="45sp"/>

 </FrameLayout>

</RelativeLayout>

再贴上java代码:

public class MainActivity extends Activity implements Runnable {

 private static final String TAG = "MainActivity";

 private ImageView mImage;
 private TextView mText;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  mImage = (ImageView) findViewById(R.id.image);
  mText = (TextView) findViewById(R.id.text);
  // onCreate()内无法到ImageView的背景,所以需要 post 到消息队列内稍后执行
  mImage.post(this);
 }

 @Override
 public void run() {
  blur(getImageViewBitmap(mImage), mText);
 }

 /**
  * 取出一个imageView的bitmap背景
  */
 public Bitmap getImageViewBitmap(ImageView imageView) {
  imageView.setDrawingCacheEnabled(true);
  // 取出ImageView的Bitmap
  Bitmap bitmap = imageView.getDrawingCache();
  // 拷贝一份bitmap用作模糊
  Bitmap bitmapCopy = bitmap.copy(bitmap.getConfig(), true);
  imageView.setDrawingCacheEnabled(false);
  return bitmapCopy;
 }

 /**
  * 模糊的具体实现
  *
  * @param inputBitmap 要模糊的 bitmap
  * @param targetView 需要被模糊背景的 View
  */
 public void blur(Bitmap inputBitmap, View targetView) {
  // 创建一个和目标View(需要背景被模糊的View)宽高一样的空的 outputBitmap
  Bitmap outputBitmap = Bitmap.createBitmap((int) (targetView.getMeasuredWidth()),
    (int) (targetView.getMeasuredHeight()), Bitmap.Config.ARGB_8888);
  // 将 outputBitmap 关联在 canvas 上
  Canvas canvas = new Canvas(outputBitmap);
  // 画布移动到目标 View 在父布局中的位置
  canvas.translate(-targetView.getLeft(), -targetView.getTop());
  Paint paint = new Paint();
  paint.setFlags(Paint.FILTER_BITMAP_FLAG);
  // 将要模糊的 inputBitmap 绘制到 outputBitmap 上
  // 因为刚才做了 translate 操作,这样就可以裁剪到目标 View 在父布局内的那一块背景到 outputBitmap 上
  canvas.drawBitmap(inputBitmap, 0, 0, paint);

  // ----接下来做模糊 outputBitmap 处理操作----

  // 创建 RenderScript
  RenderScript rs = RenderScript.create(this);
  Allocation input = Allocation.createFromBitmap(rs, outputBitmap);
  Allocation output = Allocation.createTyped(rs, input.getType());
  // 使用 ScriptIntrinsicBlur 类来模糊图片
  ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(
    rs, Element.U8_4(rs));
  // 设置模糊半径 ( 取值范围为( 0.0f , 25f ] ,半径越大,模糊效果也越大)
  blur.setRadius(25f);
  blur.setInput(input);
  // 模糊计算
  blur.forEach(output);
  // 模糊 outputBitmap
  output.copyTo(outputBitmap);
  // 将模糊后的 outputBitmap 设为目标 View 的背景
  targetView.setBackground(new BitmapDrawable(getResources(), outputBitmap));
  rs.destroy();
 }

}

导的是 v8 的包:

import android.support.v8.renderscript.Allocation;
import android.support.v8.renderscript.Element;
import android.support.v8.renderscript.RenderScript;
import android.support.v8.renderscript.ScriptIntrinsicBlur;

完全模糊

上面是局部模糊,然后我们改变一下 TextView 的宽高铺满父布局,使其和 ImageView 大小一样来实现完全模糊效果:

...
<TextView
 android:id="@+id/text"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center"
 android:text="Melody"
 android:textColor="@android:color/white"
 android:textSize="45sp"/>
...

java代码部分不需要改变,下面再看效果图:

效率如何?

为了查看操作耗时,我使用 Log 在 blur() 方法的开头和结束地方分别计算了时间,然后查看时间差:

10-09 17:04:23.664 23665-23665/com.melodyxxx.blurdemo2 E/MainActivity: spend: 120ms

可以看到居然花了 120ms,显然效率不够高,有没有优化的方法?(测试机型为 魅族 PRO 6)

效率优化

上面的是直接将原 ImageView 的 bitmap 直接模糊处理,效率不够高,所以我们可以先将原图片进行压缩处理,然后在进行模糊,下面为关键代码,scaleFactor 为压缩比例大小,例如 scaleFactor 为 2,代表先将原图压缩为原来的 1/2,然后进行模糊,效率会高很多。

...
Bitmap outputBitmap = Bitmap.createBitmap((int) (mTargetView.getMeasuredWidth() / scaleFactor),
  (int) (mTargetView.getMeasuredHeight() / scaleFactor), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(outputBitmap);
canvas.translate(-mTargetView.getLeft() / scaleFactor, -mTargetView.getTop() / scaleFactor);
canvas.scale(1 / scaleFactor, 1 / scaleFactor);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(mInputBitmap, 0, 0, paint);
...

下面是 Demo 效果图:

结果:

压缩比例为 2 时:耗时 19 ms

压缩比例为 8 时:耗时 2 ms

根据压缩比例配合不同的模糊半径可以达到不同模糊效果。

再来看 Demo 效果图中拖动 SeekBar 可以动态的实现模糊效果,首先想到的方法是每次拖动时实时计算模糊,这样的效率肯定不行,还会造成卡顿,我这里的方法是先将图片最大化模糊一次设给上方 ImageView 的背景即可,然后 SeekBar 拖动时,只需要改变最上方或者下方图片的透明度就可以达到上面的效果。

Demo apk 下载:http://fir.im/snmb

Demo 地址:点击这里

总结

除了 RenderScript 以外还有一些其他的方法也可以实现高斯模糊,例如 FastBlur 等,在模糊的时候不要将原图直接模糊处理,可采取先缩放然后再模糊,这样可以大大提高模糊的速度。好了,以上就是这篇文章的全部内容了,希望本文的内容对各位开发者能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android 高仿微信语音聊天页面高斯模糊(毛玻璃效果)

    目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高斯模糊,并把它作为整个页面的背景色. 关于Android如何快速实现高斯模糊(毛玻璃效果),网上一堆相关介绍,可参考下面文章一种快速毛玻璃虚化效果实现–Android. 下面直接给出模糊化工具类(已验证可行): import android.graphics.Bitmap; /** * 快速模糊化工

  • Android RenderScript实现高斯模糊

    昨天看了下RenderScript的官方文档,发现RenderScript这厮有点牛逼.无意中发现ScriptIntrinsic这个抽象类,有些很有用的子类.其中有个子类叫ScriptIntrinsicBlur类,大致就是将图片实现高斯模糊. ScriptIntrinsic的申明: ScriptIntrinsicBlur类的申明: 加上结合着看了下SDK中的samples,自己写了个高斯模糊. ( sample的具体位置为: SDK目录/samples/android-19/renderscri

  • Android 实现图片模糊、高斯模糊、毛玻璃效果的三种方法

    在前几天写过一个使用glide-transformations的方法实现高斯模糊的方法,今天偶然间有发现一个大神写的另一个方法,感觉挺不错的,分享一下: 效果图: 原文链接:点击访问 这使用也很简单,导入依赖,使用模糊方法就行,就这两步搞定 依赖: compile 'net.qiujuer.genius:blur:2.0.0-beta4' 实现方法有三种,第一个是Java实现的,第二个和第三个是调用C语言实现的 ,具体的区别也就是代码执行的耗时操作时间,从图片中可以看出Java使用时间远大于c运

  • Android RenderScript高斯模糊

    看代码的时候,看到了其中有.rs结尾的文件,不是很明白,还有RenderScript类,看的一脸蒙蔽,不知所云,然后百度了一下,收货还真不少,这东西在图形处理这块用处挺大的. 今天先说说ScriptIntrinsicBlur,这个类不需要定义rs文件,从这个Intrinsic单词可以看的出来,它是API17以后内置的类,专门用来处理图像的,让图片变模糊. public static Bitmap blurBitmap(Bitmap bitmap, float radius, Context co

  • Android学习教程之图片毛玻璃效果(4)

    本教程为大家分享了Android毛玻璃效果的具体代码,供大家参考,具体内容如下 BlurimageActivity.java代码: package com.siso.crazyworld; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.support.v7.app.AppCompatActivit

  • Android模糊处理简单实现毛玻璃效果

    自从iOS系统引入了Blur效果,也就是所谓的毛玻璃.模糊化效果.磨砂效果,各大系统就开始竞相模仿,这是怎样的一个效果呢,我们先来看一下,如下面的图片: 实现效果大家都知道了,如何在Android中实现呢,说白了就是对图片进行模糊化处理,小编先给大家讲一下Android高级模糊技术的原理,如下: 首先我创建了一个空的bitmap,把背景的一部分复制进去,之后我会对这个bitmap进行模糊处理并设置为TextView的背景. 通过这个bitmap保存Canvas的状态: 在父布局文件中把Canva

  • Android中实现毛玻璃效果的3种方法

    最近在做一款叫叽叽的App(男银懂的),其中有一个功能需要对图片处理实现毛玻璃的特效 进过一番预研,找到了3中实现方案,其中各有优缺点: 1.如果系统的api在16以上,可以使用系统提供的方法直接处理图片 复制代码 代码如下: if (VERSION.SDK_INT > 16) {             Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); final RenderScript rs = RenderScr

  • Android模糊处理实现图片毛玻璃效果

    本文实例讲解了Android 虚化图片.模糊图片.图片毛玻璃效果的实现方法,具体内容如下 效果如图: 在Android可以用RenderScript方便的实现这个方法: private void blur(Bitmap bkg, View view, float radius) { Bitmap overlay = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8

  • Android开发之毛玻璃效果实例代码

    这是在网上找的,不过忘了在哪里找的,经过很多比较测试,发现这个方法不会 oom,目前来看 我一直没有遇过,今天才找到这个以前建立的工程,记录下来: 先给大家展示下效果图: public class FastBlur { public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) { // This is a compromise between Gaussian Blur and Box

  • Android利用RenderScript实现毛玻璃模糊效果示例

    RenderScript 介绍 在开始之前,先看下 RenderScript 的官方介绍: RenderScript is a framework for running computationally intensive tasks at high performance on Android. RenderScript is primarily oriented for use with data-parallel computation, although serial workloads

  • Android实现动态高斯模糊效果示例代码

     写在前面 现在,越来越多的App里面使用了模糊效果,这种模糊效果称之为高斯模糊.大家都知道,在Android平台上进行模糊渲染是一个相当耗CPU也相当耗时的操作,一旦处理不好,卡顿是在所难免的.一般来说,考虑到效率,渲染一张图片最好的方法是使用OpenGL,其次是使用C++/C,使用Java代码是效率是最低,速度也是最慢的.但是Android推出RenderScript之后,我们就有了选择,测试表明,使用RederScript的渲染效率和使用C++/C不相上下,但是使用RenderScript

  • Android 利用三阶贝塞尔曲线绘制运动轨迹的示例

    本篇文章主要介绍了Android 利用三阶贝塞尔曲线绘制运动轨迹的示例,分享给大家,具体如下: 实现点赞效果,自定义起始点以及运动轨迹 效果图: xml布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rl_root&

  • Android利用贝塞尔曲线绘制动画的示例代码

    目录 彩虹系列 弹簧动画 复杂立体感动画 总结 前面我们花了几篇介绍了贝塞尔曲线的原理和绘制贝塞尔曲线,着实让我们见识到了贝塞尔曲线的美.好奇心驱使我想看看贝塞尔曲线动起来会是什么样?本篇就借由动画驱动贝塞尔曲线绘制看看动起来的贝塞尔曲线什么效果. 彩虹系列 通过动画控制绘制的结束点,就可以让贝塞尔曲线动起来.例如下面的动图展示的效果,看起来像搭了一个滑滑梯一样.实际上就是用7条贝塞尔曲线实现的,我们使用了 Animation 对象的值来控制绘制的结束点,从而实现了对应的动画效果. 具体源码如下

  • Android利用Flutter path绘制粽子的示例代码

    目录 前言 绘制 基本轮廓 粽叶 嘴巴 眼睛 腮红 手&脚 头巾 咸甜是一家 发声 动画控制嘴巴开合 用到的技术点 总结 前言 大家好,端午将至,首先提前祝小伙伴端午安康,端午作为中华民族的非常重要的传统节日,粽子那是必不可少的,但是你真的知道粽子的历史吗? 今天跟随本篇文章用Flutter path画一个会科普节日的的粽子吧- 绘制 基本轮廓 首先我们需要将粽子的基本轮廓绘制出来,通过图片可以看到粽子的轮廓是一个圆圆的三角形状, 本篇文章所有的图形都是用纯Path路径制作,这里我们可以将粽子的

  • Android 给图片加上水印的示例代码(支持logo+文字)

    本文介绍了Android 给图片加上水印的示例代码(支持logo+文字),分享给大家,具体如下: 现在我们想要往图片上打上水印,该水印应符合这样的需求的: 支持logo+文字: 文字信息支持多行展示: 用户可以选择水印在图片上的生成位置(左上.右上.右下和左下). 粗略的结构图低配版大概就长这样... 水印结构图.png 现在提供这样的一种思路去实现这一个需求,我们可以通过自定义一个view,view的布局中包含logo.公司名称和相关信息,这个view就是我们要打上图片的水印. 这样的一个vi

  • Android编程之View简单学习示例

    本文实例讲述了Android编程之View简单学习示例.分享给大家供大家参考,具体如下: View,是Android的一个超类,这个类几乎包含了所有的屏幕类型.每一个View都有一个用于绘图的画布,这个画布可以进行任意扩展. 在游戏开发中叶可以自定义视图(View),这个画布的功能更能满足我们在游戏开发中的需要.在Android中,任何一个View类都只需重写onDraw 方法来实现界面显示,自定义的视图可以是复杂的3D实现,也可以是非常简单的文本形式等. 游戏的核心是不断地绘图和刷新界面,An

  • Android 图片Bitmap的剪切的示例代码

    一.什么是Android中的Bitmap Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件. 二.Bitmap的剪切基本操作 复制代码 代码如下: public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) 从原始位图剪切图像,这是一种高

  • Android利用Dom对XML进行增删改查操作详解

    1. 概述 平常我们一般是使用JSON与服务器做数据通信,JSON的话,直接用GSON或者其他库去解析很简单.但是,其他有些服务器会返回XML格式的文件,这时候就需要去读取XML文件了. XML的解析有三种方式,在Android中提供了三种解析XML的方式:DOM(Document Objrect Model) , SAX(Simple API XML) ,以及Android推荐的Pull解析方式,他们也各有弊端,而这里来看看使用DOM的方式. 2. Dom解析 DOM解析器在解析XML文档时,

  • Android利用滑动菜单框架实现滑动菜单效果

    之前我向大家介绍了史上最简单的滑动菜单的实现方式,相信大家都还记得.如果忘记了其中的实现原理或者还没看过的朋友,请先去看一遍之前的文章Android仿人人客户端滑动菜单的侧滑特效实现代码,史上最简单的侧滑实现 ,因为我们今天要实现的滑动菜单框架也是基于同样的原理的. 之前的文章中在最后也提到了,如果是你的应用程序中有很多个Activity都需要加入滑动菜单的功能,那么每个Activity都要写上百行的代码才能实现效果,再简单的滑动菜单实现方案也没用.因此我们今天要实现一个滑动菜单的框架,然后在任

随机推荐