次の方法で共有


CameraHelper

ヘルパーは現在、カラー ビデオ プレビューまたはビデオ レコード ストリームをサポートするカメラ フレーム ソースを表示します。

重要

アプリがデバイスのカメラにアクセス、Web カメラ機能が有効になっていることを確認します。

<!--  Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information.  -->
<UserControl x:Class="HelpersExperiment.Samples.CameraHelperSample"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="using:HelpersExperiment.Samples"
             xmlns:muxc="using:Microsoft.UI.Xaml.Controls">

    <StackPanel HorizontalAlignment="Center"
                Orientation="Vertical"
                Spacing="12">
        <ComboBox x:Name="FrameSourceGroupCombo"
                  MinWidth="200"
                  HorizontalAlignment="Center"
                  Header="Frame source group">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding DisplayName}" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <muxc:InfoBar x:Name="ErrorBar"
                      Title="Error"
                      IsOpen="False"
                      Severity="Error" />
        <Border Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
                BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
                BorderThickness="1"
                CornerRadius="{StaticResource ControlCornerRadius}">
            <Image x:Name="CurrentFrameImage"
                   Height="300"
                   MinWidth="360" />
        </Border>


        <Button x:Name="CaptureButton"
                HorizontalAlignment="Center"
                Click="CaptureButton_Click"
                Content="Capture video frame"
                Style="{StaticResource AccentButtonStyle}" />
    </StackPanel>
</UserControl>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using CommunityToolkit.WinUI.Helpers;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Media.Capture.Frames;
using Windows.ApplicationModel;

#if WINAPPSDK
using Microsoft.UI.Xaml.Media.Imaging;
#else
using Windows.UI.Xaml.Media.Imaging;
#endif

namespace HelpersExperiment.Samples;

[ToolkitSample(id: nameof(CameraHelperSample), "CameraHelper", description: $"A sample for showing how to use {nameof(CameraHelper)}.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Controls dispose resources on unload")]
public sealed partial class CameraHelperSample : UserControl
{
    private CameraHelper _cameraHelper;
    private VideoFrame _currentVideoFrame;
    private SoftwareBitmapSource _softwareBitmapSource;

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
    public CameraHelperSample()
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
    {
        this.InitializeComponent();

        Loaded += CameraHelperSample_Loaded;
        Unloaded += CameraHelperSample_Unloaded;
    }

    private async void CameraHelperSample_Loaded(object sender, RoutedEventArgs e)
    {
        Loaded -= CameraHelperSample_Loaded;

        Setup();
        await InitializeAsync();
    }

    private async void CameraHelperSample_Unloaded(object sender, RoutedEventArgs e)
    {
        Unloaded -= CameraHelperSample_Unloaded;

#if !WINAPPSDK
        Application.Current.Suspending -= Application_Suspending;
        Application.Current.Resuming -= Application_Resuming;
#endif
        await CleanUpAsync();
    }

    private void Setup()
    {
        _softwareBitmapSource = new SoftwareBitmapSource();
        CurrentFrameImage.Source = _softwareBitmapSource;
#if !WINAPPSDK
        // Application.Current.Suspending += Application_Suspending;
        // Application.Current.Resuming += Application_Resuming;
#endif
    }

    private async void Application_Suspending(object? sender, SuspendingEventArgs e)
    {
        if (IsLoaded)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            await CleanUpAsync();
            deferral.Complete();
        }
    }

    private async void Application_Resuming(object? sender, object e)
    {
        await InitializeAsync();
    }

    private void CameraHelper_FrameArrived(object sender, FrameEventArgs e)
    {
        _currentVideoFrame = e.VideoFrame;
    }

    private async Task InitializeAsync()
    {
        var frameSourceGroups = await CameraHelper.GetFrameSourceGroupsAsync();
        if (_cameraHelper == null)
        {
            _cameraHelper = new CameraHelper();
        }

        var result = await _cameraHelper.InitializeAndStartCaptureAsync();
        if (result == CameraHelperResult.Success)
        {
            // Subscribe to the video frame as they arrive
            _cameraHelper.FrameArrived += CameraHelper_FrameArrived!;
            FrameSourceGroupCombo.ItemsSource = frameSourceGroups;
            FrameSourceGroupCombo.SelectionChanged += FrameSourceGroupCombo_SelectionChanged;
            FrameSourceGroupCombo.SelectedIndex = 0;
        }

        SetUIControls(result);
    }

    private async void FrameSourceGroupCombo_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (FrameSourceGroupCombo.SelectedItem is MediaFrameSourceGroup selectedGroup && _cameraHelper != null)
        {
            _cameraHelper.FrameSourceGroup = selectedGroup;
            var result = await _cameraHelper.InitializeAndStartCaptureAsync();
            SetUIControls(result);
        }
    }

    private void SetUIControls(CameraHelperResult result)
    {
        var success = result == CameraHelperResult.Success;
        if (!success)
        {
            _currentVideoFrame = null!;
        }

        ErrorBar.Title = result.ToString();
        ErrorBar.IsOpen = !success;

        CaptureButton.IsEnabled = success;
        CurrentFrameImage.Opacity = success ? 1 : 0.5;
    }

    private async void CaptureButton_Click(object sender, RoutedEventArgs e)
    {
        var softwareBitmap = _currentVideoFrame?.SoftwareBitmap;

        if (softwareBitmap != null)
        {
            if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight)
            {
                softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
            }
            if (_softwareBitmapSource != null)
            {
                await _softwareBitmapSource.SetBitmapAsync(softwareBitmap);
            }
        }
    }

    private async Task CleanUpAsync()
    {
        if (FrameSourceGroupCombo != null)
        {
            FrameSourceGroupCombo.SelectionChanged -= FrameSourceGroupCombo_SelectionChanged;
        }

        if (_cameraHelper != null)
        {
            _cameraHelper.FrameArrived -= CameraHelper_FrameArrived!;
            await _cameraHelper.CleanUpAsync();
            _cameraHelper = null!;
        }

        _softwareBitmapSource?.Dispose();
    }
}

構文

// Creates a Camera Helper and gets video frames from an available frame source.
using CommunityToolkit.WinUI.Helpers.CameraHelper;

CameraHelper _cameraHelper = new CameraHelper();
var result = await _cameraHelper.InitializeAndStartCaptureAsync();

// Camera Initialization and Capture failed for some reason
if(result != CameraHelperResult.Success)
{
  // get error information
  var errorMessage = result.ToString();
}
else 
{
  // Subscribe to get frames as they arrive
  _cameraHelper.FrameArrived += CameraHelper_FrameArrived;
}

private void CameraHelper_FrameArrived(object sender, FrameEventArgs e)
{
  // Gets the current video frame
  VideoFrame currentVideoFrame  = e.VideoFrame;

  // Gets the software bitmap image
  SoftwareBitmap softwareBitmap = currentVideoFrame.SoftwareBitmap;
}

リソースの後処理

開発者は、必要に応じて CameraHelper リソースがクリーンアップされるようにする必要があります。 たとえば、CameraHelper が 1 つのページでのみ使用されている場合は、ページから離れるときに CameraHelper をクリーンアップしてください。

同様に、アプリの中断再開を必ず処理してください。再開時に一時停止時に CameraHelper をクリーンアップし、再初期化する必要があります。

CameraHelper.CleanupAsync() を呼び出して、すべての内部リソースをクリーンアップします。 完全な例については、サンプル アプリの「CameraHelper サンプル」ページを参照してください。

カメラ ヘルパーを使用して、特定のメディア フレーム ソース グループからビデオ フレームを取得する方法を示します。


using CommunityToolkit.WinUI.Helpers.CameraHelper;

var availableFrameSourceGroups = await CameraHelper.GetFrameSourceGroupsAsync();
if(availableFrameSourceGroups != null)
{
  CameraHelper cameraHelper = new CameraHelper() { FrameSourceGroup = availableFrameSourceGroups.FirstOrDefault() };
  var result = await cameraHelper.InitializeAndStartCaptureAsync();

  // Camera Initialization succeeded
  if(result == CameraHelperResult.Success)
  {
    // Subscribe to get frames as they arrive
    cameraHelper.FrameArrived += CameraHelper_FrameArrived;

    // Optionally set a different frame source format
    var newFormat = cameraHelper.FrameFormatsAvailable.Find((format) => format.VideoFormat.Width == 640);
    if (newFormat != null)
    {
      await cameraHelper.PreviewFrameSource.SetFormatAsync(newFormat);
    }
  }
}