CameraCapture.as 3.46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/**
 * Simple Camera Capture application meant to be used where WebRTC is not supported
 * (e.g. Safari, Internet Explorer, Opera). All orchestration is assumed to happen
 * in JavaScript. The only function this application has is to capture a snapshot
 * and allow a 640x480 PNG of that snapshot to be made available to the JS as a
 * base64 encoded data URL.
 * 
 * There are really only three methods:
 *   snap() freezes the video and returns a PNG file as a data URL string. You can
 *          assign this return value to an img's src attribute.
 *   reset() restarts the the video.
 *   imageDataUrl() returns the same thing as snap() -- 
13 14 15 16
 *
 * Note that this file is merely the source code for CameraCapture.swf; to make
 * changes, you must edit this file, compile it to .swf, and check in the .swf
 * file separately
17 18 19 20 21 22 23 24 25 26 27 28 29
 */

package
{
	import flash.display.BitmapData;
	import flash.display.PNGEncoderOptions;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.external.ExternalInterface;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.utils.ByteArray;
30
	
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
	import mx.utils.Base64Encoder;
	
	[SWF(width="640", height="480")]
	public class CameraCapture extends Sprite
	{
		// We pick these values because that's captured by the WebRTC spec
		private const VIDEO_WIDTH:int = 640;
		private const VIDEO_HEIGHT:int = 480;
		
		private var camera:Camera;
		private var video:Video;
		private var b64EncodedImage:String = null;
		
		public function CameraCapture()
		{
46
			addEventListener(Event.ADDED_TO_STAGE, init); 
47 48 49 50 51 52 53 54 55 56 57 58 59 60
		}
		
		protected function init(e:Event):void {
			camera = Camera.getCamera();
			camera.setMode(VIDEO_WIDTH, VIDEO_HEIGHT, 30);
			
			video = new Video(VIDEO_WIDTH, VIDEO_HEIGHT);
			video.attachCamera(camera);
			
			addChild(video);
			
			ExternalInterface.addCallback("snap", snap);
			ExternalInterface.addCallback("reset", reset);
			ExternalInterface.addCallback("imageDataUrl", imageDataUrl);
61
			ExternalInterface.addCallback("cameraAuthorized", cameraAuthorized);
62
			ExternalInterface.addCallback("hasCamera", hasCamera);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
			
			// Notify the container that the SWF is ready to be called. 
			ExternalInterface.call("setSWFIsReady"); 
		}
		
		public function snap():String {
			// If we already have a b64 encoded image, just return that. The user
			// is calling snap() multiple times in a row without reset()
			if (b64EncodedImage) {
				return imageDataUrl();
			}
			
			var bitmapData:BitmapData = new BitmapData(video.width, video.height);
			bitmapData.draw(video); // Draw a snapshot of the video onto our bitmapData
			video.attachCamera(null); // Stop capturing video
			
			// Convert to PNG
			var pngBytes:ByteArray = new ByteArray();
			bitmapData.encode(
				new Rectangle(0, 0, video.width, video.height),
				new PNGEncoderOptions(),
				pngBytes
			);
			
			// Convert to Base64 encoding of PNG
			var b64Encoder:Base64Encoder = new Base64Encoder();
			b64Encoder.encodeBytes(pngBytes);
			b64EncodedImage = b64Encoder.toString();
			
			return imageDataUrl();
		}

		public function reset():String {
			video.attachCamera(camera);
			b64EncodedImage = null;
			
			return imageDataUrl();
		}

		public function imageDataUrl():String {
			if (b64EncodedImage) {
				return "data:image/png;base64," + b64EncodedImage;
			}
			return "";
		}
108 109
		
		public function cameraAuthorized():Boolean {
110
			return !(camera.muted);
111 112
		}
		
113 114 115
		public function hasCamera():Boolean {
			return (Camera.names.length != 0);
		}
116 117 118
	}
}