07.18Tutorial - Creating the reflection of an image dynamically in AS3
You've seen it everywhere, even in the new iTunes. Basically the idea is to create a reflection of an image, as if the surface it is standing on was mirror-like.

I've managed to hack away some code using the BitmapData, Bitmap and Sprite classes. This is probably not an efficient way to do things, especially the changeAlpha function which adapts the negative color values (why do I get that?) for each pixel.
_art is a Sprite containing the image we want to create the reflection of; in my example _art has been scaled by fixing it's width and height dynamically, therefore we need to take that into consideration when drawing it's content into a BitmapData object
_artReflection is a Sprite which will contain the reflection
Here we go:
-
import flash.display.Bitmap;
-
import flash.display.BitmapData;
-
import flash.geom.Matrix;
-
-
protected function createReflection()
-
{
-
// you'll need to rewrite this, my _art variable is a covert art from a CD loaded dynamically, and I scale it previously
-
var xscale:Number = _art.scaleX;
-
var yscale:Number = _art.scaleY;
-
-
// create my scaling matrix to draw the bitmap into a bitmap data, since even it it's containing Sprite is scaled, it will draw the thing in full proportions otherwise
-
var scaleMatrix:flash.geom.Matrix;
-
scaleMatrix = new Matrix();
-
scaleMatrix.scale(xscale, yscale);
-
-
// create a bitmap data for the source bitmap, of the full dimensions of the image we are using to create the reflection from
-
var sourceBmp:BitmapData;
-
sourceBmp = new BitmapData(_art.width, _art.height, true, 0x00ffffff);
-
-
// draw the source (covert art in my case, into the bitmap data.
-
sourceBmp.draw(_art, scaleMatrix);
-
-
// the height of my reflection is 1/3 of the original image
-
var reflectionHeight:Number = Math.round(_art.height/3);
-
-
// variable to track the row we are writing in the target bitmapdata
-
var targetRow:Number;
-
-
// this is our starting alpha value (0 to 255). The reflection starts at 1/4th of alpha, going gradually to 0
-
var curAlpha:Number = 64;
-
-
// this is the step by which the alpha will lessen on each row, calculated based on the height of our reflection
-
var steps:Number = 64 / reflectionHeight;
-
-
// create our target bitmap data, same width as the original image, and using the height we calculated earlier
-
var targetBmp:BitmapData = new BitmapData(_art.width, reflectionHeight, true, 0x00FFFFFF);
-
-
// loop through the rows of pixels, starting at the bottom of the image to be reflected
-
for(var row:Number = _art.height-1; row> _art.height - reflectionHeight; row--)
-
{
-
// our target row is opposite the sourcerow, since we are reflecting it
-
targetRow = _art.height - row - 1;
-
-
// for each row, decrement the alpha
-
curAlpha -= steps;
-
-
// we go through columns left to right in both source and target image
-
for(var col:Number = 0; col <_art.width; col++)
-
{
-
// we set the pixel in the target image, using col, targetrow, and changing the alpha value of the pixel we get from the source image on the way
-
targetBmp.setPixel32(col, targetRow, changeAlpha(sourceBmp.getPixel32(col, row), Math.round(curAlpha)));
-
}
-
}
-
-
// create a bitmap from the bitmapdata
-
var image:Bitmap = new Bitmap(targetBmp);
-
-
// add it to the sprite we use to contain the reflection
-
_artReflection.addChild(image);
-
-
// and eventually position _art and _artReflection so that _art is right OVER the _artReflection
-
}
-
-
// this function alters the alpha value of a 0xAARRGGBB color value and returns the new color value
-
protected function changeAlpha(color:uint, alpha:int):uint
-
{
-
// decompose the 0xAARRGGBB value, each component is a byte, therefore from 0 to 255 in value.
-
var blueOffset:Number = color % 256;
-
var greenOffset:Number = ( color>> 8 ) % 256;
-
var redOffset:Number = ( color>> 16 ) % 256;
-
var alphaOffset:Number = ( color>> 24) % 256;
-
-
// i'm not sure why sometimes the color values are negative, but I remember 7 years ago in C++ under windows I did this hack and it worked.
-
if(greenOffset <0)
-
greenOffset += 256;
-
if(redOffset <0)
-
redOffset += 256;
-
if(blueOffset <0)
-
blueOffset += 256;
-
-
//trace("blue:"+blueOffset+", green:"+greenOffset+", red:"+redOffset+", alpha:"+alpha);
-
-
// recompose the 0xAARRGGBB value
-
return (alpha<<24|redOffset<<16|greenOffset<<8|blueOffset);
-
}
Voilà. Post your comments or questions! Or even better, improve the efficiency of my code!

Hi,
and thanks for the useful script!
How do you create a Sprite from an image loaded dynamically? Could you post some fast code about that?
Thanks
May 12th, 2008 at 8:50 am
useful !
September 9th, 2008 at 7:59 am
link to source if you’d like help with your code, mate.
regards
March 21st, 2009 at 2:06 am
if you cast as uint you won’t get negative values…
var alphaOffset:uint = color>>> 24 & 0xFF;
var redOffset:uint = color>>> 16 & 0xFF;
var greenOffset:uint = color >>> 8 & 0xFF;
var blueOffset:uint = color & 0xFF;
//i = (x ^ (x >> 31)) - (x >> 31); this is the same as math.abs …also ternary below
greenOffset=(greenOffset <0)?(-greenOffset):(greenOffset);
redOffset=(redOffset <0)?(-redOffset):(redOffset);
blueOffset=(blueOffset <0)?(-blueOffset):(blueOffset);
thanks again, this is fun to play with…
March 23rd, 2009 at 12:37 am
That’s pretty neat stuff, definitely fun to play with. As you said, probably not the most efficient, but it can be fixed up.
October 25th, 2009 at 12:09 pm
[...] least come with the addition of online leaderboards. … Mail (will not be published) (required) …intense creativity Tutorial - Creating the reflection of an …I’ve managed to hack away some code using the BitmapData, Bitmap and Sprite classes. … _art is a [...]
March 30th, 2010 at 8:08 am