Android动态模糊效果的快速实现方法
写在前面
现在,越来越多的app里面使用了模糊效果,这种模糊效果称之为高斯模糊。大家都知道,在android平台上进行模糊渲染是一个相当耗cpu也相当耗时的操作,一旦处理不好,卡顿是在所难免的。一般来说,考虑到效率,渲染一张图片最好的方法是使用opengl,其次是使用c++/c,使用java代码是效率是最低,速度也是最慢的。但是android推出renderscript之后,我们就有了选择,测试表明,使用rederscript的渲染效率和使用c++/c不相上下,但是使用renderscript却比使用jni简单得多!同时,android团队提供了renderscript的支持库,使得在低版本的android平台上也能使用。
不过在使用renderscript之前,对于模糊一张图片,需要注意的是,我们应该尽量不要使用原尺寸分辨率的图片,最好将图片缩小比例,这小渲染的效率要高一些,速度也更快一些。
什么是renderscript
renderscript是一种低级的高性能编程语言,用于3d渲染和处理密集型计算(3d播放等和关于cpu密集型的计算)。一直以来android 在绘图性能的表现一直差强人意,引入ndk之后才有所改善,而在honeycomb 中发布了renderscript 这一杀手级在framework 后,大大的增加了android本地语言的执行能力和计算能力。现在网上介绍renderscript的文章非常少,附上一篇博客,大家可以能更好理解这门语言。
关于android renderscript 的详细说明和一些实用文档
如果需要详细了解,可以查看官方文档renderscript
动态模糊的实现
使用之前,先要在module build.gradle里面作下面的定义:
mainactivity.java
package com.jackie.blurimage; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.os.bundle; import android.support.v7.app.appcompatactivity; import android.widget.imageview; import android.widget.seekbar; import android.widget.textview; public class mainactivity extends appcompatactivity { private imageview mblurimage, moriginimage; private seekbar mseekbar; private textview mseekprogress; private int malpha; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initview(); initdata(); initevent(); } private void initview() { mblurimage = (imageview) findviewbyid(r.id.blur_image); moriginimage = (imageview) findviewbyid(r.id.origin_image); mseekbar = (seekbar) findviewbyid(r.id.seek_bar); mseekprogress = (textview) findviewbyid(r.id.seek_progress); } private void initdata() { // 获取图片 bitmap originbitmap = bitmapfactory.decoderesource(getresources(), r.drawable.blur); bitmap blurbitmap = blurutils.blur(this, originbitmap); // 填充模糊后的图像和原图 mblurimage.setimagebitmap(blurbitmap); moriginimage.setimagebitmap(originbitmap); } private void initevent() { mseekbar.setmax(100); mseekbar.setonseekbarchangelistener(new seekbar.onseekbarchangelistener() { @override public void onprogresschanged(seekbar seekbar, int progress, boolean fromuser) { malpha = progress; moriginimage.setalpha((int) (255 - malpha * 2.55)); mseekprogress.settext(string.valueof(malpha)); } @override public void onstarttrackingtouch(seekbar seekbar) { } @override public void onstoptrackingtouch(seekbar seekbar) { } }); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <framelayout android:layout_width="match_parent" android:layout_weight="1" android:layout_height="0dp"> <imageview android:id="@+id/blur_image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaletype="centercrop" android:src="@drawable/blur"/> <imageview android:id="@+id/origin_image" android:layout_width="match_parent" android:layout_height="match_parent" android:scaletype="centercrop"/> </framelayout> <linearlayout android:layout_width="match_parent" android:layout_height="80dp" android:orientation="vertical"> <seekbar android:id="@+id/seek_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginleft="16dp" android:layout_marginright="16dp" android:layout_margintop="@dimen/activity_vertical_margin"/> <textview android:id="@+id/seek_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="0" android:textsize="24sp"/> </linearlayout> </linearlayout>
从上面的代码可以看出,在framelayout上放了两张图片,然后动态更改图片的透明度来达到动态模糊效果。
blurutils.java
package com.jackie.blurimage; import android.content.context; import android.graphics.bitmap; import android.renderscript.allocation; import android.renderscript.element; import android.renderscript.renderscript; import android.renderscript.scriptintrinsicblur; /** * created by jackie on 2017/1/21. * 高斯模糊工具类 */ public class blurutils { /** * 图片缩放比例 */ private static final float scale_degree = 0.4f; /** * 最大模糊度(在0.0到25.0之间) */ private static final float blur_radius = 25f; /** * 模糊图片 * @param context 上下文 * @param bitmap 需要模糊的图片 * @return 模糊处理后的图片 */ public static bitmap blur(context context,bitmap bitmap) { //计算图片缩小的长宽 int width = math.round(bitmap.getwidth() * scale_degree); int height = math.round(bitmap.getheight() * scale_degree); //将缩小后的图片作为预渲染的图片 bitmap inputbitmap = bitmap.createscaledbitmap(bitmap, width, height, false); //创建一张渲染后的输入图片 bitmap outputbitmap = bitmap.createbitmap(inputbitmap); //创建renderscript内核对象 renderscript renderscript = renderscript.create(context); //创建一个模糊效果的renderscript的工具对象 scriptintrinsicblur scriptintrinsicblur = scriptintrinsicblur.create(renderscript, element.u8_4(renderscript)); /** * 由于renderscript并没有使用vm来分配内存,所以需要使用allocation类来创建和分配内存空间。 * 创建allocation对象的时候其实内存是空的,需要使用copyto()将数据填充进去。 */ allocation inputallocation = allocation.createfrombitmap(renderscript, inputbitmap); allocation outputallocation = allocation.createfrombitmap(renderscript, outputbitmap); //设置渲染的模糊程度,25f是最大模糊度 scriptintrinsicblur.setradius(blur_radius); //设置scriptintrinsicblur对象的输入内存 scriptintrinsicblur.setinput(inputallocation); //将scriptintrinsicblur输出数据保存到输出内存中 scriptintrinsicblur.foreach(outputallocation); //将数据填充到allocation中 outputallocation.copyto(outputbitmap); return outputbitmap; } }
效果图如下,妹纸一枚!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。