Android 高斯模糊

1,331 阅读1分钟

高斯模糊方法

public static Bitmap of(Context context, Bitmap source, BlurFactor factor) {
    int width = factor.width / factor.sampling;
    int height = factor.height / factor.sampling;

    if (Helper.hasZero(width, height)) {
      return null;
    }

    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bitmap);
    canvas.scale(1 / (float) factor.sampling, 1 / (float) factor.sampling);
    Paint paint = new Paint();
    paint.setFlags(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG);
    PorterDuffColorFilter filter =
        new PorterDuffColorFilter(factor.color, PorterDuff.Mode.SRC_ATOP);
    paint.setColorFilter(filter);
    canvas.drawBitmap(source, 0, 0, paint);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
      try {
        bitmap = Blur.rs(context, bitmap, factor.radius);
      } catch (RSRuntimeException e) {
        bitmap = Blur.stack(bitmap, factor.radius, true);
      }
    } else {
      bitmap = Blur.stack(bitmap, factor.radius, true);
    }

    if (factor.sampling == BlurFactor.DEFAULT_SAMPLING) {
      return bitmap;
    } else {
      Bitmap scaled = Bitmap.createScaledBitmap(bitmap, factor.width, factor.height, true);
      bitmap.recycle();
      return scaled;
    }
}

封装通用方法

/**
 * 高斯模糊图片通用方法
 * bmp: 图片 rad: 模糊半径 isScreenShot: 是否是全屏截图
 * 默认rad为25
 */
fun blurBitmap(activity: Activity, bmp: Bitmap?, rad: Int = 25, isScreenShot: Boolean): Bitmap? {
    if (bmp == null) return null
    var bitmap = bmp
    if (isScreenShot) {
        bitmap = cutBitmap(activity, bmp)
    }
    val blurFactor = BlurFactor().apply {
        radius = rad
        sampling = 2
        width = bitmap.width
        height = bitmap.height
    }
    return Blur.of(activity, bitmap, blurFactor)
}

如果是截屏的需要把底部导航栏给截掉,不然位置大小就有误差

裁剪方法:

private fun cutBitmap(activity: Activity, bitmap: Bitmap): Bitmap {
    var bottomHeight = 0
    if (DeviceUtils.isNavigationBarShow(activity)) bottomHeight = DeviceUtils.getBottomNavigationHeight(activity)
    return Bitmap.createBitmap(bitmap,
            0, 0, bitmap.width, bitmap.height - bottomHeight,
            null, false)
}


/**
 * 判断导航栏是否存在或显示
 * @param activity
 * @return
 */
public static boolean isNavigationBarShow(Activity activity){
    boolean show;
    Display display = activity.getWindow().getWindowManager().getDefaultDisplay();
    Point point = new Point();
    display.getRealSize(point);

    View decorView = activity.getWindow().getDecorView();
    Configuration conf = activity.getResources().getConfiguration();
    if (Configuration.ORIENTATION_LANDSCAPE == conf.orientation) {
        View contentView = decorView.findViewById(android.R.id.content);
        show = (point.x != contentView.getWidth());
    } else {
        Rect rect = new Rect();
        decorView.getWindowVisibleDisplayFrame(rect);
        show = (rect.bottom != point.y);
    }
    return show;
}

/**
 * 获取状态栏高度
 * @param context
 * @return
 */
public static int getTopBarHeight(Context context){
    int result = 0;
    int resourceId = context.getResources().getIdentifier(
            "status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = context.getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

调用方法如下:

    val bmp = BlurUtils.blurBitmap(this, screenBitmap, 25, true)

screenBitmap为当前屏幕截