Home > Flex, Java, Open Source, RIA > Flex Paint - Flex Display Object to PNG

Flex Paint - Flex Display Object to PNG

August 16th, 2006

Flex allows you to easily create beautiful UIs. But what if you want to take a piece of the UI and save it as an image? Well, using Tinic’s AS3 PNG Encoder, Remote Object, and Flash’s BitmapData and ByteArray API it’s very easy. To show how this is done, I created a simple application called Flex Paint.

Flex Paint (requires Flash 9)

How it Works

We use the Flash drawing API to draw on a canvas. Then when the “Save Image” button is clicked we do a few simple things. First we create a new BitmapData object:
var bd:BitmapData = new BitmapData(canvas.width,canvas.height);

Then we copy canvas’ pixels onto the BitmapData object:
bd.draw(canvas);

Now we convert the BitmapData object to a ByteArray encoded as a PNG:
var ba:ByteArray = PNGEnc.encode(bd);

And then upload the PNG via Remote Object:
ro.doUpload(ba);

Then Remote Object just saves the file to the file system. If you would like to download the code for Flex Paint, you can find it on Source Forge. Let me know what you think. Thanks!

Flex, Java, Open Source, RIA

  1. August 16th, 2006 at 12:03 | #1

    In case anybody else thinks for a moment that Save doesn’t work, note that there’s a popup on this page that you have to allow to see the PNG. Very nice!

  2. Jenny Ward
    August 16th, 2006 at 20:47 | #2

    fantastico!

  3. August 17th, 2006 at 20:16 | #3

    I just posted this on a blog that linked here, but you can see Tinic’s encoding code in action on my Flex Derby project, Artmatic. http://matt-rix.com/fd/artmatic/

    Check it out, let me know what you think… I’m not even sure it works with the Flash 9 release player :P It’s just a neat way to show how this stuff could be used.

  4. October 22nd, 2006 at 16:00 | #4

    hey James,

    this probably isnt the place [where's the contact page?] but i have some issues when running this page on IE6.
    The AS3 error doesnt make much sense to me, but i think it may be valueable to you.

    take a look at the screenshot for details.

    http://www.lfo-industries.com/flash9_kzzzt.png

    cheers

  5. October 22nd, 2006 at 16:32 | #5

    Can you go here:
    http://www.macromedia.com/software/flash/about/

    And let me know what version you have?

  6. Junior
    November 6th, 2006 at 11:07 | #6

    Hello, I think this method is very interesting, but I have one question:
    Where do you save java files? because flex file does not read java files.
    I do not know where you save this component.

    When I am running the application the follow error appears:
    [URL=http://imageshack.us][IMG]http://img179.imageshack.us/img179/4372/errorflexpaintzg3.png[/IMG][/URL]

    I am using coldfusion server, windows XP, flex builder 2.0 and data service 2.

    How can I make the application run?
    Thank you

  7. Junior
    November 6th, 2006 at 11:09 | #7
  8. Gufo
    April 9th, 2007 at 02:18 | #8

    excellent script!!! i were looking for it since ages….

  9. April 9th, 2007 at 04:10 | #9

    Hi James,

    I’ve done some effort in that same area.
    I used Open Lazslo, which is a Flex concurrent. I done a stress test (lots and lots of strokes) in both and my application add a better behavior, but yours seams to pick more point at the begin.
    You can check my app at http://www.mainada.net/inputdraw

    The advantage is that it integrates with javascript and directly with forms, so you can pass your drawing thru a form to your server, allowing to save drawing, process then and display them afterwards. which is nice to build drawing related webapps.

    Hope you enjoy it.

  10. April 10th, 2007 at 07:36 | #10

    Hi Tiago,

    Cool app. Is it open source? I’d like to see how the code is different in OpenLaszlo, compared to Flex. Thanks.

    -James

  11. April 11th, 2007 at 18:17 | #11

    Hello James,

    No, it is not open source. It’s a commercial product, but it has a similar free license for non-commercial projects, so that anyone can use it for their own projects (give at least something back :D).

    Nevertheless, the code is very similar to a openlaszlo application. You can see their examples for fun.
    Openlaszlo is also pretty great in some areas :)

    Any more question, just drop me an email :) I’ll be plz to reply.

    Take care.

    - Tiago

  12. Ronni
    July 22nd, 2007 at 05:48 | #12

    Hi,

    In case the paint area is too small to fit in the page,
    the canvas use the scroll bar and some of the painting is out of the screen.

    In this case the bitmap does not contain all the picture

    How can I manage this problem?

    Thanks,
    Ronnie

  13. July 24th, 2007 at 12:18 | #13

    Ronnie,

    This should work fine. Try this example:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    
      <mx:VBox width="300" height="300">
        <mx:Canvas id="c" width="500" height="500" backgroundColor="#ffffff">
          <mx:Label left="0" top="0" text="top left"/>
          <mx:Label left="0" bottom="0" text="bottom left"/>
          <mx:Label right="0" top="0" text="top right"/>
          <mx:Label right="0" bottom="0" text="bottom right"/>
        </mx:Canvas>
      </mx:VBox>
    
      <mx:Canvas id="p" width="500" height="500"/>
    
      <mx:Button label="duplicate canvas">
        <mx:click>
        import flash.display.BitmapData;
    
        var bd:BitmapData = new BitmapData(c.width,c.height);
        bd.draw(c);
    
        p.graphics.clear();
        p.graphics.beginBitmapFill(bd);
        p.graphics.drawRect(0, 0, c.width, c.height);
        </mx:click>
      </mx:Button>
    
    </mx:Application>
    

    Hope that helps.

    -James

  14. September 19th, 2007 at 20:49 | #14

    1.) MyFlexApp.mxml (layout=”vertical”) has a docked ApplicationControlBar (height =”10%”) with 2 rows of icons/menus, each row with 3 sections. Is there a better layout strategy than nesting (and/or what is the performance hit from this level of nesting?)

    AppControlBar
    VBox
    HBox
    HBox - HBox - HBox
    HBox
    HBox - HBox - HBox

    2.) Below the AppControlBar I have a (to enable drag/drop and resizing of flexmdi:MDIWindows) containing an MXML component consisting largely of layered pngs and jpgs (which make resizing “expensive”).

    Would it be better to make either the background for the MDICanvas a swf or what is contained in the canvas a swf

    in that http://www.cflex.net/showFileDetails.cfm?ObjectID=690 details how to communicate with an app loaded by SWFLoader or is this over complicating matters?

    Experimentation to ensue on my part but suggestions would be much appreciated.

  15. josh
    September 20th, 2007 at 09:26 | #15

    does this require java to be installed on the server?

    i’m making an app that is going to be using XAMPP as the webserver locally, but they might not have java installed. they will have flash installed though.

    thanks.josh.

  16. September 25th, 2007 at 16:21 | #16

    Mike - You might want to take a look at the code for the Anvil project:
    sf.net/projects/flexapps
    (Anvil is in svn - no release yet)

    I believe It has a lot of what you need already.

    Josh - This particular examples does use Java on the server. But that could pretty easily be replaced by a number of other technologies.

  17. kurt
    October 3rd, 2007 at 21:12 | #17

    great job! thanks!!

  18. October 17th, 2007 at 01:52 | #18

    Hi James

    This is awesome. Exactly what I’m looking for for my current project.
    I cant find it on sourceforge. Please can you show me the location for the code?

    Many thanks, and thank you for a great app! :)

  19. October 17th, 2007 at 01:54 | #19

    Apologies for the last post. Coffee hadn’t kicked in yet.
    I’ve found it. Thank you :)

  20. vijay visana
    November 28th, 2007 at 23:12 | #20

    Guys…
    Does it work on PDA???
    I tried it on windows mobile 5.0 and 6.0 device but it does not show up.

  21. Chris
    December 4th, 2007 at 09:25 | #21

    James, I saw your comment about the scrollbars but I don’t think that solves the issue completly. When there is a canvas that has scrollbars, do you know how to get that entire canvas (even the content that is not currently visible) to be copied into the BitmapData object? Here is a little sample that will show you that with scrollbars, only the visible section seems to be copied.

  22. December 4th, 2007 at 10:52 | #22

    Hi Chris,

    You just need to wrap your container with another container, like:

    <mx:VBox width=”100%” height=”400″ horizontalScrollPolicy=”on” verticalScrollPolicy=”on”>
    <mx:Canvas id=”c” backgroundColor=”#ffffff” horizontalScrollPolicy=”off” verticalScrollPolicy=”off”>
    <mx:Label left=”0″ top=”0″ text=”top left”/>
    <mx:Label text=”bottom left” y=”785″ x=”0″/>
    <mx:Label text=”top right” y=”0″ x=”708″/>
    <mx:Label text=”bottom right” y=”785″ x=”686″/>
    </mx:Canvas>
    </mx:VBox>

    And use the Canvas’s width and height:

    var bd:BitmapData = new BitmapData( c.width, c.height );
    bd.draw(c);

    try { p.removeChild(lbl); } catch( ex:Error ) {}

    p.graphics.clear();
    p.graphics.beginBitmapFill(bd);
    p.graphics.drawRect(0, 0, c.width, c.height);

    Let me know if that works.

    -James

  23. February 11th, 2008 at 00:38 | #23

    Hi Anenth,

    You will have to use Adobe AIR if you want to get around the upload-then-download thing.

    -James

  24. Anenth
    February 11th, 2008 at 07:34 | #24

    i am developing a drawing application, is it possible to save the bitmap data in the canvas directly into the file system?

  25. February 16th, 2008 at 04:41 | #25

    hi, Please give me a suggestion regarding:
    if i add multiple image and an text ,it is possible to save whole.

    thanks

  26. February 16th, 2008 at 11:26 | #26

    Hi Ashu,

    Yes, you certainly can do that. Anything on the screen can be saved as an image.

    -James

  27. Jeff Lemon
    February 16th, 2008 at 12:09 | #27

    Hi,
    Im moderating your code to work with amfphp but am having a few problems with the save function:

    private function doSave():void
    {
    var bd:BitmapData = new BitmapData(canvas.width,canvas.height);
    bd.draw(canvas);

    var ba:ByteArray = PNGEnc.encode(bd);

    myservice.getOperation(’imagesave1′).send(ba);

    }

    Im trying to get the var ba to send to be uploaded but it doesnt work…

    any help will greatly be appreciated

  28. February 20th, 2008 at 05:29 | #28

    Hi Jeff,

    I’m not familar with amfphp but can try to help you figure this out. Can you post your php code as well? Are you getting any errors?

    -James

  29. prince
    March 5th, 2008 at 23:47 | #29

    Hi James

    Thank you for your excellent work. this has resolved my problem

    i just used it the only problem is when click erase clears all the image can it modified so that it should erase just like paint eraser not the whole image.

    Thanks

  30. Satish
    March 26th, 2008 at 02:42 | #30

    The PNGEnc.as works inconsistently for large sized canvas. I’m trying to load a background image to the canvas and then scribble on it and try saving the entire picture with annotation.

  31. Satish
    March 26th, 2008 at 03:35 | #31

    I am not able to save large sized canvas, about 800 X 600. Please help??

  32. March 28th, 2008 at 08:30 | #32

    Hi Satish,

    You might want to try and grab the latest version - which I think you can get here:
    http://code.google.com/p/as3corelib/

    If it still doesn’t work you might want to try the JPG encoder.

    Let me know how it goes.

    -James

  33. Satish
    March 30th, 2008 at 23:15 | #33

    Hi James,

    Thanks a lot for your help. I downloaded the latest version, but the problem was actually in my servlet, i wasn’t doing a readFully() from the input stream, as a result i was writing incomplete data to my png file. Anyways, that is fixed.
    Could you suggest me a book, or free link, which can help me learn flex with java in detail. I really need it. Thanks again.

    Cheers,
    Satish

  34. Satish
    April 1st, 2008 at 00:36 | #34

    Hi james,

    I had another doubt, can i capture voice using a flex application, without using any third party server? The user has to speak something and my application has to capture whatever user said. Is it possible?

    Thanks,

    Satish

  35. Brightside
    May 3rd, 2008 at 04:31 | #35

    I was looking for an online drawing “thingy” to put on a website and I found yours. It was just what I needed. The only problem is: I don’t know shit about flash, flex or xml. So I downloaded the source code, but I don’t know how I have to upload it, I mean, which file in which map or if I have to make maps / packages. I know, really stupid question but maybe you could mail me or post me how to get it online properly. Cause, I tried it, and I got the flexpaint online but when I save I get errors like “destination not found” or something like that. So maybe I need to change something in the code or upload it correctly so it would work. Can you help me?

    I don’t know nothing but maybe with your help I can get it online AND saving, thanks!

  36. May 5th, 2008 at 06:57 | #36

    Hi Brightside,

    You will probably want to download the source code from SourceForge and get Flex Builder (or Flex SDK) and LCDS Express. There is an ant built which should still work but I haven’t touched it in a while. I hope that helps.

    -James

  37. Brightside
    May 5th, 2008 at 12:54 | #37

    Hello James,

    I’ve Flex Builder and ColdFusion 8 now. I got the resource files but I still don’t know what to do and how to do it. (I’m a total noob with Flex & Coldfusion)

    You can always contact me with mail.

    Thanks in advance!

  38. Efi
    May 6th, 2008 at 01:37 | #38

    I implemented your code and it runs but nothing is written to a file. (I am totally new to this stuff).
    PNGEnc class is in PNGEnc.as.
    I am trying to write a canvas image to a file c:\myPng.png

    Please let me know what’s wrong. Thx a lot. Efi.

    This is my code in Flex 3 :

  39. Efi
    May 6th, 2008 at 01:44 | #39

    a code in my previous comment was not shown, I add it here (canvas has some TextInput and VBox’es)

    var bd:BitmapData = new BitmapData(Canvas.width,Canvas.height);
    bd.draw(Canvas);
    var ba:ByteArray = PNGEnc.encode(bd);
    var ro:RemoteObject=new RemoteObject(”c:\myPng.png”);
    ro.doUpload(ba);

  40. May 10th, 2008 at 11:45 | #40

    Hi Efi,

    You will need to manipulate the back-end Java class which the RemoteObject is hooked to if you want to change where the image is being saved. Also if you are in AIR you can save the image directly to the hard drive using the File APIs (as opposed to the RemoteObject API).

    I hope that helps.

    -James

  41. Efi
    May 12th, 2008 at 06:04 | #41

    Thanks. I am using Flex, is it possible to use AIR’s File APIs from Flex?

  42. May 13th, 2008 at 04:43 | #42

    Do you mean use the AIR File API’s in the browser? If so, then no. AIR API’s can only be used on the desktop.

    -James

  43. David Bridges
    May 13th, 2008 at 11:19 | #43

    Hi James,

    Nice piece of code. When I set the alpha of the line to something less than one, I get the line with dots in it. What do I need to do to smooth the fill of the line out - I’m trying to approximate a highlighter pen.

    Thanks.

  44. May 15th, 2008 at 14:18 | #44

    Hi David,

    Good question. I’m not totally sure but you might want to try using smoothing. I think you set that on the BitmapData but I’m not totally sure. Let me know what you find out.

    -James

  45. Björn
    July 23rd, 2008 at 14:10 | #45

    Can you pleasy send mie a zip-file, so that I can import the flexpaint application as a flex project, because the save button does´t work. I don´t know, what to do. Do I need the AS3 corelib - if yes, how to integrate? Thank you very much

  46. July 23rd, 2008 at 17:13 | #46

    Hi Björn,

    You will need to get the code from SourceForge:
    http://sourceforge.net/project/showfiles.php?group_id=174131&package_id=200814&release_id=439840

    -James

  47. Karel
    September 1st, 2008 at 23:15 | #47

    can you please help me to work out this into jboss as local server. Thanks

  48. September 2nd, 2008 at 07:09 | #48

    Hi Karel,

    Are you having problems running this on JBoss? I am running it on JBoss without any problems.

    -James

  49. Nishanth Shetty
    September 30th, 2008 at 05:40 | #49

    Hi, everyone

    anybody knows how to store DisplayObject to XML.

    Thank you.

  50. October 1st, 2008 at 00:08 | #50

    Hi Nishanth,

    There isn’t any way to do this unfortunately.

    -James

  51. Nishanth Shetty
    October 1st, 2008 at 03:26 | #51

    Hi, James

    Thanks for your valuable response.

  52. Nishanth Shetty
    October 1st, 2008 at 04:46 | #52

    Hi, James

    Is there any posibility to convert DisplayObject to ByteArray
    (and again ByteArray to DisplayObject )?

    Thank You.

  53. October 1st, 2008 at 06:18 | #53

    Hi Shetty,

    Unfortunately not currently. DisplayObjects can not be serialized or introspected.

    Please file a feature request:
    http://bugs.adobe.com

    -James

  54. chuck
    October 1st, 2008 at 07:16 | #54

    Is there a way to only capture what was writen to the page? Not a screenshot of the image, only what was written to the page while I had the mousedown event envoked.

  55. October 2nd, 2008 at 02:31 | #55

    Hi Chuck,

    In Flash you can capture anything (there is an exception to this but it probably won’t affect you). Is the page you are referring to being rendered by Flash or by HTML in the browser?

    -James

  56. jo
    November 12th, 2008 at 12:59 | #56

    Hello to you, James,

    I want to test it on a website and, unfortunately, I have an error opening on a Flash Player 9 window when I want to save.

    The error is :

    “[RPC Fault faultString="[MessagingError message='Unknown destination 'UploadImage-ro'.']” faultCode=”InvokeFailed” faultDetail=”Couldn’t establish a connection to ‘UploadImage-ro’”]
    at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::invoke()
    at mx.rpc.remoting.mxml::Operation/http://www.adobe.com/2006/flex/mx/internal::invoke()
    at mx.rpc.remoting::Operation/send()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at mx.rpc.remoting.mxml::Operation/send()
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at mx.rpc::AbstractService/http://www.adobe.com/2006/actionscript/flash/proxy::callProperty()
    at flexpaint/::doSave()
    at flexpaint/___Button2_click()”

    Is there a way to place file in flex?

    Thank you so much
    Jo

  57. November 13th, 2008 at 02:53 | #57

    Hi Jo,

    Did you get this on my website or did you try to set this up yourself?

    -James

  1. September 10th, 2006 at 15:15 | #1
  2. April 5th, 2007 at 13:06 | #2
  3. September 10th, 2007 at 01:39 | #3