Inverting the alpha of a bitmap image in ActionScript 2

A piece of code and a demo says more than a thousand words :). This code demonstrates inversion of an alpha channel in Flash8/AS2.


/**
 * This example demonstrates inverting an alpha channel on an image.
 * Since Flash premultiplies the alpha, we need to keep two separate images: one with the color data, and 
 * one with the alpha data.  It demonstrates splitting the alpha from an image, inverting and proves 
 * premultiplying the alpha destroys color information.
 *
 * @author J.C. Wichman / Objectpainters.com
 */

import flash.geom.Rectangle;
import flash.geom.Point;
import flash.display.BitmapData;
import flash.filters.ColorMatrixFilter;

//set up some default params for the images
var width:Number = 100;
var height:Number = 100;
var fillColor:Number = 0x000000;

/**
 * Simple function that checks how many bitmaps have already been shown on stage and
 * bases the location for the next one on that information. Never use code like this
 * out of context, since its bad programming practice:).
 */
function showBitmap (pBitmap:BitmapData, title:String) {
	var imageCount:Number = this.getNextHighestDepth();
	var row:Number = Math.floor (imageCount/3);
	var columns:Number = imageCount%3;

	var newClip:MovieClip = this.createEmptyMovieClip("image"+imageCount, imageCount);
	newClip.attachBitmap(pBitmap, 0);
	newClip.createTextField("title", 1, 0, 110, 10,10);
	var textClip:TextField = newClip["title"];
	textClip.autoSize = true;
	textClip.text = "Image "+imageCount+":\n"+title;
	var tf:TextFormat = new TextFormat();
	tf.font = "Arial";
	tf.align ="center";
	textClip.setTextFormat(tf);
	
	newClip._x = (columns * 150)+10;
	newClip._y = (row * 170)+10;
}


//setting up demo rgb image, this is an image without alpha. 
//Since flash uses premultiplied alpha, adding an alpha channel will ruin the image for
//further use when we want to invert the alpha channel, so we keep colours separate from alpha
//(omg pink shirts!)
var colorImage:BitmapData = new BitmapData(width, height, false, fillColor);
for (var x = 0; x < width; x++) {
	for (var y = 0; y < height; y++) {
		//fiddle with the pixel data to show a dark gradient
		colorImage.setPixel( x,y, x<<16|y<<8|x+y);
	}
}
showBitmap (colorImage, "Colour w/o alpha");

//now we create a demo alpha bitmap. All color info is non existent, only
//alpha data is set. When x<y the alpha value is near opaque, otherwise its near transparent.
//we only use 0xAF and 0x10 instead of 0xFF and 0x00 to show partial alpha values are inverted ok as well
var demoAlpha:BitmapData = new BitmapData(width, height, true, fillColor);
for (var x = 0; x < width; x++) {
	for (var y = 0; y < height; y++) {
		demoAlpha.setPixel32( x,y, (x<y?0xAF:0x10)<<24);
	}
}
showBitmap (demoAlpha, "Alpha only");

//now imagine you didnt have a separate alpha bitmap to start with, but a starting image with alpha
//which you needed to extract first:
var alphaSplit:BitmapData = new BitmapData(width, height, true, fillColor);
//copy the alpha channel of one image to another image
alphaSplit.copyChannel(demoAlpha, new Rectangle(0,0, width, height), new Point(0,0), 8,8);
showBitmap (alphaSplit, "Alpha channel copy\n (same as previous)");

//now we are going to invert the alpha. This can be done on a pixel by pixel basis, but this might just
//be faster, you'd have to test it
var alphaInvert:BitmapData = alphaSplit.clone();
var matrix:Array = new Array();
matrix = matrix.concat([1, 0, 0, 0, 0]); // red
matrix = matrix.concat([0, 1, 0, 0, 0]); // green
matrix = matrix.concat([0, 0, 1, 0, 0]); // blue
matrix = matrix.concat([0, 0, 0, -1, 0xff]); // alpha, negate the alpha and add 255
alphaInvert.applyFilter(alphaInvert, alphaInvert.rectangle, new Point(0, 0), new ColorMatrixFilter (matrix));
showBitmap (alphaInvert, "Inversion of \nalpha channel");

//now the real action, we combine our original color pixels with the inverted alpha channel
var comboImage:BitmapData = new BitmapData(width, height, true, fillColor);
comboImage.copyPixels(colorImage, colorImage.rectangle, new Point(0,0), alphaInvert, new Point(0,0));  
showBitmap (comboImage, "Colours + \ninverted alpha");

//now to prove premultiplied alpha destroys color information:
var colorImgWithAlpha:BitmapData = new BitmapData(width, height, true, fillColor);
for (var x = 0; x < width; x++) {
	for (var y = 0; y < height; y++) {
		//fiddle with the pixel data to show a dark gradient
		colorImgWithAlpha.setPixel32( x,y, (x<y?0xfe:0x01)<<24|x<<16|y<<8|x+y);
	}
}
colorImgWithAlpha.applyFilter(colorImgWithAlpha, colorImgWithAlpha.rectangle, new Point(0, 0), new ColorMatrixFilter (matrix));
showBitmap (colorImgWithAlpha, "Colour with\n premultiplied \n inverted alpha");

Casting to Array in ActionScript 2

Imagine you have:
var my2dArray:Array = new Array();

my2dArray.push ([1,2,3,4,5]);
my2dArray.push ([6,7,8,9,0]);

And now you want to access and cast an element of myArray to an array:

var firstArray:Array = Array (my2dArray[0]);
trace (firstArray.length);

Right?
Read more