Good old MiniDisc

May 11th, 2007

Like many people these days, I own an MP3-player. It wasn’t a cheap one, but it wasn’t expensive either and, well, despite it being able to play lossless audio, the audio-quality is not up to what I prefer. So, I decided to dig up my good old MiniDisc-player I had before I switched to more modern electronics. It turned out that it’s audio quality richly exceeds that of my MP3-player, despite the fact it uses lossy compression (AAC if I recall correctly).

So… I was quite content, let me tell you that. I think I’ll seriously switch back to MiniDisc until I can afford a Cowon iAudio X5 (which is great!).

Webcam bouncy ball

May 11th, 2007

For a project, we want to be able to play with ball in a webcam-game. It took me a while to figure out a good algorithm but I managed. It’s not perfect, but good enough for prototyping. It looks like this:

Bouncing ball in Flash with AS3

Of course, you can play too.

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.

Finally a new update and a new webcam

May 11th, 2007

So… here’s another update. A rather large one, for I’ve been silent for a time. Been busy, I bet you know the drill. I’ll post them separately though, just to keep things organized.

As you’ve been able to see, the quality of my webcam is not that great. Actually, to be honest, it sucks. I thus decided to get a new one. I bought a used PS2 EyeCam, since those are rather cheap (€17.50 for this one), compared to high-quality PC-webcams, which often cost over €40.00. The quality however is very good, although, since it has to squeeze all data over a slow USB 1.1 connection, compression is certainly visible. However, I can live with that, so it’s a big value for money, I’d say.

Shot from my new webcam

Compare that to the picture of my garden you can see in my previous post!

Flashy Fisheye

April 20th, 2007

Today I figured I’d make some fisheye lens out of my webcam. So I did.

It worked out fine, even though it isn’t optimized in any way. Here you have a look at my garden:
Webcam fisheye with AS3

Of course, you can also try this for yourself if you like. To spice things up, I’ve got the source here for you:

import flash.display.*;

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

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;
this.addChild(bm_video);

//size of the fish-eye BitmapData
var feSize:uint = Math.min(bmd_video.width, bmd_video.height);

var bmd_fisheye:BitmapData = new BitmapData(feSize,feSize,false,0xFF000000);
var bm_fisheye:Bitmap = new Bitmap(bmd_fisheye);
bm_fisheye.x = my_cam.width;
bm_fisheye.y = 0;
this.addChild(bm_fisheye);

var updateInterval:uint = setInterval(update,100);

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

  //hw,hh = centre of the video bitmap
  var hw:uint = bmd_video.width / 2;
  var hh:uint = bmd_video.height / 2;

  //radius of the 'lens'
  var radius:uint = feSize / 2;

  for (var x:uint = 0; x < feSize; x++) {
    for (var y:uint = 0; y < feSize; y++) {

      //calculate distance to the centre
      var dx:int = x - radius;
      var dy:int = y - radius;
      var dist:Number = Math.sqrt(dx * dx + dy * dy);

      //skip the rest if outside of the circle we want to draw
      if (dist > radius) continue;

      //This code calculates which pixel should be copied from
      //the original bitmap.

      //first, convert the current distance to a float 0..1,
      //indicating zero to maximum distance.
      var ndist:Number = dist / radius;
      //multiply by PI/2 - which is equivalent to an angle of 0-90°
      ndist *= (Math.PI / 2);
      //Do a cosine on that, which makes the 'fish-eye' effect come true
      ndist = Math.cos(ndist);
      //Since this is still a value between 0 and 1, multiply by the radius
      ndist *= radius;
      //It is still inverse (distance 0 -> cos(0) = 1; distance 1 -> cos(pi/2) =0)
      //substract ndist from radius
      ndist = radius - ndist

      //the angle at which the current pixel is located
      var angle = Math.atan2(dx,dy) + Math.PI / 2;

      //calculate x and y in original picture,
      //x is flipped and they are relative to the centre of the image
      var ox:int = Math.cos(angle) * ndist;
      var oy:int = Math.sin(angle) * ndist;

      //make them relative to the upperleft corner of the image
      ox = hw - ox;
      oy = hh + oy;

      //finally, copy the pixels
      bmd_fisheye.setPixel(x,y,bmd_video.getPixel(ox,oy));
    }
  }
}

Surely things can be done a lot faster with specialized filters, but I just wanted to see if I could work this out myself. Perhaps I’ll improve this later.