UWP应用程序中的CapturePhotoToStorageFileAsync()非常慢

时间:2017-01-27 15:58:01

标签: c# performance uwp windows-10-mobile

我正在用C#编写一个UWP应用程序(通用Windows应用程序),用于运行O / S周年纪念版的Windows 10手机。我正在尝试使用该应用拍摄照片,然后处理照片。问题是应用程序需要很长时间才能拍照。第一张照片需要5到6秒,后续照片每张需要3秒。另一方面,同一手机中的内置相机应用程序只需1/2秒或更短时间拍照。显然我的应用程序有问题。我将其缩小为一个需要很长时间才能完成的命令 - 即CapturePhotoToStorageFileAsync()。

请注意,我的应用程序和内置的相机应用程序都将照片保存在图片库中(Windows Phone - >手机 - >图片)。唯一的区别是我的照片可以直接保存在"图片"夹。另一方面,内置的相机应用程序将照片保存在"图片\相机胶卷"夹。我怀疑这有什么不同。

我认为我的应用可能会将照片保存在云端存储中。但是当我从手机上拔下USB线时,我仍然遇到同样的问题,我已经关闭了手机上的WiFi(手机没有数据计划)。我已经验证了设置 - >系统 - >存储照片应保存在"本设备"。

手机的速度无关紧要,因为如上所述,内置的相机应用可以在同一部手机中快速拍摄照片。这意味着手机的硬件能够非常快速地拍摄照片。因此,这不是硬件问题。

该应用程序在调试器下或调试器外运行时遇到同样的问题。

当我在" Debug"中构建它时,应用程序会遇到同样的问题。模式或在"发布"模式。

我准备了一个简化版的应用程序供您审核。希望你能发现我没有注意到的错误。

MainPage.xaml中

    <Page
    x:Class="Checkout.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Checkout"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Loaded="OnLoaded">

   <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
      <Grid.RowDefinitions>
         <RowDefinition Height="4*" />
         <RowDefinition Height="*" />
         <RowDefinition Height="*" />
         <RowDefinition Height="*" />
      </Grid.RowDefinitions>
      <CaptureElement x:Name="captureElement"  Grid.Row="0" Stretch="Uniform" />
      <Button         x:Name="btnCapture"      Grid.Row="1" Content="Capture Photo" Click="btnCapture_OnClick" />
      <TextBlock      x:Name="lblMsg"          Grid.Row="2" Text="Show message here" />
      <Button         x:Name="btnTerminateApp" Grid.Row="3" Content="Terminate App" Click="btnTerminateApp_OnClick" />

   </Grid>
</Page>

MainPage.xaml.cs中

    using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Devices.Enumeration;                    // For DeviceInformation, DeviceClass.
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.Capture;                          // For MediaCapture.
using Windows.Media.Devices;                          // For FocusSettings, FocusMode, AutoFocusRange.
using Windows.Media.MediaProperties;                  // For ImageEncodingProperties.
using Windows.Storage;                                // For StorageFile.
using Windows.UI.Popups;                              // For MessageDialog().
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace Checkout
   {
   /// <summary>
   /// An empty page that can be used on its own or navigated to within a Frame.
   /// </summary>
   public sealed partial class MainPage : Page
      {
      private MediaCapture captureMgr { get; set; }

      public MainPage()
         {
         this.InitializeComponent();
         }

      private void OnLoaded( object sender, RoutedEventArgs e )
         {
         this.lblMsg.Text = "";

         // Create a new instance of MediaCapture and start the camera in preview mode.
         this.InitCapture();
         }

      private async void btnCapture_OnClick( object sender, RoutedEventArgs e )
         {
         // Acknowledge that the user has triggered a button to capture a barcode.
         this.lblMsg.Text = "-------";

         // Capture the photo from the camera to a storage-file.
         ImageEncodingProperties fmtImage = ImageEncodingProperties.CreateJpeg();
         StorageLibrary libPhoto = await StorageLibrary.GetLibraryAsync( KnownLibraryId.Pictures );
         StorageFile storefile =
            await libPhoto.SaveFolder.CreateFileAsync( "BarcodePhoto.jpg",
                                                       CreationCollisionOption.ReplaceExisting );
         await this.captureMgr.CapturePhotoToStorageFileAsync( fmtImage, storefile );

         // Tell the user that we have taken a picture.
         this.lblMsg.Text = "Picture taken";
         }

      private void btnTerminateApp_OnClick( object sender, RoutedEventArgs e )
         {
         this.ReleaseCapture();
         Application.Current.Exit();
         }

      private async void InitCapture()
         // Initialize everything about MediaCapture.
         {
         this.captureMgr = new MediaCapture();
         await this.captureMgr.InitializeAsync();

         // Use the lowest resolution in order to speed up the process.
         this.SetCaptureElementToMinResolution();

         // Start the camera preview.
         captureElement.Source = this.captureMgr;
         await this.captureMgr.StartPreviewAsync();

         // Ask the camera to auto-focus now.
         var focusControl = this.captureMgr.VideoDeviceController.FocusControl;
         var settings = new FocusSettings { Mode           = FocusMode.Continuous,
                                            AutoFocusRange = AutoFocusRange.FullRange };
         focusControl.Configure( settings );
         await focusControl.FocusAsync();

         #region Error handling
         MediaCaptureFailedEventHandler handler = (sender, e) =>
            {
             System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Run(async () =>
               {
               await new MessageDialog( "There was an error capturing the video from camera.", "Error" ).ShowAsync();
               });
            };

         this.captureMgr.Failed += handler;
         #endregion
         }

      private async void SetCaptureElementToMinResolution()
         // Set the CaptureElement to the minimum resolution that the device
         // can handle. We need to set it to lowest resolution in other to
         // speed up the process.
         {
         VideoEncodingProperties resolutionMin = null; 
         int nMinResolutionSoFar = -1;
         var lisResolution = this.captureMgr.VideoDeviceController.GetAvailableMediaStreamProperties( MediaStreamType.Photo );

         for( var i = 0; i< lisResolution.Count; i++ )
            {
            VideoEncodingProperties resCur = (VideoEncodingProperties)lisResolution[ i ];
            int nCurResolution = (int)( resCur.Width * resCur.Height );
            if (nMinResolutionSoFar == -1)
               {
               nMinResolutionSoFar = nCurResolution;
               resolutionMin       = resCur;
               }
            else if ( nMinResolutionSoFar > nCurResolution )
               {
               nMinResolutionSoFar = nCurResolution;
               resolutionMin       = resCur;
               }
            }

         await this.captureMgr.VideoDeviceController.SetMediaStreamPropertiesAsync( MediaStreamType.Photo, resolutionMin );
         }

      private async void ReleaseCapture()
         // Release the resources used for capturing photo.
         {
         try
            {
            captureElement.Source = null;
            await this.captureMgr.StopPreviewAsync();
            this.captureMgr.Dispose();
            }
         catch( Exception ex )
            {
            String sErrMsg = String.Concat( "Fail to release resources related to the ",
                                            "use of the camera. The error message is: ",
                                            ex.Message );
            await new MessageDialog( sErrMsg, "Error" ).ShowAsync();
            }
         }


      }
   }

如果您想在计算机中试用此应用程序,请创建一个新项目,并在项目中启用以下功能:Internet(默认),麦克风和网络摄像头。然后从上面显示的那两个文件中复制代码。

请尝试一下,让我知道你的电脑/手机是怎么回事。

我的手机是Microsoft Lumia 550,Windows 10 Mobile,1GB RAM,版本1607,操作系统版本:10.0.14393.693。

提前感谢您的帮助。

杰伊陈

0 个答案:

没有答案