PolarDistort class

A few weeks ago I made a quick SWF showing Polar Distortion. I said then that I should probably make a class out of it. Finally got around to doing that. The original file was just BitmapData -> BitmapData. The class uses any DisplayObject as an input. It gives you a few other parameters such as inner radius, outer radius, seam angle, and an invert feature, which lets the top of the input image be in the center of the circle instead of the outside.

Here’s an example of it in use, showing how it can be used on a raw text field. The text field is editable, just hit refresh after you type.

[kml_flashembed movie=”http://www.bit-101.com/blog/wp-content/uploads/2008/03/polartest.swf” width=”600″ height=”600″ /]

Again, this is not just text, but any Bitmap, MovieClip, Sprite, TextField or any other DisplayObject. Usage is as so:

[as]var pd:PolarDistort = new PolarDistort(mytext, 100, 0, false);
pd.render(bmpd);[/as]

The constructor signature is:

[as]public function PolarDistort(sourceObject:DisplayObject, innerRadius:Number = 0, outerRadius:Number = 0, inverted:Boolean = false)[/as]

If outer radius is 0, it will draw the full radius of the output BitmapData.

The render method takes a BitmapData.

Download the class here:

PolarDistort.as

It’s well commented and documented, so you should be up to speed pretty quickly.

Note, although I’ve optimized this where I could, it’s never going to be good for animation. It’s a draw once and sit back and admire type of thing. Still think it’s pretty cool though.

Here is regular distort and inverted distort on the exact same photo for reference:

polar_regular.pngpolar_invert.png

This entry was posted in Flash. Bookmark the permalink.

9 Responses to PolarDistort class

  1. Nik says:

    Wow! That’s awesome. Thanks for posting the source Keith, this will be great to learn a few things from..

    Nik

  2. eme says:

    great!
    it’s cool to see strings of a single character repeated , and adding them one by one. i specially like w’s and y’s.
    there’s kind of a minimum width limitation. it will accept a single ‘m’, but not a single ‘i’
    ok enough, back to work

  3. kp says:

    Yeah, there’s some weirdness using text fields. It seems the width does not always get calculated correctly. It works perfectly on any kind of graphic though, right down to the pixel. I think it’s got to do with the way the glyphs of the font are scaled. It’s not always a smooth progression. I bet if I embedded the font it would be fine.

  4. owen says:

    Nice work! Had some trouble getting it to work, but all good now 🙂
    This line was producing an error as I was getting a number higher than 2880:

    var optHeight = _source.height * scale;

  5. kp says:

    owen, is your image taller than wide? The previous lines:

    var optWidth:Number = Math.round(Math.min(cx * Math.PI * 2, 2880));
    var scale:Number = optWidth / _source.width;

    should make sure that the width is 2880 max. Then that scale figure is used to make the optHeight with the same aspect ratio as the original. So unless it is taller than wide, the height should never exceed 2880. Of course, it was an assumption on my part that people would use long, narrow images like panoramas exclusively. I guess I should fix that.

  6. owen says:

    Yes, turns out it was, thanks for pointing that out!

    The other thing I noticed is that there is a Math.sqrt call in the loop. Is it possible to remove that? It would result in a big speed increase. Normally if I’m doing a distance check I’ll square the distance I’m comparing, like so:

    dist = dx * dx + dy * dy;
    if(dist > (inner * inner) && dist < (outer * outer))
    {
    etc.

    I notice that you’re using the sqrt’d distance later on, so maybe not?

  7. kp says:

    Yeah, you are right, that would help. I’ll probably make some changes to it over the weekend.

Leave a Reply