The [Embed] metadata tag has been in AS3 since the beginning, but few know how to use it fully. Today’s article shows how you can go beyond the standard usage to maximize the usefulness of [Embed]. Read on for some useful tricks you may not know about and take another step toward mastering AS3.

First of all, let’s talk about the basics of [Embed] in case it’s a new concept to you. This metadata tag tells the compiler to embed a file into the SWF and bind it to whatever comes after it. A huge majority of the code you see using this, including every [Embed] on this site, looks like this:

public class MyClass
{
	// Embed "someimage.png" and bind it to the SOME_IMAGE variable
	[Embed(source="someimage.png")]
	private static const SOME_IMAGE:Class;
 
	public function foo(): void
	{
		// Instantiate the bound variable to get an object with the file's data
		var someImageObj:Object = new SOME_IMAGE();
 
		// Since we bound a PNG image file, the object you get is a Bitmap
		var someImage:Bitmap = someImageObj as Bitmap;
 
		// ... do whatever you'd like with someImage
		trace("Dimensions: " + someImage.width + "x" + someImage.height);
	}
}

The above works for images. This works for arbitrary data files:

public class MyClass
{
	// Embed "somedata.dat" and bind it to the SOME_DATA variable
	[Embed(source="somedata.dat", mimeType="application/octet-stream")]
	private static const SOME_DATA:Class;
 
	public function foo(): void
	{
		// Instantiate the bound variable to get an object with the file's data
		var someDataObj:Object = new SOME_DATA();
 
		// Since we bound a binary file, the object you get is a ByteArray
		var someData:ByteArray = someDataObj as ByteArray;
 
		// ... do whatever you'd like with someData
		trace("Size KB: " + (someData.length / 1024));
	}
}

The only difference is in adding the mimeType to the [Embed] tag to tell the compiler to embed the file as a ByteArray rather than a Bitmap. There are other types you can embed (e.g. Font), but we’ll limit to these two types for the purposes of this article.

One of the disadvantages to the above approach is that the mx.core.BitmapAsset class will be included in your SWF and thus add to its file size even though you almost certainly only care that it ultimately derives from Bitmap and therefore has all the useful properties like having an accessible BitmapData for manipulator and uploading to Stage3D textures. It turns out that if you’re willing to use an alternative syntax for the [Embed] metadata tag that you can actually skip embedding these mostly-irrelevant classes. This isn’t covered in Adobe’s documentation. Here’s how the alternate version looks:

///////////////
// SomeImage.as
///////////////
 
[Embed(source="someimage.png")]	
public class SomeImage extends Bitmap
{
	public function get dimensions(): String
	{
		return width + "x" + height;
	}
}
 
/////////////
// MyClass.as
/////////////
public class MyClass
{
	public function foo(): void
	{
		// Instantiate the bound class to get the embedded image
		var someImage:SomeImage = new SomeImage();
 
		// ... do whatever you'd like with someImage
		trace("Dimensions: " + someImage.dimensions);
	}
}

Here you’re explicitly providing a class to bind the file to rather than using a variable typed as a Class. So you don’t need any casting and know at compile time exactly what you’re instantiating. You can also add functionality to the class like how SomeImage has a function to return a String description of its dimensions. Unfortunately, it requires that you add another file if you want to use the embedded resource file from more than one source code (i.e. .as) file.

Here’s how this alternate version would look for arbitrary, binary data:

///////////////
// SomeData.as
///////////////
 
[Embed(source="somedata.dat", mimeType="application/octet-stream")]
public class SomeData extends ByteArray
{
	public function get lengthKB(): uint
	{
		return length / 1024;
	}
}
 
/////////////
// MyClass.as
/////////////
public class MyClass
{
	public function foo(): void
	{
		// Instantiate the bound class to get the embedded data
		var someData:SomeData = new SomeData();
 
		// ... do whatever you'd like with someData
		trace("Size KB: " + someData.lengthKB);
	}
}

In summary, this alternate syntax allows you to avoid embedding extra classes like mx.core.BitmapAsset, derive classes from embedded files to add on functionality, and gain some compile-time confidence by skipping the need for casting from plain Object. Why not give it a try next time you need to [Embed]?

Spot a bug? Have a question or suggestion? Post a comment!