UWPで前面カメラからキャプチャする
前回はXamarin.Macでやったので,UWPでもやってみます。 リポジトリはこちら。
appxmanifest
Package.appxmanifest
のCapabilitiesで,ウェブカメラへのアクセスを許可します。デスクトップで動かす場合はマイクへのアクセス許可も必要。
多分保存もしたくなると思うので,ピクチャライブラリへのアクセスも許可。
<Capabilities> <Capability Name="internetClient" /> <uap:Capability Name="picturesLibrary" /> <DeviceCapability Name="webcam" /> <DeviceCapability Name="microphone" /> </Capabilities>
UIを作る
CaptureElement
とシャッター用に Button
を配置しましょう。ざっくりこんな感じ。
<Page.BottomAppBar> <CommandBar ClosedDisplayMode="Compact"> <AppBarButton Icon="Play" Label="Start" /> <AppBarButton Icon="Stop" Label="Stop" /> <AppBarButton Icon="Camera" Label="Capture" /> </CommandBar> </Page.BottomAppBar> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <CaptureElement x:Name="LiveView" Stretch="Uniform" /> </Grid>
ライブビュー
MainPage.xaml.cs
がロードされた辺りでデバイスを探索しましょう。
private MediaCapture captureSource; private bool isStarted; protected override async void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture); // 背面とか前面とかは適当にこの辺で絞る // using Panel = Windows.Devices.Enumeration.Panel; var camera = devices.FirstOrDefault(d => d.EnclosureLocation?.Panel == Panel.Front); var settings = new MediaCaptureInitializationSettings {VideoDeviceId = camera.Id}; captureSource = new MediaCapture(); await captureSource.InitializeAsync(settings); LiveView.Source = captureSource; }
UIに作っておいた開始・停止ボタンのクリックイベントで captureSource.Start/StopPreviewAsync()
を呼び出します。
private async void StartLiveView(object sender, RoutedEventArgs e) { if (isStarted) return; await captureSource.StartPreviewAsync(); isStarted = true; } private async void StopLiveView(object sender, RoutedEventArgs e) { if (!isStarted) return; await captureSource.StopPreviewAsync(); isStarted = false; }
実行するとこんな感じ。これはSurface Bookで実行しているので Panel.Front/Back
両方でカメラデバイスを見つけることができますが,そうでないPCでは適宜調整が必要かと思います。
キャプチャ
キャプチャボタンのクリックイベントでこんな感じに記述します。
private async void CaptureImage(object sender, RoutedEventArgs e) { if (!isStarted) return; var fn = $"{DateTime.Now:yyyyMMdd-HHmmss}.jpg"; var file = await KnownFolders.CameraRoll.CreateFileAsync(fn, CreationCollisionOption.GenerateUniqueName); await captureSource.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), file); }
単純にJPEGとして保存できればいいだけならこれで必要十分。もちろんストリームを開いてなんか処理をしてから保存,とかもここからできるわけです。
次回予告
次は Xamarin.iOS でやります。