Flex 2 BitmapData Tricks and Techniques
Most seasoned flash developers know that the Bitmap API has been around in the Flash player since the relase of FP8. Those that know all about the Bitmap API appreciate it for its many benefits... Those that don't know about it, trust me, you appreciate it too... you just don't know it. In Flex 2, you can take advantage of the Bitmap API to implement some very powerful and useful techniques that simply are not possible in non-Flash-based web applications.
Some of you may be asking: What is the Bitmap API?
The Bitmap API refers to the flash player's functionality that renders every visual object within a swf as a bitmap (which gets cached), rather than redrawing the entire object every frame interval. Only objects that are marked as "dirty" will be redrawn. The amount of resources used to render each frame is significantly reduced, thus improving the runtime performance of swf files on the client machine. You can find some more information on the Bitmap API at:
So now what? You can capture the BitmapData from any visual component. Why would you ever want to do that? I've got a few reasons (and this is just the tip of the iceberg).
My first example shows how to put this code to use, although its rather boring compared to my other examples. It takes the BitmapData of the specified UI component and pushes it into an Image object. This code example can also be found on JAM.

Launch Application
View Source
Download Source
Bitmap-Based Imaging Effects
Wouldn't it be cool if you moved one thing around on the screen, and it left motion trails? What if you wanted to capture part of a component, distort the image (colors, blur, size, crop, etc...) and then show it in a different part of your application? Well, the getUIComponentBitmapData function makes this difficult-sounding task much easier.
In this example, I have an image that is at 0,0 (top left corner) and is the exact same size as my application. The alpha on that image is 90%. On every "ENTER_FRAME" event, it takes a snapshot of the entire application and pushes it into the image. This causes the "trail" effect that you will see. Since the alpha is only 90%, it will eventually fade out, creating the fading image effect. The code is amazingly short, powerful and efficient.

Note: This process will become very processor intensive at high resolutions.
Launch Application
View Source
Download Source
User Interface Component Mirroring
Have you ever had the need to mirror the user interface? I know, this is not a common need but take it a step further (which I will do later in this post), and you have some really useful tools in your toolbox. This next example takes the BitmapData from a tree inside of a panel and pushes it into an Image inside of another panel. This occurs every 100 milliseconds. You'll see that there is a slight delay, but overall it mirrors the interaction very effectively.
Launch Application
View Source
Download Source
The next example acutally mirrors a flv file by pushing the BitmapData of the video playback's current frame into an Image object on every "ENTER_FRAME" event. You'll notice that a few frames are dropped per second, but you really have to look very closely to see the difference. One thing to keep in mind, more frames will be dropped on slower client machines.

Disclaimer: This video clip was downloaded from Google video. This is a scene from the surfing movie Billabong Odyssey, which is a great movie (that I do personally own). I highly reccommend it.
Launch Application
View Source
Download Source
Application Sharing
In my opinion, this next example is really amazing. It is also incredibly simple, yet powerful. I've extended my "User Interface Mirroring" example to share data between two different browsers using local shard objects. Keep in mind, this code only works on the same machine, but who is to say that you can't change that. You could easily chage the local shared object to a remote shared object, incorporating Flash Media Server, and this will work across different client machines. Also, what is stopping you from doing a RemoteObject call to push the image data to a server? This would enable you to pull down the image from the server to any client machine, without the use of Flash Media Server.

View Captivate Demo
Launch Broadcaster Application
Launch Receiver Application
View Source
Download Source
Side Note: If you looked at the source, you might be wondering why I didn't use getPixels and setPixels instead of my own functions to loop through the pixel arrays. I found a bug in the Flash player and get an "End Of File" error when using get pixels and set pixels on items rendered within the player memory. I'm putting together a test case to send to Adobe for this. I didn't use a BitmapData object on the local shared object because the player can't deserialize it back into a BitmapData object when reading the object back from the local shared object. Instead, I saved it in the LSO as a ByteArray.
Screen Exports
I think this next example is really cool too. Have you ever wanted to export your flex application's current view to the client machine? Using this approach, you can capture the UI as a jpg that can be downloaded by the user. This technique could have a number of uses:

Note: this last example is hosted at tricedesigns.com, that is my personal ColdFusion server.
View Captivate Demo
Launch Application
View Partial Source
Download Partial Source
Questions or comments, you can contact me at andrew.trice( at )cynergysystems.com.
Some of you may be asking: What is the Bitmap API?
The Bitmap API refers to the flash player's functionality that renders every visual object within a swf as a bitmap (which gets cached), rather than redrawing the entire object every frame interval. Only objects that are marked as "dirty" will be redrawn. The amount of resources used to render each frame is significantly reduced, thus improving the runtime performance of swf files on the client machine. You can find some more information on the Bitmap API at:
- http://www.adobe.com/devnet/flash/articles/bitmap_caching.html
- http://www.adobe.com/devnet/flash/articles/image_api_03.html
private function getUIComponentBitmapData( target : UIComponent ) : BitmapData
{
var bd : BitmapData = new BitmapData( target.width, target.height );
var m : Matrix = new Matrix();
bd.draw( target, m );
return bd;
}
{
var bd : BitmapData = new BitmapData( target.width, target.height );
var m : Matrix = new Matrix();
bd.draw( target, m );
return bd;
}
So now what? You can capture the BitmapData from any visual component. Why would you ever want to do that? I've got a few reasons (and this is just the tip of the iceberg).
- Bitmap-Based Imaging Effects
- UI Component Mirroring
- Application Sharing
- Screen Exports
My first example shows how to put this code to use, although its rather boring compared to my other examples. It takes the BitmapData of the specified UI component and pushes it into an Image object. This code example can also be found on JAM.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">
<mx:Script>
<![CDATA[
import mx.core.UIComponent;
private function captureFullScreen() : void
{
var bd : BitmapData = getBitmapData( UIComponent( mx.core.Application.application ) );
targetImage.source = new Bitmap( bd );
}
private function captureHiddenDatagrid() : void
{
var bd : BitmapData = getBitmapData( UIComponent( hiddenDg ) );
targetImage.source = new Bitmap( bd );
}
private function getBitmapData( target : UIComponent ) : BitmapData
{
var bd : BitmapData = new BitmapData( target.width, target.height );
var m : Matrix = new Matrix();
bd.draw( target, m );
return bd;
}
]]>
</mx:Script>
<mx:Button
id="captureButton"
label="Capture Full Screen"
click="captureFullScreen()" />
<mx:Button
id="captureButton2"
label="Capture Hidden Datagrid"
click="captureHiddenDatagrid()"
x="153"/>
<mx:Image
id="targetImage"
x="10"
y="30"/>
<mx:DataGrid
x="99"
y="64"
id="hiddenDg"
visible="false">
<mx:columns>
<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
<mx:DataGridColumn headerText="Column 3" dataField="col3"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">
<mx:Script>
<![CDATA[
import mx.core.UIComponent;
private function captureFullScreen() : void
{
var bd : BitmapData = getBitmapData( UIComponent( mx.core.Application.application ) );
targetImage.source = new Bitmap( bd );
}
private function captureHiddenDatagrid() : void
{
var bd : BitmapData = getBitmapData( UIComponent( hiddenDg ) );
targetImage.source = new Bitmap( bd );
}
private function getBitmapData( target : UIComponent ) : BitmapData
{
var bd : BitmapData = new BitmapData( target.width, target.height );
var m : Matrix = new Matrix();
bd.draw( target, m );
return bd;
}
]]>
</mx:Script>
<mx:Button
id="captureButton"
label="Capture Full Screen"
click="captureFullScreen()" />
<mx:Button
id="captureButton2"
label="Capture Hidden Datagrid"
click="captureHiddenDatagrid()"
x="153"/>
<mx:Image
id="targetImage"
x="10"
y="30"/>
<mx:DataGrid
x="99"
y="64"
id="hiddenDg"
visible="false">
<mx:columns>
<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
<mx:DataGridColumn headerText="Column 3" dataField="col3"/>
</mx:columns>
</mx:DataGrid>
</mx:Application>
Launch Application
View Source
Download Source
Bitmap-Based Imaging Effects
Wouldn't it be cool if you moved one thing around on the screen, and it left motion trails? What if you wanted to capture part of a component, distort the image (colors, blur, size, crop, etc...) and then show it in a different part of your application? Well, the getUIComponentBitmapData function makes this difficult-sounding task much easier.
In this example, I have an image that is at 0,0 (top left corner) and is the exact same size as my application. The alpha on that image is 90%. On every "ENTER_FRAME" event, it takes a snapshot of the entire application and pushes it into the image. This causes the "trail" effect that you will see. Since the alpha is only 90%, it will eventually fade out, creating the fading image effect. The code is amazingly short, powerful and efficient.

Note: This process will become very processor intensive at high resolutions.
Launch Application
View Source
Download Source
User Interface Component Mirroring
Have you ever had the need to mirror the user interface? I know, this is not a common need but take it a step further (which I will do later in this post), and you have some really useful tools in your toolbox. This next example takes the BitmapData from a tree inside of a panel and pushes it into an Image inside of another panel. This occurs every 100 milliseconds. You'll see that there is a slight delay, but overall it mirrors the interaction very effectively.
Launch Application
View Source
Download Source
The next example acutally mirrors a flv file by pushing the BitmapData of the video playback's current frame into an Image object on every "ENTER_FRAME" event. You'll notice that a few frames are dropped per second, but you really have to look very closely to see the difference. One thing to keep in mind, more frames will be dropped on slower client machines.

Disclaimer: This video clip was downloaded from Google video. This is a scene from the surfing movie Billabong Odyssey, which is a great movie (that I do personally own). I highly reccommend it.
Launch Application
View Source
Download Source
Application Sharing
In my opinion, this next example is really amazing. It is also incredibly simple, yet powerful. I've extended my "User Interface Mirroring" example to share data between two different browsers using local shard objects. Keep in mind, this code only works on the same machine, but who is to say that you can't change that. You could easily chage the local shared object to a remote shared object, incorporating Flash Media Server, and this will work across different client machines. Also, what is stopping you from doing a RemoteObject call to push the image data to a server? This would enable you to pull down the image from the server to any client machine, without the use of Flash Media Server.

View Captivate Demo
Launch Broadcaster Application
Launch Receiver Application
View Source
Download Source
Side Note: If you looked at the source, you might be wondering why I didn't use getPixels and setPixels instead of my own functions to loop through the pixel arrays. I found a bug in the Flash player and get an "End Of File" error when using get pixels and set pixels on items rendered within the player memory. I'm putting together a test case to send to Adobe for this. I didn't use a BitmapData object on the local shared object because the player can't deserialize it back into a BitmapData object when reading the object back from the local shared object. Instead, I saved it in the LSO as a ByteArray.
Screen Exports
I think this next example is really cool too. Have you ever wanted to export your flex application's current view to the client machine? Using this approach, you can capture the UI as a jpg that can be downloaded by the user. This technique could have a number of uses:
- Capture the user's screen when an error occurs
- Save the current image within the application: possibly for a flex-based image editing solution... yes, I am working on one of those as a side project :-)
- Distributed application sharing... this could be a great asset for remote application assistance

Note: this last example is hosted at tricedesigns.com, that is my personal ColdFusion server.
View Captivate Demo
Launch Application
View Partial Source
Download Partial Source
Questions or comments, you can contact me at andrew.trice( at )cynergysystems.com.





1 Comments:
hii andrew i read ur posts they where really amazing and i appreciate your efforts done towards bitmap......but can u help me in splitting an image
.........actually i want to split a image in 4 parts ....can u post a eaxmple for the said..........because i have done using copy pixels and done by using an rectangle and trying to fit the image in rectangle of specific dimension but nothing is working may u please..........guide me.......hoping for a reply
Post a Comment
<< Home