MotivationsA couple of weeks ago, we started to play with blur effect on Android. We found that blurred components enhanced pretty well any modern design app.
Like any new hotness, we wanted to use it with caution since we could be tend to apply such an effect everywhere. The use case on which we finally based our playground was the DialogFragment. For us, the goal of a Dialog is to bring emphasis on a component when no other action should be available. Thus, blurring the entire screen displayed in the background of a dialog actually make sense as it helps to bring the emphasis we are looking for : the user is even less distracted by the content under dialog than he is with only a dimming effect. Even if in pratice more and more dialogs can (and must) be replaced by better component in term of user experience, we believe that they are still relevant for some use-cases so let's see how we managed to implement the BlurDialogFragment class!
An impressive study made by Pavel DudkaFirst of all, we based the blurring part on the impressive works of Pavel Dudka : Advanced blurring techniques. We were very impressed by the efficiency of the FastBlur algorithm once the source image was downscaled. To summarize the Pavel's approach, we don't need an hight-quality image since "blurring process itself is all about loosing pixels". That's why a downscale factor is applied to the source Bitmap in order to reduce the time of the blurring process. With this pre-processing and according to his benchmark, the FastBlur algorithm is 6 times faster than ScriptIntrinsicBlur from RenderScript.
Despite his results, Pavel wrote the following warning concerning the memory allocation used by the FastBlur algorithm :
WARNING! Please note that FastBlur uses hell a lot of additional memory (it is copying entire bitmap into temp buffers), so even if it works perfect for small bitmaps, I would not recommend using it for blurring entire screen since you can easily get OutOfMemoryException on low-end devices. Use your best judgement.
Unfortunately, "blurring the entire screen" was exactly what we were looking for. Therefore we decided to take Pavel's warning into account and find out by ourselves the memory trace of both blurring methods. Our goal was to provide the more efficient implementation which means finding the best ratio between execution time and memory allocation. For the whole set of metrics presented bellow, we used a Nexus 4 running a 4.4.4 stock rom.
Let's start with the FastBlur approach.
Fast blur 3072ko (screen capture) + 192ko (DownScaled+RGB_565) + 192ko(Buffer used by FastBlur) = 3456ko
And what's about ScriptIntrinsicBlur ?
RenderScript 3072ko (screen capture) + 384ko (DownScaled+ARGB_8888) = 3456koAccording to our results and the Pavel's study, the FastBlur approach is 6 times faster than RenderScript for the same memory trace. In fact, despite the buffer, the FastBlur approach can be performed on a RGB_565 encoded Bitmap which reduces the memory allocation by half whereas the ScriptIntrinsicBlur can only be applied on a ARGB_8888 encoded Bitmap. Therefore, we decided to use FastBlur instead of RenderScript for our BlurDialogFragment. If we missed something, don't hesitate to give us your input by using the disqus at the end! We will really appreciate that. You can also directly contribute to our project as explained here!
Bring the magicOnce the blurring part was achieved, we simply had to encapsulate the whole behaviour into a BlurDialogFragment which process blurring effect off the UI thread. Here is a screenshot of the result:
As usual the whole project is open-source and can be found on GitHub. In addition, a sample app can be downloaded on the Google Play store. It allows you to play with the blur radius and the downscale parameters in order to obtain the wished effect. Don't hesitate to use the gradle dependency to use it in your project! Any feedback, both positive and negative, are welcome (=