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

自定义Glide BlurTransformation半径超过25时失效问题求助

解决Glide自定义BlurTransformation半径超过25失效的问题

我完全懂你的困扰——自己手写的Glide模糊变换,一把radius设成25以上就直接失效,还不想引入第三方库对吧?这事儿根源很明确:RenderScript自带的ScriptIntrinsicBlur本身就把最大模糊半径限制在了25,超过这个值的参数会被直接忽略,所以咱们得手动绕开这个限制。

核心思路:多次迭代小半径模糊叠加

既然单次模糊最多只能到25,那我们就通过多次模糊来模拟大半径的效果。比如要实现50的模糊半径,就连续做两次25半径的模糊;如果要60,就做两次25加一次10,以此类推。虽然叠加出来的效果和原生大半径会有细微差异,但视觉上已经足够接近,完全能满足需求。

修改后的完整代码

我给你调整了原有的BlurTransformation,加入了大半径处理逻辑,还优化了资源回收和缓存策略:

public class BlurTransformation extends BitmapTransformation {
    private RenderScript rs;
    private float radius;

    // 允许传入自定义模糊半径,方便灵活调整
    public BlurTransformation(Context context, float radius) {
        super();
        rs = RenderScript.create(context);
        // 过滤掉无效的负数半径
        this.radius = Math.max(0, radius);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        Bitmap blurredBitmap = toTransform.copy(Bitmap.Config.ARGB_8888, true);
        ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));

        // 处理超过25的大半径:循环迭代模糊
        float remainingRadius = radius;
        while (remainingRadius > 25) {
            applyBlur(script, blurredBitmap, 25);
            remainingRadius -= 25;
        }
        // 处理剩余不足25的半径部分
        if (remainingRadius > 0) {
            applyBlur(script, blurredBitmap, remainingRadius);
        }

        return blurredBitmap;
    }

    // 提取重复的模糊逻辑到单独方法,减少代码冗余
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    private void applyBlur(ScriptIntrinsicBlur script, Bitmap bitmap, float currentRadius) {
        Allocation input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_FULL, Allocation.USAGE_SHARED);
        Allocation output = Allocation.createTyped(rs, input.getType());

        script.setInput(input);
        script.setRadius(currentRadius);
        script.forEach(output);
        output.copyTo(bitmap);

        // 及时释放Allocation资源,避免内存泄漏
        input.destroy();
        output.destroy();
    }

    @Override
    public void updateDiskCacheKey(MessageDigest messageDigest) {
        // 把半径加入缓存Key,确保不同半径的模糊结果不会共用缓存
        messageDigest.update(("blur transformation radius:" + radius).getBytes());
    }

    // 销毁RenderScript资源,防止内存泄漏
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        rs.destroy();
    }
}

关键修改点说明

  • 可配置半径:新增了带radius参数的构造方法,不用硬写25,灵活度更高
  • 大半径处理:通过循环叠加多次25半径的模糊,实现超过25的模糊效果
  • 资源优化:每次模糊后主动销毁Allocation,并在类销毁时释放RenderScript,避免内存泄漏
  • 缓存优化:把radius加入磁盘缓存Key,避免不同半径的模糊结果互相覆盖

使用示例

比如你需要设置50的模糊半径,直接这么用就行:

Glide.with(context)
     .load(yourImageUrl)
     .transform(new BlurTransformation(context, 50))
     .into(yourImageView);

要是你追求更细腻的效果,也可以把每次迭代的半径调小(比如15),但次数越多性能消耗会越高,记得在效果和性能之间做权衡~

内容的提问来源于stack exchange,提问作者mW3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:59:06