Accessing the Camera in a Windows 8 Metro Style App using HTML and JavaScript
Overview
I have recently been coding a Windows 8 Metro Style App using the new Windows 8 Release Preview bits and Visual Studio Express 2012 RC. The app is going to be a retro shooter that takes advantage of HTML5 Canvas for the main game engine and then several Windows 8 Metro Style App Features.
One of the things I wanted to do in the game was to keep Player Profiles. These profiles track player high scores, player names and a player avatar. Eventually these high scores could be used in a leaderboard running in the cloud.
I thought it would be neat to let players take a picture of themselves for their Avatar by accessing the webcam. Fortunately for us WinRT makes this super easy to use. We can even pull up prebuilt camera capture UI by using the built-in Windows.Media.Capture API’s. If you are an existing Windows Phone Developer this may remind you a lot of Windows Phone Development Tasks – something I absolutely loved.
Features like camera timer, settings, and even picture cropping are all done for us via the Windows.Media.Capture.CameraCaptureUI. For those looking for more control you also have the ability to call into Windows.Media.Capture.MediaCapture. You won’t get a default UI with MediaCapture but you do get full control of the streams. MediaCapture is also a way to record Audio streams in your app.
Here is what the default Capture Capture UI looks like when using the cropping tool:
After cropping the photo to my liking and tapping the OK button my new Avatar is automatically set. The new Avatar Image is automatically scaled correctly thanks to the predefined CSS styling we have created.
Sweet!
Declaration and Initialization
One of the joys of doing Windows 8 Metro Style development with HTML and JavaScript is that it feels like Web Programming. In fact my entire game header is done using normal <div> tags and CSS Styles. Inside of my default.html file I defined the following header to display the player score, level, name and avatar picture:
<div id="divGame">
<div id="txtScore">Score: 0</div>
<div id="txtLevel">Level: 0</div>
<div id="divPlayer">
<div id="txtPlayerName">Player1</div>
<img id="imgPlayer" src="/images/helmet.png" />
</div>
<div>
I then defined a CSS Style for the Avatar Picture using it’s imgPlayer id.
#imgPlayer {
max-width: 100px;
max-height: 50px;
float:left;
margin-right:10px;
}
The Windows Library for JavaScript (WinJS) gives us a way to create a Windows 8 AppBar easily by just a few lines of HTML (more on WinJS Controls later). By opening the AppBar and tapping the cmdCamera button our players will get the option to take a new Avatar picture.
<div id="AppBar" data-win-control="WinJS.UI.AppBar" data-win-options="">
<button id="cmdHome" data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdHome',label:'Menu',icon:'home',section:'selection',tooltip:'Menu'}">
</button>
<button id="cmdCamera" data-win-control ="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdCamera',label:'Cadet Photo',icon:'camera',section:'global',tooltip:'Change Cadet Photo'}">
</button>
<button id="cmdName" data-win-control ="WinJS.UI.AppBarCommand" data-win-options="{id:'cmdName',label:'Cadet Name',icon:'url(images/accept.png)',section:'global',tooltip:'Change Cadet Name',type:'flyout',flyout:'nameFlyout'}">
</button>
</div>
All of the AppBar buttons tap events are handled using standard JavaScript EventListeners:
//AppBar Commands
document.getElementById("cmdCamera").addEventListener("click", capturePhoto, false);
document.getElementById("cmdName").addEventListener("click", showCadetNameUpdate, false);
document.getElementById("cmdHome").addEventListener("click", showMenu, false);
document.getElementById("submitButton").addEventListener("click", updateCadetName, false);
That’s it! We now have a working Game Header and AppBar for our game. When a player clicks on the Camera Button we will invoke a call to the capturePhoto function.
Opening the Camera Capture UI
capturePhoto is where the magic happens. The first thing we do is make a call to WinRT using the Windows.Media.Capture namespace. This gives us a reference to CameraCaptureUI where we can set default properties. For my game I am telling the camera to use a 16x9 aspect ratio and lock to the photo mode. If I wanted the user to capture video I could easily do this as well by using Windows.Media.Capture.CameraCaptureUIMode.video.
//WinRT Camera API
function capturePhoto() {
try {
var dialog = new Windows.Media.Capture.CameraCaptureUI();
var aspectRatio = { width: 16, height: 9 };
dialog.photoSettings.croppedAspectRatio = aspectRatio;
dialog.captureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.photo).then(function (file) {
if (file) {
imgPlayer.src = URL.createObjectURL(file);
} else {
//No Photo captured
}
}, function (err) {
displayError(err);
});
} catch (err) {
displayError(err);
}
}
This is where you will start to see all of the Async goodness inside of WinRT. The Camera Capture UI will run asynchronously while it awaits the user to take a picture. I handle the callback by invoking a JavaScript Promise using the then keyword. The promise will call a function when the user takes a photo and if there is an object it will set the source of my imgPlayer tag to be that file. Those of you familiar with Web programming will recognize the URL.createObjectURL call so that my <img> tag knows where to reference the new source file.
Conclusion
Hopefully you have seen how easy it is to access the WebCam on Windows 8 now thanks to WinRT and the Windows.Media.Capture API’s. As Always - if you are currently working on a Windows 8 app I would love to hear about it!
You may also want to check out my previous Windows 8 Metro Style Development Tips:
- Accessing the Accelerometer in a Windows 8 Metro Style App using HTML and JavaScript
- Using KnockoutJS in Windows 8 Metro Style Apps
- Illegal characters in path when deploying a Metro Style App
- Playing Music and Sound Effects in a Windows 8 Metro Style App using HTML and JavaScript
- Connecting to WCF RIA Services in a Windows 8 Metro Style App using Upshot.js and Knockout.js
- Help! Visual Studio 11 Beta Dark Theme incorrectly using White Background
- Adding Touch support to a Windows 8 Metro Style App using HTML and JavaScript
- Defining Layout in a Windows 8 Metro Style App using CSS3, HTML and JavaScript
- Handling Fullscreen, Snapped and Filled states in Windows 8 Metro Style apps using CSS3 and JavaScript
- “The application could not be started.” error when debugging a Windows 8 Metro Style App
Comments
Anonymous
April 25, 2012
Nice...easier than I would've expected.Anonymous
June 01, 2012
how to convert BitmapImage to Array Bytes and Array Bytes to BitmapImage Get CameraCapture ;)