AS Reference  :  Notes Index  :  Resources  :  About/Contact  :  Downloads

The BitmapData Class (Flash 8 or higher required)

The new online love of my life is NOAA, whose publicly available data files are a wonder. A couple weeks ago I discovered their weather forecasting web service, which can be used with Flash's WebService class to produce a Flash-based weather forecast for up to a week for any city in the US. The people at NOAA were very helpful in explaining some of the finer points of the forecast RSS file, and providing links to more information. Yesterday I found a whole new source of interesting data at NOAA's Geophysical Data Center. Among the data provided (for free) here is a complete database of global elevations.

What does this have to do with the BitmapData class? My first thought when I found this data was to try to use it to produce a sort of topographic map using traditional attachMovie methods to create a dot movieclip which I would attach repeatedly and color based on information in the data file. This quickly proved to be unworkable, as it took way too long to render the number of points required with vector graphics. Enter the BitmapData class, whose purpose is to allow the (relatively) quick rendering of bitmap (pixel-based) data in Flash. The results, including the amount of time taken for each step of the process (for 45,000 points) is shown above. A couple seconds to render a map for an area covering 20 degrees longitude and 10 degrees latitude is quite nice, I think.

BitmapData Class

Rendering bitmap data in a Flash movieclip is simple. Here's an outline of the BitmapData-related steps I used to make the sample above:

  1. Import the BitmapData class
  2. Create a new instance of the BitmapData class, specifying the width and height of the image to be created
  3. Use setPixel to specify the color of each pixel within the bitmap
  4. Create a movieclip to attach the bitmap to, and position it on stage (I did this with code, but it could be done in the IDE instead)
  5. Attach the bitmap to the movieclip, specifying whether smoothing is to be used or not (default is not)

This is the code to do that:

import flash.display.BitmapData;

// .. set up variables and read file data ..

   var topodata:BitmapData = new BitmapData(filedata.ncols, filedata.nrows);

   for (var row=0; row < filedata.nrows; row++) {
      for (var col=0; col < filedata.ncols; col++) {
         cell = row*filedata.ncols+col;
         for (var j=1; j<=colors.length; j++) {		 
            // .. find the right color for this pixel .. 
            topodata.setPixel(col, row, cellcolor);
            break;
         }
      }
   }
   
   this.createEmptyMovieClip("map1", 1);
   map1._x = 15;
   map1._y = 10;   
   
   map1.attachBitmap(topodata, 2, "auto", true);  
  

In the sample above, I created two movieclips and did a separate attachBitmap (of the same bitmapdata instance) to each, specifying smoothing for the top one and not for the bottom one, so you can see the difference when they are expanded.

Other notes about this sample

As is evident above, plotting elevations does not produce a true topographic map with contours or an accurate physical map (which would show actual land boundaries, shading of elevation changes, and an indication of the rainfall associated with an area by its color). But it does a pretty nice approximation, as can be seen by moving the slider at the bottom, which allows simultaneous viewing of a physical map of the same area (a piece of a National Geographic map which I scanned and skewed to get the latitude and longitude lines to match my rendering). And it brings out some interesting features by comparison, such as the fact that the area around the mouth of the Volga (appropriately named the Caspian Depression) is so low-lying that it is not distinguished from the water at all in my rendering, which makes me think the river must overflow a lot and which a bit of googling showed to in fact be the case). I played around with the color ranges for an hour or so, trying to get the best picture of actual landforms based on elevation and finally settled for using gradations of blue for everything at sea level and below, green starting with 50m, and yellow-going-to-red at 500m and above. This produces certain anomalies, such as the Crimean peninsula appearing to be an island instead of a peninsula, but it's so far the best combination of color ranges I've come up with to include an indication of lakes (often a bit higher than sea level) as well as oceans and seas. It does make obvious things like how deep the Black Sea is (especially compared to its neighbor, the Caspian). The color of each pixel was determined by finding its depth in an array of depth ranges I set up, and using the color range calculations described at the bottom of this page to get an intermediate value.

How to get the elevation data

The data I used for the map was obtained by using NOAA's GOEDAS Grid Translator with the input shown below:

This produces a comma-delimited text file which can be downloaded and read in using the LoadVars object and its onData method to create an array of elevation points to plot. Notice that the GEODAS program produces an indication of the number of rows and columns, which you can also plug into your Flash movie.

Parsing the data

To read the data from the text file created by GOEDAS, I used a loadVars instance with this onLoad function:

lv.onData = function(s:String) {
   // create an array where each element is one line from the data file
   // (covers all possible representations of a new line in the file)
   pts = s.split("\r\n");
   if (pts.length==1) pts = s.split("\r");
   if (pts.length==1) pts = s.split("\n");

   // put the 3rd comma-delimited value into the pts array	
   // overwriting its previous value
   for (var i=0; i <pts.length; i++) {
      var temp:Array = pts[i].split(',');
      pts[i] = Number(temp[2]);
   }
   drawPoints();
}

If you need to save a reference to the latitude and longitude associated with each point, you can do so by saving the first and second items in the comma-delimited string as well. If you don't need those points at all, you can get a smaller file from GEODAS by selecting the ASCII raster format instead of XYZ.

A zip file of the complete fla and data file used to produce the maps above may be downloaded by subscription from the link above at right. A faster version of this, made by saving the data from GEODAS in a compiled swf, can be found in the next sample in this section.

Intro
Flash: What & How
Example Sites
Create
Draw, Edit Shapes
Gradients
More Drawing Tips
Import
A Sample
Animate
Frames, Keyframes
Motion Tweens
More Motion Tweens
Shape Tweens
Masks
Control
Stop/Replay
Movieclips Intro
Movieclip Reference
Site Structure 1
Slideshow Movieclip
Contact Form
Scroll Resume
Preloader
Site Structure 2
Publish
Display Options
Player Detection
Optimize
AS 2.0 Basics
Intro to Syntax
Playhead Commands
Playhead Cmds 2
Coded Tween
onEnterFrame
Intro to Classes
Declare/Assign
Comments, Trace
Simple Data Types
Arrays & Objects
Code Blocks
Operators
Beyond Buttons
Code Structure
Toggle Controls
Group of Buttons
Drag and Hit
Distort Magnifier
Scroll Text
Bee Game
Dart Shooter
Sound Control
Easing Slider
Easing Slider 2
Components Intro
Timers & Delays
Dynamic Content
Intro
Drawing API
Create Text
Attach Movieclips
Easing Slider 3
Easing Slider 4
Load jpg/swf
Sliding Viewer
Preload swf
XML
Easing Slider 5
Server Comm
LoadVars (w/ PHP)
AS - PHP Lookup
Text File
Database 1:LoadVars
Database 2:Remoting
Read from directory
AS 2.0 Classes
Intro
Math
Key
Date
Color
EventDispatcher
New Samples
Pie Chart
Event-model Emailer
Tween Sequence
Fuse Sequence
SVG in Flash
Bitmap Topo
SWF as Data Holder
Two-level Menu
Yahoo! Flash Maps
Class-based Game
ASTB Samples
Disclaimer
3D Outlines
Bounce Collide
Address Book
Save Drawings
Home  :  Notes Index  :  Resources  :  About/Contact  :  Downloads