使用 Windows 内置相机 UI 捕获照片和视频Capture photos and video with the Windows built-in camera UI

本文介绍如何使用 CameraCaptureUI 类通过内置于 Windows 中的照相机 UI 来捕获照片或视频。This article describes how to use the CameraCaptureUI class to capture photos or videos by using the camera UI built into Windows. 此功能易于使用。This feature is easy to use. 只需几行代码,应用程序就能获得用户捕获的照片或视频。It allows your app to get a user-captured photo or video with just a few lines of code.

如果要提供自己的照相机 UI,或方案需要更可靠的、低级别的捕获操作控制,则应使用 MediaCapture 类,并实现自己的捕获体验。If you want to provide your own camera UI, or if your scenario requires more robust, low-level control of the capture operation, then you should use the MediaCapture class, and implement your own capture experience. 有关详细信息,请参阅 使用 MediaCapture 捕获基本的照片、视频和音频For more information, see Basic photo, video, and audio capture with MediaCapture.

备注

如果你的应用程序仅使用CameraCaptureUI,则不应在应用程序清单文件中指定网络摄像机麦克风功能。You shouldn't specify the webcam nor microphone capabilities in your app manifest file if your app only uses CameraCaptureUI. 如果这样做,你的应用程序将以设备的相机隐私设置显示,但即使用户拒绝对你的应用程序的照相机访问,这也不会阻止 CameraCaptureUI 捕获媒体。If you do, your app will be displayed in the device's camera privacy settings, but even if the user denies camera access to your app, this won't prevent the CameraCaptureUI from capturing media.

这是因为 Windows 内置的摄像头应用是受信任的第一方应用,需要用户按下按钮来启动照片、音频和视频捕获。This is because the Windows built-in camera app is a trusted first-party app that requires the user to initiate photo, audio, and video capture with a button press. 如果你在使用 CameraCaptureUI 作为唯一的照片捕获机制时指定了网络摄像机或麦克风功能,则在提交到 Microsoft Store 时,你的应用程序可能无法使用 Windows 应用程序认证包证书。Your app may fail Windows Application Certification Kit certification when submitted to Microsoft Store if you specify the webcam or microphone capabilities when using CameraCaptureUI as your only photo capture mechanism.

如果你使用MediaCapture以编程方式捕获音频、照片或视频,则必须在应用程序清单文件中指定网络摄像机麦克风功能。You must specify the webcam or microphone capabilities in your app manifest file if you're using MediaCapture to capture audio, photos, or video programmatically.

使用 CameraCaptureUI 捕获照片Capture a photo with CameraCaptureUI

若要使用相机捕获 UI,请将 Windows.Media.Capture 命名空间包含在你的项目中。To use the camera capture UI, include the Windows.Media.Capture namespace in your project. 若要针对返回的图像文件执行文件操作,请包含 Windows.StorageTo do file operations with the returned image file, include Windows.Storage.

using Windows.Media.Capture;
using Windows.Storage;
#include <winrt/Windows.Media.Capture.h>
#include <winrt/Windows.Media.Playback.h>
#include <winrt/Windows.Storage.h>
using namespace winrt;
using namespace Windows::Media::Capture;
using namespace Windows::Storage;

若要捕获照片,请创建新的 CameraCaptureUI 对象。To capture a photo, create a new CameraCaptureUI object. 通过使用对象的 PhotoSettings 属性,您可以指定返回的照片的属性,如照片的图像格式。By using the object's PhotoSettings property, you can specify properties for the returned photo, such as the image format of the photo. 默认情况下,相机捕获 UI 支持在返回照片之前对其进行裁剪。By default, the camera capture UI supports cropping the photo before it's returned. 这可以通过 AllowCropping 属性来禁用。This can be disabled with the AllowCropping property. 此示例设置 CroppedSizeInPixels 以要求返回的图像像素为 200 x 200。This example sets the CroppedSizeInPixels to request that the returned image be 200 x 200 in pixels.

备注

移动设备系列中的设备不支持 CameraCaptureUI 中的图像裁剪。Image cropping in the CameraCaptureUI isn't supported for devices in the Mobile device family. 在这些设备上运行应用时,将忽略 AllowCropping 属性的值。The value of the AllowCropping property is ignored when your app is running on these devices.

调用 CaptureFileAsync 并指定 CameraCaptureUIMode.Photo 以指定应捕获的照片。Call CaptureFileAsync and specify CameraCaptureUIMode.Photo to specify that a photo should be captured. 如果捕获成功,该方法将返回包含该图像的 StorageFile 实例。The method returns a StorageFile instance containing the image if the capture is successful. 如果用户取消捕获,则返回的对象为 NULL。If the user cancels the capture, the returned object is null.

CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.PhotoSettings.Format = CameraCaptureUIPhotoFormat.Jpeg;
captureUI.PhotoSettings.CroppedSizeInPixels = new Size(200, 200); 

StorageFile photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);

if (photo == null)
{
    // User cancelled photo capture
    return;
}
CameraCaptureUI captureUI;
captureUI.PhotoSettings().Format(CameraCaptureUIPhotoFormat::Jpeg);
captureUI.PhotoSettings().CroppedSizeInPixels({ 200, 200 });

StorageFile photo = co_await captureUI.CaptureFileAsync(CameraCaptureUIMode::Photo);

if (!photo)
{
    // User cancelled photo capture
    co_return;
}

为包含捕获的照片的 StorageFile 提供一个动态生成的名称,并将其保存在应用的本地文件夹中。The StorageFile containing the captured photo is given a dynamically generated name and saved in your app's local folder. 为了更好地组织您捕获的照片,您可以将该文件移动到其他文件夹。To better organize your captured photos, you can move the file to a different folder.

StorageFolder destinationFolder = 
    await ApplicationData.Current.LocalFolder.CreateFolderAsync("ProfilePhotoFolder", 
        CreationCollisionOption.OpenIfExists);

await photo.CopyAsync(destinationFolder, "ProfilePhoto.jpg", NameCollisionOption.ReplaceExisting);
await photo.DeleteAsync();
StorageFolder destinationFolder =
    co_await ApplicationData::Current().LocalFolder().CreateFolderAsync(L"ProfilePhotoFolder",
        CreationCollisionOption::OpenIfExists);

co_await photo.CopyAsync(destinationFolder, L"ProfilePhoto.jpg", NameCollisionOption::ReplaceExisting);
co_await photo.DeleteAsync();

若要在应用中使用你的照片,你可能希望创建可以与多个不同的通用 Windows 应用功能结合使用的 SoftwareBitmap 对象。To use your photo in your app, you may want to create a SoftwareBitmap object that can be used with several different Universal Windows app features.

首先,将 Windows 映像 命名空间包含在项目中。First, include the Windows.Graphics.Imaging namespace in your project.

using Windows.Storage.Streams;
using Windows.Graphics.Imaging;
#include <winrt/Windows.Graphics.Imaging.h>
#include <winrt/Windows.Storage.Streams.h>
using namespace Windows::Graphics::Imaging;
using namespace Windows::Storage::Streams;

调用 OpenAsync 以从图像文件获得一个流。Call OpenAsync to get a stream from the image file. 调用 BitmapDecoder.CreateAsync 以获取流的位图解码器。Call BitmapDecoder.CreateAsync to get a bitmap decoder for the stream. 然后,调用 GetSoftwareBitmap 以获取图像的 SoftwareBitmap 表示形式。Then, call GetSoftwareBitmap to get a SoftwareBitmap representation of the image.

IRandomAccessStream stream = await photo.OpenAsync(FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();
IRandomAccessStream stream = co_await photo.OpenAsync(FileAccessMode::Read);
BitmapDecoder decoder = co_await BitmapDecoder::CreateAsync(stream);
SoftwareBitmap softwareBitmap = co_await decoder.GetSoftwareBitmapAsync();

若要在 UI 中显示该图像,请在 XAML 页面中声明 Image 控件。To display the image in your UI, declare an Image control in your XAML page.

<Image x:Name="imageControl" Width="200" Height="200"/>
<Image x:Name="imageControl" Width="200" Height="200"/>

若要在 XAML 页面中使用软件位图,请在项目中包含正在使用的 Windows.UI.Xaml.Media.Imaging 命名空间。To use the software bitmap in your XAML page, include the using Windows.UI.Xaml.Media.Imaging namespace in your project.

using Windows.UI.Xaml.Media.Imaging;
#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
using namespace Windows::UI::Xaml::Media::Imaging;

图像控件要求图像源为 BGRA8 格式,预乘的 alpha 或无 alpha。The Image control requires that the image source be in BGRA8 format with premultiplied alpha or no alpha. 调用静态方法 SoftwareBitmap ,以使用所需的格式创建新的软件位图。Call the static method SoftwareBitmap.Convert to create a new software bitmap with the desired format. 接下来,创建一个新的 SoftwareBitmapSource 对象,并调用 SetBitmapAsync 将软件位图分配给该源。Next, create a new SoftwareBitmapSource object and call it SetBitmapAsync to assign the software bitmap to the source. 最后,设置 Image 控件的 Source 属性以显示 UI 中已捕获的照片。Finally, set the Image control's Source property to display the captured photo in the UI.

SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap.Convert(softwareBitmap,
        BitmapPixelFormat.Bgra8, 
        BitmapAlphaMode.Premultiplied);

SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);

imageControl.Source = bitmapSource;
SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap::Convert(softwareBitmap,
    BitmapPixelFormat::Bgra8,
    BitmapAlphaMode::Premultiplied);

SoftwareBitmapSource bitmapSource;
co_await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);

imageControl().Source(bitmapSource);

使用 CameraCaptureUI 捕获视频Capture a video with CameraCaptureUI

若要捕获视频,请创建新的 CameraCaptureUI 对象。To capture a video, create a new CameraCaptureUI object. 通过使用对象的 VideoSettings 属性,可以指定返回视频的属性,例如视频的格式。By using the object's VideoSettings property, you can specify properties for the returned video, such as the format of the video.

调用 CaptureFileAsync 并指定 视频 来捕获视频。Call CaptureFileAsync and specify Video to capture a video. 如果捕获成功,该方法将返回包含该视频的 StorageFile 实例。The method returns a StorageFile instance containing the video if the capture is successful. 如果取消捕获,则返回的对象为 null。If you cancel the capture, the returned object is null.

CameraCaptureUI captureUI = new CameraCaptureUI();
captureUI.VideoSettings.Format = CameraCaptureUIVideoFormat.Mp4;

StorageFile videoFile = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Video);

if (videoFile == null)
{
    // User cancelled photo capture
    return;
}
CameraCaptureUI captureUI;
captureUI.VideoSettings().Format(CameraCaptureUIVideoFormat::Mp4);

StorageFile videoFile = co_await captureUI.CaptureFileAsync(CameraCaptureUIMode::Video);

if (!videoFile)
{
    // User cancelled photo capture
    co_return;
}

根据应用方案处理所捕获视频文件。What you do with the captured video file depends on the scenario for your app. 本文的其余部分向你介绍了如何从一个或多个已捕获的视频快速创建媒体组合并将其显示在你的 UI 中。The rest of this article shows you how to quickly create a media composition from one or more captured videos and show it in your UI.

首先,添加一个 MediaPlayerElement 控件,其中视频组合将显示在 XAML 页面上。First, add a MediaPlayerElement control in which the video composition will display on your XAML page.

<MediaPlayerElement x:Name="mediaPlayerElement" Width="320" Height="240" AreTransportControlsEnabled="True"/>

当视频文件从相机捕获 UI 返回时,通过调用**CreateFromStorageFile** 创建新的MediaSourceWhen the video file returns from the camera capture UI, create a new MediaSource by calling CreateFromStorageFile. 调用与 MediaPlayerElement 关联的默认 MediaPlayerPlay 方法以播放视频。Call the Play method of the default MediaPlayer associated with the MediaPlayerElement to play the video.

mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(videoFile);
mediaPlayerElement.MediaPlayer.Play();
mediaPlayerElement().Source(MediaSource::CreateFromStorageFile(videoFile));
mediaPlayerElement().MediaPlayer().Play();