A basic understanding of coding with the ActionScript 3 syntax is required. Prior experience working with Flash Professional and Photoshop is helpful.
Beginning
The ideal image format to use when building web apps is, hands down, the Portable Network Graphics (PNG) file format. Besides using lossless data compression, the PNG image format offers the following benefits:
These are just a few of the reasons this format is used most often by designers when displaying logos, Flash assets, and graphics for the web. The only downside I've noticed with using PNG files is the slightly increased file size that is the result of the extra 8-bit (alpha channel data information) that it supports.
In this article, I describe a strategy for using ActionScript 3 to optimize graphic assets in your Flash projects. By following these instructions, you'll learn how to use two JPEG files to reproduce the alpha channel of a PNG file. This technique enables you to reduce the file size of images rendered in Flash by leveraging the PNG file format's support for transparency.
Although bandwidth is ever increasing, there are still many reasons why you should strive to develop projects with the smallest possible file size. With the latest trends of mobile and wireless devices, it's difficult to predict the bandwidth available to your target users. Delivering an app with optimized graphics (making it faster and easier to download) is always a good goal to achieve, regardless of the platform.
Since Flash is the leader in delivering rich media advertising, the element that typically increases the file size the most in a project is the visual content, or more specifically the image files used for display.
Portable Network Graphic (PNG) files are most commonly used when transparency is required for a design. However, including PNG files often causes an increase in a project's file size because of the extra channel required for the alpha information, even if there is only a very small area of transparency in the image. While transparency is a necessity for complex layouts, every pixel in the graphic has one byte of extra data added to support the transparent areas. For example, a transparent 100 × 100 pixel PNG image is 10 KB of lossless information larger than a non-transparent image of the same size, due to the alpha channel. You can imagine how this could potentially increase, adding to the size of your project as well as the individual file sizes of the PNG images. (A transparent PNG file that's 500 × 500 pixels contains 250 KB of added lossless information.)
It is possible to achieve the same effect of a PNG file set with alpha transparency by mapping two JPEG files together with ActionScript at runtime to produce the alpha channel. To accomplish this, you need the two JPEG source files—one to hold all the pixels that will need to be visible, the original, and one to act as the mask for those pixels, the matte—and a small amount of code to merge the exact pixels from both original and matte into a final transparent image.
To follow along with these instructions, do one of the following:
Note: The sample_project folder contains a file named Readme.txt with information about the folder structure of this project. Be sure to read it before continuing with these instructions.
The sample_project folder will be your work environment. The folder structure is set up to mirror that of the folder labeled completed, located at the same root level. The sample project contains the masterImage.png which is referenced within this tutorial, or you can replace that with one of your own.
Follow these steps:
In this part, you'll create the matte (a black and white image) that will contain the data about which parts of the Original.jpg pixel data should show through (as though transparent) and what parts should be displayed (the opaque graphics).
Follow these steps:
Note: If desired, you can temporarily hide the white background layer to confirm that the black clipping mask on the top contains areas of transparency, with the checkerboard pattern showing through. Be sure to turn the visibility of the bottom white layer back on before continuing.
Using these two JPEG images (Original.jpg and GrayScale.jpg), you'll recreate the appearance of the original transparent PNG graphic with ActionScript at runtime.
There are still a few more steps to create and edit the Flash file before you add the code. Follow these steps:
A definition for this class could not be found in this class path, so one will automatically be generated in the SWF file upon export.
In the next section, you'll add the ActionScript code to convert the two JPEG graphics and make them appear as though they are a single PNG file with transparency.
In the first part of this article, you created two JPEG files using the same PNG file:
You also created a new Flash file. Then you imported the two files listed above and set the Linkage properties of both JPEG files to Export for ActionScript to make the image data available to the SWF at runtime.
In this section, you'll create a new class file that contains the code to merge the two JPEG images and generate the alpha channel. Follow these steps:
package
{
//import the necessary definitions
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.ByteArray;
public class ColorAndAlphaCompared extends Bitmap
{ //variable to hold our grayscale bitmap
private var _greyScale:BitmapData;
//variable to hold our colored bitmap
private var _coloredImage:BitmapData;
//variable to hold the resultant bitmap
private var _newBitmapData:BitmapData;
//variable to hold the our greyscaleImagePixels
private var _origVector:Vector.<uint>;
//variable to hold the our coloredImagePixels
private var _colorVector:Vector.<uint>;
private var _vector:Vector.<uint>;
//pass in references to our colored & grayscale images into our constructor.
public function ColorAndAlphaCompared(bitmapData : BitmapData,greyScaled : BitmapData)
{
_vector = new Vector.<uint>();
_greyScale=greyScaled;
_coloredImage=bitmapData;
//instantiate new BitmapData with the width & height of either of our jpg references and set its transparent property to true.
_newBitmapData=new BitmapData(greyScaled.width,greyScaled.height,true,0x00000000);
/*use the lock method on our newBitmapData to prevent our redraws as we add new pixels to it*/
_newBitmapData.lock();
/*pass our bitmapData into the constructor of the super class this class extends. (Bitmap class)*/
super(_newBitmapData);
/*store the pixels of the entire bounds of our greyScale image*/
_origVector=_greyScale.getVector(_greyScale.rect);
/*since we will never adjust the vectors length set its fixed value to true*/
_origVector.fixed=true;
/*store the pixels of the entire bounds of our coloredImage*/
_colorVector=_coloredImage.getVector(_coloredImage.rect);
/*set the fixed variable to true*/
_colorVector.fixed=true;
/*begin the analysis of the two vectors*/
readWrite();
}
/*readWrite:
* This method will loop through each index of both our vectors and store the
* analyzed version into a final vector
*/
protected function readWrite():void
{
/*how many times do we need to analyze our data*/
var totalPixels:int=_colorVector.length;
var i:int=0;
/*define the length of our resultant vector*/
_vector.length=totalPixels;
/*set fixed property to true*/
_vector.fixed=true;
/*loop through all pixels until 0 is reached*/
while (--totalPixels)
{
/*set the current index of the vector to the result of the two analyzed pixels*/
_vector[totalPixels]=int(shiftPixels(int (_origVector[totalPixels]),int(_colorVector[totalPixels])));
} /* end of our loop*/
/* set the new pixels into the bound area of our _newBitmapData*/
_newBitmapData.setVector(_newBitmapData.rect, _vector);
/* unlock _newBitmapData so that the player will redraw the new content*/
_newBitmapData.unlock();
/*rid the unused content to to free up memory*/
dispose();
}
/*shiftPixels:
*This method accepts two different pixels. One to represent the value of
*alpha and the other merely as the color value. The two pixels are merged
*into a resulting 32bit ARGB value and returned to the caller of the
*method.
*/
private function shiftPixels(alphaChannel : uint,colorChannel : uint):uint
{
/*extract the blue channel from the pixel representing the alpha value*/
var decimal:uint=alphaChannel>>16&0xFF;
/*prepend our blue channel as the alpha of our colorChannel pixel*/
var argb : uint = (decimal << 24) | (ColorAndAlphaCompared.extractRED(colorChannel)<<16) | (ColorAndAlphaCompared.extractGREEN(colorChannel)<<8) | ColorAndAlphaCompared.extractBLUE(colorChannel);
/*return the combined ARGB value*/
return argb;
}
/*Dispose:
*This method frees up memory used when creating the Transparent image
*/
private function dispose():void
{
/*rid the greyScale image*/
_greyScale.dispose();
/*rid the _coloredImage image*/
_coloredImage.dispose();
/*remove the vectors*/
_vector=_colorVector=_origVector=null;
/*remove references to our jpgs*/
_greyScale=_coloredImage=null;
}
/*extractAlpha:
*This method extracts the alpha value of a supplied hex value
*/
static private function extractALPHA(hex : uint):uint
{
return hex >> 24 & 0xff;
}
/*extractRED:
*This method extracts the red value of a supplied hex value
*/
static private function extractRED(hex : uint):uint
{
return hex >> 16 & 0xff;
}
/*extractGREEN:
*This method extracts the green value of a supplied hex value
*/
static private function extractGREEN(hex : uint):uint
{
return hex >> 8 & 0xff;
}
/*extractBLUE:
*This method extracts the blue value of a supplied hex value
*/
static private function extractBLUE(hex : uint):uint
{
return hex & 0xff;
}
}
}
You have now successfully generated the ActionScript class that utilizes the bitmap data of the two JPEG files to create an alpha channel.
In this section, you'll create one more ActionScript class file. This serves as the document class for the FLA file named BuiltPNG.fla that you saved in the sample_project/flash/bin folder.
Follow these steps:
This class is not only the base class for the BuiltPNG.swf, but also contains the code that connects the images imported into the Library to the ColorAndAlphaCompared class. This is also the class that displays the combined results of the two merged JPEG files.
package
{
//import the necessary definitions
import ColorAndAlphaCompared;
import flash.display.Sprite;
public class FullColor extends Sprite
{
public function FullColor()
{
/*add the instance of ColorAndAlphaCompared to our DisplayList and pass in the references to our colored image & grayscale Image)*/
addChild(new ColorAndAlphaCompared(new Original(1,1),new Grayscale(1,1)));
}
}
}
At this point, all the pieces are in place. The last step is to hook up the project's document class and test the movie to see the results. Follow these steps:
Flash Player loads to display the results. The image data of the two JPEG files has been combined to form a transparent image, which closely resembles the original masterImage.png you opened at the beginning of this sample project. If desired, you can return to Flash, change the Stage color of the BuiltPNG.fla file and publish the file again. You'll see that the color of the Stage shows through the areas that were transparent in the original PNG file (see Figure 4).
The FullColor.as file instantiates the ColorAndAlphaCompared class and passes in a reference to both JPEG files, which are located in the SWF's Library.
The ColorAndAlphaCompared.as file programmatically manipulates the two JPEG source files into a new Bitmapdata with an alpha channel. Because the ColorAndAlphaCompared class extends the Bitmap class, the FullColor.as file adds the instance of the returned bitmap to the Stage. When the final image is rendered, it is immediately visible.
The ColorAndAlphaCompared class accepts two BitmapData files. In this example, it accepts a grayscale image file and a full color image file. The code extracts a 32-bit pixel value for every pixel that both images contain. After extraction, the pixel values of both images are systematically added together to generate a new 32-bit pixel image.
Since the grayscale JPEG image you created is only one color, you could use any channel to represent the alpha channel. This is possible because all three channels hold the exact same information. Next, through the use of binary shifting (bits being shifted to the left or right) the eight bits of data that were extrapolated from the grayscale image are shifted left by 24 bits (which is the equivalent of being multiplied by 16,777,216). This places those eight bits in the alpha channel where the code then appends the Red, Green, and Blue channels of the original image. This process forms an ARGB 32-bit pixel bitmap object. Finally, after each pixel is examined, the final bitmap is drawn and added to the Stage.
Try experimenting with these two classes, using a wide variety of different images in a range of file sizes. Be sure to check the original and resulting file sizes to see how dramatically you can reduce the file size of bitmap assets in your Flash projects.

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License
| 04/23/2012 | Auto-Save and Auto-Recovery |
|---|---|
| 04/23/2012 | Open hyperlinks in new window/tab/pop-up ? |
| 04/21/2012 | PNG transparencies glitched |
| 04/01/2010 | Workaround for JSFL shape selection bug? |
| 02/13/2012 | Randomize an array |
|---|---|
| 02/11/2012 | How to create a Facebook fan page with Flash |
| 02/08/2012 | Digital Clock |
| 01/18/2012 | Recording webcam video & audio in a flv file on local drive |