Use MediaCapture on a Windows 8 desktop app
Asked Answered
P

3

7

On a Windows 8 desktop app, I need to take a photo using the camera in C# 4.5.

I've tried to use the CameraCaptureUI class, but it is not available on a desktop app.

So I try to use the MediaCapture class, which is available for Metro app or desktop app. It works great, based on the example found here : http://code.msdn.microsoft.com/windowsapps/media-capture-sample-adf87622/

var capture = new MediaCapture();
// Find the camera device id to use
string deviceId = "";
var devices = await Windows.Devices.Enumeration.DeviceInformation.FindAllAsync(Windows.Devices.Enumeration.DeviceClass.VideoCapture);
for (var i = 0; i < devices.Count; i++) {
     Console.WriteLine(devices[i]);
     deviceId = devices[i].Id;
}

// init the settings of the capture
var settings = new MediaCaptureInitializationSettings();
settings.AudioDeviceId = "";
settings.VideoDeviceId = deviceId;
settings.PhotoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.Photo;
settings.StreamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.Video;
await capture.InitializeAsync(settings);

// Find the highest resolution available
VideoEncodingProperties resolutionMax = null;
int max = 0;
var resolutions = capture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo);
for (var i = 0; i < resolutions.Count; i++) {
     VideoEncodingProperties res = (VideoEncodingProperties)resolutions[i];
     Console.WriteLine("resolution : " + res.Width + "x" + res.Height);
     if (res.Width * res.Height > max) {
          max = (int)(res.Width * res.Height);
          resolutionMax = res;
     }
}
await capture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, resolutionMax);

ImageEncodingProperties imageProperties = ImageEncodingProperties.CreateJpeg();
var fPhotoStream = new InMemoryRandomAccessStream();

// THE 2 LINES I NEED TO ADD
// captureElement.Source = capture;
// await capture.StartPreviewAsync();

// Take the photo and show it on the screen
await capture.CapturePhotoToStreamAsync(imageProperties, fPhotoStream);
await fPhotoStream.FlushAsync();
fPhotoStream.Seek(0);

byte[] bytes = new byte[fPhotoStream.Size];
await fPhotoStream.ReadAsync(bytes.AsBuffer(), (uint)fPhotoStream.Size, InputStreamOptions.None);

BitmapImage bitmapImage = new BitmapImage();
MemoryStream byteStream = new MemoryStream(bytes);
bitmapImage.BeginInit();
bitmapImage.StreamSource = byteStream;
bitmapImage.EndInit();
image.Source = bitmapImage;

I can take a photo using the camera, but I'm unable to show a preview before taking the photo. To be able to show the preview, I have to use the component CaptureElement, for example with the following code :

captureElement.Source = mediaCapture;
await mediaCapture.startPreviewAsync();

Unfortunately, I cannot use a CaptureElement on a non store app. Is there another component that I can use in a WPF or WinForm app, to be able to show the preview of the camera ?

Pauiie answered 25/1, 2013 at 15:56 Comment(4)
Check out easywebcam.codeplex.comPlectrum
Thank you for your quick answer, but it's not really what I'm looking for. I've already tested this project and it only allows me to take a photo from a webcam stream. It's not like taking a real photo with autofocus and flash... I use a recent tablet with 8Mp camera, so it's possible to take relatively good photos using the windows 8 Camera application. I'm looking for a solution to be able to reproduce the same app, but on a desktop app not a metro app.Pauiie
Ray20: Have you had success getting the camera flash to activate? When I use the same API on Windows 8 (WinForms) I am able to take a photo, but it comes out super dark. The flash never activates and it appears that auto focusing doesn't work either. I am using a tablet also.Vapor
I still have the problem with the dark picture did any of you found a solution for that?Leenaleeper
K
4

Late reply, but in case that helps folks in the future: previewing MediaCapture in WPF can be done via D3DImage and some native interop (create a custom Media Foundation Sink, grab DirectX 11 textures, convert them to DirectX 9). It is a bit of code but can be encapsulated so it is still simple to call from C#. Here is some code sample: https://github.com/mmaitre314/MediaCaptureWPF

Kenzi answered 19/7, 2015 at 22:42 Comment(0)
K
0

After the picture is taken I do the following:

_ms.Seek(0);
var _bmp = new BitmapImage();
_bmp.SetSource(_ms);
preview1.Source = _bmp;

The preview XAML control is

<Image x:Name="preview1" Margin="850,90,102,362" />
Kola answered 15/10, 2013 at 15:4 Comment(0)
P
0

Unfortunately, I cannot use a CaptureElement on a non store app. Is there another component that I >can use in a WPF or WinForm app, to be able to show the preview of the camera ?

For a solution to using something similar to CaptureElement in a non-WinRT application, I've found this: http://wpfcap.codeplex.com/

I have used it on a wpf control hosted in a Windows forms app and had no problems. Only that I had to keep using MediaCapture to capture photos and I'm also having the problem of the pictures too dark on the tablet (ok on pc). It seems that calling capture.CapturePhotoToStreamAsync sincronously takes the photo as you see it on the preview.

Patras answered 3/6, 2014 at 9:56 Comment(1)
A link to a potential solution is always welcome, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.Genetic

© 2022 - 2024 — McMap. All rights reserved.