Animation / Bitmap / Canvas / ImageView / RenderScript

Blurring Images – Part 7

In the previous article we performed some simple optimisations which enormously improved the frame rate of our animations. However, we mentioned that increasing the size of the area that we wish to blur will slow the frame rate because the complexity of the blur operation will increase exponentially. In this article we’ll look at an alternative approach which should permit us to animate larger areas.

The basic approach that we’re going to take is very similar the general pattern that we’ve been using throughout this series. Perform the heavy processing operations outside of the critical section (i.e. onDraw()). In the previous article we moved all of the object allocation out of onDraw() and saw a fairly impressive improvement in terms of the frame rate that we were able to achieve. However, we can improve this further if we are able to move the blur operation itself (and the marshalling to and from the RenderScript memory space). But how can we do that when the way that Android animation framework adapts the frame rate to the hardware speed makes it all but impossible to predict the what the individual frames of the animation will be? The solution that we’ll try is to blur the entire image once, and for each frame we’ll perform our cookie cutter (i.e. copying only the area which corresponds to the bounds of our custom TextView) for each frame.

It is worth mentioning that this will improve performance, but will also be much more costly in terms of memory usage because we’ll hold two copies of the entire background image rather than the one that we held previously. Also, the initial blur operation will be much more expensive processing-wise because it is a much larger image that we are performing the blur on, and marshalling backwards and forwards.

So, let’s take a look at the code for our new version of BlurredTextView:

The actual blur is being performed within the initBlur() method, and our onDraw() is now much simpler. Our cleanupBlur() method is no longer needed, but we’ll leave an empty method body to avoid any changes to MainActivity.

If we run this, the animation is pretty smooth, but there is a noticeable delay before the animation begins:

If we look at the TimingLogger output from the blur operation we can see that it is taking almost half a second to perform:

The blur operation itself is actually really fast, but it is the marshalling of the much larger bitmap which is really taking the time. This only goes to reinforce the earlier assertion that things would slow down considerably as the size of the bitmap increased. However, this is now being performed once, and the operation that we now have to perform for each frame being drawn is much lighter.

Checking the frame rate, we can see that we now get almost 60fps:

While the frame rate will still be affected of the size of the TextView increases, this approach will still perform much better because the operation that we are doing is one of the steps required when we do the blurring on a frame-by-frame basis – we’re simply moving the blur out of that sequence.

It is also worth noting that in our example, the blur operation is performed when we start the animation, so we experience a delay. We could improve this by instead performing the blur when we detect a change to the background image, and we would then have the blurred image ready when we start the animation.

That concludes this series on blurring images. We have looked at a number of different techniques but, possibly more importantly, we have also covered some techniques for identifying and resolving bottlenecks to optimise performance particularly when performing animations.

The source code for this article is available here.

© 2014, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 Blurring Images – Part 7 by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at

Leave a Reply

Your email address will not be published. Required fields are marked *