Taking a snapshot of Flex app, from Flex!

On a recent Flex project, we needed to take a snapshot of what's shown on the screen and save it as an image. I had seen somewhere that this was possible, but couldn't locate how exactly it was to be done. Turns out it's very easy to do such a screen capture / screen grab using Flex.

The essential steps are:

  • Create a new BitmapData object.
  • Copy the target component's pixel data into BitmapData object.
  • Convert the BitmapData object to a PNG encoded ByteArray (using the PNGEnc library)
  • Convert the ByteArray to a Base64Encoded string so that we can send the data safely to the backend.
  • On the backend (PHP via WebORB in our case), decode the data and write it to a file.

Most of the piece come from two places. James Ward has described this technique in his Flex Paint sample. And Tinic Uro has written the PNG Encoder library. Let's see the code now.

Here's the Flex Code:

XML:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
  3. <mx:Script>
  4. <![CDATA[
  5. import mx.utils.Base64Encoder;
  6. import mx.rpc.events.ResultEvent;
  7. import mx.utils.ObjectUtil;
  8. import mx.controls.Alert;
  9. import mx.rpc.events.FaultEvent;
  10. import mx.core.UIComponent;
  11.  
  12. public function onResult(event:ResultEvent) :void
  13. {
  14. Alert.show(ObjectUtil.toString(event.result));
  15. }
  16.  
  17. public function onFault(event:FaultEvent) :void
  18. {
  19. Alert.show("Got error: "+event.message);
  20. }
  21.  
  22. public function takeSnapshot(target:UIComponent) :void
  23. {
  24. var bd:BitmapData = new BitmapData(target.width,target.height);
  25. bd.draw(target);
  26. var ba:ByteArray = PNGEnc.encode(bd);
  27. var be:Base64Encoder = new Base64Encoder();
  28. be.encodeBytes(ba);
  29. var encodedData:String = be.flush();
  30. ro.saveImage(encodedData);
  31. }
  32. ]]>
  33. </mx:Script>
  34.  
  35. <mx:Button click="takeSnapshot(targetPanel)" label="Save Image" x="10" y="100"/>
  36.  
  37. <mx:Panel id="targetPanel">
  38. <mx:Canvas backgroundColor="#EEEEEE">
  39. <mx:Label text="Hello World" />
  40. </mx:Canvas>
  41. </mx:Panel>
  42.  
  43. <mx:RemoteObject id="ro" destination="serviceEndpoint" result="onResult(event)" fault="onFault(event)"/>
  44. </mx:Application>

We use WebORB for backend connectivity. Assuming you have the connection in place, we can simply call a method passing the base 64 encoded string and save it on the server. If you don't have RemoteObject / Web Service, you can also use an HTTP POST. The reason to use Base 64 encoding is to get a string we can safely pass around, instead of a byte array.

Here's the PHP side of the code:

PHP:
  1. public function saveImage($encodedPNGData)
  2. {
  3. if ($encodedPNGData != "")
  4. {
  5. $binaryData = base64_decode($encodedPNGData);
  6. $file = "assets/images/something.png";
  7. file_put_contents($file, $binaryData);
  8. return $file;
  9. }
  10. return null;
  11. }

I could resize and do anything else with the image on the PHP side now.

Hope you find some creative use of this :)

 

9 comments ↓

#1 James Urquhart on 09.10.07 at 4:20 pm

Nice!

Currently i am concentrating on OpenLaszlo development at the moment, so i probably won’t be able to make use of this code. Still, it is possible to access flash api’s from OpenLaszlo, so maybe i can make use of that rather interesting ByteArray class to at least handle binary data.

#2 vinay on 09.10.07 at 4:47 pm

Hello Sir

This is a cool stuff

In fact it helped me but can you clarify this

PNGEnc.encode

what it does and is it a class[could not locate it in the help]

#3 vinay on 09.11.07 at 11:07 am

Oops

I got the answer of my question

U have already mentioned it

Reading Skills have gone down :)

#4 maxim on 09.15.07 at 7:53 pm

Hi!

You mention uploading the file could work with HTTP POST. How would that work?
I don’t have flex data services nor WebORB installed.

grtz!

#5 Nirav on 09.16.07 at 9:56 am

Hi Maxim,

Make an HTTP Service and pass the base 64 encoded string as a parameter.

For more, a look at HTTPService Live Docs, Adobe article on using Flex with PHP and Mike Potter’s similar article.

HTH.

:Nirav

#6 Maxim on 09.18.07 at 4:12 am

Wicked,

Thanks Nirav.

Implemented it into http://www.redesignme.org

greetings!

#7 JmfD on 10.22.08 at 7:32 pm

I just came across this, and I was still having trouble with getting the HTTP Service to work can anyone help me out?

#8 Nirav on 10.23.08 at 1:11 pm

@JmfD: What are the troubles you are having with HTTP Service to get this to work? Are you getting POST request on server? Can you dump everything that’s coming in POST and see what you get?

#9 JmfD on 10.23.08 at 7:15 pm

I’m pretty new to Flex and I don’t know how to pass the base 64 encode string as a parameter. When I’m trying to change it to a HTTP Post I get an error about how saveImage is undefined.

Leave a Comment