使用 Windows 內建相機 UI 來擷取相片和視訊
本文介紹如何使用 CameraCaptureUI 類別透過 Windows 內建的相機 UI 來擷取相片或影片。 這項功能很容易使用。 它可讓您的應用程式使用幾行程式碼來取得使用者擷取的相片或影片。
如果您想提供自己的相機 UI,或者您的案例需要對擷取作業進行更強大的低階控制,那麼您應該使用 MediaCapture 類別,並實作您自己的擷取體驗。 有關更多資訊,請參閱使用 MediaCapture 進行基本相片、影片和音訊擷取。
注意
如果您的應用程式僅使用 CameraCaptureUI,則不應在應用程式清單檔案中指定網路相機或麥克風功能。 如果您這樣做,您的應用程式將顯示在裝置的相機隱私設定中,但即使使用者拒絕相機存取您的應用程式,這也不會阻止 CameraCaptureUI 擷取媒體。
這是因為 Windows 內建相機應用程式是受信任的第一方應用程式,需要使用者透過按下按鈕來啟動相片、音訊和影片擷取。 如果您在使用 CameraCaptureUI 做為唯一的相片擷取機制時指定網路相機或麥克風功能,則您的應用程式在提交至 Microsoft Store 時可能無法通過 Windows 應用程式認證套件之認證
如果您使用 MediaCapture 以程式設計方式擷取音訊、相片或影片,則必須在應用程式清單檔案中指定網路相機或麥克風功能。
使用 CameraCaptureUI 擷取相片
若要使用相機擷取 UI,請在專案中包含 Windows.Media.Capture 命名空間。 若要使用傳回的影像檔執行檔案作業,請包含 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 物件。 透過使用物件的 PhotoSettings 屬性,您可以指定傳回相片的屬性,例如相片的影像格式。 預設情況下,相機擷取 UI 支援在傳回相片之前對其進行裁剪。 可以使用 AllowCropping 屬性來停用此功能。 此範例設定 CroppedSizeInPixels 以要求傳回的影像為 200 x 200 像素。
注意
行動裝置系列中的裝置不支援 CameraCaptureUI 中的影像裁剪。 當您的應用程式在這些裝置上執行時,AllowCropping 屬性的值將被忽略。
呼叫 CaptureFileAsync 並指定 CameraCaptureUIMode.Photo 以指定應擷取相片。 如果擷取成功,則方法將傳回包含影像的 StorageFile 執行個體。 如果使用者取消擷取,則傳回的物件為 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 被賦予動態產生的名稱並儲存在應用程式的本機資料夾中。 若要更妥善地組織所擷取的相片,您可以將檔案移至不同的資料夾。
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 物件。
首先,在專案中包含 Windows.Graphics.Imaging 命名空間。
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 從影像檔中取得串流。 呼叫 BitmapDecoder.CreateAsync 以取得串流的點陣圖解碼器。 然後,呼叫 GetSoftwareBitmap 取得影像的 SoftwareBitmap 表示法。
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 控制項。
<Image x:Name="imageControl" Width="200" Height="200"/>
<Image x:Name="imageControl" Width="200" Height="200"/>
若要在 XAML 頁面中使用軟體點陣圖,請在專案中包含 Windows.UI.Xaml.Media.Imaging 命名空間。
using Windows.UI.Xaml.Media.Imaging;
#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
using namespace Windows::UI::Xaml::Media::Imaging;
Image 控制項要求影像來源為 BGRA8 格式,含預乘 alpha 或不含 alpha。 呼叫靜態方法 SoftwareBitmap.Convert 以建立具有所需格式的新軟體點陣圖。 接下來,建立一個新的 SoftwareBitmapSource 物件並呼叫它 SetBitmapAsync 以將軟體點陣圖指派給來源。 最後,設定 Image 控制項的 Source 屬性以在 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 擷取影片
若要擷取影片,請建立新的 CameraCaptureUI 物件。 透過使用物件的 VideoSettings 屬性,您可以指定傳回影片的屬性,例如影片的格式。
呼叫 CaptureFileAsync 並指定 Video 以擷取影片。 如果擷取成功,則方法將傳回包含影片的 StorageFile 執行個體。 如果您取消擷取,則傳回的物件為 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;
}
您使用擷取的影片檔案所執行的動作取決於您應用程式的案例。 本文的其餘部分會示範如何快速從一或多個擷取的影片建立媒體組合,並將其顯示在 UI 中。
首先,新增一個 MediaPlayerElement 控制項,其中影片組合將顯示在 XAML 頁面上。
<MediaPlayerElement x:Name="mediaPlayerElement" Width="320" Height="240" AreTransportControlsEnabled="True"/>
當影片檔案從相機擷取 UI 傳回時,透過呼叫 CreateFromStorageFile 建立一個新的 MediaSource。 呼叫與 MediaPlayerElement 關聯的預設 MediaPlayer 的 Play 方法來播放影片。
mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(videoFile);
mediaPlayerElement.MediaPlayer.Play();
mediaPlayerElement().Source(MediaSource::CreateFromStorageFile(videoFile));
mediaPlayerElement().MediaPlayer().Play();