Blurring in real time on android is still a hurdle. Here's a comprehensive comparison between some of the viable mechanisms:
StackBlur (already listed in the answer by Onur
under the moniker fastBlur
):
How it looks (at radius 20):
Logged time(ms) to generate each BitmapDrawable
:
I/(10266): Total time taken: 35
I/(10266): Total time taken: 54
I/(10266): Total time taken: 48
I/(10266): Total time taken: 36
I/(10266): Total time taken: 48
I/(10266): Total time taken: 39
I/(10266): Total time taken: 49
I/(10266): Total time taken: 50
I/(10266): Total time taken: 35
I/(10266): Total time taken: 47
Average => ~ 44.1 ms => 22 drawables per second
RenderScript:
ScriptIntrinsicBlur
provides a consistently fast blur. Its available api 8 onwards using the support library.
What it looks like (at radius 20):
Logged time(ms) to generate each BitmapDrawable
:
I/(9342): Total time taken: 14
I/(9342): Total time taken: 16
I/(9342): Total time taken: 13
I/(9342): Total time taken: 28
I/(9342): Total time taken: 14
I/(9342): Total time taken: 12
I/(9342): Total time taken: 14
I/(9342): Total time taken: 19
I/(9342): Total time taken: 13
I/(9342): Total time taken: 13
Average => ~ 15.6 ms => 64 drawables per second
RenderScript (radius = 3) + Scaling (20%):
This is another way of getting a decent(?) but fast blur. What we do is scale the bitmap to a fraction of its size - say 20% - and apply the blur algorithm on the scaled down version. Once that is done, we scale the bitmap to its original size. Results are not as good as using the blur algorithm on the original, but they are passable. Also notice that the radius value shouldn't be too high or the resulting bitmap will be indiscernible.
What it looks like:
Logged time(ms) to generate each BitmapDrawable
:
I/(11631): Total time taken: 5
I/(11631): Total time taken: 19
I/(11631): Total time taken: 3
I/(11631): Total time taken: 7
I/(11631): Total time taken: 7
I/(11631): Total time taken: 5
I/(11631): Total time taken: 7
I/(11631): Total time taken: 17
I/(11631): Total time taken: 5
I/(11631): Total time taken: 4
Average => ~ 7.9 ms => 126 drawables per second
StackBlur (radius = 3) + Scaling (20%):
Same concept as #3 above. Reduce size to 20% and apply stackblur on the scaled bitmap.
I/(12690): Total time taken: 4
I/(12690): Total time taken: 20
I/(12690): Total time taken: 4
I/(12690): Total time taken: 4
I/(12690): Total time taken: 5
I/(12690): Total time taken: 5
I/(12690): Total time taken: 4
I/(12690): Total time taken: 21
I/(12690): Total time taken: 3
I/(12690): Total time taken: 4
Average => ~ 7.4 ms => 135 drawables per second
Tests carried out on Nex4.
Bitmap size - 200px x 200px
Another tip: methods buildDrawingCache()
and getDrawingCache()
themselves take a long time. An alternative to this is to create a Bitmap using the dimensions of the view you need to blur:
Bitmap toDrawOn = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);
// Create a canvas - assign `toDrawOn` as an offscreen bitmap to it
Canvas holdingCanvas = new Canvas(toDrawOn);
// Now, let the view draw itself on this canvas
yourView.draw(holdingCanvas);
The view is now drawn on toDrawOn
and you can use it however you please.
This, in my experience is much faster than generating and accessing a view's drawing cache.
If you need help implementing any of the 4 methods listed above, let me know in comments.
Do keep in mind that the gifs above have been downscaled and whatnot. If you'd like to see original screen-capture (mp4) files - check this Link.