前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Windows Community Toolkit: 使用CameraPreview拍照

Windows Community Toolkit: 使用CameraPreview拍照

作者头像
Edi Wang
发布2019-07-08 19:23:34
5520
发布2019-07-08 19:23:34
举报
文章被收录于专栏:汪宇杰博客汪宇杰博客

在UWP应用里,如果我们需要调用设备的摄像头拍照并保存到文件,这曾经是比较复杂的。开发者需要了解许多知识,也要写一定量代码才能完成(就像你可以从微软样例代码(https://github.com/Microsoft/Windows-universal-samples)中找到的Camera相关例子那样)。实际上,在许多情况下,我们仅需要用最简单的默认摄像头选项来拍照。这种场合里我们的关注点在应用逻辑本身,而不需要花费数个小时在如何调通摄像头代码上。

现在,有了Windows Community Toolkit,这件事情得十分简单。

CameraPreview控件提供了一个非常直接的方式让我们操作摄像头,而不用了解其中的细节原理。

1

使用NuGet安装

代码语言:javascript
复制
PM> Install-Package Microsoft.Toolkit.Uwp.UI.Controls

2

在你的UWP应用中启用WebCam权限

你可以直接从Visual Studio的界面中打开Package.appxmanifest文件来操作

也可以手工编辑这个文件的代码,加入DeviceCapability节点

代码语言:javascript
复制
<Capabilities>
  <Capability Name="internetClient" />
  <uap:Capability Name="picturesLibrary" />
  <DeviceCapability Name="webcam" />
</Capabilities>

3

创建应用界面

首先,在你的Page或者UserControl里加入下面的命名空间

代码语言:javascript
复制
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"

然后加入CameraPreview控件,这仅需要一行XAML代码

代码语言:javascript
复制
<controls:CameraPreview x:Name="CameraPreviewControl" PreviewFailed="CameraPreviewControl_OnPreviewFailed" />

PreviewFailed事件不是必须的,但建议加上,这样可以提高用户体验也便于debug

为了演示,我添加了3个按钮

代码语言:javascript
复制
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="20,0,0,0">
    <Button Content="Start" x:Name="BtnStart" Margin="0,0,0,10" Click="BtnStart_Click" />
    <Button Content="Stop" x:Name="Stop" Margin="0,0,0,10" Click="Stop_Click"/>
    <Button Content="Capture" x:Name="BtnCapture" Click="BtnCapture_Click" />
</StackPanel>

4

代码

首先,我们完成PreviewFailed事件处理。我想要在摄像头启动失败的情况下给用户弹出一个错误消息的对话框:

代码语言:javascript
复制
private async void CameraPreviewControl_OnPreviewFailed(object sender, PreviewFailedEventArgs e)
{
    await new MessageDialog(e.Error, "ERROR").ShowAsync();
}

注意,async void仅仅用于像这样的事件处理函数,其他地方请用async Task

现在让我们启动摄像头

代码语言:javascript
复制
private async void BtnStart_Click(object sender, RoutedEventArgs e)
{
    await CameraPreviewControl.StartAsync();
}

到这部为止,你已经能够看到正常工作的界面了,摄像头的画面也会出现在你的应用里。

要停止摄像头,仅需调用Stop()方法

代码语言:javascript
复制
private void Stop_Click(object sender, RoutedEventArgs e)
{
    CameraPreviewControl.Stop();
}

那么我们如何拍照并保存到文件系统呢?我们需要另一个事件处理函数:

CameraPreviewControl.CameraHelper.FrameArrived

这个例子里,我把事件处理代码加在Start按钮里:

代码语言:javascript
复制
private async void BtnStart_Click(object sender, RoutedEventArgs e)
{
    await CameraPreviewControl.StartAsync();
    CameraPreviewControl.CameraHelper.FrameArrived += CameraPreviewControl_FrameArrived;
}

在事件处理函数中,我想要把当前的摄像头画面保存到一个私有字段里:

代码语言:javascript
复制
private VideoFrame _currentVideoFrame;
private void CameraPreviewControl_FrameArrived(object sender, FrameEventArgs e)
{
    _currentVideoFrame = e.VideoFrame;
}

现在当我们点击Capture按钮,我们就把当前的这帧画面保存到本地文件系统。摄像头的图形是用SoftwareBitmap对象来表示的。我们能够通过_currentVideoFrame?.SoftwareBitmap来访问到。

让用户选择文件保存的位置,我们需要用FileSavePicker,它会返回一个StorageFile对象,表示我们要保存的照片文件。你也可以选择文件格式,我这里选择照片最常用的JPG格式。

代码语言:javascript
复制
private async void BtnCapture_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);
        }


        var savePicker = new FileSavePicker
        {
            SuggestedStartLocation = PickerLocationId.Desktop
        };
        savePicker.FileTypeChoices.Add("Jpg Image", new[] { ".jpg" });
        savePicker.SuggestedFileName = "example.jpg";
        StorageFile sFile = await savePicker.PickSaveFileAsync();


        await WriteToStorageFile(softwareBitmap, sFile);
    }
}

最后一步,把SoftwareBitmap保存到StorageFile的代码如下

代码语言:javascript
复制
private static async Task<FileUpdateStatus> WriteToStorageFile(SoftwareBitmap bitmap, StorageFile file)
{
    StorageFile sFile = file;
    if (sFile != null)
    {
        CachedFileManager.DeferUpdates(sFile);


        using (var fileStream = await sFile.OpenAsync(FileAccessMode.ReadWrite))
        {
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, fileStream);
            encoder.SetSoftwareBitmap(bitmap);
            await encoder.FlushAsync();
        }


        FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(sFile);
        return status;
    }
    return FileUpdateStatus.Failed;
}

Tips

如果你想要了解CameraPreivew控件,可以点击官网GitHub了解一下:

https://github.com/Microsoft/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/CameraPreview

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 汪宇杰博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档