The ultimate AS2 BitmapData saving solution

Posted on Saturday 21 October 2006

First of all, sorry for the over-the-top title, it’s a nod to Grant Skinner, whose BitmapData saving post inspired me to get back to the drawing board to find a better solution than what I had previously. The previous solution was very fast in an intranet setting, and very low on resources on the php side as it saved the data as a .bmp directly instead of using the terribly slow imagesetpixel loop in GD. However, it did not use any sort of compression, worked only in 24 bit color mode, and required ImageMagick to be installed.

Last thing first, John O’Neal suggested I save as a GD image instead of BMP and Mathieu showed a working example. This avoids using a pixel loop on the PHP side which was one of the main bottlenecks, while requiring only GD, not ImageMagick. Second, Grant Skinner showed that compression using run-length encoding was fast both on the php and on the Flash side, so I implemented the idea. Finally, I implemented three bit-depths, 12, 24 and 32, which are appropriate in various situations.

The result: a solution which is fast on the Flash side, fast on transit because of the compression, fast on the php side because of the lack of a pixel loop. The result is appropriate for a wide variety of circumstances, from low-quality webcam snapshots to high-quality 32 bit freeze frames of movieclips with way too much vector data (the old put everything on a guide layer and swap for a PNG32 snapshot switcheroo… I really wish cacheAsBitmap worked as advertised).

You can download it here. The PHP side requires amfphp to run.

Technical notes: I had to pull some hacks together on this one on the php side to get rid of the pixel loop. Basically I am first saving as a 32-bit GD image and then as a PNG. The GD image is a very simple format, basically some headers and then the pixels in AARRGGBB format (where AA is actually the inverse of the alpha, that is, 00 is opaque and FF is transparent). For 32-bit images it went fine. However, for 24 bit images, I had a string which looked like RRGGBBRRGGBB (and so on and so forth for all pixels) and needed it to be 00RRGGBB00RRGGBB, without using a loop, so I used the little known chunk_split function to insert the 00s. The next big issue was with the 12 bit images, where I would receive RGBRGB and I needed to have RRGGBBRRGGBB (and then 00RRGGBB, but that part was solved). For this one I used another little known function, strtr, with a huge replacement table and it works fabulously. The lesson is: in PHP, avoid loops on big items at all costs, and if there is a C level function that does the job, use it.

As for the run-length encoding, for the 32 bit images, I had to use RLE on three pixel blocks because 6 doesn’t divide 32 (I’m using base64 encoding). In the 12 bit case, I apply RLE on two-pixel blocks, as the replacement loop becomes a lot slower in php because of the extra matched without getting any significant positive impact on the transfer size.

Update (10/22/2006): A bug on the php side with 32-bit encoding was corrected and the zip file has been updated (no changes on the actionscript side).


WordPress database error: [Can't open file: 'wp_comments.MYD'. (errno: 145)]
SELECT * FROM wp_comments WHERE comment_post_ID = '214' AND comment_approved = '1' ORDER BY comment_date

No comments have been added to this post yet.

Leave a comment




Your e-mail address is never displayed. If you run into issues with SpamKarma blocking you, email me at $patrick->5etdemi(com)


RSS feed for comments on this post | TrackBack URI