Search code examples
javaandroidkotlinandroid-renderscript

How to remove the blur from root view in android


I am using this class to blur the background of the root view in my activity:

object BlurBuilder {
private val BITMAP_SCALE = 0.4f
private val BLUR_RADIUS = 20f


fun blur(v: View): Bitmap {

    return calculateBlur(v.context, getScreenshot(v))
}


fun calculateBlur(ctx: Context, image: Bitmap): Bitmap {
    val width = Math.round(image.width * BITMAP_SCALE)
    val height = Math.round(image.height * BITMAP_SCALE)

    val inputBitmap = Bitmap.createScaledBitmap(image, width, height, false)
    val outputBitmap = Bitmap.createBitmap(inputBitmap)

    val rs = RenderScript.create(ctx)
    val theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
    val tmpIn = Allocation.createFromBitmap(rs, inputBitmap)
    val tmpOut = Allocation.createFromBitmap(rs, outputBitmap)
    theIntrinsic.setRadius(BLUR_RADIUS)
    theIntrinsic.setInput(tmpIn)
    theIntrinsic.forEach(tmpOut)
    tmpOut.copyTo(outputBitmap)

    return outputBitmap
}


fun getScreenshot(v: View): Bitmap {
    val b = Bitmap.createBitmap(v.width, v.height, Bitmap.Config.ARGB_8888)
    val c = Canvas(b)
    v.draw(c)
    return b
    }
  }

And in my activity I have the following:

 fun applyBlur() {
    val view = this.findViewById(android.R.id.content).rootView

    if (view.width > 0) {
        val image = BlurBuilder.blur(view)

        window.setBackgroundDrawable(BitmapDrawable(this.resources, image))
    } else {
        view.viewTreeObserver.addOnGlobalLayoutListener({
            val image = BlurBuilder.blur(view)
            window.setBackgroundDrawable(BitmapDrawable(this.resources, image))
        })
    }
}

With this technique I blur the root view of my activity depending on the blur radius. How can I do the reverse ? I tried to put the BLUR_RADIUS to 0.1f but it still does not work.

Please provide some explanation on how can I achieve this. Thank you!


Solution

  • Blur is a destructive operation and reversing it requires some complex math and computations, you'd better add a flag, and check it in the blur function, if the flag is false, for example -- just pass the original background through, like:

    var contentBG: Drawable? = null
    var needBlur = true
    fun applyBlur() {
        val view = this.findViewById(android.R.id.content).rootView
    
        if (view.width > 0) {
            contentBG ?: let { contentBG = view.background }
            val drawable = if (needBlur)
                BitmapDrawable(this.resources, BlurBuilder.blur(view))
            else contentBG
            window.setBackgroundDrawable(drawable)
        } else {
            view.viewTreeObserver.addOnGlobalLayoutListener({
                val image = BlurBuilder.blur(view)
                window.setBackgroundDrawable(BitmapDrawable(this.resources, image))
            })
        }
    }