一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

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

时间:2017-03-01 编辑:简简单单 来源:一聚教程网

写在前面

现在,越来越多的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的文章非常少,附上一篇博客,大家可以能更好理解这门语言。

如果需要详细了解,可以查看官方文档RenderScript

动态模糊的实现

使用之前,先要在Module build.gradle里面作下面的定义:

MainActivity.java

 

 代码如下 复制代码

packagecom.jackie.blurimage;

  

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapFactory;

importandroid.os.Bundle;

importandroid.support.v7.app.AppCompatActivity;

importandroid.widget.ImageView;

importandroid.widget.SeekBar;

importandroid.widget.TextView;

  

publicclassMainActivityextendsAppCompatActivity {

  privateImageView mBlurImage, mOriginImage;

  privateSeekBar mSeekBar;

  privateTextView mSeekProgress;

  

  privateintmAlpha;

  

  @Override

  protectedvoidonCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

  

    initView();

    initData();

    initEvent();

  }

  

  privatevoidinitView() {

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

  }

  

  privatevoidinitData() {

    // 获取图片

    Bitmap originBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.blur);

    Bitmap blurBitmap = BlurUtils.blur(this, originBitmap);

  

    // 填充模糊后的图像和原图

    mBlurImage.setImageBitmap(blurBitmap);

    mOriginImage.setImageBitmap(originBitmap);

  }

  

  privatevoidinitEvent() {

    mSeekBar.setMax(100);

  

    mSeekBar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener() {

      @Override

      publicvoidonProgressChanged(SeekBar seekBar,intprogress,booleanfromUser) {

        mAlpha = progress;

  

        mOriginImage.setAlpha((int) (255- mAlpha *2.55));

        mSeekProgress.setText(String.valueOf(mAlpha));

      }

  

      @Override

      publicvoidonStartTrackingTouch(SeekBar seekBar) {

  

      }

  

      @Override

      publicvoidonStopTrackingTouch(SeekBar seekBar) {

  

      }

    });

  }

}

 

activity_main.xml

 

 代码如下 复制代码

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:orientation="vertical">

  

  

    android:layout_width="match_parent"

    android:layout_weight="1"

    android:layout_height="0dp">

  

    

      android:id="@+id/blur_image"

      android:layout_width="match_parent"

      android:layout_height="match_parent"

      android:scaleType="centerCrop"

      android:src="@drawable/blur"/>

  

    

      android:id="@+id/origin_image"

      android:layout_width="match_parent"

      android:layout_height="match_parent"

      android:scaleType="centerCrop"/>

  

  

  

    android:layout_width="match_parent"

    android:layout_height="80dp"

    android:orientation="vertical">

  

    

      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"/>

  

    

      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"/>

  

 

从上面的代码可以看出,在FrameLayout上放了两张图片,然后动态更改图片的透明度来达到动态模糊效果。

BlurUtils.java

 

 代码如下 复制代码

packagecom.jackie.blurimage;

  

importandroid.content.Context;

importandroid.graphics.Bitmap;

importandroid.renderscript.Allocation;

importandroid.renderscript.Element;

importandroid.renderscript.RenderScript;

importandroid.renderscript.ScriptIntrinsicBlur;

  

/**

 * Created by Jackie on 2017/1/21.

 * 高斯模糊工具类

 */

  

publicclassBlurUtils {

  /**

   * 图片缩放比例

   */

  privatestaticfinalfloatSCALE_DEGREE =0.4f;

  /**

   * 最大模糊度(在0.0到25.0之间)

   */

  privatestaticfinalfloatBLUR_RADIUS = 25f;

  

  /**

   * 模糊图片

   * @param context  上下文

   * @param bitmap  需要模糊的图片

   * @return     模糊处理后的图片

   */

  publicstaticBitmap blur(Context context,Bitmap bitmap) {

    //计算图片缩小的长宽

    intwidth = Math.round(bitmap.getWidth() * SCALE_DEGREE);

    intheight = 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);

  

    returnoutputBitmap;

  }

}

 

效果图如下,妹纸一枚!

热门栏目