I’m a huge fan of working with BitmapData inside Flash. It’s remarkably powerful and can be used to create a huge and varied amount of work. Perhaps you’ve seen Erik Natzke’s brilliant work, or Grant Skinner’s Interactive Elm Tree experiment, and have been wondering how you can use Flash as a viable artistic medium?

One approach to this question is to redraw an image based on certain algorithms, much as Photoshop would treat an image via a filter. Flash makes it easy to read pixel data and manipulate images. Circle Art allows the user to ‘paint’ with a magic brush that is affected by not just the mouse’s position but also the pixels under and around the cursor. For example, Circle Art can filter this source image:

pretty lady source image

pretty lady source image

into something like this:

or this:

Hollowed circles

Hollowed circles

or this:

Circle Art variation 3

Circle Art variation 3

Cicle Art Variation Octopus with skinny flat head

Cicle Art Variation Octopus with skinny flat head

Circle Art Variation 5

Circle Art Variation 5


Circle Art variation 6

Circle Art variation 6

Some video examples of Circle Art:

Or, with a slightly different pastel-like render loop:

The way this works is actually quite simple. At it’s core, Circle Art is responsible for reading a pixel and examining pixels in four directions (up, down, left, right) until the examined pixel’s color exceeds a given tolerance from the source pixel’s color. Once all four points have been found, we draw a circle centered inbetween the four points and color it the source pixel’s color. That is, essentially, the bulk of it, and what this means is that areas of the source image that have smoother colors will yield larger circles, and the areas of higher contrasting colors will produce smaller circles.

There’s a bit more magic going on, such as adding randomness to the source pixel’s x and y location so that if the user isn’t moving their mouse they’ll still be creating new circles, and a little blend mode action to excite the output image.

The fun part is playing with all the parameters to see how they affect the output. The pastel video above is only a few variables away from the other video, yet the effect appears nearly entirely different.

You can play with the demo here and download the source here.

And now, an explanation of the CircleArt class:

Most of the class should be fairly straightforward. We attach a bitmap as a source image, and set an event listener up to begin drawing circles at the mouseX and mouseY positions until the mouse is released. There are a few little hooks in there, such as the variable _loopCount which tell flash to draw more than one circle per loop, which makes the effect populate much faster.

The drawCircle method does the bulk of the work. First, pick a pixel ‘close’ to where the mouse is located:

private function drawCircle( xm:uint, ym:uint ) : void {
		var x:Number = Math.min( _sourceBD.width, Math.max(0, xm + Math.random() * _randomizer - Math.random() * _randomizer ) );
		var y:Number = Math.min( _sourceBD.height, Math.max(0, ym + Math.random() * _randomizer - Math.random() * _randomizer ) );

Next, get the color of the pixel and set up our local variables:

	var col:Number = _sourceBD.getPixel(x, y);

	var bounds:Rectangle = new Rectangle(x, y, _spacing, _spacing);

	var i:uint;
	var col2:uint
	var w:uint = _sourceBD.width;
	var h:uint = _sourceBD.height;

	var minX:uint = x - _spread;
	var minY:uint = y - _spread;
	var maxX:uint = x + _spread;
	var maxY:uint = y + _spread;

Now look in each direction (left, up, down, and right) up to the min and max values or until we encounter a pixel that has a greater color difference between the source pixel than our _threshold value. We store the values of each location by means of a rectangle.

	//left
	for (i = x - _jumpRate; i > minX; i -= _jumpRate) {
		col2 = _sourceBD.getPixel(i, y);
		if ( discreetColors( col, col2, _tolerance ) ) {
			bounds.left = i;
			break;
		}
	}

	//right
	for (i = x + _jumpRate; i  minY; i -= _jumpRate) {
		col2 = _sourceBD.getPixel(x, i);
		if ( discreetColors( col, col2, _tolerance ) ) {
			bounds.top = i;
			break;
		}
	}

	//bottom
	for (i = y + _jumpRate; i < maxY; i += _jumpRate) {
		col2 = _sourceBD.getPixel(x, i);
		if ( discreetColors( col, col2, _tolerance ) ) {
			bounds.bottom = Math.max(_spacing, i);
			break;
		}
	}

Now we’ll determine the area in which to draw our circle. Our circle will always be symmetrical (although interesting experiments occur when you draw different shapes), so we’ll pick the smaller of the rectangle’s width and height, but always ensure it’s larger than our _spacing variable, as sometimes Flash would be drawing a circle of zero radius.

	var width:Number = bounds.width;
	var height:Number = bounds.height;
	var scale:Number = Math.max( _spacing, Math.min( width, height ) );

	var halfSize:uint = Math.max(2, scale / 2);
	_circle.graphics.clear();
	_circle.graphics.lineStyle(0, col, .9 );
	_circle.graphics.drawCircle(0, 0, halfSize);

Finally, we’re ready to position our circle and draw it. Experimenting with difference BlendModes yields interesting results, as does adding filters to the circle, or altering the drawing order. In short, you can create many many different effects in these few lines of code:

	var mtx:Matrix = new Matrix();
	mtx.translate( bounds.left + bounds.width / 2, bounds.top + bounds.height / 2 );

	_circle.filters = [];

	// take a 'snapshot'
	_canvasBD.draw( _circle, mtx, null, BlendMode.NORMAL );

	_blurFilter.blurX = scale;
	_blurFilter.blurY = scale;
	_circle.filters = [_blurFilter];

	// draws on FIRE
	_canvasBD.draw( _circle, mtx, null, BlendMode.ADD );

}

And there you have it! I’d love to see what you come up with. The next steps for me are allowing the user to upload any image, as well as capturing the mouse movements so we can play back an ‘animation’ of the user’s mouse movements. I’d also like to take a note from Erik Natzke’s book and output large images that, perhaps one day, could be printed onto canvas.