/* * IMAGETRANSFOMERR * * Turns one image into another image. It does this by first progressively turning the first image into a singel-colored square, and then progressively turning it into the second image. * Using an image-size that's a power of 2 means it is easy to go from single pixels to one single-color square by just multiplying the size to check with 2 each time. * * To recreate, you'll need to have the Flash9 ActionScript3 Preview installed, you can get it at http://labs.adobe.com/technologies/flash9as3preview/ * Create a new 256x256 FLA, and put 'ImageTransformer' (without quotes) as its Document Class. Test Movie et voila! * * @author Edwin Heijmen * @version 0.1 */ package { import flash.display.*; import flash.net.*; import flash.events.*; import flash.geom.*; import flash.utils.Timer; public class ImageTransformer extends MovieClip { private var imageW:Number; // width (is also height since we're dealing with a square image) private var squares:uint; // number of squares to check (same horizontall & vertically) private var sqSize:uint = 2; // size of square to use for averaging colors private var tggl:uint = 0; // toggle used to // used for loading images, displaying and updating it private var img1:Loader; private var img1loaded:Boolean = false; private var img2:Loader; private var img2loaded:Boolean = false; private var bm:Bitmap = null; private var bm1:Bitmap = null; private var bm2:Bitmap = null; private var bmd:BitmapData; private var bmd2:BitmapData; private var rect:Rectangle; private var myTimer:Timer; public function ImageTransformer () { // constructor // // load in pictures img1 = new Loader(); img1.contentLoaderInfo.addEventListener(Event.COMPLETE, image1Completed); var requestImage1:URLRequest = new URLRequest("ggoo_256x256.jpg"); img1.load(requestImage1); img2 = new Loader(); img2.contentLoaderInfo.addEventListener(Event.COMPLETE, image2Completed); var requestImage2:URLRequest = new URLRequest("ggoo_256x256_2.jpg"); img2.load(requestImage2); } private function image1Completed (event:Event):void { // image 1 has loaded in complete // img1loaded = true; // check if image 2 has loaded in too loadingCompleted(); } private function image2Completed (event:Event):void { // image 2 has loaded in complete // img2loaded = true; // check if image 1 has loaded in too loadingCompleted(); } private function loadingCompleted ():void { // loading is done, start working // if (img1loaded&&img2loaded) { // both images are loaded in // // get width & height imageW = img1.contentLoaderInfo.width; // number of squares to check horizontally squares = imageW/sqSize; // // first make sure we can distort image bm = Bitmap(img1.content); bmd = bm.bitmapData; addChild(bm); // cloe bitmapdata to use for 'depixelization' bm1 = new Bitmap(bmd.clone()); // // store bitmapdata of second image bm2 = Bitmap(img2.content); // // start executing function myTimer = new Timer(100); myTimer.addEventListener("timer",doPixelate); myTimer.start(); } } private function doPixelate (event:Event):void { // pixelates an image // var tX:uint; var tY:uint; var c1:uint; var c2:uint; var c3:uint; var c4:uint; var avg:uint; var sqNum:uint = squares*squares; // total number of squares to check var sq2:uint = sqSize/2; // loop over image based on number of squares to check and size of square for (var i:uint=0;iimageW) { squares = 1; sqSize = imageW; // determine which bitmap to use to 'depixelate' to if (tggl==1) bmd2 = bm1.bitmapData; else bmd2 = bm2.bitmapData; tggl = 1-tggl; // myTimer.removeEventListener("timer",doPixelate); myTimer.addEventListener("timer",doDepixelate); } } private function doDepixelate (event:Event=null):void { // depixelates an image // var tX:uint; var tY:uint; var c:uint; var colArr:Array; var sqNum:uint = squares*squares; // total number of squares to check var sq2:uint = sqSize/2; // loop over image based on number of squares to check and size of square for (var i:uint=0;iimageW) { sqSize = 2; squares = imageW/sqSize; myTimer.removeEventListener("timer",doDepixelate); myTimer.addEventListener("timer",doPixelate); } } private function determineAverage (c1:uint,c2:uint,c3:uint,c4:uint):uint { // determines the average of the 4 supplied colors // wrapped inside a function so it is easy to change this around for different effects // // calculate channels var c1Arr:Array = getColorChannels(c1); var c2Arr:Array = getColorChannels(c2); var c3Arr:Array = getColorChannels(c3); var c4Arr:Array = getColorChannels(c4); // // get averages for red, green & blue var red:uint = uint((c1Arr[0]+c2Arr[0]+c3Arr[0]+c4Arr[0])/4); var green:uint = uint((c1Arr[1]+c2Arr[1]+c3Arr[1]+c4Arr[1])/4); var blue:uint = uint((c1Arr[2]+c2Arr[2]+c3Arr[2]+c4Arr[2])/4); // // return averaged color return red<<16|green<<8|blue; } private function determine4Colors (pX:uint,pY:uint,c:uint):Array { // determines the 4 new colors for the depixelation based on color c and the image to depixelate // var colArr:Array = new Array(); var red:uint; var green:uint; var blue:uint; var sq2:uint = uint(sqSize/2); var o:uint = uint(sq2/2); // to determine middle of each new square var mX:uint = pX+o; var mY:uint = pY+o; // get color of 4 pixels in the second image var c1:uint = bmd2.getPixel(mX,mY); var c2:uint = bmd2.getPixel(mX+sq2,mY); var c3:uint = bmd2.getPixel(mX,mY+sq2); var c4:uint = bmd2.getPixel(mX+sq2,mY+sq2); // // calculate channels var c1Arr:Array = getColorChannels(c1); var c2Arr:Array = getColorChannels(c2); var c3Arr:Array = getColorChannels(c3); var c4Arr:Array = getColorChannels(c4); var cArr:Array = getColorChannels(c); var cA0:Number = cArr[0]/2; var cA1:Number = cArr[1]/2; var cA2:Number = cArr[2]/2; // // get averages for each of the 4 squares // top-left red = uint(c1Arr[0]/2+cA0); green = uint(c1Arr[1]/2+cA1); blue = uint(c1Arr[2]/2+cA2); colArr.push(red<<16|green<<8|blue); // top-right red = uint(c2Arr[0]/2+cA0); green = uint(c2Arr[1]/2+cA1); blue = uint(c2Arr[2]/2+cA2); colArr.push(red<<16|green<<8|blue); // bottom-left red = uint(c3Arr[0]/2+cA0); green = uint(c3Arr[1]/2+cA1); blue = uint(c3Arr[2]/2+cA2); colArr.push(red<<16|green<<8|blue); // bottom-right red = uint(c4Arr[0]/2+cA0); green = uint(c4Arr[1]/2+cA1); blue = uint(c4Arr[2]/2+cA2); colArr.push(red<<16|green<<8|blue); // // return return colArr; } private function drawSquare (pX:uint,pY:uint,c:uint):void { // draws a square of size sqSize at (pX,pY) of color c // // define region to fill rect = new Rectangle(pX,pY,sqSize,sqSize); // fill it bmd.fillRect(rect,c); } private function getColorChannels (c:uint):Array { // returns the red, green & blue colors for the supplied color // // see http://flash-creations.com/notes/actionscript_operators.php under Bitwise operators // var cArr:Array = new Array(); cArr.push((c>>16)); // red cArr.push((c>>8)&0xff); // green cArr.push(c&0xff); // blue // return return cArr; } } }