Why cacheAsBitmap is bad! by Thibault Imbert

One of the feature I would really love to see in a future release of the Flash Player is a native rasterizer for display objects. Imagine something like :

myMovieClip.rasterize = true;

This code would rasterize your DisplayObject as an animated PNG. It would bring crazy improvements for designers and coders who want to improve the rendering performance of any animation. This would be in fact the same behavior as the Banana Slice component I talked about.

When talking about this, some people could think "Well, you have cacheAsBitmap for that". The reason why such a feature would rock is mainly due to the fact that cacheAsBitmap is very dangerous. Well, it won't hurt you :) , but it can definitely hurt your application performance.

As I said before, when cacheAsBitmap is set, the DisplayObject is cached as a bitmap on memory and the Flash Player is using this copy to render it on screen. The main problem that we have here is that if you do more than moving this DisplayObject on x and y, for each frame the Flash Player is updating the cached copy on memory before updating the screen. So if you apply any rotation, scale, alpha, or even if you have any key frames in your DisplayObject you will get performance decrease.

Hopefully, you can bypass this limitation by creating a BitmapData by yourself, draw the MovieClip on it, and pass it to multipe Bitmap instances. So let's take a simple example, in the folllowing movie, when you click on the "cacheAsBitmap" button, I create multiple instances of an Apple MovieClip, set cacheAsBitmap, and move them on screen :

var apple:Apple;

for (var i:int = 0; i< 100; i++)
{
apple = new Apple();

apple.cacheAsBitmap = true;

addChild ( apple );
}

When you click on the "draw" button, I first create an instance of the apple MovieClip, draw it on a BitmapData and then create Bitmap instances linked to the one and unique BitmapData instance :

var source:AppleSource = new AppleSource();

var buffer:BitmapData = new BitmapData ( source.width, source.height, true );

buffer.draw ( source );

var bitmapApple:BitmapApple;

for (var i:int = 0; i< 100; i++ )
{
bitmapApple = new BitmapApple( buffer );

addChild ( bitmapApple );
}

Online demo :

A Flash animation should have appeared here, but it seems that your browser has an older version of the Flash Player or it is not installed at all. Please, install the last release of the Flash Player now, then reload this page.

As you can see, manual rasterizing is king :)

You can download the sources here

Comments (17)

  1. GillesV wrote::

    Indeed. I’ve come to the same conclusion when I was asked to create a really animation-heavy tile-based game.

    I wrote my own “slicing” class to easily rasterize movieclips and have them play back at different framerates.

    The only downside to this is memory. BitmapData is stored in RAM uncompressed, so a simple animation can quickly eat up dozens of MB’s of RAM if you’re not careful.

    You can read my original post here: http://blog.vandenoostende.com/?p=47 and download the scripts there.

    But yeah, a native animation rasterizer would be neat ;)

    Tuesday, September 30, 2008 at 8:22 pm #
  2. TK wrote::

    We could create something like this as a subclass of Sprite or movieclip. Is this the same thing as frame-ripping?

    Tuesday, September 30, 2008 at 8:26 pm #
  3. Tek wrote::

    I don’t know why but it remember me some really recent debate with the worst flash activist ever. :)

    Really enjoying the post and the example. I hope that Adobe will do something special for your “rasterize” idea.

    Tuesday, September 30, 2008 at 8:28 pm #
  4. zedia.net wrote::

    In your code, I think you did 2 errors, in the first sample, I think it should be
    var apple:Apple;
    instead of
    var apple:Pomme;

    And in the second sample:
    var bitmapApple:BitmapApple; intsead of
    var bitmap:AppleBitmap;

    Nice work on the demo.

    Tuesday, September 30, 2008 at 8:43 pm #
  5. Thibault Imbert wrote::

    Hi Gilles,

    I saw your AnimationSlicer which is very nice. I agree with you, the only drawback here is memory usage. In common cases it is reasonable, and having a native rasterizer could solve such behavior. I will definitely push such a feature for a future release.

    TK,

    Yes, there are many ways to do it. In this example I extended Bitmap and passed the BitmapData to it, but you could extend MovieClip and do all the rasterizing inside it and add a final bitmap showing each frame as a child.

    Tek,

    hehe yes, I was sure you would remember it :)

    Tuesday, September 30, 2008 at 9:19 pm #
  6. Thibault Imbert wrote::

    Hi Zedia,

    Thanks ;) Copy & paste doh !

    Tuesday, September 30, 2008 at 9:26 pm #
  7. julien wrote::

    impressive difference, thanks for the tip

    Tuesday, September 30, 2008 at 11:31 pm #
  8. Mr.doob wrote::

    Take a look at this class, it does just that:

    http://code.google.com/p/mrdoob/source/browse/trunk/libs/net/hires/utils/display/BitmapDataSequence.as

    ;)

    Wednesday, October 1, 2008 at 1:01 am #
  9. Macaca wrote::

    A sliced game may well use 100 mb of RAM.. so what about it? I don’t have a problem with that. Your average downloadable game will do that too. It’s actually very smart: usethe vectors/gradients/etc for data storage (=download time), and unpack (rasterize) for hyper run speed.

    Wednesday, October 1, 2008 at 9:46 am #
  10. Thibault Imbert wrote::

    Hi Mr.doob,

    Nice class :) You could also use the getBounds method to detect if the DisplayObject is not aligned at 0,0. Use a matrix and translate the matrix passed to the draw method, to always have your bitmap entirely drawn.

    Wednesday, October 1, 2008 at 10:42 am #
  11. Mr.doob wrote::

    You’re right!! Will put that on the next version, thanks! :D

    Wednesday, October 1, 2008 at 7:32 pm #
  12. tomsamson wrote::

    yeah, nice.
    tek: can´t be the worst flash activist ever if everyone remembers him and even if people kid about him he inspires others :)

    Friday, October 10, 2008 at 8:44 am #
  13. P48l0 wrote::

    WOW this really add some speed! i´m getting %600 speed improve on a site i was having using cacheAsBitmap on some sprites.

    Tuesday, February 23, 2010 at 5:53 pm #
  14. Doooooo wrote::

    Would this benefit a case where only one DisplayObject is on screen?

    Saturday, April 3, 2010 at 9:34 pm #
  15. Thibault Imbert wrote::

    Hi Doooooo,

    Yes, this would benefit if the DisplayObject is moving and contains complex content like gradients, alpha transparency.

    In terms of rendering performance, bitmap will always win :)

    best,

    Thibault

    Saturday, April 3, 2010 at 9:51 pm #
  16. Brian wrote::

    When you rewrite the movieclip to a Bitmap, you are changing the registration point. I’ve been trying for several hours to be able to use this code to improve performance, but I need to keep rotating my object around the center like hands of a clock… Any ideas of if this is even possible?

    Thursday, February 24, 2011 at 4:29 pm #
  17. MatrixTurn wrote::

    An Easy way to optimize is to use a simple library MatrixTurn and boost your fps. All shape of movieclipclip are automatically “cacheAsBitmap” in execution and also a lot of effects are possible.

    Check the source here :
    http://sourceforge.net/projects/matrixturn/

    Tuesday, July 17, 2012 at 9:05 am #

Trackbacks/Pingbacks (12)

  1. `Why cacheAsBitmap is bad » ideaography` on Wednesday, October 1, 2008 at 3:02 am

    [...] http://www.bytearray.org/?p=290 [...]

     
  2. cacheAsBitmap vs. Bitmap.draw() at Logging Robby Abaya on Wednesday, October 1, 2008 at 12:46 pm

    [...] Why cacheAsBitmap is bad [ by Thibault Imbert ] [...]

     
  3. Why cacheAsBitmap is bad on Monday, October 6, 2008 at 4:05 pm

    [...] http://www.bytearray.org/?p=290 [...]

     
  4. [...] Why cacheAsBitmap is bad [ by Thibault Imbert ] (from ByteArray.org) Share and Enjoy: [...]

     
  5. PixelSalad blog - Conversion DisplayObject vers Bitmap on Wednesday, February 4, 2009 at 6:21 pm

    [...] ne pas utiliser le fameux cacheAsBitmap de Flash? En fait pas mal de raisons explique ce choix, mais surtout, je n’ai jamais trouvé moyen d’obtenir d’aussi [...]

     
  6. Use cacheAsBitmap correctly - or not at all « Bagonca on Friday, April 17, 2009 at 7:14 pm

    [...] Why cacheAsBitmap is bad Flex Move Effect Messes Up Mask Alignment [...]

     
  7. Flash optimization on mobile | RIAgora on Friday, April 16, 2010 at 11:21 am

    [...] – Consider bitmaps versus vectors. I’ve shown to the audience a benchmark application that demonstrates the good usage of the cacheAsBitmap property. My advice is the following. If you manipulate graphical elements using the X and Y axis only, please set the cacheAsBitmap property to true. It will dramatically improve the performances of your applications. Transparency is very expensive, avoid the alpha channel, avoid filters and blend modes. If you use the rotation property, don’t use cacheAsBitmap, but the Draw sample detailed here: http://www.bytearray.org/?p=290 [...]

     
  8. All I don't know » FFK10 – Flashforum conference notes on Tuesday, April 20, 2010 at 5:55 pm

    [...] Great tip: ByteArray.org – Why cacheAsBitmap is bad [...]

     
  9. Why cacheAsBitmap is bad « Test Online on Wednesday, November 17, 2010 at 6:49 am

    [...] release of the Flash Player is a native rasterizer for display objects. Imagine something like : view source [...]

     
  10. cacheAsBitmap - was hilft es wirklich? - Flashforum on Wednesday, January 12, 2011 at 1:56 pm

    [...] [...]

     
  11. [...] I always thought it would help, but it doesn’t. I stumbled across this article: “Why cacheAsBitmap is bad!” by Thibault Imbert and learned why I should use BitmapData.draw of the cacheAsBitmap property. [...]

     
  12. The WebGL potential | TypedArray.org on Wednesday, April 3, 2013 at 11:12 pm

    [...] really hard to build things efficiently on top of it. I wrote a blog post a long time ago on why cacheAsBitmap is evil and how similar results could be achieved using lower-level primitives with minimal side [...]