Flashier fisheye
May 11th, 2007The 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:
..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.
