You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:41:18