David Harris's Technology Blog

ColdFusion, Flex, and other stuff...   (and 354,856 hours, 44 mins in to my plan for global domination)

Search:

Calendar:

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      

Subscribe:

Enter your email address to subscribe to this blog.

Archives By Subject:

Tags:

action script adobe air ajax cfug coldfusion flash flex frameworks free software fxug general jpgmetadatareader mac off topic opensource papervision spry

Recent Entries:

No recent entries.

Top Posts:

Recent Comments:

Top Commenters:

My Links:

RSS:


Saving images from Flex using ColdFusion: Simple Example with source code

As Promised, here is a simpler example of saving a Flex UI Component on the fly as a JPG using ColdFusion.

Here is the CFC code:

<cfcomponent output="false">
   
   <cffunction name="saveImage" access="remote" output="false" returntype="string">

    <cfargument name="data" type="binary" required="true" />
      
      <cfset var sPath   = "">
      <cfset var sFile   = "">
      
      <cflock name="writeImage" type="exclusive" throwontimeout="false" timeout="5">
         
         <cfset sFile   = "IMG.jpg" >
         
         <cfset sPath = expandPath( "#sFile#" )>
         <cffile action="write" file="#sPath#" output="#arguments.data#" >
         
      </cflock>
      
      <cfreturn sFile>
      
</cffunction>
   
</cfcomponent>

Here is the Flex Code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" backgroundColor="0xFFFFFF" >
   <mx:Script>
      <![CDATA[
      
         import mx.managers.PopUpManager;
         import mx.controls.Label;
         import mx.rpc.events.FaultEvent;
         import mx.controls.Alert;
         import mx.rpc.events.ResultEvent;
         import mx.core.UIComponent;
         import com.adobe.images.JPGEncoder;
         import mx.events.ColorPickerEvent;
         
         private var popUp:Label;
         
         private function onFontChange(event:ColorPickerEvent ):void
         {
            //Change the Text Color
taTextArea.setStyle( "color" , event.color );
            
         }

         private function onBGChange(event:ColorPickerEvent ):void
         {
            //Change the background color       
      taTextArea.setStyle( "backgroundColor" , event.color );
            
         }
         
         private function onCBChange( event:Event ) :void
         {
            
            //Set the font weight
            taTextArea.setStyle( "fontWeight" , cbBold.selected ? "bold" : "normal" );
            
         }
         
         private function onSaveClick( event:Event ):void
         {
         
            //pop up a "Saving" message
            popUp   = PopUpManager.createPopUp(textEditor , Label , true ) as Label;
            PopUpManager.centerPopUp( taTextArea );
            popUp.setStyle( "fontSize" , "20" );
            popUp.text = "SAVING";
            
            //Get the JPG encoder
            var jpgEncoder:JPGEncoder   = new JPGEncoder( 75 );
            
            //Get the UI component
            var bd:BitmapData         = getUIComponentBitmapData( textEditor );   
            
            //Convert the UI component to a JPG
            var ba:ByteArray         = jpgEncoder.encode( bd );
            
            //Send the ByteArray to the CFC to be saved
            ro.saveImage( ba );
            
         }
         
         private function onResult( event:ResultEvent ):void
         {
            
            //remove the popup
            PopUpManager.removePopUp( popUp );

            //load the image URL and load the image
            imgJPG.source   = event.result;
            imgJPG.load();



         }
         
         private function onFault(event:FaultEvent):void
         {            
            //remove the popup
            PopUpManager.removePopUp( popUp );
            
            //Turn off busy
            ro.showBusyCursor   = false;
            
            Alert.show("It broke! \n" + event.message );
            
         }
         
         //Andrew Trice's Function see: http://www.cynergysystems.com/blogs/page/andrewtrice?entry=flex_2_bitmapdata_tricks_and
         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;
         }
      ]]>
   </mx:Script>
   
   <!-- RemoteObject tag to point to the CFC on the server -->
   <mx:RemoteObject
      id="ro"
      showBusyCursor="true"
      destination="ColdFusion"
      source="textExample.WriteImage">

   
      <mx:method name="saveImage"
         result="onResult(event)"
         fault="onFault(event)"
      />

   </mx:RemoteObject>
   
   <mx:HBox>
      
      <mx:VBox
         id="textEditor"
         dropShadowEnabled="true"
         borderColor="0x000000"
         borderStyle="solid"
         paddingBottom="10"
         paddingLeft="10"
         paddingRight="10"
         paddingTop="10"
         cornerRadius="10"
         backgroundColor="0xdddddd"
         >

      
         <mx:TextArea
            id="taTextArea"
            width="100%"
            height="200"
            focusIn="taTextArea.selectionBeginIndex = 0;taTextArea.selectionEndIndex = taTextArea.text.length;"
            fontSize="16"
            >

            
            <mx:text>Put your Text in here</mx:text>
            
         </mx:TextArea>
         
         <mx:Form>
         
            <mx:FormItem label="Font Color:">                     
               <mx:ColorPicker id="cpFontColor" change="onFontChange( event );" />
            </mx:FormItem>
            
            <mx:FormItem label="Back Ground Color:">
               <mx:ColorPicker id="cpBGColor" change="onBGChange( event );" selectedColor="0xFFFFFF" />            
            </mx:FormItem>
            
            <mx:FormItem label="Bold:">
               <mx:CheckBox id="cbBold" change="onCBChange( event );" />
            </mx:FormItem>
            
            <mx:FormItem label="Save Text Editor as JPG:">
               
               <mx:Button
                  id="btnSave"   
                  label="Save"               
                  click="onSaveClick( event );"
               />

            </mx:FormItem>
         </mx:Form>
      </mx:VBox>
      
      <mx:VBox backgroundAlpha="0.5">
         
         
         <mx:Label fontSize="16" fontWeight="bold" text="The Image:" visible="{imgJPG.source != null}" />
         <mx:Image id="imgJPG" />
   
      </mx:VBox>
   </mx:HBox>
   
</mx:Application>

In you Flex project, you will have to get the core lib form http://as3corelib.googlecode.com/ and set it up as a reference.

My Flex Playing requires Adobe Flash Player 9. Get Adobe Flash..

NB: It is possible that if two of you click "Save" at the same time, you will see the other persons image!

Credits:

Related Blog Entries

Comments
I thank you for this post! You saved me a whole lot of time researching this and finding that souce download. You rock.
# Posted By Lu Sancea | 9/10/07 7:07 AM
Glad you found it helpful! :-)
# Posted By David | 9/10/07 4:58 PM
I´m new in flex 2 and try your examples, but give me all time this error, when i want to save , can you help me ?

It broke!
(mx.messaging.messages::RemotingMessage)#0
body = (Array)#1
[0] (flash.utils::ByteArray)#2
bytesAvailable = 0
endian = "bigEndian"
length = 13745
objectEncoding = 3
position = 13745
clientId = (null)
destination = ""
headers = (Object)#3
messageId = "94CB8A24-207A-FD1E-337F-1B705C1D90E8"
operation = "saveImage"
source = "textExample.WriteImage"
timestamp = 0
timeToLive = 0
# Posted By carlos | 9/19/07 1:46 PM
Hi Carlos,

I first guess would be that the Flex project isn't looking at the ColdFusion instance correctly, as the "destination" value is empty.

In Flex Builder:
1. Right click on the project
2. Select "Flex Compiler"
3. Append this argument to the "additional compiler arguments:
--services=[Path to your CF instance]\WEB-INF\flex\services-config.xml
4. then in "Build path", set "Output folder" to be a path in to your CF instance, and "Output folder URL" to be the URL to that folder.
eg: mine are:
Output Folder: C:\Inetpub\wwwroot\jpgExample
Output Folder URL: http://localhost/jpgExample

HTH
# Posted By David | 9/19/07 3:56 PM
thank you for the tip, but now I have a problem with the following error when compiling the application :
Error : The services configuration includes a channel-definition 'my-cfamf' that has an endpoint with a context.root token but a context root has not been defined. Please specify a context-root compiler argument.
I Append this argument to the "additional compiler arguments: "
-locale en_US --services=D:\CFusionMX7\wwwroot\WEB-INF\flex\services-config.xml

I install Colfusion in this director D:\CFusionMX7 .
Excuse to bother you, but could help me
# Posted By carlos | 9/20/07 12:02 PM
looks like you need to add "-context-root /"
so you end up with this:

-locale en_US --services=D:\CFusionMX7\wwwroot\WEB-INF\flex\services-config.xml -context-root /

hth
# Posted By David | 9/20/07 12:19 PM
First off, thanks for the work you put into the example... very cool. I'm thinking about doing something like this in one of my applications but when I send the UIComponent to Alex Trice's 'getUIComponentBitmapData' function, it doesn't take into consideration that some of the container might be hidden due to scroll bars. How can I send the full container so scroll bars are ignored and I get a complete image? I'm trying to add a help feature to an app where the user can create screenshots of a canvas at any time. Any ideas? Thanks in advance and thanks for the great blog.
# Posted By Merritt | 9/27/07 11:12 AM
Hi Merrit,

I did a quick test previously on that exact issue, and was planning to a but more in-depth to see how/if this is possible.

...watch this space... :)
# Posted By David | 9/27/07 2:49 PM
very good example , thank you
# Posted By aelxx | 4/15/08 1:04 AM
Can I use this code to take snapshot of entire desktop like printscreen
button do it?
Or can I take the snap shot of active window?
# Posted By Khurram | 10/11/09 3:27 AM