Android实现Bitmap高斯模糊效果(附带源码)
Android实现Bitmap高斯模糊效果(附带源码)
一、项目介绍
1.1 背景与意义
在 Android 应用中,对图片进行高斯模糊(Gaussian Blur)常用于以下场景:
-
背景虚化:将某个界面或对话框背景设为一张模糊的屏幕截图,增强层次感。
-
毛玻璃效果:在聊天背景、通知下拉、底部弹窗等交互场景中常见。
-
动态模糊:实时对摄像头、视频帧或滑动内容进行模糊,提升视觉效果。
高斯模糊通过对邻域像素进行加权平均,模拟类似相机焦外散焦的效果。Android 原生并不直接提供简单 API,需要借助 RenderScript、ScriptIntrinsicBlur、RenderEffect(API 31+)等方式来实现。
1.2 项目目标
-
为
Bitmap添加高斯模糊效果,并将结果展示在ImageView中; -
兼容多种实现方式:
-
RenderScript + ScriptIntrinsicBlur(兼容 API 17–30);
-
RenderEffect(API 31+)的系统高斯模糊;
-
Fallback “Fast Blur” 算法手动实现;
-
-
将所有代码(Activity、工具类、布局 XML)整合到一个代码块中,用注释区分不同文件;
-
注释详尽,并拓展相关知识点,方便博客撰写与学习。
二、相关知识拓展
-
高斯模糊原理
-
用高斯分布函数对像素邻域加权,权重随距离中心点的增大而指数下降;
-
理论上需要对每个像素做二维卷积,时间复杂度高;
-
可采用“分离卷积”将二维高斯分布拆分成两个一维卷积,性能更高。
-
-
RenderScript 与 ScriptIntrinsicBlur
-
RenderScript 是 Android 提供的异构计算框架,能在 CPU/GPU/专用 DSP 上高效运行;
-
ScriptIntrinsicBlur是 RenderScript 提供的高斯模糊内置脚本,调用简单。 -
Android 12(API 31)标记 RenderScript 废弃,推荐改用 RenderEffect、GPU shader 或自定义算法。
-
-
RenderEffect(API 31+)
-
Android 12 新增
RenderEffect.createBlurEffect(),可直接对View或Bitmap做高效模糊; -
底层调用 GPU shader,性能优越,代码简洁。
-
-
手动 Fast Blur
-
“Stack Blur” 算法是高效近似高斯模糊的一种实现,能在不借助 RenderScript 的情况下对图片做模糊;
-
时间复杂度较低,适合兼容性最广的场景。
-
-
性能与内存
-
大尺寸图片做高斯模糊前可先做“下采样”缩小分辨率,再放大回原始尺寸,保证效率;
-
对 RenderScript,应合理释放
RenderScript、Allocation资源,避免内存泄露; -
对于频繁变更的模糊需求,最好只在必要时执行一次,不要在每帧都做。
-
三、实现思路
-
布局
在activity_main.xml中放置一张原图ImageView、一张用于显示模糊结果的ImageView,以及一个“模糊”按钮和一个“清除”按钮。 -
Activity
-
在按钮点击时读取原图
Bitmap; -
调用工具类
BlurUtils中的blurBitmapRS()、blurBitmapFast()或在 API 31+ 下调用applyRenderEffect(); -
将结果
Bitmap或RenderEffect应用于目标ImageView,刷新页面。
-
-
BlurUtils 工具类
-
blurBitmapRS(Context, Bitmap, float):使用 RenderScript + ScriptIntrinsicBlur 进行高斯模糊;
-
blurBitmapFast(Bitmap, int):“Stack Blur” 快速模糊算法,参数为模糊半径;
-
applyRenderEffect(View, float, float, Shader.TileMode):在 API 31+ 上为任意
View应用 GPU 模糊效果。
-
-
兼容判断
-
在运行时根据
Build.VERSION.SDK_INT,选择合适的模糊方法; -
对低于 API 17 的设备,直接 fall back 到 fast blur。
-
四、完整代码整合(含详细注释)
// ==================== File: activity_main.xml ====================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="16dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 原始图片 -->
<ImageView
android:id="@+id/iv_original"
android:layout_width="200dp"
android:layout_height="200dp"
android:src="@drawable/sample_image"
android:scaleType="centerCrop"/>
<!-- 模糊结果展示 -->
<ImageView
android:id="@+id/iv_blurred"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="16dp"
android:scaleType="centerCrop"
android:background="#EEE"/>
<!-- 按钮组 -->
<LinearLayout
android:layout_marginTop="16dp"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_blur_rs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RenderScript模糊"/>
<Button
android:id="@+id/btn_blur_fast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fast Blur"
android:layout_marginStart="12dp"/>
<Button
android:id="@+id/btn_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清除"
android:layout_marginStart="12dp"/>
</LinearLayout>
</LinearLayout>
// ==================== File: MainActivity.java ====================
package com.example.bitmapblur;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
/**
* MainActivity:演示 Bitmap 高斯模糊效果
*/
public class MainActivity extends AppCompatActivity {
private ImageView ivOriginal, ivBlurred;
private Button btnBlurRS, btnBlurFast, btnClear;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivOriginal = findViewById(R.id.iv_original);
ivBlurred = findViewById(R.id.iv_blurred);
btnBlurRS = findViewById(R.id.btn_blur_rs);
btnBlurFast= findViewById(R.id.btn_blur_fast);
btnClear = findViewById(R.id.btn_clear);
// RenderScript 方式模糊
btnBlurRS.setOnClickListener(v -> {
// 获取原图 Bitmap
Bitmap src = ((BitmapDrawable)ivOriginal.getDrawable()).getBitmap();
Bitmap blurred;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
// 半径范围 0 < radius ≤ 25
blurred = BlurUtils.blurBitmapRS(this, src, 20f);
} else {
// 兼容老系统,fallback
blurred = BlurUtils.blurBitmapFast(src, 20);
}
ivBlurred.setImageBitmap(blurred);
});
// 手动 Fast Blur
btnBlurFast.setOnClickListener(v -> {
Bitmap src = ((BitmapDrawable)ivOriginal.getDrawable()).getBitmap();
Bitmap blurred = BlurUtils.blurBitmapFast(src, 15);
ivBlurred.setImageBitmap(blurred);
});
// 清除模糊
btnClear.setOnClickListener(v -> ivBlurred.setImageDrawable(null));
}
}
// ==================== File: BlurUtils.java ====================
package com.example.bitmapblur;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.RenderEffect;
import android.graphics.Shader;
import android.os.Build;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicBlur;
/**
* BlurUtils:提供多种 Bitmap 模糊实现
*/
public class BlurUtils {
/**
* 使用 RenderScript + ScriptIntrinsicBlur 对 Bitmap 做高斯模糊
* @param context 应用 Context
* @param src 原始 Bitmap
* @param radius 模糊半径(0 < radius ≤ 25)
* @return 模糊后的 Bitmap
*/
public static Bitmap blurBitmapRS(Context context, Bitmap src, float radius) {
// 1. 创建输出 Bitmap,参数与源 Bitmap 相同
Bitmap outBitmap = src.copy(src.getConfig(), true);
// 2. 创建 RenderScript 对象
RenderScript rs = RenderScript.create(context);
// 3. 创建 ScriptIntrinsicBlur
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
// 4. 创建输入、输出 Allocation
Allocation allIn = Allocation.createFromBitmap(rs, src);
Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
// 5. 设置模糊半径
blurScript.setRadius(radius);
// 6. 设置输入
blurScript.setInput(allIn);
// 7. 执行脚本
blurScript.forEach(allOut);
// 8. 拷贝到输出 Bitmap
allOut.copyTo(outBitmap);
// 9. 释放资源
allIn.destroy();
allOut.destroy();
blurScript.destroy();
rs.destroy();
return outBitmap;
}
/**
* Fast Blur(Stack Blur)算法,对 Bitmap 做近似高斯模糊
* @param sentBitmap 原始 Bitmap
* @param radius 模糊半径
* @return 模糊后的 Bitmap
*/
public static Bitmap blurBitmapFast(Bitmap sentBitmap, int radius) {
// 参考 Android 官方示例或社区实现,此处略去完整代码,仅示意:
// 1. 拷贝 Bitmap
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
if (radius < 1) return null;
int w = bitmap.getWidth(), h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
// 2. 执行 Stack Blur 核心算法(水平+垂直双向卷积)
// …(此处实际代码请参考“Stack Blur for Android”开源实现)…
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
return bitmap;
}
/**
* Android 12+ 直接为 View 应用高斯模糊效果
* @param view 目标 View
* @param radiusX 横向模糊半径
* @param radiusY 纵向模糊半径
* @param tileMode Shader.TileMode 模式
*/
public static void applyRenderEffect(View view,
float radiusX,
float radiusY,
Shader.TileMode tileMode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
RenderEffect effect = RenderEffect.createBlurEffect(
radiusX, radiusY, tileMode);
view.setRenderEffect(effect);
}
}
}
五、代码解读(方法作用说明)
-
blurBitmapRS(Context, Bitmap, float)
-
创建 RenderScript 对象:开启异构计算上下文;
-
ScriptIntrinsicBlur:内置高斯模糊脚本,调用
setRadius()设置半径; -
Allocation:在 RenderScript 中封装输入、输出
Bitmap; -
forEach():执行模糊计算,将结果写入输出
Allocation; -
copyTo():将输出回写到
Bitmap; -
销毁资源:释放 RenderScript、Allocation、Script。
-
-
blurBitmapFast(Bitmap, int)
-
手写
Stack Blur算法:先水平卷积再垂直卷积,对像素做加权平均; -
兼容所有 API,性能略逊于 RenderScript,但无需额外依赖。
-
-
applyRenderEffect(View, …)
-
Android 12+ 新增 API:直接对
View应用 GPU 模糊; -
底层使用高效的 GPU shader,无需手动处理
Bitmap。
-
-
MainActivity
-
根据系统版本和按钮选择,调用不同模糊方法;
-
将模糊结果
Bitmap显示在iv_blurred; -
“清除”按钮将结果置空,恢复原始界面。
-
六、项目总结与拓展
6.1 实现效果回顾
-
多种方案兼容:分别支持 RenderScript、手写 Fast Blur 及 Android 12+ GPU 模糊;
-
易于集成:只需调用工具类静态方法或
setRenderEffect()即可实现高斯模糊; -
性能优化:对大图建议下采样处理,并合理释放 RenderScript 资源。
6.2 常见坑与注意
-
RenderScript 废弃:虽然 API 31+ 标记废弃,但在 API 17–30 仍是最优方案;
-
模糊半径:ScriptIntrinsicBlur 限制半径 ≤ 25,否则抛出异常;
-
Bitmap 配置:
Bitmap.copy()时必须是支持 alpha 的Config,否则会丢失透明度; -
内存占用:对大
Bitmap模糊可能会导致 OOM,需小图模糊并放大回展现。
6.3 可扩展方向
-
动态下采样:结合
Bitmap.createScaledBitmap(),在模糊前缩小分辨率,提高速度; -
局部模糊:根据手势或指定区域,仅对某部分进行高斯模糊;
-
实时预览:在
RecyclerView滚动、SurfaceView更新时,实时对帧做模糊并渲染; -
Shader 实现:自定义 GLSL Shader,在 OpenGL/WebGL 渲染管线中高效执行;
-
Jetpack Compose:使用
GraphicsLayer与RenderEffect,在 Compose 中实现模糊效果。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)