うさぎ駆動開発

UWP, Xamarin.Macを中心によしなしごとを書いていきます。

UWPで前面カメラからキャプチャする

前回はXamarin.Macでやったので,UWPでもやってみます。 リポジトリはこちら。

github.com

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では適宜調整が必要かと思います。 f:id:ailen0ada:20160918163551p:plain

キャプチャ

キャプチャボタンのクリックイベントでこんな感じに記述します。

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 でやります。