Use MediaCapture on a Windows 8 desktop app

2019-02-10 03:17发布

问题:

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 ?

回答1:

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



回答2:

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" />


回答3:

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.