package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Loader; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.filters.BlurFilter; import flash.filters.GlowFilter; import flash.geom.Matrix; import flash.geom.Rectangle; import flash.net.URLRequest; [SWF(backgroundColor="#ffffff", frameRate="30")] public class ShadedRelief extends Sprite { private var loader : Loader = new Loader(); public function ShadedRelief() { loader.load( new URLRequest("molokai.png") ); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaded); } private var sourceBitmap : BitmapData; // source DEM private var reliefBitmap : BitmapData; // relief map output private var tintBitmap : BitmapData; // hypsometric tint output private function onLoaded( event : Event ) : void { sourceBitmap = new BitmapData( loader.width, loader.height ); sourceBitmap.draw( loader ); reliefBitmap = new BitmapData( loader.width, loader.height,true, 0 ); tintBitmap = new BitmapData( loader.width, loader.height); drawMap(); } private function drawMap() : void { // the color ramp for hypsometric tinting var gradientColors : Array = [0x0000ff,0x004000,0x679167, 0x81b279, 0xbfdfa8, 0xd0b8aa]; var gradientRatios : Array = [1,3,1*255/4,2*255/4,3*255/4,4*255/4]; var gradientAlphas : Array = [0,1,1,1,1,1]; var matrix : Matrix = new Matrix(); matrix.createGradientBox(255,5); var gradientShape : Shape = new Shape(); gradientShape.graphics.beginGradientFill("linear",gradientColors,gradientAlphas,gradientRatios,matrix); gradientShape.graphics.drawRect(0,0,255,5); gradientShape.graphics.endFill(); // draw gradient to a BitmapData and sample 256 colors from it var gradBmp : BitmapData; gradBmp = new BitmapData(255,5); gradBmp.draw(gradientShape); var colors : Array = []; for ( var n : int = 0; n < 256; n ++ ) { colors.push( gradBmp.getPixel32(n,2) ); } colors[0] = 0xffccccff; colors[1] = 0xffccccff; // loop through every pixel in the source image for ( var i : int = 0; i < sourceBitmap.width; i ++ ) { for ( var j : int = 0; j < sourceBitmap.height; j ++ ) { // draw hypsometric tint color var centerValue : Number = sourceBitmap.getPixel( i,j ) & 0x0000ff; tintBitmap.setPixel32( i,j,colors[int(centerValue)] ); // get slope values var topValue : Number = sourceBitmap.getPixel( i, Math.max(j-1,0) ) & 0x0000ff; var leftValue : Number = sourceBitmap.getPixel( Math.max(i-1,0), j ) & 0x0000ff; var rightValue : Number = sourceBitmap.getPixel( Math.min(i+1,sourceBitmap.width-1), j ) & 0x0000ff; var bottomValue : Number = sourceBitmap.getPixel( i, Math.min(j+1,sourceBitmap.height-1) ) & 0x0000ff; var slx : Number = (rightValue - leftValue)/3; var sly : Number = ( bottomValue - topValue )/3; var sl0 : Number = Math.sqrt( slx*slx + sly*sly ); // get aspect var phi : Number = Math.acos( slx/sl0 ); if ( sl0 == 0 ) { phi = 0; } var azimuth : Number; if ( slx > 0 ) { if ( sly > 0 ) azimuth = phi + 1.5*Math.PI; else if ( sly < 0 ) azimuth = 1.5*Math.PI - phi; else phi = 1.5*Math.PI; } else if ( slx < 0 ){ if ( sly < 0 ) azimuth = phi + .5*Math.PI; else if ( sly > 0 ) azimuth = .5*Math.PI - phi; else azimuth = .5*Math.PI; } else { if ( sly < 0 ) azimuth = Math.PI; else if ( sly > 0 ) azimuth = 0; } // get reflectance var sunElev : Number = Math.PI*.25; var sunAzimuth : Number = 1.75*Math.PI; var L : Number = Math.cos( azimuth - sunAzimuth )*Math.cos( Math.PI*.5 - Math.atan(sl0) )*Math.cos( sunElev ) + Math.sin( Math.PI*.5 - Math.atan(sl0) )*Math.sin( sunElev ); // draw reflectance to a gray in the relief map var grayValue : Number = int(255 * L); if ( grayValue < 0 ) { grayValue = 0; } // exclude ocean if ( centerValue >= 3 ) reliefBitmap.setPixel32(i,j,0xff << 24 | grayValue << 16 | grayValue << 8 | grayValue); } } // render images! var tintMap : Bitmap = new Bitmap(tintBitmap); tintMap.scaleX = tintMap.scaleY = .25; tintMap.filters = [ new BlurFilter(1.2,1.2) ]; addChild(tintMap); var reliefMap : Bitmap = new Bitmap( reliefBitmap ); addChild( reliefMap ); reliefMap.scaleX = reliefMap.scaleY = .25; reliefMap.filters = [ new BlurFilter(2,2),new GlowFilter(0xffffff,.75,45,45,3,2) ]; reliefMap.alpha = .3; } } }