AS3 Quickie – drawWithQuality()

Since Flash Player 9, we’ve been able to use the BitmapData.draw() method in order to capture visual data from a display object. The major limitation of using this method, is that it will render the visual at the stage quality with which the swf has been embedded/compiled. One trick to get around this is to switch the stage quality on the fly, via ActionScript – yet this is not a supported workflow. With Flash Player 11.3 we have a new method with which to render drawn visuals at any desited stage quality: BitmapData.drawWithQuality().

In the example below, the swf is embedded with a stage quality of “medium”. Clicking on the top square will invoke the regular draw() command which uses the default stage quality to render the data. The second square will employ drawWithQuality() and render with the stage quality set to “low”, while the bottom square will do the same – but use stage quality “best” to render the image. Essentially; medium, low, and best – from top to bottom.


Requires Flash Player 11.3 or above!

Go ahead and toggle between each quality setting to see the differences. I’ve rendered the resulting BitmapData scaled nearly 2x the original size and with a white background to further accentuate the quality differences in the image. Also, a variety of display elements exist within the MovieClip symbol itself for further illustration: shapes, images, filters, et cetera.

To accomplish this, we must first perform the necessary imports:

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.StageQuality;

We need to declare a Bitmap instance to display the BitmapData gathered from the stage using either the draw() or drawWithQuality() methods of the BitmapData class:

private var savaBitmap:Bitmap;

..and add it to the display list:

savaBitmap = new Bitmap();
addChild(savaBitmap);

With the Bitmap instance in place and a MovieClip instance already on stage- we simply need to craete a new BitmapData instance to hold our data, invoke drawWithQuality() using the desired stage quality, and then apply that data to our existing Bitmap on stage:

var qualityBitmapData:BitmapData = new BitmapData(savanovic.width, savanovic.height);
qualityBitmapData.drawWithQuality(savanovic, null, null, null, null, false, StageQuality.BEST);
savaBitmap.bitmapData = qualityBitmapData;

We can substitute any stage quality we wish in place of that last argument. Here is a quick list of those which are available through flash.display.StageQuality:

  • StageQuality.BEST
  • StageQuality.HIGH
  • StageQuality.HIGH_16X16
  • StageQuality.HIGH_16X16_LINEAR
  • StageQuality.HIGH_8X8
  • StageQuality.HIGH_8X8_LINEAR
  • StageQuality.MEDIUM
  • StageQuality.LOW

The full code is below. Note that the FLA contains upon the Stage a MovieClip with the instance ID of savanovic from which we are gathering the visual data:

package  {
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.StageQuality;
	import flash.events.MouseEvent;
	import flash.events.Event;
	import flash.geom.Matrix;

	public class Main extends Sprite {
		public var savanovic:MovieClip;

		private var savaBitmap:Bitmap;
		private var normalBitmapData:BitmapData;
		private var yuckyBitmapData:BitmapData;
		private var qualityBitmapData:BitmapData;

		public function Main() {
			this.addEventListener(Event.ADDED_TO_STAGE, init);
		}

		protected function init(e:Event):void {
			savaBitmap = new Bitmap();
			savaBitmap.x = 45;
			savaBitmap.y = 10;
			addChild(savaBitmap);

			drawData();
		}

		protected function drawData():void {
			var scaleFactor:Number = 1.7;
			var savaMatrix:Matrix = new Matrix();
			savaMatrix.scale(scaleFactor, scaleFactor);

			normalBitmapData = new BitmapData(savanovic.width*scaleFactor, savanovic.height*scaleFactor);
			normalBitmapData.draw(savanovic,savaMatrix);
			yuckyBitmapData = new BitmapData(savanovic.width*scaleFactor, savanovic.height*scaleFactor);
			yuckyBitmapData.drawWithQuality(savanovic, savaMatrix, null, null, null, false, StageQuality.LOW);
			qualityBitmapData = new BitmapData(savanovic.width*scaleFactor, savanovic.height*scaleFactor);
			qualityBitmapData.drawWithQuality(savanovic, savaMatrix, null, null, null, false, StageQuality.BEST);

			renderButtons();
		}

		protected function renderButtons():void {
			var b1:Sprite = new Sprite();
			b1.graphics.beginFill(0x000000, 0.7);
			b1.graphics.drawRect(0,0,25,25);
			b1.graphics.endFill();
			b1.addEventListener(MouseEvent.CLICK, drawNormalPixels);
			b1.x = 10;
			b1.y = 10;
			addChild(b1);

			var b2:Sprite = new Sprite();
			b2.graphics.beginFill(0x000000, 0.7);
			b2.graphics.drawRect(0,0,25,25);
			b2.graphics.endFill();
			b2.addEventListener(MouseEvent.CLICK, drawYuckyPixels);
			b2.x = 10;
			b2.y = b1.y + b1.height + 10;
			addChild(b2);

			var b3:Sprite = new Sprite();
			b3.graphics.beginFill(0x000000, 0.7);
			b3.graphics.drawRect(0,0,25,25);
			b3.graphics.endFill();
			b3.addEventListener(MouseEvent.CLICK, drawQualityPixels);
			b3.x = 10;
			b3.y = b2.y + b2.height + 10;
			addChild(b3);
		}

		protected function drawNormalPixels(e:MouseEvent):void {
			savaBitmap.bitmapData = normalBitmapData;
		}

		protected function drawYuckyPixels(e:MouseEvent):void {
			savaBitmap.bitmapData = yuckyBitmapData;
		}

		protected function drawQualityPixels(e:MouseEvent):void {
			savaBitmap.bitmapData = qualityBitmapData;
		}

	}

}

Want the full package? Download below:
Packaged code and Flash Professional CS6 project



This Quickie has been brought to you by the rampaging Serbian vampire Sava Savanovic. Let’s hope they fix his watermill soon so that he can get some rest!

One comment:

Comments are closed.