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 }
  • 相关阅读:
    redis中save和bgsave区别
    go语言标准库
    numpy 学习:数组改变形状、副本和view
    Python 开始:变量、操作符、print()和type()
    numpy 学习:数据类型和空值
    Python 数据类型:布尔类型和None
    numpy 学习:数组的拼接、堆叠和拆分
    numpy 学习:数组的查找
    Databricks 第12篇:Notebook 工作流
    numpy 学习:通用函数(包含数学函数)
  • 原文地址:https://www.cnblogs.com/supperwu/p/7251572.html
Copyright © 2011-2022 走看看