January 31, 2011
Fast Radial Blur

Given my track record of last year - a total of 4 blog posts - I do not have very high hopes that I'll do much better in 2011, but since I decided not to speak on any conferences this year I might have a little bit more time to share my experiments here instead of on stages only. I don't want to over-promise, but I hope that over the next weeks I'll find the time to finally explain and release the source codes for several projects that I have exclusively shown in my talks over the last years. Of course some of them have in the time since I've presented them been independently discovered by others, but I think I've still got a few aces in my pockets which are worth sharing.

I'll start with a simple visual effect: Radial Blur, which can give images the 200mph speed zoom look. In a naive approach you could achieve this effect by replacing every pixel with a weighted average of all neighboring pixels within the blur radius that lie on a line that goes through the center of zoom and the pixel itself. The problem with this method is that it is very slow since it would require many calculations to collect each neighbor and since the angle is different at every pixel there is not much room for other optimizations, like reusing already read pixels, which is key for every fast blur algorithm.

But using a neat trick that I remembered from my early Photoshop days allows to speed up this process a lot. Here is a demo:

The way this works is by converting the pixels from cartesian mapping (where the axes are x & y) to polar mapping (with axes angle & distance to the center) which arranges them in a way that all the neighbors that need to be averaged arrange themselves nicely in a straight line. This allows us to use a simple native Blur filter to quickly calculate the average. Depending if the blur is in x direction or y direction the final result will either be a Radial Blur (the well-known zoom effect) or a Circular Blur (which looks like a fast spinning wheel). The final step is to convert the pixels back from polar mapping to cartesian.

Open this link in a new window to see the process in a step by step demo.

By default the mapping uses the center of the image as the center of the polar coordinate system. This will result the center of the zoom to also be in the center of the image. So what if we want the zoom center to be at a different location? There are two ways of going about this - unfortunately I did not manage the faster way to work correctly yet which would be to simply use that center in the mapping algorithm. For some reason I have not found the right equations which work both ways. So for now I am using the slower method which does always work:

The trick here is to first make the image bigger by padding the borders so that the desired center of the zoom is temporarily the center of the image. So if you want the zoom center to be in the upper half of the image you add as many border pixels to the top that the chosen spot becomes the new vertical center. Then follows the cartesian-to-polar transform, the linar blur and the polar-to-cartesian mapping. The final step is to crop the image back to its original size by removing the previously added top pixels.

Another issue are artifacts that show due to the mapping. The problem is that since all the pixels that lie on a circle with a certain radius are mapped to a straight line, once the circumference of that circle gets bigger than the width of the mapped image pixel information gets lost. To fix this it is required to make the bitmap that holds the polar map as wide as the biggest possible circumference. Unfortunately that is not always possible since the temporary bitmaps could get pretty huge this way. The good news is that since we are blurring those artifacts will mostly not become too visible. Only for small blurs it improves the quality when using a bigger resolution for the cartesian image map.

You can find the source code for the RadialBlur class and the required pixel bender kernels as usual inside QuasimondoLibs

Posted at January 31, 2011 07:45 PM | Further reading
Comments

Why do I feel the urge to comment as 'Amazing!' :)

Posted by: Burak KALAYCI on January 31, 2011 11:13 PM

hey, where's the "i like" button? :D

Posted by: on February 1, 2011 01:37 PM

Hehe - as you might have noticed, this is an old-school blog. No "likes". But feel free to click my "flattr" button in the top right corner :-)

Posted by: Mario Klingemann on February 1, 2011 01:54 PM

Would it be possible to extend BitmapFilter so we could use it as a normal bitmapdata filter, and have syntax like this:

bmd.applyFilter(bmd, bmd.rect, new Point(200, 100), new RadialBlur() );

Posted by: Mark on February 3, 2011 02:26 PM

Unfortunately the docs say "You can neither directly instantiate nor extend BitmapFilter."

http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/filters/BitmapFilter.html?filter_flex=4

Posted by: Mario Klingemann on February 3, 2011 02:35 PM

What if you rotate rectangular regions flat? Then you could blur them horizontally or vertically, apply a blurry triangular alpha channel and rotate them back. It wouldn't be as accurate, but it could be fast. It's worth a try. Sometimes its okay to fake it!

Posted by: Elliot Geno on February 6, 2011 12:46 AM

I guess a visual example would help me here - sorry, but I don't understand what you mean with "rotate rectangular regions flat" and what a "triangular alpha channel" is.

Posted by: Mario Klingemann on February 6, 2011 01:35 AM

Let me work on an example. Basically I'm going to break the bitmap into triangular sections emanating from the selected point. I will rotate those sections to 0 degrees, blur them, then rotate them back to their original angle. The more subdivisions the more accurate it will look, however it will never look as accurate as you show here. We'll see how fast it is... It might still be pretty slow!

Posted by: Elliot Geno on February 6, 2011 05:20 AM

By the way... I am glad to see you blogging again! Thanks!

Posted by: Elliot Geno on February 6, 2011 05:21 AM

Ah, now I understand - I'm curious to see what you will come up with. I expect to see artifacts at the edges of the triangles since when you blur them "in thin air" they will have no neighboring pixels at the borders. You might be able to get around that if you cut the image twice into triangles, but the second time you rotate the main angle by half one triangle's width. Then you use a blending map that will only blend the inner parts of the triangles together.

Posted by: Mario Klingemann on February 6, 2011 02:03 PM

I thought so too, so I'm thinking I might be able to "hide" the artifacts by assembling the triangles over a copy of the original bitmap. That way the original color will show through. I might even blur the copy a bit on both x and y but I might not need to.

Posted by: Elliot Geno on February 7, 2011 01:42 AM
Post a comment
Name:


Email Address:


URL:


Comments:


Remember info?



Thank you!

Most Visited Entries
Sketches, Works & Source Code
Lectures
Contact
Backlog
In Love with
Powered by
Movable Type 2.661

© Copyright Mario Klingemann

Syndicate this site:
RSS 1.0 - RSS 2.0

Quasimondo @ flickr
Quasimondo @ LinkedIn
Quasimondo @ Twitter
Quasimondo @ Facebook
Quasimondo @ MySpace
Quasimondo is a Bright
Citizen of the TRansnational Republic
My other blog in german
Impressum


My family name is written Klingemann,
not Klingelmann, Klingeman, Klingaman, Kingemann,
Kindermann, Killingaman, Klingman, Klingmann, Klingonman
Klingemman, Cleangerman, Klingerman or Kleangerman

profile for Quasimondo at Stack Overflow, Q&A for professional and enthusiast programmers