RenderScript模糊Bitmap后图像损坏问题求助
我来帮你排查一下导致图像损坏的几个可能原因,以及对应的修复方案:
1. 变量名拼写错误
先看你调用模糊方法的代码:
defautIcon = ImageUtils.drawableToBitmap(notification.getLargeIcon().loadDrawable(this)); largeIcon = RenderScriptBlur.blur(getContext(), defauticon, 15);
这里defautIcon和defauticon是两个不同的变量(注意末尾的Icon和icon大小写差异),这会导致你传递给模糊方法的是未初始化的变量(或者null),直接生成损坏的图像。先把变量名统一修正过来。
2. 错误回收传入的Bitmap
在RenderScriptBlur的blur方法里,最后一行调用了bitmap.recycle();,这会直接回收你传入的原Bitmap。如果后续代码还需要使用这个原Bitmap,就会导致它被回收后无法正常渲染,表现为图像损坏。应该移除这行代码,让调用者自行决定是否回收原Bitmap。
3. 废弃的Bitmap配置
在ImageUtils.drawableToBitmap方法中,当Drawable为null时,你使用了Bitmap.Config.ARGB_4444——这个配置已经被官方废弃,并且可能导致颜色精度不足或渲染异常。建议替换为Bitmap.Config.ARGB_8888,和其他分支保持一致。
4. 模糊后Bitmap尺寸被缩小
你的RenderScriptBlur默认使用BITMAP_SCALE = 0.4f,也就是把原Bitmap缩小到40%后再模糊,最终返回的是这个小尺寸的Bitmap。如果直接把它作为通知的largeIcon,系统显示时会将其拉伸回原尺寸,导致图像模糊、失真甚至损坏。
解决办法二选一:
- 将
BITMAP_SCALE改为1.0f(不缩放),但模糊效率会稍低; - 在模糊完成后,把输出Bitmap缩放回原尺寸(可以参考我下面修复后的代码注释)。
5. RenderScript资源未完全释放
虽然你调用了rs.destroy(),但最好显式销毁Allocation和ScriptIntrinsicBlur实例,避免资源泄漏间接导致图像处理异常。
修复后的完整代码示例
修正后的ImageUtils.drawableToBitmap方法
public static Bitmap drawableToBitmap(Drawable drawable) { if (drawable == null) { // 替换废弃的ARGB_4444为ARGB_8888 return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); } Bitmap bitmap; if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if (bitmapDrawable.getBitmap() != null) { return bitmapDrawable.getBitmap(); } } int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); if (width <= 0 || height <= 0) { bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); } else { bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; }
修正后的RenderScriptBlur类
public class RenderScriptBlur { private static final float BITMAP_SCALE = 0.4f; private static final int BLUR_RADIUS = 7; public static Bitmap blur(Context context, Bitmap bitmap) { return blur(context, bitmap, BITMAP_SCALE, BLUR_RADIUS); } public static Bitmap blur(Context context, Bitmap bitmap, float bitmap_scale) { return blur(context, bitmap, bitmap_scale, BLUR_RADIUS); } public static Bitmap blur(Context context, Bitmap bitmap, int blur_radius) { return blur(context, bitmap, BITMAP_SCALE, blur_radius); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static Bitmap blur(Context context, Bitmap bitmap, float bitmap_scale, int blur_radius) { // 先检查传入的Bitmap是否有效 if (bitmap == null || bitmap.isRecycled()) { return null; } // ScriptIntrinsicBlur要求模糊半径在0-25之间,做个限制 float safeRadius = Math.max(0, Math.min(blur_radius, 25)); Bitmap inputBitmap = Bitmap.createScaledBitmap(bitmap, Math.round(bitmap.getWidth() * bitmap_scale), Math.round(bitmap.getHeight() * bitmap_scale), false); Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); RenderScript rs = RenderScript.create(context); ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); theIntrinsic.setRadius(safeRadius); theIntrinsic.setInput(tmpIn); theIntrinsic.forEach(tmpOut); tmpOut.copyTo(outputBitmap); // 显式销毁所有RenderScript资源 theIntrinsic.destroy(); tmpIn.destroy(); tmpOut.destroy(); rs.destroy(); // 如果你需要返回和原Bitmap尺寸一致的模糊图,取消下面两行注释 // outputBitmap = Bitmap.createScaledBitmap(outputBitmap, bitmap.getWidth(), bitmap.getHeight(), false); // inputBitmap.recycle(); // 回收临时缩小的Bitmap return outputBitmap; } }
修正后的调用代码
// 统一变量名,避免拼写错误 Bitmap defaultIcon = ImageUtils.drawableToBitmap(notification.getLargeIcon().loadDrawable(this)); // 可以加个非空判断,避免传入null if (defaultIcon != null) { Bitmap largeIcon = RenderScriptBlur.blur(getContext(), defaultIcon, 15); // 后续使用largeIcon的逻辑 }
额外检查点
- 确保
notification.getLargeIcon().loadDrawable(this)返回的Drawable不为null,如果为null,ImageUtils会生成1x1的Bitmap,模糊后自然是损坏的; - 确认你的设备系统版本在API 17(JELLY_BEAN_MR1)及以上,RenderScript从这个版本开始支持
ScriptIntrinsicBlur; - 如果需要兼容更低版本,可以考虑使用FastBlur等Java实现的模糊方案。
内容的提问来源于stack exchange,提问作者Soptq
相关产品推荐
相关产品推荐

