Posts Tagged ‘ ACTIONSCRIPT 3

Create a webcam face detection within OpenLaszlo by using ActionScript3

Today i found a smart script for a webcam face detection on www.quasimondo.com.
Now i will try to do this within OpenLaszlo, thus post based also on this sample.. 😉

Click here for a quick demo 😉

First of all, we have to download the sourcecode in the Marilena_mod10.zip from www.quasimondo.com and extract it.

To be able to use the source code, we have to compile the ActionScript files into a SWC file. Therefore we need a Flex SDK. If you not already installed it, read here how do you do this under Ubuntu Linux.
When you have the Flex SDK available, navigate into the src directory from the extracted sourcecode and compile the SWC with the following action:

compc -source-path ./ -include-sources ./ -optimize -output ../faceDetection.swc

 
The result is the faceDetection.swc file, which must now be provided to OpenLaszlo. How you can do this, read it here in detail. In short, copy it into your flexlib directory within your OpenLaszlo WEB-INF directory.

Now you can import the required base libaries into a self implemented class by using a passthrough tag:

<class name="faceDetector" width="480" height="640">
	
	<switch>
		<unless property="$as3">
			<handler name="oninit">
			<![CDATA[
				Debug.error("ActionScript 3 required");
			]]>
			</handler>				
		</unless>
		<otherwise>
			<passthrough>
				import com.quasimondo.bitmapdata.CameraBitmap;
				import jp.maaash.ObjectDetection.ObjectDetector;
				import jp.maaash.ObjectDetection.ObjectDetectorEvent;
				import jp.maaash.ObjectDetection.ObjectDetectorOptions;
				...
			</passthrough>

			...

 
The first great step is now done and we will further implement a complete class for using the face detection, so that we in future just have include a tag for using it.
We will do this also on our base sample. The result is a port to OpenLaszlo of these, with just a few differences:

<!---	Object Variables -->
<attribute name="detector" type="expression"/>
<attribute name="camera" type="expression"/>
<attribute name="faceRectContainer" type="expression"/>
<attribute name="detectionMap" type="expression"/>
<attribute name="drawMatrix" type="expression"/>

<!---	Scale factor of the image -->
<attribute name="scaleFactor" type="number" value="4"/>

<!---	Is currently a face detected?! -->
<attribute name="faceDetected" type="boolean" value="false" />
	
<!---	Weight of the face rect -->
<attribute name="rectLineWeight" type="number" value="2"/>

<!---	Starting the initiation -->
<handler name="oninit">
<![CDATA[

	if(this.scaleFactor==0) {
		Debug.error("scaleFactor must be greater 0");
	}

	this.initUI();
	this.initDetector();
]]>
</handler>				

<!---	Init the UI -->
<method name="initUI" args="" returns="void">
<![CDATA[
	var view = new Sprite();
	this.getDisplayObject().addChild(view);

	this.camera = new CameraBitmap(this.width, this.height, 15);
	this.camera.addEventListener(Event.RENDER, this.cameraReadyHandler);
	view.addChild( new Bitmap(this.camera.bitmapData) );
			
	this.detectionMap = new BitmapData(this.width/this.scaleFactor, this.height/this.scaleFactor, false, 0);
	this.drawMatrix = new Matrix(1/this.scaleFactor, 0, 0, 1/this.scaleFactor);
		
	this.faceRectContainer = new Sprite();
	view.addChild(this.faceRectContainer);
]]>
</method>


<!---	Is called when the camera is ready -->
<method name="cameraReadyHandler" args="event:Event" returns="void">
<![CDATA[
	this.detectionMap.draw(this.camera.bitmapData, this.drawMatrix, null, "normal", null, true);
	this.detector.detect(this.detectionMap);
]]>
</method>


<!---	Init the detector -->
<method name="initDetector" args="" returns="void">
<![CDATA[

	// Creat a new ObjectDetector
	this.detector = new ObjectDetector();
	
	// ..and give them the required options 
	var options:ObjectDetectorOptions = new ObjectDetectorOptions();
	options.min_size  = 30;
	this.detector.options = options;
	this.detector.addEventListener(ObjectDetectorEvent.DETECTION_COMPLETE, this.detectionHandler);
]]>
</method>


<!---	Is called at every detection -->
<method name="detectionHandler" args="e:ObjectDetectorEvent" returns="void">
<![CDATA[				

	var g :Graphics = this.faceRectContainer.graphics;
	g.clear();
	if(e.rects) {
		g.lineStyle(this.rectLineWeight);
		e.rects.forEach( function( r :Rectangle, idx :int, arr :Array ) :void {
			
			// Set face detected
			if(!faceDetector.faceDetected) faceDetector.setAttribute("faceDetected", true);
										
			// Timer when face deteced is reset
			if(typeof this.resetDetectionDelegate == "undefined") {
				this.resetDetectionDelegate = new LzDelegate(faceDetector, "resetDetection");
				lz.Timer.addTimer(this.resetDetectionDelegate, 500);
			}
			else {
				lz.Timer.resetTimer(this.resetDetectionDelegate, 500);
			}
			g.drawRect( r.x * faceDetector.scaleFactor, r.y * faceDetector.scaleFactor, r.width * faceDetector.scaleFactor, r.height * faceDetector.scaleFactor );
		});
	}
						
]]>
</method>

<!---	Is called when no face is anymore detected -->
<method name="resetDetection" args="something" returns="void">
<![CDATA[
	if(this.faceDetected) this.setAttribute("faceDetected", false);
]]>
</method>	

 
After finishing the impĺementation of the face detection class, just have to include the new class and place the tag on the required target. We do the as sample in the source code from the snapShot article i have written some days ago:

<simplelayout axis="y" spacing="0" />
<view name="videoView" width="$once{canvas.imageWidth*2}" height="$once{canvas.imageHeight}">
	<simplelayout axis="x" spacing="0" />
	<view name="videoView" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
		<faceDetector name="faceDetector" id="faceDetector" scaleFactor="2" rectLineWeight="1"
					  width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
			<handler name="onfaceDetected">
			<![CDATA[
				Debug.write(this, "onfaceDetected("+this.faceDetected+")")
			]]>
			</handler>
		</faceDetector>
	</view>
	
	<view name="snapshot" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}" />
</view>
			
<view layout="axis: x; spacing:0">
	<button text="Take a snapshot" onclick="canvas.takeSnapshot();" width="$once{canvas.imageWidth}" enabled="${faceDetector.faceDetected}" />
	<button text="Save snapshot" onclick="canvas.saveImage();" width="$once{canvas.imageWidth}" enabled="${canvas.shotAvailable}" />		
</view>	

 
How you see, we just exchange the videoview-tag with the faceDetection-tag, and add the faceDetected-constraint to the enabled attribute of the snapshot button.
This was very easy, or?! And the result pretty nice.. 🙂
Thanks in this place to Mario Klingemann and all other they have optimize and work on this code.

Click here for a demo 😉

Sourcecode: OpenLaszlo - FaceDetection.zip (1621)

If you found some bugs or have some Tips, please contact me.

Read and write files from local filesystem with OpenLaszlo by using ActionScript3

Today i will try to read and write local files from a local storage. After a few searches with google, i found several similar samples. Now i integrate these with the sample from www.mikechambers.com within my OpenLaszlo code. For both, reading and writing files, we need the usual main structure, with a runtime switch and passthrough for the actionscript libraries.

Click here for a quick demo 😉

At first, we have look at the reading of a file. For that we create a few small functions, some of them act as an event handler.
 
1. The function that invokes the loading. Here we instantiate a FileReference object, register the required eventlistener and open the browser window for selecting a file. Further you will find here the fileFilterValue variable, within you are able to restrict the allowed file types for selecting.

<!---	called when the user clicks the load file button -->
<method name="loadFile" returns="void">
<![CDATA[	
	
	// create the FileReference instance
	this.fr = new FileReference();

	// listen for when they select a file
	this.fr.addEventListener(Event.SELECT, this.onFileSelect);

	// listen for when then cancel out of the browse dialog
	this.fr.addEventListener(Event.CANCEL, this.onCancel);

	// open a native browse dialog that filters for text files
	this.fr.browse([new FileFilter(this.fileFilterValue, this.fileFilterValue)]);
								
]]>
</method>

 
2. The function that is called, when the user has selected a file. Here we register two further eventlistener, the onLoadError and onLoadComplete eventlistener, and starting the loading progress.

<!---	called when the user selects a file this.from the browse dialog -->
<method name="onFileSelect" args="e:Event" returns="void">
<![CDATA[
	Debug.write(this, "->onFileSelect()");

	// listen for when the file has loaded
	this.fr.addEventListener(Event.COMPLETE, this.onLoadComplete);

	// listen for any errors reading the file
	this.fr.addEventListener(IOErrorEvent.IO_ERROR, this.onLoadError);

	// load the content of the file
	this.fr.load();						
]]>
</method>

 
3. The onLoadComplete function is called, when the file is transferred to the flash application. Here we receive the file contents and clean up the FileReference instance.

<!---	called when the file has completed loading -->
<method name="onLoadComplete" args="e:Event" returns="void">
<![CDATA[
	Debug.write(this, "->onLoadComplete()");

	// get the data this.from the file as a ByteArray
	var data:ByteArray = this.fr.data;

	// Get the file content
	this.setAttribute("fileContent", data.readUTFBytes(data.bytesAvailable));
	
	// clean up the FileReference instance	
	this.fr = null;					
]]>
</method>

 
4. The onLoadError function will be called in case of a transfer-error.

<!---	called if an error occurs while loading the file -->
<method name="onLoadError" args="e:IOErrorEvent" returns="void">
<![CDATA[
	Debug.error(this, "->onLoadError(): " + e.text);					
]]>
</method>

 
5. The onCancel function is used of both, the reading and writing action, and is just called when the user aborts the file selecting browser window or file saving browser window.

<!---	called if the user cancels out of the file save dialog -->
<method name="onCancel" args="e:Event">
<![CDATA[
	Debug.write(this, "->onCancel()");
	this.fr = null;						
]]>
</method>

 
For the writing of files you need just the three following functions, some of that are also act as a event handler.

1. The saveFile function invokes the saving action. Here we instantiate again a FileReference object, register the requiered eventlistener and open the browser window for selecting the destination for the file.

<!---	called when the user clicks the save file button -->
<method name="saveFile" args="fileContent ='', fileName ='test.txt'" returns="void">
<![CDATA[	
	
	// create the FileReference instance
	this.fr = new FileReference();

	// listen for the file has been saved
	this.fr.addEventListener(Event.COMPLETE, this.onFileSave);

	// listen for when then cancel out of the save dialog
	this.fr.addEventListener(Event.CANCEL, this.onCancel);

	// listen for any errors that occur while writing the file
	this.fr.addEventListener(IOErrorEvent.IO_ERROR, this.onSaveError);

	// open a native save file dialog, using the default file name
	this.fr.save(fileContent, fileName);
								
]]>
</method>

 
2. The onSaveError function will be called in case of an error while saving.

<!---	called if an error occurs while saving the file -->
<method name="onSaveError" args="e:IOErrorEvent">
<![CDATA[
	Debug.write(this, "->onSaveError(): ", e.text);
	this.fr = null;								
]]>
</method>				

 
3. The onFileSave function will be called when the file is successfully saved.

<!---	called once the file has been saved -->
<method name="onFileSave" args="e:Event">
<![CDATA[
	Debug.write(this, "->onFileSave()");
	this.fr = null;							
]]>
</method>

 
All these functions are capsuled in a class, that is extends the node object.

<class name="readAndWriteFileReference" extends="node">

	<passthrough>
		import flash.net.FileReference;
		import flash.net.FileFilter;
		import flash.events.IOErrorEvent;
		import flash.events.Event;
		import flash.utils.ByteArray;
	</passthrough>

	<!---	FileReference -->
	<attribute name="fr" type="expression" />

	...

Is this class implemented, you will only need to create an instance of that and bind an eventlistener with it. Now you are able to load and write file contents, just by calling the load and save function. A canvas could look like:

<canvas name="readAndWriteFileReference" width="800" height="550">
	
	<include href="./readAndWriteFileReference.lzx" />
		
	<attribute name="columnWidth" type="number" value="400"/>
	<attribute name="textHeight" type="number" value="${canvas.height-canvas.buttonBar.height}"/>
	
	<readAndWriteFileReference name="readAndWriteFile">
		<handler name="onfileContent">
		<![CDATA[				
			canvas.textView.textLoad.setAttribute("text", this.fileContent);
		]]>
		</handler>				
	</readAndWriteFileReference>		
		
	<simplelayout axis="y" spacing="0" />
	<view name="textView" width="$once{canvas.columnWidth*2}" height="$once{canvas.textHeight}">
		<simplelayout axis="x" spacing="0" />
		<edittext name="textSave" width="$once{canvas.columnWidth}" height="$once{canvas.textHeight}" multiline="true" />
		<edittext name="textLoad" width="$once{canvas.columnWidth}" height="$once{canvas.textHeight}" multiline="true" />
	</view>
				
	<view name="buttonBar" layout="axis: x; spacing:0" height="27">
		<button text="Save file" onclick="canvas.readAndWriteFile.saveFile(canvas.textView.textSave.text, 'test.txt');" width="$once{canvas.columnWidth}" />
		<button text="Load file" onclick="canvas.readAndWriteFile.loadFile();" width="$once{canvas.columnWidth}" />		
	</view>	
				
</canvas>

And now, happy loading and saving 😉

Click here for a quick demo 😉

Sourcecode: OpenLaszlo - ReadAndWriteFileReference.zip (1084)

If you found some bugs or have some Tips, please contact me.

Take webcam snapshot with OpenLaszlo

Today i have played a bit with my webcam, and tried to make some pictures and save that as jpeg files.

Click here for a demo 😉

At first we must integrate the webcam within a base structure of openlaszlo code. It’s needed to include some ActionScript libraries to realize our little project.
It’s advisable to implement in the base strukture a switch tag for handle the runtime, and also a passthrough tag for including the ActionScript 3 libraries.
This base structure could be look like:

<?xml version="1.0" encoding="UTF-8" ?>
<canvas width="100%" height="100%">
	
	<switch>
		<unless property="$as3">
			<handler name="oninit">
			<![CDATA[
				Debug.error("ActionScript 3 required");
			]]>
			</handler>				
		</unless>
		<otherwise>
		
			<passthrough>				
				import flash.net.*;
				import com.adobe.images.JPGEncoder;
				import flash.utils.ByteArray;
				import flash.display.Bitmap;
				import flash.display.BitmapData;
				import flash.media.Camera;
				import flash.geom.Matrix;
			</passthrough>

		</otherwise>
	</switch>
		
</canvas>

After that we create some views and include a videoview and a camera-tag inside.

<simplelayout axis="y" spacing="0" />
<view name="videoView" width="$once{canvas.imageWidth*2}" height="$once{canvas.imageHeight}">
	<simplelayout axis="x" spacing="0" />
	<view name="videoView" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
		<videoview name="video" oninit="this.stream.broadcast()" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
			<camera name="webcam" show="true" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}" bandwidth="0" picturequality="1.0" />
		</videoview>
	</view>
	
	<view name="snapshot" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}" />
</view>
			
<view layout="axis: x; spacing:0">
	<button text="Take a snapshot" onclick="canvas.takeSnapshot();" width="$once{canvas.imageWidth}" />
	<button text="Save snapshot" onclick="canvas.saveImage();" width="$once{canvas.imageWidth}" />		
</view>

I don’t know what i do wrong, but i have the feeling that the bandwidth and quality changes does not work (using lps 4.9.0). So, i additional change these values within the oninit handler. If you have a tip, or know what’s the problem of that, please contact me 😉
Here now my oninit handler:

<handler name="oninit">
<![CDATA[
	
	// Get the webcam 
	var cam:Camera = Camera.getCamera();
	
	// Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second. To specify that Flash Player video can use as much bandwidth as needed to maintain the value of quality , pass 0 for bandwidth . The default value is 16384.
	var bandwidth:int = 0; 
	
	// This value is 0-100 with 1 being the lowest quality. 
	// Pass 0 if you want the quality to vary to keep better framerates
	var quality:int = 100; 
	
	// Set bandwidth and quality
	cam.setQuality(bandwidth, quality);
	
	// Set measurements and framerate
	cam.setMode(canvas.imageWidth, canvas.imageHeight, 30, false); 
	
]]>
</handler>

For taking a snapshot from the webcam, we write a small function:

<method name="takeSnapshot">
<![CDATA[
	// create a new bitmap object
	var tempSnapshot:BitmapData =new BitmapData(canvas.imageWidth, canvas.imageHeight, true, 0x00FFFFFF);
	tempSnapshot.draw(canvas.videoView.videoView.video.getDisplayObject(), new Matrix());
	
	// place the snapshop i a view
	var targetView = canvas.videoView.snapshot.getDisplayObject();
	targetView.addChild(new Bitmap(tempSnapshot));
	
	canvas.setAttribute("shotAvailable", true);	
]]>
</method>	

Further we want save the snapshot at a local machine. Therefore we must convert the snapshot into a image and send it to the client.

In order to convert the snapshot into a image, we need the JPGEncoder ActionScript library from Mike Chambers.
Some days ago i write about, how to integrate this in OpenLaszlo. You will find the article here.
Here now the function for converting the snapshot into a image:

<method name="saveImage">
<![CDATA[
	
	if(canvas.shotAvailable) {
		
		// Take the snapshot movieclip
		var sketch_mc = canvas.videoView.snapshot.getDisplayObject();
		
		// Get the image data from that
		var jpgSource:BitmapData = new BitmapData(sketch_mc.width, sketch_mc.height);
		jpgSource.draw(sketch_mc);
		
		// Create a Jpeg from the image data
		var jpgEncoder:JPGEncoder = new JPGEncoder(85);
		var jpgStream:ByteArray = jpgEncoder.encode(jpgSource);
		
		// Create an URLRequest with the image
		var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
		var jpgURLRequest:URLRequest = new URLRequest("./snapShotHandle.php?name=sketch.jpg");
		jpgURLRequest.requestHeaders.push(header);
		jpgURLRequest.method = URLRequestMethod.POST;
		jpgURLRequest.data = jpgStream;
		
		// Send the image for download
		navigateToURL(jpgURLRequest, "_blank");
	}
	
]]>
</method>	

For saving the image, we use use a small PHP script like:

<?php

// create filename
$filename = date("Y-m-d_H:i:s", time())."_".uniqid(mt_rand(), true).".jpg";

if(isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
	
	// add headers for download dialog-box
	header('Content-Type: image/jpeg');
	header("Content-Disposition: attachment; filename=".$filename);
	echo $GLOBALS["HTTP_RAW_POST_DATA"];

}

?>

That’s all you need…
Click here for a demo 😉

Sourcecode: OpenLaszlo - SnapShot.zip (1053)

If you found some bugs or have some Tips, please contact me.

OpenLaszlo SWF10/Flash Download with a fileReference

To download a file with script within a flash movie, you can use a FileReference.

Two points needed attention:
1. The download-event must be explicit fired, as sample by a onclick event.
2. The security requirements by the adobe flash player must be met. This mean that if the downloading file is a remote file on a separate server, the server needs a crossdomain.xml file with the needed security configuration.

Here’s a small sample for a download within a flash movie generated with OpenLaszlo:

<?xml version="1.0" encoding="UTF-8" ?>
<canvas name="URLRequestDownload" width="100%" height="100%">
		
	<switch>
		<unless property="$as3">
			<handler name="oninit">
			<![CDATA[
				Debug.error("ActionScript 3 required");
			]]>
			</handler>				
		</unless>
		<otherwise>
		
			<button text="download">
				<passthrough>
					import flash.net.FileReference;
					import flash.net.URLRequest;
				</passthrough>
					
				<handler name="onclick">
				<![CDATA[
					var fileref:FileReference = new FileReference();
					var request:URLRequest = new URLRequest("http://thomas.deuling.org/wp-content/plugins/download-monitor/download.php?id=1");
					fileref.download(request, "2011-05-04_openlaszlo_lineheight.zip");
				]]>
				</handler>
			</button>
	
		</otherwise>
	</switch>
		
</canvas>

Here’s to a sample for a crossdomain.xml that allows every access:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-access-from domain="*" to-ports="*" secure="false"/>
  <allow-http-request-headers-from domain="*" headers="*" secure="false" />
</cross-domain-policy>

Tip:
If you’re not sure if the flash player needs a crossdomain.xml, or where he is call the crossdomain.xml, use the firebug in your firefox and look at the network-panel. There you can see every request to the crossdomain.xml. 😉

As an extentions for this, you could catch the ProgressEvent for display the download progress and many more.

You will find all the other available events and many informations here.