Inverting the alpha of a bitmap image
Friday, November 30th, 2007A 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 imagesvar 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 gradientcolorImage.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 wellvar 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 imagealphaSplit.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 itvar alphaInvert:BitmapData = alphaSplit.clone();var matrix:Array = new Array();matrix = matrix.concat([1, 0, 0, 0, 0]); // redmatrix = matrix.concat([0, 1, 0, 0, 0]); // greenmatrix = matrix.concat([0, 0, 1, 0, 0]); // bluematrix = matrix.concat([0, 0, 0, -1, 0xff]); // alpha, negate the alpha and add 255alphaInvert.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 channelvar 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 gradientcolorImgWithAlpha.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");- Download this code: invertBitmapAlpha.txt