Posted on Friday 9 June 2006
Mario Klingemann and Alessandro Crugnola have already posted their solutions to the problem of saving the contents of a BitmapData instance using PHP, and I figured I would share my own solution which solves it in an original way. For this current project I’m working on, the bitmap data is to be sent across an intranet, so that the size of the data sent is not the bottleneck itself. So I sought to create a bitmap exporter which requires the least processing possible from the Flash side and from the PHP side.
On the Flash side, the solution is to encode the bitmap using base64, that is, without compression. This creates fairly large files to send across the wire, but again in an intranet context it’s fine. On the php side of things, amfphp is used to give an ID to the incoming bitmap, and in the first phase simply appends the chunks of data sent by Flash in a .rgb file. The base64 encoding is easily decoded using base64_decode. Once the data has been completely sent, usually other solutions will write out the bitmap using GD, which is a major bottleneck as setpixel is really slow. But there is a better solution. The .rgb string can be manipulated and resaved as a .bmp file in a straightforward fashion. The transformation from one to the other only involves a couple of string functions, so that it is very fast. At this point, because of the way .bmp files are encoded, the image will be flipped horizontally. When one wants to save the data to a practical format like png or jpg, one calls a remote function which invokes ImageMagick with the -flop argument to correct the flipping, and receives the location of the saved file (this requires using shell_exec, which is usually only enabled on dedicated servers).
In short, this method saves bitmaps as fast as possible by skipping compression, by avoiding any type of loop on the php side, by avoiding amfphp bottlenecks, and by using the very fast ImageMagick for compression and image manipulation (flipping). Of course, you could use elements of Mario’s implementation to add LZW compression to the mix. You can download the sample files here. I haven’t had a chance to add some sanity checking on the remote service, especially when calling shell_exec, but please think about security if you mean to deploy this solution.


