Android中如何直接为Bitmap添加模糊效果?求替代ImageView的方案
直接对Bitmap添加模糊效果的几种方案
一、API 31+ 使用RenderEffect(官方推荐)
你之前用的RenderEffect不仅能作用于View,也可以通过Canvas直接应用到Bitmap上。drawToBitmap()拿不到View应用RenderEffect后的Bitmap,是因为RenderEffect属于View渲染阶段的临时效果,不会修改底层原始Bitmap。可以通过创建新Bitmap,在Canvas上绘制原Bitmap时叠加模糊效果:
private fun blurBitmapApi31Plus(originalBitmap: Bitmap, radius: Float): Bitmap { val blurredBitmap = Bitmap.createBitmap(originalBitmap.width, originalBitmap.height, originalBitmap.config) val canvas = Canvas(blurredBitmap) val renderEffect = RenderEffect.createBlurEffect(radius, radius, Shader.TileMode.CLAMP) canvas.save() canvas.setRenderEffect(renderEffect) canvas.drawBitmap(originalBitmap, 0f, 0f, null) canvas.restore() return blurredBitmap }
调用时直接传入原Bitmap和模糊半径即可,这个方案和你之前的View模糊逻辑一致,属于官方现代API。
二、兼容低版本:RenderScript实现
RenderScript可以高效实现Bitmap模糊,虽然API 31+被标记为废弃,但依然可以正常使用,也能通过AndroidX的RenderScript库兼容更低版本:
1. 依赖配置(AndroidX版本)
在Module级别的build.gradle中添加:
android { defaultConfig { renderscriptTargetApi 33 renderscriptSupportModeEnabled true } }
2. 模糊实现代码
private fun blurBitmapWithRenderScript(context: Context, originalBitmap: Bitmap, radius: Float): Bitmap { val rs = RenderScript.create(context) val input = Allocation.createFromBitmap(rs, originalBitmap) val output = Allocation.createTyped(rs, input.type) val blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)) blurScript.setInput(input) blurScript.setRadius(radius.coerceIn(0.1f, 25f)) // RenderScript模糊半径限制在0.1-25之间 blurScript.forEach(output) val bitmapCopy = originalBitmap.copy(originalBitmap.config, true) output.copyTo(bitmapCopy) rs.destroy() return bitmapCopy }
注:这里创建了原Bitmap的副本进行处理,避免修改原始Bitmap对象。
三、替代方案:自定义高斯模糊算法(不推荐)
如果不想依赖RenderScript或高版本API,也可以手动实现高斯模糊算法,但效率远低于前两种方案,仅适合小尺寸Bitmap:
// 简化版高斯模糊实现,仅作示例 private fun blurBitmapManual(originalBitmap: Bitmap, radius: Int): Bitmap { val width = originalBitmap.width val height = originalBitmap.height val pixels = IntArray(width * height) originalBitmap.getPixels(pixels, 0, width, 0, 0, width, height) val blurRadius = radius.coerceAtMost(25) val kernelSize = blurRadius * 2 + 1 val kernel = FloatArray(kernelSize) val sigma = blurRadius / 3.0f var sum = 0f // 构建高斯核 for (i in 0 until kernelSize) { kernel[i] = Math.exp(-((i - blurRadius) * (i - blurRadius)) / (2 * sigma * sigma)).toFloat() sum += kernel[i] } // 归一化核 for (i in kernel.indices) kernel[i] /= sum // 横向模糊 val tempPixels = IntArray(width * height) for (y in 0 until height) { for (x in 0 until width) { var r = 0f var g = 0f var b = 0f for (k in 0 until kernelSize) { val neighborX = x + k - blurRadius if (neighborX in 0 until width) { val pixel = pixels[y * width + neighborX] r += Color.red(pixel) * kernel[k] g += Color.green(pixel) * kernel[k] b += Color.blue(pixel) * kernel[k] } } tempPixels[y * width + x] = Color.rgb(r.toInt(), g.toInt(), b.toInt()) } } // 纵向模糊 for (x in 0 until width) { for (y in 0 until height) { var r = 0f var g = 0f var b = 0f for (k in 0 until kernelSize) { val neighborY = y + k - blurRadius if (neighborY in 0 until height) { val pixel = tempPixels[neighborY * width + x] r += Color.red(pixel) * kernel[k] g += Color.green(pixel) * kernel[k] b += Color.blue(pixel) * kernel[k] } } pixels[y * width + x] = Color.rgb(r.toInt(), g.toInt(), b.toInt()) } } val blurredBitmap = Bitmap.createBitmap(width, height, originalBitmap.config) blurredBitmap.setPixels(pixels, 0, width, 0, 0, width, height) return blurredBitmap }
四、第三方库方案
如果不想自己实现,也可以使用成熟的第三方库,比如Glide的BlurTransformation,只需在加载Bitmap时添加转换即可,不过需要引入Glide依赖。
内容的提问来源于stack exchange,提问作者thebluepandabear
相关产品推荐
相关产品推荐

