We have had to work a lot with loading and displaying images over the past couple of years. There are a couple things that we always find ourselves needing to do and looking for the best way to do it. When an image is loaded and it needs to be manipulated to fit into a given area, we don’t want to just scale it, we want to fit it in a give area by scaling proportionally and cropping it so that there is no distortion. This also frees up memory in the Flash Player for other activities, especially if the image is attached to some form of motion.
What we have done, is put a couple of functions together that can do any or all of our needs for cutting and sizing images dynamically in Flash with ActionScript. A lot of times, functions are created and shared with little explanation of their need and function, we felt the need to share both so you can have a more complete understanding of what is really going on. There are a couple pieces of the puzzle that should be understood when working with images in ActionScript. There are two main components:
BitmapData Class – think of this class as the behind the scenes control for your images, it extends the Object class so it is not meant to be placed on the stage. With the BitmapData class, you can manipulate pixels, colours, pretty much anything about an image you want.
Bitmap Class – this is the face of the BitmapData class. A Bitmap in AS3 is an extension of a DisplayObject which means it can be added to the stage. The Bitmap class acts as a container for a BitmapData object, so you can’t manipulate very much about it.
Here is a quick example of how to use the BitmapData alongside the Bitmap class.
// create a new, black BitmapData object BitmapData(width, height, transparent, fillColor) ; var bmpd:BitmapData = new BitmapData(300, 200, false, 0x000000) ; // addChild(bmpd) – this would throw an error because it is not a DisplayObject // create a Bitmap to display the BitmapData var bmp:Bitmap = new Bitmap(bmpd); addChild(bmp); // add the bitmap to the stage
BitmapData gives you a canvas that you can draw on. You can draw the stage to a BitmapData object, you can actually draw any DisplayObject to BitmapData, and/or you can set individual pixels within the object to any value you need.
The complicated part, in our opinion when working with BitmapData is trying to properly scale and crop the object so that it fits your needs. Here are some quick methods for cropping and scaling to help out.
* make you you import all necessary classes to do this. Here are all the classes that get used in the following examples:
import flash.display.BitmapData; import flash.display.Bitmap; import flash.display.DisplayObject; import flash.geom.Matrix; import flash.display.PixelSnapping;
First, we will show you a little function that will draw any display object you specify to a cropped area and return the bitmap. The function itself is documented line-by-line, so that you can follow along with what is going on in the code.
/**
* cropBitmap
* @ARG_object the display object to crop
* @ARG_x the horizontal amount to shift the crop (0 = no shift)
* @ARG_y the vertical amount to shift the crop (0 = no shift)
* @ARG_width width to crop to
* @ARG_height height to crop to
**/
function cropBitmap( ARG_object:DisplayObject, ARG_x:Number, ARG_y:Number, ARG_width:Number, ARG_height:Number):Bitmap {
// create a rectangle of the specific crop size
var cropArea:Rectangle = new Rectangle(0, 0, ARG_width, ARG_height);
// create a BitmapData object the size of the crop
var bmpd:BitmapData = new BitmapData(ARG_width, ARG_height);
// create the cropped Bitmap object from the bitmap data
var croppedBitmap:Bitmap = new Bitmap(bmpd, PixelSnapping.ALWAYS, true);
// create the matrix that will shift the crop from 0,0
var cropMatrix:Matrix = new Matrix();
cropMatrix.translate(-ARG_x, -ARG_y);
// draw the supplied object, cropping to the cropArea with the cropMatrix offseting the result
bmpd.draw( ARG_object, cropMatrix, null, null, cropArea, true );
return croppedBitmap; // return the cropped bitmap
}
Next, here is a quick example of a function that will take a display object and draw a scaled version of it to a Bitmap.
/**
* scaleBitmap
* @ARG_object the display object to scale
* @ARG_scaleX the amount to scale horizontally (1 = no scale)
* @ARG_scaleY the amount to scale vertically (1 = no scale)
**/
function scaleBitmap( ARG_object:DisplayObject, ARG_scaleX:Number, ARG_scaleY:Number ):Bitmap {
// create a BitmapData object the size of the crop
var bmpd:BitmapData = new BitmapData(ARG_object.width * ARG_scaleX, ARG_object.height * ARG_scaleY);
// create the scaled Bitmap object from the BitmapData
var scaledBitmap:Bitmap = new Bitmap(bmpd, PixelSnapping.ALWAYS, true);
// create the matrix that will perform the scaling
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(ARG_scaleX, ARG_scaleY);
// draw the object to the BitmapData, applying the matrix to scale
bmpd.draw( ARG_object, scaleMatrix );
return scaledBitmap; // return the scaled Bitmap
}
Finally, we took what we built in the crop and the scale methods and built a method to scale an image to proportionally fit within a rectangular area. We added the ability to make it fill the whole box or to fit inside the box, if it is cropped you can tell it to center the cropped image inside the rectangle. We didn’t add documentation to anything in this function that you would have seen in the previous functions but the new stuff has a couple comments where we thought it might help explain things a little better.
/**
* fitImage
* @ARG_object the display object to work with
* @ARG_width width of the box to fit the image into
* @ARG_height height of the box to fit the image into
* @ARG_center should it offset to center the result in the box
* @ARG_fillBox should it fill the box, may crop the image (true), or fit the whole image within the bounds (false)
**/
function fitImageProportionally( ARG_object:DisplayObject, ARG_width:Number, ARG_height:Number, ARG_center:Boolean = true, ARG_fillBox:Boolean = true ):Bitmap {
/** we use the to quickly calculate the target scale amount **/
// capture the original width and height of the display object
var tempW:Number = ARG_object.width;
var tempH:Number = ARG_object.height;
// size the image (not proportionally) to the box
ARG_object.width = ARG_width;
ARG_object.height = ARG_height;
// get the scale amount to fit the image in the box
// if fillBox is checked, take the larger scale value otherwise take the smaller
var scale:Number = (ARG_fillBox) ? Math.max(ARG_object.scaleX, ARG_object.scaleY) : Math.min(ARG_object.scaleX, ARG_object.scaleY);
// reset the image size
ARG_object.width = tempW;
ARG_object.height = tempH;
// see if there is a need to crop the bitmap
if (ARG_object.width * scale > ARG_width || ARG_object.height * scale > ARG_height) {
// need to crop
var cropArea:Rectangle = new Rectangle(0, 0, ARG_width, ARG_height);
var croppedBmpd:BitmapData = new BitmapData(ARG_width, ARG_width);
var croppedBitmap:Bitmap = new Bitmap(croppedBmpd, PixelSnapping.ALWAYS, true);
var cropMatrix:Matrix = new Matrix();
cropMatrix.scale(scale, scale);
// if the resulting crop is to be centered
if (ARG_center) {
// get the offsets
var offsetX:Number = Math.abs((ARG_width / 2) - ((ARG_object.width * scale) / 2));
var offsetY:Number = Math.abs((ARG_height / 2) - ((ARG_object.height * scale) / 2));
// offset the matrix
cropMatrix.translate(-offsetX, -offsetY);
}
croppedBmpd.draw( ARG_object, cropMatrix, null, null, cropArea, true );
return croppedBitmap;
} else {
// no need to crop, just scale and return the bitmap
var scaleBmpd:BitmapData = new BitmapData(ARG_object.width * scale, ARG_object.height * scale);
var scaledBitmap:Bitmap = new Bitmap(scaleBmpd, PixelSnapping.ALWAYS, true);
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(scale, scale);
scaleBmpd.draw( ARG_object, scaleMatrix );
return scaledBitmap;
}
}
If you are one of those people that likes to have as little code as possible, some of this code can be shortened by doing things like creating the matrix in the draw function and applying the offsets and scales in the constructor, ie: new Matrix (1, 0, 0, 1, -offsetX, -offsetY). We find it much more readable the way we have outlined it above. If you have any thoughts on optimization for the code able please let us know and we will take a look and revise if needed.
** EDIT
We have modified the function slightly and it has been working much better… This version takes the input, scales it and then determines if it needs cropping. Take a look below:
private function fitImageProportionally( ARG_object:DisplayObject, ARG_width:Number, ARG_height:Number, ARG_center:Boolean = true, ARG_fillBox:Boolean = true ):Bitmap {
var tempW:Number = ARG_object.width;
var tempH:Number = ARG_object.height;
ARG_object.width = ARG_width;
ARG_object.height = ARG_height;
var scale:Number = (ARG_fillBox) ? Math.max(ARG_object.scaleX, ARG_object.scaleY) : Math.min(ARG_object.scaleX, ARG_object.scaleY);
ARG_object.width = tempW;
ARG_object.height = tempH;
var scaleBmpd:BitmapData = new BitmapData(ARG_object.width * scale, ARG_object.height * scale);
var scaledBitmap:Bitmap = new Bitmap(scaleBmpd, PixelSnapping.ALWAYS, true);
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(scale, scale);
scaleBmpd.draw( ARG_object, scaleMatrix );
if (scaledBitmap.width > ARG_width || scaledBitmap.height > ARG_height) {
var cropMatrix:Matrix = new Matrix();
var cropArea:Rectangle = new Rectangle(0, 0, ARG_width, ARG_height);
var croppedBmpd:BitmapData = new BitmapData(ARG_width, ARG_height);
var croppedBitmap:Bitmap = new Bitmap(croppedBmpd, PixelSnapping.ALWAYS, true);
if (ARG_center) {
var offsetX:Number = Math.abs((ARG_width -scaleBmpd.width) / 2);
var offsetY:Number = Math.abs((ARG_height - scaleBmpd.height) / 2);
cropMatrix.translate(-offsetX, -offsetY);
}
croppedBmpd.draw( scaledBitmap, cropMatrix, null, null, cropArea, true );
return croppedBitmap;
} else {
return scaledBitmap;
}
}

Great Clips Coupons…
[...]right here are a few links to internet websites I always connect to because we feel there’re worth browsing[...]…
Thank you!! really usefull and great Functions!!!
[...] useful to make a thumb in ActionScript 3 ! EDIT : deleted my previous script, this one coming from Cult Creative is awesome : /** * fitImage * @ARG_object the display object to work with * @ARG_width width of the [...]
I spent two days trying to find this kind of information, not just something to compy and paste but some explanation of what is going on.
Thanks a million *a billion * five trillion.
A true treasure for someone like me learning AS3
nice code i understand very well