Using BitmapData.setVector for better performance

During the ByteArray workshop yesterday we wrote some code that parsed a PSD file and displayed it in the Flash Player. As part of this I showed setting the pixels of the BitmapData object using the setPixels method. I had heard that this method was slow but Thibault confirmed this for me. He suggested that I try a new method that was introduced in Flash Player 10 called setVector. This allows you to take a Vector object containing 32-bit floating point numbers and use it to set the pixels in the bitmap. Below is the original code using setPixel which required a nested for loop.

1
2
3
4
5
6
7
8
var bmd:BitmapData = new BitmapData(width, height);
for(var y:int=0; y<height; ++y)
{
    for(var x:int=0; x<width; ++x)
    {
        bmd.setPixel(x, y, r.readUnsignedByte()<<16 | g.readUnsignedByte()<<8 | b.readUnsignedByte());
    }          
}

The new code which takes advantage of setVector is shown below. There is one trick to getting this to work. You have to shift a value of 255 (aka 0xFF) to the far left byte as you need to provide an ARGB number for it to work. Otherwise your pixel would have an alpha of zero.

1
2
3
4
5
6
7
8
9
10
var numPixels:int = width*height;
var pixels:Vector.<uint> = new Vector.<uint>(numPixels, true);
           
for(i=0; i<numPixels; ++i)
{
    pixels[i] = 0xFF<<24 | r.readUnsignedByte()<<16 | g.readUnsignedByte()<<8 | b.readUnsignedByte();
}          
           
var bmd:BitmapData = new BitmapData(width, height);
bmd.setVector(new Rectangle(0, 0, width, height), pixels);

The BitmapData class is smart enough to put all the values into the right places in the bitmap so you don’t have to deal with nested loops.

Lee


Commentary

  1. Renato Moya says:

    Impressive, there’s only one thing I don’t get. Why the shifting is made by 24? Can anyone explain that to me?

  2. lee says:

    @Renato sure let me try to explain. A 32-bit ARGB color has the following bit pattern:

    AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB

    Now say that you have have a 24-bit color and an 8-bit alpha value like:

    RRRRRRRRGGGGGGGGBBBBBBBB and AAAAAAAA

    In order to combine them so that AAAAAAAA is to the far left, you need to shift it to the left 24 places.

  3. wonderwhy-er says:

    Hmm. Interesting. So using such method to fill rectangle of pixels if fast. Will need to play with it.
    Was making small research in to getPixel vs bytearray vs vector got this http://wonderwhy-er.deviantart.com/art/CDK-tests-2-1-132330754 Well in my tests it turned out that scanning using getPixel is faster then getting ByteArray or Vector representation of it and trying to scan there. Another thing is that it shewed different results in different versions of Flash Player which is disturbing…

    Ah it seems that programming for Flash trying to achieve best performance becomes more and more like a doing some black magic.

  4. leef says:

    hmmm, would be nice if Adobe wrote added this method to the BitmapData class?

  5. marvin says:

    just besides: thanks for always improving even issues concerning performance. is there any chance to say how much faster it is in detail?

  6. Hassan says:

    Parse a PSD file in Flash Player? This is absolutely stunning! Could you make a GTAL tut out of it?

  7. Some time ago I wrote a blog post about a library from the libspark project which reads photoshop documents. http://www.leichtgewicht.at/272/libspark-psdparser

  8. David says:

    This is a great tip. But I was caught more by the psd parser you mentioned. I wish I was more proficient with byte arrays. I’ve been looking for a starting point for writing/reading similar data structures. Specifically, compressing files and folders to simulate a file type. Do you know of any libraries or resources for writing and extracting compressed files? Thanks again :)

  9. Renato Moya says:

    Ohh, I get it now Lee, thanks for the explanation.

  10. andrew says:

    I’ve been in the Flash on the beach workshop, and i lost the URL to the psd format specification. where can i find wich bytes i need to read?
    cheers.

  11. Daniel says:

    Hmm, how exactly can setVector be faster than setPixels? I mean, I understand why it’s faster than setting a pixel at a time. But pusing a byteArray into setPixels sounds like it would have less overhead than a typed vector?

  12. paddy says:

    you’re a star Lee, Thanks for posting this. The session at FOTB really helped my understanding of working with bytes.

  13. leef says:

    how are you getting the rgb values?

  14. Michael Avila says:

    Lee, what syntax highlighter are you using on this blog? It looks very similar to my emacs config and would like to use it for my own blog. Hope you can help. Take care.

  1. [... During the ByteArray workshop yesterday we wrote some code that parsed a PSD file and displayed it in the Flash Player. As part of this I showed setting the pixels ...]

Leave a Comment