Working and creating images in Flex could not be as easy as it looks. When you load an image loaded from the remote server you will tipicaly receive a ByteArray data. The ByteArray image doesn't contain any information such as the width and height of that data. Moreover you must know when the entire bytearray it's been fully loaded on the client.
To do this we need to load the bytearray with the Loader Class.
So we need to extend an mx.control.Image Class and add the loader information:
private var _loader:Loader = new Loader();
Now wee need to implement a method to load the bytes:
public function loadBytes(bytes:ByteArray, context:LoaderContext = null):void
{
_loader.loadBytes(bytes, context);
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBytesLoaded);
}
This method will load the byte array image and add the listener to know when is ready.
After the event.complete handler will bring up with the loader information:
private function onBytesLoaded( e:Event ):void
{
source = _loader.content;
width = _loader.contentLoaderInfo.width;
height = _loader.contentLoaderInfo.height;
removeChild(_loader);
}
You can see that now we can set the source for the image and than set the correct width and height getting the information from the _loader.contentLoaderInfo.
Finally we remove the loader.
Here you can find the complete source for the ByteArrayImage Class:
The Class
package
{
import flash.display.Loader;
import flash.events.Event;
import flash.system.LoaderContext;
import flash.utils.ByteArray;
import mx.controls.Image;
public class ByteArrayImage extends mx.controls.Image
{
private var _loader:Loader = new Loader();
public function ByteArrayImage()
{
}
override protected function createChildren():void
{
_loader.visible = false;
addChild(_loader);
}
public function loadBytes(bytes:ByteArray, context:LoaderContext = null):void
{
_loader.loadBytes(bytes, context);
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBytesLoaded);
}
private function onBytesLoaded( e:Event ):void
{
source = _loader.content;
width = _loader.contentLoaderInfo.width;
height = _loader.contentLoaderInfo.height;
removeChild(_loader);
}
}
}
A simple implementation:
import flash.image.JPEG;
import flash.image.PNG32;
myJPG:ByteArray = new JPEG( bitmapData , 300, 300, 80 );
myPNG:ByteArray = new PNG32( bitmapData , 1500, 1260 );
myByteImage:ByteArrayImage = new ByteArrayImage();
myByteImage.loadBytes( myJPG or myPNG );
Reference:
ByteArray LiveDocs
Loader LiveDocs
Comments (4)
where is the overridden function "createChildren" implemented in the Flex source code? By overriding this function, what is the intended result? Thanks.
Posted by Jed Schneider | November 25, 2008 10:35 PM
Posted on November 25, 2008 22:35
This is the overrided function:
override protected function createChildren():void
{
_loader.visible = false;
addChild(_loader);
}
By overriding this when you add to stage the ByteArrayImage automaticaly create and and the child "_loader" setted to invisible. The _loader child component need to load the byteArray.
Posted by Liviu Stoica | November 29, 2008 5:38 PM
Posted on November 29, 2008 17:38
Whenever I try to call loadBytes as you suggested I receive the next error:
Error #2044: Unhandled IOErrorEvent:. text=Error #2124: Loaded file is an unknown type.
Posted by Anton Serbin | January 30, 2009 4:14 PM
Posted on January 30, 2009 16:14
hi there!
Is it possible to do this for VideoDisplay components?
My question is, basically: after i load the video into an array using FileReference.load(), how do i show the video in the component. The source property of the VideoDisplay only accepts String and i want to show a video form the client side, so obviously i cannot access the file path. Any ideas?
Posted by Rui | July 2, 2009 1:11 PM
Posted on July 2, 2009 13:11