Home > ActionScript, Tutorials > Bitmap Basics

Bitmap Basics

September 13th, 2010 Leave a comment Go to comments

After i posted my last item on Perlin Noise in bitmaps, i realised that it wasn’t much help if you don’t know much about bitmaps, so here’s an introduction…

Why use Bitmap? Well for starters, Bitmaps render a lot quicker than Sprites, Shapes etc – not a problem if you only have 10 items on the stage but a big issue if you have hundreds or thousands of objects all moving around. Thats not to say you should always use bitmaps – they usually look awful when scaled for instance – but they definitely have their moments.

Simply put, the Bitmap class allows you to display images – either from the library, an external file or created programmatically. Before we look at how we do that, lets take a look at the class itself to see how it works.

var bmd:BitmapData = null;
var pixelSnap:String = "auto";
var smooth:Boolean = false;
var bm:Bitmap = new Bitmap(bmd, pixelSnap, smooth);
addChild(bm);

bmd – this holds the actual image information.
pixelSnapping – whether to align the image with pixel boundaries (either “auto”, “always” or “never”).
smoothing – whether to smooth the image when it is scaled (true) or allow pixelation (false).

In this example, we create a new bitmap object (using the default parameters) and add it to the stage. If you run it, nothing seems to happen – thats because bitmapData (the image information) is set to null; the bitmap is on the stage but as it has zero width and height you can’t see it!

Adding something meaningful instead of null is what we want, so lets start by showing how to grab an image from the library and display that.

Displaying an image from the library

To add an image from the library at runtime is pretty easy. You just have to make a change to the properties of the image in the library to make it work.

First, create a new .fla file and import an image into the library by selecting file / import / import to library. Right-click on an image in the library to bring up the properties inspector.

Image Properties InspectorMake sure that ‘Export for ActionScript’ and ‘Export in frame 1′ are both selected (if you can’t see them, try clicking on ‘Advanced’ to reveal more options). For ‘Class’, you can leave the default name or change it; either way, make a note of it because we’ll need it later.

In my example i have changed the name to ‘MyImage’ (there are restrictions on naming – you can only use the following characters: A-Z, a-z, 0-9 and underscore, and the first character can’t be a number). None of the other options need changing so leave them as they are for now.

When you click ‘OK’ a warning popup will appear – you can safely ignore that as we are not using the features it is warning us about – so click ‘OK’ again.

Now we can start coding. We’ll add the code to the timeline rather than in a seperate class, to keep it simple.

//grab a copy of the image from the library
//using the Class name we assigned earlier
var bmd:MyImage = new MyImage();
//create a Bitmap object and pass in the image information
//in this and other examples, i won't bother with the pixelSnapping
//and smoothing parameters for Bitmap - the default settings are fine
var bm:Bitmap = new Bitmap(bmd);
//add bitmap to the stage
bm.x = 50;
bm.y = 50;
addChild(bm);

Pretty straight-forward if you ask me! Just change the two mentions of ‘MyImage’ to whatever Class name you gave the image in the library earlier. Here’s the result:

{BitmapExample1}

Now in this case it is obviously much easier just to drag the image from the library to the stage rather than messing about with properties and code – much less effort. The advantage of doing it this way is that you have much more control if you need it – e.g: tiling the image as a background.

Displaying an image from a file

If you’re loading an image at runtime, you need to use the Loader class to load your image. The details of the Loader class are beyond this introduction but there are plenty of good tutorials around if you want to know more, including a full example in the Adobe documentation.

Here’s a simple example. This time as a class rather than directly on the timeline:

package
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.net.URLRequest;
 
	[SWF(backgroundColor="#CCCCCC", frameRate="30", width="200", height="200")]
	public class BitmapExample2 extends Sprite
	{
		//store reference to loader object
		private var ldr:Loader;
 
		public function BitmapExample2()
		{
			//do some general housekeeping
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			//create a new loader object
			ldr = new Loader();
			//create a url request object pointing to the image file to load
			var req:URLRequest = new URLRequest("image2.jpg");
			//listen for the load complete event
			ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loadHandler);
			//start loading the image file
			ldr.load(req);
		}
 
		//called when image has loaded
		private function loadHandler(event:Event):void
		{
			//grab image from the loader
			//the image data is stored in the content property
			//we use "as Bitmap" so the compiler doesn't throw a compile time error in strict mode
			var bm:Bitmap = ldr.content as Bitmap;
			//add bitmap to stage
			bm.x = 50;
			bm.y = 50;
			addChild(bm);
			//remove listener from loader
			ldr.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadHandler);
			//delete loader object
			ldr = null;
		}
 
	}
}

First, in the constructor we set up the Loader object and tell it to load the image. When the image has loaded, loadHandler(…) is called. In loadHandler, we create the bitmap object and add it to the stage. Lastly, we remove the listener from the loader object and set it to null. This allows garbage collection to remove the loader object as we don’t need it any more.

For this example it’s overkill, but it’s good to get into the habit of clearing up your unused listeners and objects – when you come to create something more complex it becomes a necessity. However, thats a whole other subject so i shouldn’t digress.

Note that when we grab the image from the loader object, we create the Bitmap object directly – ie: we dont have to create a seperate BitmapData object and pass it in as we did in the previous example. Again you now have full control over the image data to do something interesting with. Just one more situation to cover now…

Creating an image with code

To create a new bitmap from scratch, we just to create our own custom BitmapData object. We do it like this:

var w:uint = 100;
var h:uint = 100;
var transparent:Boolean = false;
var colour:uint = 0xFF0000;
var bmd:BitmapData = new BitmapData(w, h, transparent, colour);

w & h – width and height of the image. The maximum allowed values vary depending on which player you are targetting: for FP9 or AIR1.1 (or earlier) the maximum is 2880 for width or height. For FP10 and AIR1.5 onwards, the maximum is 8191 for width or height but with a further limit that width x height is less or equal to 16,777,215. E.g: for a width of 8191, the maximum height is 2048.

Setting transparent to true, clearly (ahem!) gives a transparent bitmap and the colour is the initial fill/background colour of the image in RGB (transparent = false) or ARGB (transparent = true).

In this example, we create a 100×100 bitmap:

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
 
	[SWF(backgroundColor="#CCCCCC", frameRate="30", width="200", height="200")]
	public class BitmapExample3 extends Sprite
	{
		public function BitmapExample3()
		{
			//do some general housekeeping
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			//create a new BitmapData object
			var bmd:BitmapData = new BitmapData(100, 100, true, 0x80FFFF00);
			//create bitmap and pass in BitmapData object
			var bm:Bitmap = new Bitmap(bmd);
			//add bitmap to stage
			bm.x = 50;
			bm.y = 50;
			addChild(bm);
		}
 
	}
}

Note that transparency is set to true so we use an ARGB format for the colour – alpha is set at 50% and RGB part set as yellow.

Doing something

Now that we have our bitmap object (and its underlying bitmapData property) we can manipulate pixels at will. We can apply filters or use drawing methods to change the image – this is will be the subject of my next post but for now i will leave you with a simple example of drawing on a bitmap with a rectangular fill:

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.geom.Rectangle;
 
	[SWF(backgroundColor="#CCCCCC", frameRate="30", width="200", height="200")]
	public class BitmapExample4 extends Sprite
	{
		public function BitmapExample4()
		{
			//do some general housekeeping
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
 
			//create a new BitmapData object
			var bmd:BitmapData = new BitmapData(100, 100, false, 0x000000);
			//rectangle object points to area of bitmapdata to fill
			var rect:Rectangle = new Rectangle(0, 0, 100, 5);
                        //keep looping until rect.y equals height of bitmapdata
                        while (rect.y!=100)
                        {
				//fill the area of bitmapdata signified by rect
				//with a random colour
				bmd.fillRect(rect, Math.random()*0xFFFFFF);
				//move rect down 5 rows
				rect.y += 5;
			}
			//create bitmap and pass in BitmapData object
			var bm:Bitmap = new Bitmap(bmd);
			//add bitmap to stage
			bm.x = 50;
			bm.y = 50;
			addChild(bm);
		}
 
	}
}

{BitmapExample4}

Not exactly art, i know. Hopefully, when we get into filters next time, you’ll be more impressed. Until then, happy coding.

SOURCE CODE: Bitmap-Basics.zip

*