How to Scale in Flash (Bitmap Smoothing)

I apologize to my neglected readers. I’ve been busy lately with a new puppy, and finding a new house. Plus, this stagnant air in Salt Lake City is killing me. But, I’m done making excuses so let’s talk about bitmap smoothing and scaling. I also have some questions for any ActionScript gurus out there that might be able to help.

Flash has some pretty sweet features that we can take advantage of. One of them revolves around the bitmap and bitmap data classes. Let’s say you are creating a photo album and wish to use Flash to accomplish the task. Let’s also say that at some point you are going to have a large image for viewing, but you’ll also want some thumbnails to help in navigating through all your photos.

Assume you have 200 photos that you want to show to the world. One way of going about creating thumbnails would be to setup an action in Photoshop that would take care of the resizing. Hey, it gets the job done, but it’s not sexy and requires the additional file size of all the thumbnails. If you’re familiar with PHP and GD, you could write a script that creates thumbnails on the fly, but that requires you know another language. I say we just do it with ActionScript.

The Basics

Scaling our thumbnails is not really that hard once you understand the concept. Here is what we want to do:

  • Dynamically import our images from a folder on our server
  • Take the bitmap data from that image and cast it as a bitmap
  • Scale down the original image into a thumbnail
  • Apply smoothing to achieve a clean, non-pixelated look

Importing our images

I’ll briefly show some code on how to import the images off your server, but this isn’t the focus of this tutorial so I haven’t built in any fancy preloaders or other user feedback. You may want to do so in your final implementation.

The first thing we’ll do it create a method that starts the loading process. We’ll pass in the URL (a string) to the method so it knows where to grab the image from.

private function startLoad(_loc:String):void {

	//Instantiate the loader (I've defined this outside of the method for global
	//use within the class
	_loader = new Loader();
	_loaderInfo = _loader.contentLoaderInfo;

	//Add a listener that will do some shizzle when the picture is all loaded
	_loaderInfo.addEventListener(Event.COMPLETE, onComplete, false, 0, true);

        try {
            	_loader.load(new URLRequest(_loc));
        } catch (err:Error) {
                trace("Unable to load content:\n" + err.message);
        }

}

This starts our picture loading. Once it’s all loaded it will start the onComplete method, which will begin the hard work. Here is that method.

private function onComplete(evt:Event):void {

	//Be a good boy and remove your listener
	_loaderInfo.removeEventListener(Event.COMPLETE, onComplete);

	//Create a sprite to hold our large (unscaled) image
	var _main:Sprite = new Sprite();

	//Copy the pixel data and cast as a bitmap (we could also just add the loader
	//to accomplish the same thing
	var _unscaled:Bitmap = new Bitmap(_loader.getChildAt(0).bitmapData);

	//Put the bitmap in the sprite
	_main.addChild(_unscaled);

	//Add the sprite to the display list
	addChild(_main);

	//Create a new sprite to hold our thumbnail
	var _thumb:Sprite = new Sprite();

	//Move it underneath (or some place else out of the way)
	_thumb.y = 600;

	//Copy the bitmap data of the large image again
	var _scaled:Bitmap = new Bitmap(_loader.getChildAt(0).bitmapData);

	//Scale the bitmap
	_scaled.scaleX = _scaled.scaleY = .25;

	//Apply the smoothing
	_scaled.smoothing = true;

	//Add scaled bitmap to the sprite
	_thumb.addChild(_scaled);

	//Add the sprite to the display list
	addChild(_thumb);

}

Okay, so what did we do here? We created two container sprites that hold the bitmap object. Think of the bitmap we’ve created as a screenshot of the larger image. It provides us with the actual color and location of each pixel. We want to put it into a sprite to allow us to treat it like a button in the future. You can’t attach listeners to bitmap objects.

The only thing left to do is to run the method. It might look something like this.

startLoad('somefolder/image.jpg');

This should get the ball rolling. The above snippets of code aren’t everything you need. If you are writing this in the document class or some other external class you’ll need to import the proper classes. Let me know if you need any help on that, but I’m assuming you probably know what to do.

Stage quality

I consider this part to be the bummer. If you’ve followed through and tested your movie you are probably saying, “That thumbnail looks like ass.” And it really does. It probably looks jagged and crummy. Up until this point, the only way I’ve figured out how to fix this is to set the stage quality to BEST. You can do it like so.

//Make sure to place this in the constructor method of your doc class.
stage.quality = StageQuality.BEST;

Now, if you had chosen to scale the image up instead of down. It would look pretty darn good. You wouldn’t need to change the stage quality at all. To me this is the end goal, because I would rather not take the performance hit from setting the quality to best.

My question to you guys

I would really love to know how others are choosing to do this. Especially if you’ve figured out a way to scale down without having to change the stage quality. Just shoot me an email, tweet, or comment so that I can let others know the goodness that is bitmap smoothing. I’m pretty sure there’s a way, but I just haven’t figured it out yet. The above works, but just make sure your users can deal with extra processing crunch.

This entry was posted in Flash/AS, Flash/ActionScript, Tutorials and tagged , , , , , . Bookmark the permalink.

2 Responses to How to Scale in Flash (Bitmap Smoothing)

  1. JP DeVries says:

    I think this is a great approach, I’ve successfully implemented it.
    One note, instead of creating a new Bitmap instance of the loaded image like this:
    var _scaled:Bitmap = new Bitmap(_loader.getChildAt(0).bitmapData);

    you can also directly refer to it using the Loader.content property:
    var _scaled:Bitmap = Bitmap(_loader.content);

  2. Matt says:

    Perfect. Nice catch. I’m all for typing less code.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">