/**
* Copyright Kio ( http://wonderfl.net/user/Kio )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/tmfX
*/
package {
import flash.geom.Rectangle;
/* JPEGCam v1.0.9 */
/* Webcam library for capturing JPEG images and submitting to a server */
/* Copyright (c) 2008 - 2009 Joseph Huckaby <jhuckaby@goldcartridge.com> */
/* Licensed under the GNU Lesser Public License */
/* http://www.gnu.org/licenses/lgpl.html */
import flash.display.*;
import flash.events.*;
import flash.utils.*;
import flash.media.Camera;
import flash.media.Video;
import flash.external.ExternalInterface;
import flash.net.*;
import flash.system.Security;
import flash.system.SecurityPanel;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.geom.Matrix;
import com.adobe.images.JPGEncoder;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.events.KeyboardEvent;
public class Webcam extends Sprite {
private var video:Video;
private var encoder:JPGEncoder;
private var shuttersnd:Sound;
private var beepsnd:Sound;
private var sound:Boolean;
private var channel:SoundChannel = new SoundChannel();
private var jpeg_quality:int;
private var video_width:int;
private var video_height:int;
private var server_width:int;
private var server_height:int;
private var camera:Camera;
private var bmp:Bitmap;
private var bmpdata:BitmapData;
private var url:String;
private var stealth:int=0;
private var tf:TextField;
//keycodes
private var hotkeysnap:uint = 27;
private var hotkeyctrl:uint = 17;
private var hotkeyesc:uint = 27;
public function Webcam() {
// class constructor
flash.system.Security.allowDomain("*");
var flashvars:Object = LoaderInfo(this.root.loaderInfo).parameters;
video_width = Math.floor( flashvars.width );
video_height = Math.floor( flashvars.height );
server_width = Math.floor( flashvars.server_width );
server_height = Math.floor( flashvars.server_height );
stage.scaleMode = StageScaleMode.NO_SCALE;
if (!video_width) video_width = 480; //for testing only
if (!video_height) video_height = 320; //for testing only
if (!server_width) server_width = 480; //for testing only
if (!server_height) server_height = 320; //for testing only
// stage.scaleMode = StageScaleMode.EXACT_FIT;
stage.align = StageAlign.TOP_LEFT;
stage.stageWidth = Math.max(video_width, server_width);
stage.stageHeight = Math.max(video_height, server_height);
// Hack to auto-select iSight camera on Mac (JPEGCam Issue #5, submitted by manuel.gonzalez.noriega)
// From: http://www.squidder.com/2009/03/09/trick-auto-select-mac-isight-in-flash/
var cameraIdx:int = -1;
for (var idx:int = 0, len:int = Camera.names.length; idx < len; idx++) {
if (Camera.names[idx] == "USB Video Class Video") {
cameraIdx = idx;
idx = len;
}
}
if (cameraIdx > -1) camera = Camera.getCamera( String(cameraIdx) );
else camera = Camera.getCamera();
if (camera != null) {
camera.addEventListener(ActivityEvent.ACTIVITY, activityHandler);
video = new Video( Math.max(video_width, server_width), Math.max(video_height, server_height) );
video.attachCamera(camera);
addChild(video);
if ((video_width < server_width) && (video_height < server_height)) {
video.scaleX = video_width / server_width;
video.scaleY = video_height / server_height;
}
camera.setQuality(0, 100);
camera.setKeyFrameInterval(10);
camera.setMode( Math.max(video_width, server_width), Math.max(video_height, server_height), 30);
// set key event listener
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);
// do not detect motion (may help reduce CPU usage)
camera.setMotionLevel( 100 );
ExternalInterface.addCallback('_snap', snap);
ExternalInterface.addCallback('_configure', configure);
ExternalInterface.addCallback('_upload', upload);
ExternalInterface.addCallback('_reset', reset);
if (flashvars.shutter_enabled == 1) {
sound = true;
shuttersnd = new Sound();
shuttersnd.load( new URLRequest( flashvars.shutter_url ) );
beepsnd = new Sound();
beepsnd.load( new URLRequest( flashvars.beep_url ) );
}
else sound = false;
jpeg_quality = 90;
ExternalInterface.call('webcam.flash_notify', 'flashLoadComplete', true);
}
else {
trace("You need a camera.");
ExternalInterface.call('webcam.flash_notify', "error", "No camera was detected.");
}
}
public function set_quality(new_quality:int):void {
// set JPEG image quality
if (new_quality < 0) new_quality = 0;
if (new_quality > 100) new_quality = 100;
jpeg_quality = new_quality;
}
public function configure(panel:String = SecurityPanel.CAMERA):void {
// show configure dialog inside flash movie
Security.showSettings(panel);
}
private function activityHandler(event:ActivityEvent):void {
trace("activityHandler: " + event);
}
public function snap(url:String, new_quality:int, shutter:Boolean, new_stealth:int = 0, timer:int=0, new_flash:int = 0):void {
// take snapshot from camera, and upload if URL was provided
if (timer>0) {
Message(String(timer));
timer--;
if (shutter) channel = beepsnd.play();
setTimeout( snap, 1000, url, new_quality, shutter, new_stealth, timer, new_flash);
}
else {
Message(""); //clear the message, if there
if (new_flash>0) doFlash(0xAAAAAA, new_flash); //add a flash
if (new_quality) set_quality(new_quality);
stealth = new_stealth;
trace("in snap(), drawing to bitmap");
if (shutter) {
channel = shuttersnd.play();
setTimeout( snap2, 10, url );
}
else setTimeout( snap2, 10, url );
}
}
public function snap2(url:String):void {
// take snapshot, convert to jpeg, submit to server
bmpdata = new BitmapData( Math.max(video_width, server_width), Math.max(video_height, server_height) );
bmpdata.draw( video );
if (!stealth) {
// draw snapshot on stage
bmp = new Bitmap( bmpdata );
bmp.scaleX = video_width / server_width;
bmp.scaleY = video_height / server_height;
addChild( bmp );
// stop capturing video
video.attachCamera( null );
removeChild( video );
}
// if URL was provided, upload now
if (url) upload( url );
}
public function upload(url:String):void {
if (bmpdata) {
if ((video_width > server_width) && (video_height > server_height)) {
// resize image downward before submitting
var tmpdata:BitmapData = new BitmapData(server_width, server_height);
var matrix:Matrix = new Matrix();
matrix.scale( server_width / video_width, server_height / video_height );
tmpdata.draw( bmpdata, matrix, null, null, null, true ); // smoothing
bmpdata = tmpdata;
} // need resize
trace("converting to jpeg");
var ba:ByteArray;
encoder = new JPGEncoder( jpeg_quality );
ba = encoder.encode( bmpdata );
trace("jpeg length: " + ba.length);
var head:URLRequestHeader = new URLRequestHeader("Accept","text/*");
var req:URLRequest = new URLRequest( url );
req.requestHeaders.push(head);
req.data = ba;
req.method = URLRequestMethod.POST;
req.contentType = "image/jpeg";
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onLoaded);
trace("sending post to: " + url);
try {
loader.load(req);
}
catch (error:Error) {
trace("Unable to load requested document.");
ExternalInterface.call('webcam.flash_notify', "error", "Unable to post data: " + error);
}
}
else {
ExternalInterface.call('webcam.flash_notify', "error", "Nothing to upload, must capture an image first.");
}
}
public function onLoaded(evt:Event):void {
// image upload complete
var msg:String = "unknown";
if (evt && evt.target && evt.target.data) msg = evt.target.data;
ExternalInterface.call('webcam.flash_notify', "success", msg);
}
public function reset():void {
// reset video after taking snapshot
if (bmp) {
removeChild( bmp );
bmp = null;
bmpdata = null;
video.attachCamera(camera);
addChild(video);
}
}
public function keyDownListener(e:KeyboardEvent):void {
if (e.keyCode == hotkeysnap){
snap('', jpeg_quality, sound, 0, 3, 25);
setTimeout( reset, 6000); // wait 6 seconds and then reset camera
}
if (e.keyCode == hotkeyctrl){
}
if (e.keyCode == hotkeyesc){
}
}
private function Message(msg:String):void {
if (tf) removeChild(tf);
tf = new TextField();
tf.autoSize = TextFieldAutoSize.CENTER;
tf.width = 100;
tf.text = msg;
tf.textColor = 0xD4E2FA;
tf.scaleY =10;
tf.x = video_width/2-(tf.width/2);
tf.y = video_height/2-(tf.height/2);
tf.blendMode = BlendMode.INVERT;
addChild(tf);
}
private function doFlash(fillcol:int, duration:int):void {
var flashing:Shape = new Shape; // initializing the variable named rectangle
flashing.graphics.beginFill(fillcol); // choosing the colour for the fill, here it is red
flashing.graphics.drawRect(0, 0, video_width,video_height); // (x spacing, y spacing, width, height)
flashing.graphics.endFill(); // not always needed but I like to put it in to end the fill
flashing.blendMode = BlendMode.ADD;
addChild(flashing); // adds the rectangle to the stage
setTimeout( removeChild, duration, flashing); //remove the shape with a delay
}
}
}