Out With Thee →← AS2 to AS3 Migration Cheat Sheet

Improving Performance with BitmapData

Way back in Performance Tips Part I, I mentioned the idea of using BitmapData to capture a dynamic “screen shot” of the movieclip when transitioning between different sections of your site/application/whatever. The idea is to render a flat bitmap — a JPG, basically — instead of all of those PNGs and videos and vector graphics you have floating around here.

I issued a challenge to Cathy, one of our finest designers here, to come up with something so fantastically slow that there was no way even BitmapData could save it. She did not disappoint. She’s got our test beachball from the Visualizer, some rare interview footage from our elite Foosball Team, alpha PNG clouds, and on and on.

Check out the results here, or download the demo for yourself.

Click from Josh to Caleb and back, clicking the “Capture Screenshot” button to toggle whether or not you want to generate bitmapdata of the section before transitioning or just play it out as is. When on, you should notice the transition is significantly less “chunky” in playback.

Cathy then explains the OUT transition between each section:

“The mask animation is based off a couple of simple animated circles, which are nested inside one another and duplicated horizontally and vertically. Then, all of these nested clips are put into one mask clip, which is set to “erase” blend mode, and put on top of the movieclip containing the content to be masked. Erase simply inverts the effect this mask would normally have. The mask clip and the content clip are then further nested inside a clip which has a “layer” blend mode. The layer mode is very important, the masking trick won’t work without it.”

So there you have it. Blend modes, vectors, PNGs, videos…all of the components you need to create one horribly slow web site, right? To give her an even better chance of breaking this down, I wrote everything with the Flash 8 player in mind, as its pretty clear that FP9 can handle itself.

The ScreenShot technique is very simple. One needn’t know a single thing about BitmapData to use it. This is more or less the entire thing:


_bmp = new BitmapData($draw_mc.getBounds().xMax, $draw_mc.getBounds().yMax, true, 0);
_bmp.draw($draw_mc);
$destination_mc.createEmptyMovieClip(_SCREENSHOT_NAME, $destination_mc.getNextHighestDepth()).attachBitmap(_bmp, 2);
}

All we do is pass in a clip we want to draw and where we want to attach the finished bitmap to. Then we set the actual section (”Josh” or Caleb’s interview, in this case) to go to a keyframe where nothing exists — clearing all of the complex drawing out so the player can focus it’s attention strictly on the mask transition.

I really recommend you try it out on a slower machine to see the vast difference in performance.

March 6th, 2007  by Stephen  /  11 Comments

Comments on “Improving Performance with BitmapData”

  1. This is s great tip that I’ve recently had to use on a project that I was working on with a friend. Bitmapdata definitely can help out a lot when you really need that extra processing power. Nice to see you guys gave us a excellent example of how it can really work.

    Rich on March 6th, 2007 at 5:40 pm
  2. I was waiting for this example a while and I have to say it was worth it. Wonderful example and I commend you all for taking the time to help out the Flash community. Again, nice job, and keep up all the great work guys(and gals)!

    Mike on March 6th, 2007 at 6:10 pm
  3. on my machine there is no difference. I guess I need to get an older PC to test on. That brings up the question of what minimum spec do you develop for?

    fredo on March 7th, 2007 at 12:02 am
  4. I’m not sure how easy that technique is to pull off well. It’s kind of jarring when the whole background stops and a transition occurs, especially if you previously had subtle animations. Seems to be that fading out the video, or some other visual effect would be better.

    I’m not a fan of jerky Flash, even if it looks lovely.

    Kevin Cannon on March 7th, 2007 at 7:07 am
  5. Video killed the vector star! hehe :)

    This is useful for my machine in the office. Actually think this performance advantages in a motion that you can not handle with flash’s vector rendering… A collosal CPU power should need, this technique could be very useful then.

    Again nice trick with Flash 8 guys. But if you need to back the previous animation you can not synchronized the video with the bitmap :(

    May be some transition effects should be fine like fade out the bitmap.

    Özgür ALTAY on March 8th, 2007 at 4:28 am
  6. Badass! So simple, yet so effetive.

    Like mentioned in the comments of the Screenshot class, I tweaked it to include negative movieclip bounds:

    var myMatrix:Matrix = new Matrix();
    myMatrix.translate(-$draw_mc.getBounds().xMin, -$draw_mc.getBounds().yMin);
    _bmp = new BitmapData($draw_mc._width,$draw_mc._height,true,0);
    _bmp.draw ( $draw_mc, myMatrix, new ColorTransform() );

    $destination_mc.createEmptyMovieClip(_SCREENSHOT_NAME,$destination_mc.getNextHighestDepth()).attachBitmap(_bmp,2);

    $destination_mc [ _SCREENSHOT_NAME ]._x += $draw_mc.getBounds().xMin;
    $destination_mc [ _SCREENSHOT_NAME ]._y += $draw_mc.getBounds().yMin;

    Works for me! Thanks again for this useful class

    Nick on March 9th, 2007 at 6:55 pm
  7. Great ine tnx! I’m trying to get this to work but somehow it doesn’t work when externally loaded flv’s are involved… any sugestions?

    skemone on March 18th, 2007 at 11:03 am
  8. […] BIG SPACESHIP LABS / » Improving Performance with BitmapData (tags: flash performance bitmap tips actionscript) […]

    izms » Blog Archive » links for 2007-08-05 on August 5th, 2007 at 6:18 pm
  9. Hi, Recently I needed this method for one of my tasks, the condition was to make it in AS3.
    If you will use it, just place on the stage a Movie Clip called “draw_mc” which will be the source of capture, and a Button with the instance name “but”, so here is the result:

    //importing packages————————–
    import flash.events.MouseEvent;
    import flash.display.Bitmap;
    import flash.display.BitmapData;

    //var———————————————-
    var myBitmapData:BitmapData = new BitmapData(draw_mc.width, draw_mc.height);

    //Capture function———————————
    function capture(event:Event){
    myBitmapData.draw(draw_mc);
    var bmp:Bitmap = new Bitmap(myBitmapData);
    this.addChild(bmp);
    bmp.x = draw_mc.x;
    bmp.y = draw_mc.y + draw_mc.height*2;
    }
    function click_Handler(event:MouseEvent){
    capture(event);
    }
    but.addEventListener(MouseEvent.MOUSE_DOWN, click_Handler);

    Radu on September 12th, 2007 at 6:18 am
  10. So many uses. So very simple. Thanks all!

    kevin on January 8th, 2008 at 11:47 pm
  11. Hi, can you please update the links on this? I’ve been working on something similar and this would really help, thanks!

    James Allen on May 3rd, 2008 at 8:03 pm