zoukankan      html  css  js  c++  java
  • How To Scan QRCode For UWP (2)

    这篇随笔主要介绍照相预览功能,重要使用的是MediaCapture对象,MediaCapture对象还可以用来处理录音和录制视频,本文只讨论照相功能。

    1:查找摄像头

    后置摄像头优先,找不到后置摄像头就返回找到的可用的摄像头列表的第一个。

     1 /// <summary>
     2         /// Queries the available video capture devices to try and find one mounted on the desired panel.
     3         /// </summary>
     4         /// <param name="desiredPanel">The panel on the device that the desired camera is mounted on.</param>
     5         /// <returns>A DeviceInformation instance with a reference to the camera mounted on the desired panel if available,
     6         ///          any other camera if not, or null if no camera is available.</returns>
     7         private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
     8         {
     9             // Get available devices for capturing pictures.
    10             var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
    11 
    12             // Get the desired camera by panel.
    13             DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
    14 
    15             // If there is no device mounted on the desired panel, return the first device found.
    16             return desiredDevice ?? allVideoDevices.FirstOrDefault();
    17         }

    2:初始Camera

    首先需要创建一个MediaCapture实例,MediaCapture类位于Windows.Media.Capture命名空间。然后需要允许App访问Camera,需要修改Package.appxmanifest文件,选择Capabilities Tab 勾选中 Microphone  & Webcam。 调用MediaCapture.InitializeAsync方法并指定要初始化上一步找到的Camera。

    如果MediaCapture使用的过程中抛出了Error,此时就需要释放MediaCapture资源,可以在MediaCapture的Failed事件来处理。

    此外还使用了isInitialized 标志位来判断是否已经成功初始化了Camera。

    3:预览

    需要调用MediaCapture.StartPreviewAsync(),在预览过程中使用了DisplayRequest对象RequestActive方法来防止设备屏幕休眠。
    同样使用了isPreviewing来判断Camera是否处于预览状态。
    经过三个步骤后,就可以正常预览Camera了。

    MediaCapture对象的StopPreviewAsync方法用来停止预览,停止预览后,设备就可以允许睡眠了,需要调用DisplayRequest对象RequestRelease。

    4:其他

    当App转换为Suspending状态时,先使用SuspendingOperation.GetDeferral()请求延迟挂起操作,释放完MediaCapture资源,最后调用SuspendingDeferral.Complete() 通知操作系统App已经准好被挂起了。当App转换为Resuming状态时,需要再次开启Camera。
    可以分别处理Application.Current.Suspending跟Application.Current.Resuming事件。

    附上代码:

      1 using System;
      2 using System.Linq;
      3 using System.Threading.Tasks;
      4 using Windows.ApplicationModel;
      5 using Windows.Devices.Enumeration;
      6 using Windows.Media.Capture;
      7 using Windows.System.Display;
      8 using Windows.UI.Core;
      9 using Windows.UI.Popups;
     10 using Windows.UI.Xaml;
     11 using Windows.UI.Xaml.Controls;
     12 using Windows.UI.Xaml.Navigation;
     13 
     14 // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
     15 
     16 namespace ScanQRCode
     17 {
     18     /// <summary>
     19     /// An empty page that can be used on its own or navigated to within a Frame.
     20     /// </summary>
     21     public sealed partial class MainPage : Page
     22     {
     23         const int borderThickness = 5;
     24 
     25         private MediaCapture mediaCapture;
     26         private bool isInitialized = false;
     27         private bool isPreviewing = false;
     28 
     29         // Prevent the screen from sleeping while the camera is running.
     30         private readonly DisplayRequest displayRequest = new DisplayRequest();
     31 
     32         public MainPage()
     33         {
     34             this.InitializeComponent();
     35 
     36             // Useful to know when to initialize/clean up the camera
     37             Application.Current.Suspending += Application_Suspending;
     38             Application.Current.Resuming += Application_Resuming;
     39         }
     40 
     41         /// <summary>
     42         /// Occures on app suspending. Stops camera if initialized.
     43         /// </summary>
     44         /// <param name="sender"></param>
     45         /// <param name="e"></param>
     46         private async void Application_Suspending(object sender, SuspendingEventArgs e)
     47         {
     48             // Handle global application events only if this page is active.
     49             if (Frame.CurrentSourcePageType == typeof(MainPage))
     50             {
     51                 var deferral = e.SuspendingOperation.GetDeferral();
     52 
     53                 await CleanupCameraAsync();
     54 
     55                 deferral.Complete();
     56             }
     57         }
     58 
     59         /// <summary>
     60         /// Occures on app resuming. Initializes camera if available.
     61         /// </summary>
     62         /// <param name="sender"></param>
     63         /// <param name="o"></param>
     64         private async void Application_Resuming(object sender, object o)
     65         {
     66             // Handle global application events only if this page is active
     67             if (Frame.CurrentSourcePageType == typeof(MainPage))
     68             {
     69                 await StartCameraAsync();
     70             }
     71         }
     72 
     73         private void InitFocusRec()
     74         {
     75             leftTopBorder.BorderThickness = new Thickness(borderThickness, borderThickness, 0, 0);
     76             rightTopBorder.BorderThickness = new Thickness(0, borderThickness, borderThickness, 0);
     77             leftBottomBorder.BorderThickness = new Thickness(borderThickness, 0, 0, borderThickness);
     78             rightBottomBorder.BorderThickness = new Thickness(0, 0, borderThickness, borderThickness);
     79 
     80             var borderLength = 20;
     81             leftTopBorder.Width = leftTopBorder.Height = borderLength;
     82             rightTopBorder.Width = rightTopBorder.Height = borderLength;
     83             leftBottomBorder.Width = leftBottomBorder.Height = borderLength;
     84             rightBottomBorder.Width = rightBottomBorder.Height = borderLength;
     85 
     86             var focusRecLength = Math.Min(ActualWidth / 2, ActualHeight / 2);
     87             scanGrid.Width = scanGrid.Height = focusRecLength;
     88             scanCavas.Width = scanCavas.Height = focusRecLength;
     89 
     90             scanStoryboard.Stop();
     91             scanLine.X2 = scanCavas.Width - 20;
     92             scanAnimation.To = scanCavas.Height;
     93 
     94             scanStoryboard.Begin();
     95         }
     96 
     97         private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
     98         {
     99             InitFocusRec();
    100         }
    101 
    102         protected override async void OnNavigatedTo(NavigationEventArgs e)
    103         {
    104             await StartCameraAsync();
    105         }
    106 
    107         private async Task StartCameraAsync()
    108         {
    109             if (!isInitialized)
    110             {
    111                 await InitializeCameraAsync();
    112             }
    113 
    114             if (isInitialized)
    115             {
    116                 PreviewControl.Visibility = Visibility.Visible;
    117             }
    118         }
    119 
    120         /// <summary>
    121         /// Queries the available video capture devices to try and find one mounted on the desired panel.
    122         /// </summary>
    123         /// <param name="desiredPanel">The panel on the device that the desired camera is mounted on.</param>
    124         /// <returns>A DeviceInformation instance with a reference to the camera mounted on the desired panel if available,
    125         ///          any other camera if not, or null if no camera is available.</returns>
    126         private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
    127         {
    128             // Get available devices for capturing pictures.
    129             var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
    130 
    131             // Get the desired camera by panel.
    132             DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
    133 
    134             // If there is no device mounted on the desired panel, return the first device found.
    135             return desiredDevice ?? allVideoDevices.FirstOrDefault();
    136         }
    137 
    138         /// Initializes the MediaCapture
    139         /// </summary>
    140         private async Task InitializeCameraAsync()
    141         {
    142             if (mediaCapture == null)
    143             {
    144                 // Attempt to get the back camera if one is available, but use any camera device if not.
    145                 var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Back);
    146 
    147                 if (cameraDevice == null)
    148                 {
    149                     //No camera device!
    150                     return;
    151                 }
    152 
    153                 // Create MediaCapture and its settings.
    154                 mediaCapture = new MediaCapture();
    155 
    156                 // Register for a notification when something goes wrong
    157                 mediaCapture.Failed += MediaCapture_Failed;
    158 
    159                 var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
    160 
    161                 // Initialize MediaCapture
    162                 try
    163                 {
    164                     await mediaCapture.InitializeAsync(settings);
    165                     isInitialized = true;
    166                 }
    167                 catch (UnauthorizedAccessException)
    168                 {
    169                     await ShowMessage("Denied access to the camera.");
    170                 }
    171                 catch (Exception ex)
    172                 {
    173                     await ShowMessage("Exception when init MediaCapture. " + ex.Message);
    174                 }
    175 
    176                 // If initialization succeeded, start the preview.
    177                 if (isInitialized)
    178                 {
    179                     await StartPreviewAsync();
    180                 }
    181             }
    182         }
    183 
    184         /// <summary>
    185         /// Starts the preview after making a request to keep the screen on and unlocks the UI.
    186         /// </summary>
    187         private async Task StartPreviewAsync()
    188         {
    189             // Prevent the device from sleeping while the preview is running.
    190             displayRequest.RequestActive();
    191 
    192             // Set the preview source in the UI.
    193             PreviewControl.Source = mediaCapture;
    194             // Start the preview.
    195             try
    196             {
    197                 await mediaCapture.StartPreviewAsync();
    198                 isPreviewing = true;
    199             }
    200             catch (Exception ex)
    201             {
    202                 await ShowMessage("Exception starting preview." + ex.Message);
    203             }
    204         }
    205 
    206 
    207         /// <summary>
    208         /// Handles MediaCapture failures. Cleans up the camera resources.
    209         /// </summary>
    210         /// <param name="sender"></param>
    211         /// <param name="errorEventArgs"></param>
    212         private async void MediaCapture_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs)
    213         {
    214             await CleanupCameraAsync();
    215         }
    216 
    217 
    218         /// <summary>
    219         /// Cleans up the camera resources (after stopping the preview if necessary) and unregisters from MediaCapture events.
    220         /// </summary>
    221         private async Task CleanupCameraAsync()
    222         {
    223             if (isInitialized)
    224             {
    225                 if (isPreviewing)
    226                 {
    227                     // The call to stop the preview is included here for completeness, but can be
    228                     // safely removed if a call to MediaCapture.Dispose() is being made later,
    229                     // as the preview will be automatically stopped at that point
    230                     await StopPreviewAsync();
    231                 }
    232 
    233                 isInitialized = false;
    234             }
    235 
    236             if (mediaCapture != null)
    237             {
    238                 mediaCapture.Failed -= MediaCapture_Failed;
    239                 mediaCapture.Dispose();
    240                 mediaCapture = null;
    241             }
    242         }
    243 
    244         /// <summary>
    245         /// Stops the preview and deactivates a display request, to allow the screen to go into power saving modes, and locks the UI
    246         /// </summary>
    247         /// <returns></returns>
    248         private async Task StopPreviewAsync()
    249         {
    250             try
    251             {
    252                 isPreviewing = false;
    253                 await mediaCapture.StopPreviewAsync();
    254             }
    255             catch (Exception ex)
    256             {
    257                 // Use the dispatcher because this method is sometimes called from non-UI threads.
    258                 await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
    259                 {
    260                     await ShowMessage("Exception stopping preview. " + ex.Message);
    261                 });
    262             }
    263 
    264             // Use the dispatcher because this method is sometimes called from non-UI threads.
    265             await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    266             {
    267                 PreviewControl.Source = null;
    268 
    269                 // Allow the device to sleep now that the preview is stopped.
    270                 displayRequest.RequestRelease();
    271             });
    272         }
    273 
    274         private async Task ShowMessage(string message)
    275         {
    276             var messageDialog = new MessageDialog(message);
    277             await messageDialog.ShowAsync();
    278         }
    279     }
    280 }
  • 相关阅读:
    BEC listen and translation exercise 44
    中译英12
    BEC listen and translation exercise 43
    中译英11
    BEC listen and translation exercise 42
    中译英10
    BEC listen and translation exercise 41
    中译英9
    BEC listen and translation exercise 40
    中译英8
  • 原文地址:https://www.cnblogs.com/supperwu/p/7251572.html
Copyright © 2011-2022 走看看