Archive for the ‘Actionscript 3’ Category

AS3 BitmapData AMF solution using IExternalizable

Using bitmaps in an AS3 remoting environment isn’t that easy. If I’m getting it right, the problem is that the BitmapData object needs constructor parameters, wich isn’t combinable with the handy [RemoteClass(alias= ] method of invoking the objects when streaming data into a ByteArray.

A walkaround is to wrap the BitmapData into a custom class implementing the IExternalizable interface. This interface forces the writing and reading of data through methods where the serialization can be taken care of.
In the example below (a renamed copy of this class, thank you Greg! – unfortunately I couldn’t find your lastname…), the bitmap data storage is done through encoding/decoding as png data. Loading is then performed via a Loader object.

package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.events.Event;
    import flash.utils.ByteArray;
    import flash.utils.IDataInput;
    import flash.utils.IDataOutput;
    import flash.utils.IExternalizable;
    import mx.graphics.codec.PNGEncoder;

    [RemoteClass(name="ExtBitmap")]
    public class ExtBitmap implements IExternalizable
    {
        public var imageData:BitmapData;

        protected var loader:Loader;

        public function ExtBitmap(){
            loader = new Loader();
            loader.contentLoaderInfo.addEventListener(
                   Event.COMPLETE, handleBytesLoaded);
        }

        public function handleBytesLoaded(event:Event):void{
            trace('handleBytesLoaded');
            imageData = Bitmap(loader.content).bitmapData;
        }

        public function writeExternal(out:IDataOutput):void{
            trace('writeExternal');
            var encoder:PNGEncoder = new PNGEncoder();
            var bytes:ByteArray = encoder.encode(imageData);
            bytes.position = 0; // may not be necessary
            out.writeDouble(bytes.length);
            out.writeBytes(bytes);
        }

        public function readExternal(input:IDataInput):void{
            trace('readExternal');
            var length:Number = input.readDouble();
            var pngData:ByteArray = new ByteArray();
            input.readBytes(pngData,0,length);
            loader.loadBytes(pngData);
        }
    }
}

Let’s hope that this kind of wierdness can be forgotten in AS4…

Custom file formats in AS3 using AMF

There’s always something interesting going on in the actionscript world of brothers Jacob (jacwright.com) and Tyler Wright (xtyler.com). I’ve been using their Flight Framework (www.flightxd.com) for some time now, and it’s the first of the many flex/as3 frameworks I’ve tried that has really made me more productive. Check it out!

In a recent article, Jacob is pointing out the possibility to use AMF serialization for storing objects to disc, on server, on clipboard or anywhere. The complicated stuff involved in saving more complex objects like bitmaps or sound have scared me away so far from trying it out. (The IExternalizable interface has such a scary name, for example..!) But Jacs article gave me the inspiration to try it, and some quick prototyping has given positive results – including storing arrays containing bitmaps! Thanks, Jac!

AS3: Loading sound from bytearray

When fiddling with using zip in Flex/As3, I discovered that the Sound class doesn’t have a .loadBytes method (corresponding to the Loader class .loadBytes method). I was able to get the byteArray data out of the zip, but no way to feed a Sound object with it! Grr..!

Luckily, there are lots of gifted bravehearts and generous brightheads around in the blogosphere!

Thanks to article by Chris at flexiblefactory.co.uk about reading sound from a FileReference, I could make it work! Here is how his elegant solution works – well, at least “kind of how”…:

  • Reading the mp3 bytearray code from the file
  • Building a SWF from the ground up, including the messy header stuff, and embedding the mp3 data into it
  • Loading the SWF into a Loader object, and typecast it from there as a SoundClass to a Sound object
  • Play! :-)

Thank you, Chris!