欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android动态模糊效果的快速实现方法

程序员文章站 2024-02-20 10:54:29
写在前面 现在,越来越多的app里面使用了模糊效果,这种模糊效果称之为高斯模糊。大家都知道,在android平台上进行模糊渲染是一个相当耗cpu也相当耗时的操作,一旦...

写在前面

现在,越来越多的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里面作下面的定义:

Android动态模糊效果的快速实现方法

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; 
  } 
} 

效果图如下,妹纸一枚!

Android动态模糊效果的快速实现方法

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。