Flashier fisheye

May 11th, 2007

The little fisheye experiment from earlier has been updated. It wasn’t optimized in any way, nor quite organized. I now only calculate the displacements only once instead of every frame, which of course is a major improvement. Furthermore, I build a nice class around it, making it easier to implement (or share). Here goes…

At first, here’s the fishEye class:

package {

  import flash.display.BitmapData;
  import flash.geom.Point;
  import flash.Math;
  import flash.Array;

  public class fishEye extends BitmapData {

    private var size:uint;
    private var source:BitmapData;

    private var displacement:Array;

    public function fishEye(source:BitmapData, bgColor:uint = 0x00000000) {
      this.source = source;
      size = Math.min(source.width, source.height);

      var radius:Number = size / 2;
      displacement = new Array(size);

      var hw:uint = source.width / 2;
      var hh:uint = source.height / 2;

      for (var i:uint = 0; i < size; i++) {
        displacement[i] = new Array(size);
        for (var j:uint = 0; j < size; j++) {
          var dx:int = i - radius;
          var dy:int = j - radius;
          var dist:Number = Math.sqrt(dx * dx + dy * dy);

          if (dist > radius) continue;

          var ndist:Number = dist / radius;
          ndist *= (Math.PI/2);
          ndist = Math.cos(ndist);
          ndist *= radius;
          ndist = radius - ndist;

          var angle:Number = Math.atan2(dx,dy) + Math.PI / 2;

          var ox:int = Math.cos(angle) * ndist;
          var oy:int = Math.sin(angle) * ndist;

          ox = hw - ox;
          oy = hh + oy;

          displacement[i][j] = { x: ox, y: oy };

        }
      }
      super(size, size, false, bgColor);
    }

    public function update() {
      for (var i:uint = 0; i < size; i++) {
        for (var j:uint = 0; j < size; j++) {
          if (displacement[i][j]) setPixel32(i,j,source.getPixel32(displacement[i][j].x,displacement[i][j].y));
        }
      }
    }
  }
}

A quick example of an implementation:

import fishEye;

var my_cam:Camera = Camera.getCamera();
my_cam.setMode(320,240,30);

var my_video:Video = new Video();
my_video.width = my_cam.width;
my_video.height = my_cam.height;
my_video.attachCamera(my_cam);

var bmd_video:BitmapData = new BitmapData(my_cam.width,my_cam.height);
var bm_video:Bitmap = new Bitmap(bmd_video);
bm_video.x = 0;
bm_video.y = 0;
addChild(bm_video);

var bmd_fisheye:fishEye = new fishEye(bmd_video);
var bm_fisheye:Bitmap = new Bitmap(bmd_fisheye);
bm_fisheye.x = my_cam.width;
bm_fisheye.y = 0;
addChild(bm_fisheye);

var updateInterval:uint = setInterval(update,1000 / my_cam.fps);

function update() {
  bmd_video.draw(my_video);
  bmd_fisheye.update();
}

It looks the same as before:

Faster fisheye with AS3

..but it’s a lot faster, go check it out. Flash has also something like a displacementMap filter, which I still have to try out, but as I’m trying to familiarize myself with AS3 (coming along nicely) I decided to take this path instead of the easy way.

Leave a Reply