Over a million developers have joined DZone.

Walkthrough: Capturing Photos in your Windows 8 App

DZone's Guide to

Walkthrough: Capturing Photos in your Windows 8 App

· Mobile Zone ·
Free Resource
Windows 8 apps easily access all the sensors on a Windows 8 machine. But Windows 8 apps can’t access any sensors on a Windows 8 machine without first asking the user’s permission.

Asking Permission

Windows 8 apps are safe. That’s fundamental. Where desktop apps could (and can) do whatever the developer wants, Windows 8 apps are limited only to what the user allows.

Developers ask for device access by the application manifest. This XML file is in every Windows 8 app. It is manipulated by the GUI editor or notepad (for the die hard).

The manifest is how applications tell the operating system what sensors it intends to use. Just the manifest is not enough. Once requested, the operating system will verify access with the user first. 


Important note: checking webcam lets you capture photos. However, to capture video (including access to the vide stream) you need to ask for webcam and microphone. That’s just how it works.

Capture a Photo

Why do you want to capture a photo? There are a million reasons. Maybe you want to apply filters and effects. Maybe you want to update the user’s account photo. Or, maybe something else. Whatever reason, you can!

Do you remember with desktop applications, to open a file you call the OpenFileDialog? You didn’t build the dialog, you just invoke it. The user picks some file and, presto, the dialog hands it to your code.

Just like that OpenFileDialog, the Windows 8 CameraCaptureUI dialog lets the user take a photo or video and simply hands the resulting image back to you. All you do is invoke it.


The best part of the capture dialog is that it handles everything for you. Cropping photos, re-taking photos, camera settings – they are all part of the dialog and implemented for you, for free.

Here’s how:


In the code above, those three lines really are it. I instantiate the capture UI and call it CaptureFileAsync() method, indicating by its argument if the result should be a photo, video or either. In the second command (third line) I move the resulting file (defaulted in the temporary file) to my application’s isolated storage.

Capturing Video

The CameraCaptureUI is the same mechanism for capturing video. In fact, other than the CaptureFileAsync() argument value, it’s the same code and demonstrated in the section above.

Previewing the Camera

Because the CameraCaptureUI is a stand-alone, brokered dialog, it means it does its job and then returns the result. It could happen that your application needs (or wants) to show the user a preview of the camera – even to the point of handling the monotony that the CameraCaptureUI handles for you out of the gate.

No problem. Enter the <MediaCapture /> XAML element. (Note: there’s a Windows 8 SDK sample for this). This clever element lets developers preview the output of the camera without using the CameraCaptureUI.

You can create a simple UI that previews and shows a captured photo like this:


The screen above is accomplished with some very simple XAML:


In the XAML above, I implement the <MediaCapture /> element which we use to preview the camera on the device. To make this work, however, you need to do a little code behind. Like this:


In the code above, I am effectively “turning on” the MediaCapture element. First with it’s InitializeAsync() method, and then it’s StartPreviewAsync() method.

Capture a picture or video like this:


In the code above I create the target file. Then I use the MediaCapture which is the source of my CaptureElement to call CapturePhotoToStorageFileAsync(); This well-named method takes the current preview frame and saves it to the specified file. Presto, your own camera!

Best of luck!





Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}

Developers ask for \r\ndevice...","authors":[{"realName":"Jerry Nixon","isMVB":true,"isStaff":false,"aboutAuthor":"Jerry Nixon is the Microsoft Developer Evangelist in Colorado. He has scary knowledge about Architecture, XAML, and SQL Server. He has terrifying knowledge about Windows Phone, the Kinect, and C#. And, he has simply ridiculous knowledge on Windows Desktop development in Windows 8. ","claimed":null,"name":"Jerry Nixon","tagline":null,"company":"Microsoft","id":954995,"avatar":"https://secure.gravatar.com/avatar/1679f0ca80c657f1fca8fbcc74eeefe1?d=identicon&r=PG","isClaimed":false,"url":"/users/954995/Jerry+Nixon.html"}]}]; TH.installWidgetController('article.content', 'articleContent5', WMODEL_DATA, typeof controller == 'function' ? controller : null, [{name: 'partners', data: true},{name: 'DEFAULT', data: true}], ' oUhbblYOaqbcblYOaqbcC', null); })(); (function() { function controller($scope, $service, $location, SideBarService, $timeout) { if ($scope.edition) { $scope.date = moment($scope.editionDate).utc().format('MMM DD, YYYY'); } SideBarService.ctx.pageSize = $scope.pageSize; SideBarService.ctx.isPreview = $scope.isPreview; SideBarService.ctx.mode = $scope.mode; SideBarService.fn.loader = $service; var $window = $(window); function checkWidth() { var windowsize = $window.width(); $scope.width = windowsize; } // Execute on load checkWidth() // Bind event listener $(window).resize(checkWidth); if ($scope.edition) { SideBarService.ctx.edition = $scope.edition; } SideBarService.fn.scrollCheck = function() { $scope.$emit('thIfScrollCheck'); }; var currentFilter; $scope.$on('$locationChangeSuccess', function() { if (!$location.search().filter) { $scope.filter = 'latest'; } else { $scope.filter = $location.search().filter; if ($scope.filter == 'latest') { $location.search('filter', null); } } if (currentFilter == $scope.filter) { return; } currentFilter = $scope.filter; SideBarService.ctx.filter = $scope.filter; }); $scope.display = SideBarService.getList(); $scope.$watchCollection(function() { return SideBarService.getList(); }, function (n) { $scope.display = n; }); $scope.isActive = SideBarService.isActive; $scope.isExcluded = SideBarService.isExcluded; $scope.loadMore = SideBarService.load; $scope.loading = function() { return SideBarService.ctx.loading; }; TH.on('TapBarStatusChange', function(expanded) { if (expanded) { SideBarService.unblock(); } }) } var WMODEL_DATA = {}; WMODEL_DATA.mode = null; WMODEL_DATA.isPreview = false; WMODEL_DATA.editionName = ""; WMODEL_DATA.editionDate = null; WMODEL_DATA.pageSize = 20; WMODEL_DATA.edition = null; WMODEL_DATA.OPTIONS = {}; TH.installWidgetController('sidebar.content.list', 'sidebarContentList8', WMODEL_DATA, typeof controller == 'function' ? controller : null, [{name: 'DEFAULT', data: true}], ' oUhbkSMaaqbcdvVkcC', null); })(); (function() { function controller($scope) { var $window = $(window); function checkWidth() { var windowsize = $window.width(); var $element = $('div.sidebar.sidebarTapBar'); $scope.width = windowsize; if(windowsize <= 1024 && $scope.edition){ $('.fixContentRight').removeClass('fixContentRight'); // $element.removeClass('expanded'); // $element.addClass('tapNotExpanded'); $('.tap').show(); }else if($scope.edition){ $('.tap').hide(); $('.mainContentRow').addClass('fixContentRight'); $element.removeClass('tapNotExpanded'); $element.addClass('expanded'); } } // Execute on load checkWidth(); // Bind event listener $(window).resize(checkWidth); } var WMODEL_DATA = {}; WMODEL_DATA.edition = null; WMODEL_DATA.slot = null; WMODEL_DATA.OPTIONS = {}; TH.installWidgetController('sidebar.tapBar', 'sidebar', WMODEL_DATA, typeof controller == 'function' ? controller : null, null, ' oUhbkSMadabfWVcC oUhbkSMadabbWQbVkcC', null); })(); (function() { function controller($scope, shareThis, TH$Dialog, TH$Service, $location) { $scope.getEditUrl = function(id, type) { if (!type || type == 'article') { return '/content/' + id + '/edit.html'; } else { return '/dzone/staff/' + type + (type == 'refcard' ? 'z' : 's') + '/' + id + '/edit.html'; } }; $scope.share = function(socialNet, url, title){ shareThis.shareThis(socialNet, url, title); }; // $scope.mailShareLink = function(article) { // return 'mailto:?subject=' + encodeURIComponent(article.header.title) + '&body=Article: ' + encodeURIComponent('https://dzone.com/' + article.header.link); // }; $scope.canDelete = function(article) { return article.canDelete; }; $scope.canPublish = function(article) { return article.canPublish; }; $scope.canEdit = function(article) { return article.canEdit; }; $scope.toggleComments = function(article) { if(!article.isLocked) { TH$Service.action('articles.lockNode', {type: 'node', id: article.id}).then(function(result) { if(result){ article.isLocked = true; TH$Dialog.success('You have disabled all comments for this Article'); }else{ TH$Dialog.error('error','Your requested was denied') } }); }else { TH$Service.action('articles.unlockNode', {type: 'node', id: article.id}).then(function(result) { if(result){ article.isLocked = false; TH$Dialog.success('You have enabled all comments for this Article'); }else{ TH$Dialog.error('error','Your requested was denied') } }); } }; $scope.toggleLimitComments = function (article) { if (!article.isLimited) { TH$Service.action('articles.limitNode', {type: 'node', id: article.id}).then(function (result) { if (result) { article.isLimited = true; TH$Dialog.success('You have limited comments for this Article. Now all comments will go through moderation.'); } else { TH$Dialog.error('error', 'Your requested was denied') } }); } else { TH$Service.action('articles.unlimitNode', {type: 'node', id: article.id}).then(function (result) { if (result) { article.isLimited = false; TH$Dialog.success('You removed the limits for comments on this Article'); } else { TH$Dialog.error('error', 'Your requested was denied') } }); } }; $scope.shareTwitter = function($event, title, url){ $event.preventDefault(); $event.stopPropagation(); var twitter = 'https://twitter.com/intent/tweet'; var link = $location.protocol() + '://' + location.host + url; var ref = location.host; var params = '?text='+title+'&url='+link+'&ref=dzone.com&via=DZone'; var win = window.open(twitter+params, '_blank'); win.focus(); }; $scope.edit = function(link) { TH$Dialog.open({ loadWidget: 'links.postPreview', widgetArgs: { edit: link.id }, size: 'xbig' }).then(function (result) { $scope.link.title = result.title; $scope.link.linkDescription = result.content; $scope.link.thumb = result.thumb; $scope.link.tags = result.topics; }); }; $scope.deleteLink = function(article) { var title = article.title; var type = 'link'; if(article.header){ title = (article.header.type == 'article') ? article.header.title : article.title; type = (article.header.type == 'article') ? 'article' : 'link'; } TH$Dialog.confirm('Do you want to delete "' + title + '"?').then(function() { return TH$Service.action('delete', {type: type, id: article.id}); }).then(function() { article.deleted = true; }); }; } var WMODEL_DATA = {}; WMODEL_DATA.OPTIONS = {}; TH.installWidgetController('content.commentsSlider', 'contentCommentsSlider7', WMODEL_DATA, typeof controller == 'function' ? controller : null, null, ' oUhbaqbcaibvnWffWVcC', null); })(); (function() { var WMODEL_DATA = {}; WMODEL_DATA.name = "commentsSlider"; WMODEL_DATA.slot = null; WMODEL_DATA.OPTIONS = {"name":"commentsSlider"}; TH.installWidgetController('components.slider', 'componentsSlider6', WMODEL_DATA, typeof controller == 'function' ? controller : null, null, ' oUhballbvbdSaoUhM', null); })();