May 2018


          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 30
31            
 
FEEDS
 
ARCHIVES
 
RECENT ENTRIES
 
OTHER BLOGGERS
 
AGGREGATORS
 
SOCIAL NETWORKS
:: 12/23/2010 ::
AIR Videographer with the Camera class
Return   Back To Top
Happy Holidays to everyone. Here's an early St. Nick present from my blog. This "Videographer" Adobe AIR application shows an example of leveraging the Camera class (flash.media.Camera) to capture an image from a desktop User's webcam, doing file uploads with AIR and ColdFusion, and automatically posting to facebook and flickr accounts. This example also uses the ImageShrinker.swc (ImageShrinker.swc) to manipulate the images prior to the actual physical upload and posting to facebook and flickr.

Here's the "Videographer" Adobe AIR application: Videographer.air. The source code is included in the installed application. You will need to install the Adobe AIR runtime if you do not already have it installed.

A screenshot of the application shows a simple UI - a Start Cam button, textinputs for entering a facebook and flickr uploads email address, a Capture button that grabs a photo from the live video, and an Upload button that uploads the file, via ColdFusion, to a webserver and sends an email to the facebook and flickr email addresses that you specify. There is User feedback via the AIR statusBar.

Screenshot of the AIR application

The next screenshot shows editing the file permission (Windows) on the config.xml, so the AIR application can update the facebook and flickr email addresses:

Screenshot of the config.xml file permission - adding write permission

The last screenshot shows the resulting facebook and flickr photos (ImageShrinker was set at 450 px width and height):

Screenshot of the facebook and flickr uploaded photos

        Tip Jar:

Main application:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:s="library://ns.adobe.com/flex/spark"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:comp="*"
    preinitialize="preinit()"
    creationComplete="initSO()"
    width="736" height="396" viewSourceURL="srcview/index.html">

    <fx:Declarations>
        <mx:RemoteObject id="roImageService"
             destination="ColdFusion"
             endpoint="{_remoteGateway}"
             source="airtraining.Videographer.info.airination.cfcs.EmailGateway"
             showBusyCursor="true">
            <mx:method name="sendImgToFacebook" result="sendImgToFacebookHandler(event)"
            fault="roFaultHandler(event)"/>
        </mx:RemoteObject>
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import info.airination.actionscripts.CameraStream;
            import info.airination.actionscripts.ImageProcessingService;
            import info.airination.actionscripts.PNGEnc;
            import info.airination.actionscripts.UpDater;

            import mx.controls.Alert;
            import mx.core.UIComponent;
            import mx.events.FileEvent;
            import mx.managers.CursorManager;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.utils.ObjectUtil;
            import mx.utils.UIDUtil;

            import net.tw.util.air.ImageShrinker;
            import net.tw.util.air.events.ImageShrinkerEvent;

            private var camStream:CameraStream;
            private var uiComp:UIComponent;
            private var _imgShrinker:ImageShrinker;
            private var _imgInFile:File;
            private var _imgOutFile:File;
            private var _service:ImageProcessingService;
            public var _updateURL:String;
            public var _serverUrl:String;
            private var _configFile:File = File.applicationDirectory.resolvePath("config.xml");
            private var _configXml:XML;
            private var fname:String = "";
            private var blnError:Boolean = false;
            private var myTimer:Timer = new Timer(100, 0);
            private var soUpdateSNEs:SharedObject = SharedObject.getLocal("UpdateSNEs");
            [Embed("assets/images/clark.png")] public var imgAlert:Class;

            [Bindable]private var blnUploadComplete:Boolean = false;
            [Bindable]private var blnCamRunning:Boolean = false;
            [Bindable]private var blnCaptured:Boolean = false;
            [Bindable]public var blnUpdateSNEs:Boolean = false;
            [Bindable]private var _imageURL:String = "";
            [Bindable]private var _imageName:String = "";
            [Bindable]private var _remoteGateway:String;
            [Bindable]public var _fbemailaddress:String;
            [Bindable]public var _flickremailaddress:String;
            [Bindable]public var _webUrl:String;

            public function preinit(): void {
                loadConfig();
                _service = ImageProcessingService.instance;
                var myUpdater:UpDater = new UpDater();
                myUpdater.onPreInit();
            }

            private function loadConfig(): void {
                var fs:FileStream = new FileStream();
                fs.open(_configFile, FileMode.READ);
                var s:String = fs.readUTFBytes(fs.bytesAvailable);
                _configXml = new XML(s);
                _remoteGateway = _configXml.services.remoting.endPoint.toString();
                _serverUrl = _configXml.services.serverRoot.url.toString();
                _updateURL = _configXml.services.updateURL.url.toString();
                _webUrl = _configXml.services.webURL.url.toString();
                _fbemailaddress = _configXml.services.fbemailaddress.email.toString();
                _flickremailaddress = _configXml.services.flickremailaddress.email.toString();
            }

            private function loadConfig2(): void {
                var fs:FileStream = new FileStream();
                fs.open(_configFile, FileMode.READ);
                var s:String = fs.readUTFBytes(fs.bytesAvailable);
                _configXml = new XML(s);
                _remoteGateway = _configXml.services.remoting.endPoint2.toString();
                _serverUrl = _configXml.services.serverRoot.url2.toString();
                _updateURL = _configXml.services.updateURL.url2.toString();
                _webUrl = _configXml.services.webURL.url2.toString();
                _fbemailaddress = _configXml.services.fbemailaddress.email2.toString();
                _flickremailaddress = _configXml.services.flickremailaddress.email2.toString();
            }

            private function initSO(): void {
                CheckSO();
            }

            private function CheckSO(): void {
                if (soUpdateSNEs==null) {
                    Alert.show("Cannot create shared object", "Error");
                } else {
                    if (soUpdateSNEs.data.blnUpdateSNEs!=undefined) {
                        blnUpdateSNEs=soUpdateSNEs.data.blnUpdateSNEs;
                    } else {
                        saveInfo();
                    }
                }
            }

            public function saveInfo(): void {
                soUpdateSNEs.data.blnUpdateSNEs=blnUpdateSNEs;
            }

            private function clearInfo(): void {
                soUpdateSNEs.data.blnUpdateSNEs=false;
                CheckSO();
            }

            private function attachCameraStream(): void {
                camStream = new CameraStream();
                var ref : UIComponent = new UIComponent();
                pnlVideo.addElement(ref);
                ref.addChild(camStream);
                myTimer.addEventListener("timer", onDisplay);
                myTimer.start();
            }

            private function onDisplay(event:TimerEvent): void {
                blnCamRunning = camStream.blnActive;
                if (blnCamRunning) {
                    CursorManager.removeBusyCursor();
                    myTimer.removeEventListener("timer", onDisplay);
                    myTimer.stop();
                }
            }

            private function captureSnapshot(): void {
                tgpImages.removeAllElements();
                var uiComp:UIComponent = new UIComponent();
                uiComp.width = camStream._cameraWidth;
                uiComp.height = camStream._cameraHeight;
                uiComp.addChild(camStream.getSnapshot());
                tgpImages.addElement(uiComp);
                var bd:BitmapData = new BitmapData(uiComp.width,uiComp.height);
                bd.draw(uiComp);
                var ba:ByteArray = info.airination.actionscripts.PNGEnc.encode(bd);
                _imgInFile = File.documentsDirectory.resolvePath("images");
                var date:Date = new Date();
                fname = UIDUtil.createUID() + ".png";
                _imgInFile = File.documentsDirectory.resolvePath(_imgInFile.url + '/' + fname);
                var fileStream:FileStream = new FileStream();
                fileStream.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
                fileStream.open(_imgInFile, FileMode.WRITE);
                fileStream.writeBytes(ba);
                fileStream.close();
                blnCaptured = true;
            }

            private function doUpload(): void {
                blnUploadComplete = false;
                progressBar.setProgress(0, 100);
                progressBar.label = "Loading 0%";
                progressBar.visible = true;
                var OutFileDir:File = File.documentsDirectory.resolvePath("images");
                OutFileDir.createDirectory();
                _imgOutFile = new File();
                _imgOutFile.addEventListener(Event.COMPLETE, onUploadComplete);
                _imgOutFile.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
                _imgOutFile.addEventListener(ProgressEvent.PROGRESS, onProgressEvent);
                _imgOutFile.url = OutFileDir.url + '/' + fname;
                _imgShrinker = new ImageShrinker();
                _imgShrinker.addEventListener(ImageShrinkerEvent.SHRINK_SUCCESS, imgSHRINK_SUCCESS);
                _imgShrinker.addEventListener(ImageShrinkerEvent.SHRINK_ERROR, imgSHRINK_ERROR);
                _imgShrinker.inputImage = _imgInFile;
                _imgShrinker.outputImage = _imgOutFile;
                _imgShrinker.maxHeight = 450;
                _imgShrinker.maxWidth = 450;
                _imgShrinker.shrink();
                this.status = 'uploading image';
                this.enabled = false;
            }

            private function onProgressEvent(event:ProgressEvent): void {
                progressBar.setProgress(event.bytesLoaded, event.bytesTotal);
                var percent:String = Number(event.bytesLoaded/event.bytesTotal * 100).toFixed(0);
                progressBar.label = "Loading " + percent + "%";
                trace("Loading " + percent + "%");
            }

            private function onUploadComplete(e:Event): void {
                var f:File = e.currentTarget as File;
                this.status = f.name + " uploaded";
                this.enabled = true;
                progressBar.label = "Complete.";
                roImageService.sendImgToFacebook(_fbemailaddress, _flickremailaddress, fname, tiCaption.text);
            }

            private function onIOError(e:IOErrorEvent): void {
                this.enabled = true;
                var f:File = e.currentTarget as File;
                Alert.show("An error happened during uploading an image (" + f.name + ").", "HTTP Error",
                4, null, null, imgAlert, 4);
                progressBar.visible = false;
            }

            private function imgSHRINK_SUCCESS(e:ImageShrinkerEvent): void {
                _imgShrinker.removeEventListener(ImageShrinkerEvent.SHRINK_SUCCESS, imgSHRINK_SUCCESS);
                this.enabled = true;
                this.status = "SHRINK_SUCCESS";
                _service.uploadImage(_imgOutFile);
                cursorManager.removeBusyCursor();
                var myTimer5:Timer = new Timer(2000, 0);
                myTimer5.addEventListener("timer", onTimer5);
                myTimer5.start();
            }

            private function imgSHRINK_ERROR(e:ImageShrinkerEvent): void {
                _imgShrinker.removeEventListener(ImageShrinkerEvent.SHRINK_ERROR, imgSHRINK_ERROR);
                this.enabled = true;
                this.status = "SHRINK_ERROR";
                Alert.show(ObjectUtil.toString(e.error));
                cursorManager.removeBusyCursor();
                var myTimer5:Timer = new Timer(2000, 0);
                myTimer5.addEventListener("timer", onTimer5);
                myTimer5.start();
            }

            private function onTimer5(event:TimerEvent): void {
                this.status = "";
                progressBar.visible = false;
            }

            private function sendImgToFacebookHandler(event:ResultEvent): void {
                if (event.result) {
                    this.status = "image capture sent to facebook and flickr";
                } else {
                    Alert.show("Image capture NOT sent to facebook\n\nMake sure to edit the config.xml
                    file and replace the fbemailaddress with your personal facebook email upload address.",
                    "Ooops", 4, null, null, imgAlert, 4);
                }
            }

            private function roFaultHandler(event:FaultEvent): void {
                if (blnError) {
                    // dump error message
                    Alert.show(ObjectUtil.toString(event.fault), "Ooops", 4, null, null, imgAlert, 4);
                } else {
                    blnError = true;
                    // try again
                    loadConfig2();
                }
            }

            private function viewSrc(): void {
                var u:URLRequest = new URLRequest("http://www.airination.info/airtraining/Videographer/srcview/index.html");
                navigateToURL(u,"_blank");
            }
        ]]>
    </fx:Script>
    <s:HGroup x="52" y="36" width="647" height="300">
        <s:Panel id="pnlVideo" title="Your Live Video" width="320" height="299">
            <s:Button id="btnCapture" mouseUp="{(!blnCamRunning)?CursorManager.setBusyCursor():null}"
            click="{(!blnCamRunning)?attachCameraStream():captureSnapshot()}" x="124" y="244"
            label="{(blnCamRunning)?'Capture':'Start Cam'}"/>
        </s:Panel>
        <s:Panel title="Your Snapshot" x="306" y="52" width="320" height="299">
            <s:TileGroup id="tgpImages" x="0" y="0" width="320" height="240" />
            <comp:SocialNetworkEmails id="SNE"  x="42" y="60" visible="{(!blnUpdateSNEs)?true:false}"/>
            <mx:ProgressBar id="progressBar" mode="manual" visible="false" labelPlacement="center" />
            <s:Button id="btnUpload" click="doUpload()" x="120" y="244" label="Upload"
            enabled="{(blnCaptured)?true:false}"/>
            <s:TextInput x="198" y="244" width="110" id="tiCaption" text="my video capture" toolTip="This text will be used
            as the caption for your photo." visible="{(blnCamRunning)?true:false}"/>
        </s:Panel>
    </s:HGroup>
    <mx:LinkButton x="329" y="343" label="View Source" id="btnViewSrc" click="viewSrc()" textDecoration="underline"
    buttonMode="true" useHandCursor="true"/>
    <mx:Image x="425" y="344" source="assets/images/facebook-icon.gif" click="clearInfo()" toolTip="Click to reset the
    'facebook uploads email' address." buttonMode="true" useHandCursor="true" width="16" height="16" id="btnFBReset"/>
</s:WindowedApplication>

SocialNetworkEmails component to collect the facebook and flickr uploads emails:


<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="loadEmails()"
         xmlns:mx="library://ns.adobe.com/flex/mx" width="234" height="158">
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.core.FlexGlobals;

            private var _configFile:File = File.applicationDirectory.resolvePath("config.xml");
            private var _configXml:XML;

            [Bindable]private var _fbemailaddress:String = "";
            [Bindable]private var _flickremailaddress:String = "";

            private function loadEmails(): void {
                _fbemailaddress = FlexGlobals.topLevelApplication._fbemailaddress;
                _flickremailaddress = FlexGlobals.topLevelApplication._flickremailaddress;
            }

            private function saveSNE(): void {
                if (tiFBEmail.text != '' && tiFlckrEmail.text != '') {
                    // read config file
                    var fs:FileStream = new FileStream();
                    fs.open(_configFile, FileMode.READ);
                    var s:String = fs.readUTFBytes(fs.bytesAvailable);
                    _configXml = new XML(s);
                    _fbemailaddress = tiFBEmail.text;
                    FlexGlobals.topLevelApplication._fbemailaddress = _fbemailaddress;
                    _flickremailaddress = tiFlckrEmail.text;
                    FlexGlobals.topLevelApplication._flickremailaddress = _flickremailaddress;
                    fs.close();
                    // update config file
                    var applicationDirectoryPath:File = File.applicationDirectory;
                    var nativePathToApplicationDirectory:String = applicationDirectoryPath.nativePath.toString();
                    nativePathToApplicationDirectory+= "\\config.xml";
                    if (!FlexGlobals.topLevelApplication.blnUpdateSNEs) {
                        Alert.show("To save your changes, you must give write permission to the config.xml located here: "
                        + nativePathToApplicationDirectory, "Notice", 4, null, null, FlexGlobals.topLevelApplication.imgAlert, 4);
                    }
                    var file:File = new File(nativePathToApplicationDirectory);
                    var newXMLStr:String = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<config>\n
                    \t<services>\n\t\t<remoting>\n\t\t\t<endPoint>" + _configXml.services.remoting.endPoint.toString()
                    + "</endPoint>\n\t\t\t<endPoint2>" + _configXml.services.remoting.endPoint2.toString()
                    + "</endPoint2>\n\t\t</remoting>\n\t\t<serverRoot>\n\t\t\t<url>"
                    + _configXml.services.serverRoot.url.toString() + "</url>\n\t\t\t<url2>"
                    + _configXml.services.serverRoot.url2.toString() + "</url2>\n\t\t</serverRoot>\n\t\t<updateURL>\n
                    \t\t\t<url>" + _configXml.services.updateURL.url.toString() + "</url>\n\t\t\t<url2>"
                    + _configXml.services.updateURL.url2.toString() + "</url2>\n\t\t</updateURL>\n\t\t<webURL>\n
                    \t\t\t<url>" + _configXml.services.webURL.url.toString() + "</url>\n\t\t\t<url2>"
                    + _configXml.services.webURL.url2.toString() + "</url2>\n\t\t</webURL>\n\t\t<fbemailaddress>\n
                    \t\t\t<email>" + _fbemailaddress.toString() + "</email>\n\t\t\t<email2>" + _fbemailaddress.toString()
                    + "</email2>\n\t\t</fbemailaddress>\n\t\t<flickremailaddress>\n\t\t\t<email>"
                    + _flickremailaddress.toString() + "</email>\n\t\t\t<email2>" + _flickremailaddress.toString()
                    + "</email2>\n\t\t</flickremailaddress>\n\t</services>\n</config>";
                    var fsw:FileStream = new FileStream();
                    fsw.open(file, FileMode.WRITE);
                    fsw.writeUTFBytes(newXMLStr);
                    fsw.close();
                    FlexGlobals.topLevelApplication.blnUpdateSNEs = true;
                    FlexGlobals.topLevelApplication.saveInfo();
                } else {
                    Alert.show("You must enter your own personal 'upload email addresses' for your Facebook and Flickr accounts.", "Ooops",
                    4, null, null, FlexGlobals.topLevelApplication.imgAlert, 4);
                    FlexGlobals.topLevelApplication.blnUpdateSNEs = false;
                    FlexGlobals.topLevelApplication.saveInfo();
                }
            }
        ]]>
    </fx:Script>

    <s:Label x="10" y="10" text="Facebook uploads email:" textAlign="right" width="140"/>
    <s:TextInput x="10" y="30" width="212" id="tiFBEmail" text="{(_fbemailaddress!='')?_fbemailaddress:''}"/>
    <s:Label x="10" y="69" text="Flickr uploads email:" textAlign="left" width="140"/>
    <s:TextInput x="10" y="89" width="212" id="tiFlckrEmail" text="{(_flickremailaddress!='')?_flickremailaddress:''}"/>
    <s:Button x="82" y="119" label="Save" id="btnSave" click="saveSNE()"/>
</s:Group>

CameraStream class:


package info.airination.actionscripts
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.*;
    import flash.geom.Matrix;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.system.Security;
    import flash.system.SecurityPanel;

    public class CameraStream extends Sprite {

        public static const DEFAULT_CAMERA_WIDTH : Number = 320;
        public static const DEFAULT_CAMERA_HEIGHT : Number = 240;
        public static const DEFAULT_CAMERA_FPS : Number = 30;

        private var video:Video;
        private var camera:Camera;

        public var _cameraWidth : Number;
        public var _cameraHeight : Number;
        public var blnActive:Boolean = false;

        public function CameraStream() {

            camera = Camera.getCamera();
            camera.addEventListener(ActivityEvent.ACTIVITY, onActive);

            _cameraWidth = DEFAULT_CAMERA_WIDTH;
            _cameraHeight = DEFAULT_CAMERA_HEIGHT;

            if(camera != null) {
                camera.setMode(_cameraWidth, _cameraHeight, DEFAULT_CAMERA_FPS)
                video = new Video(camera.width, camera.height);
                video.attachCamera(camera);
                addChild(video);
            }
            else {  Security.showSettings(SecurityPanel.CAMERA)
                trace("What are you waiting for? Go get a camera. :-)");
            }
        }

        public function getSnapshotBitmapData():BitmapData
        {
            var snapshot:BitmapData = new BitmapData(_cameraWidth, _cameraHeight);

            snapshot.draw(video,new Matrix());
            return snapshot;
        }

        public function getSnapshot():Bitmap
        {
            var bitmap : Bitmap = new Bitmap(getSnapshotBitmapData());
            return bitmap;
        }

        private function onActive(event:ActivityEvent): void {
            blnActive = true;
        }
    }
}

ColdFusion EmailGateway.cfc:


<cfcomponent output="false">

	<cffunction name="sendImgToFacebook" output="false" access="remote" returntype="Boolean">
		<cfargument name="fbemailaddress" required="true" />
		<cfargument name="flickremailaddress" required="true" />
		<cfargument name="imgName" required="true" />
		<cfargument name="imgCaption" required="true" />

		<cftry>
			<cfmail from="owner@u-saw-it.com"
					 to="#fbemailaddress#"
					 cc="#flickremailaddress#"
					 subject="#imgCaption#" type="html">
					 <cfmailparam file="D:\home\webhtml5.info\wwwroot\airtraining\Videographer\images\#imgName#"
					 type="image/png">
					 Sent from my Adobe AIR Videographer...
			</cfmail>
		<cfcatch type="any">
			<cfthrow message="#cfcatch.message# #cfcatch.detail#">
			<cfreturn false>
		</cfcatch>
		</cftry>

		<cfreturn true>
	</cffunction>

</cfcomponent>
 
Related Entries:
 

canada goose femme pas cher Soldes Louboutin Chaussures Soldes Louboutin louis vuitton taschen outlet louboutin outlet uk billig canada goose canada goose tilbud goyard pas cher longchamp bags outlet Monlcer udsalg billige parajumpers YSL replica sac louis vuitton pas cher Canada Goose Pas Cher Canada Goose Outlet UK Moncler Outlet uk goyard replica bags polo Lacoste pas cher Bolsos Longchamp España Moncler Jakker tilbud Doudoune moncler pas cher Parajumpers Jakker tilbud Ralph Lauren Soldes Parajumpers Outlet louis vuitton replica Moncler Jas sale Billiga Canada Goose Jacka Canada Goose outlet Billiga Moncler Doudoune Canada Goose Pas Cher Canada Goose Pas Cher Louboutin Soldes Canada Goose Pas Cher Hemers replica Doudoune Canada Goose Pas Cher prada replica Canada Goose Pas Cher Canada Goose Soldes Doudoune Canada Goose Pas Cher Canada Goose Pas Cher Canada Goose outlet Canada Goose outlet Canada Goose outlet