软件编程
位置:首页>> 软件编程>> Android编程>> Android动态模糊效果的快速实现方法

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

作者:shineflowers  发布时间:2022-06-20 13:14:26 

标签: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里面作下面的定义:

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动态模糊效果的快速实现方法

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com