How To Scan QRCode For UWP (3)

这一节主要介绍如何去设置MediaCapture拍照的分辨率。

MediaCapture 包含一个 VideoDeviceController对象,凭借它可以控制摄像头的很多设置,其中包括设置拍照的分辨率。 首先通过GetAvailableMediaStreamProperties方法来获取设备所支持的 Encoding Properties,要注意的是即使你指定了MediaStreamType为Photo,这个API也会有可能同时返回 ImageEncodingProperties /VideoEncodingProperties对象。 因此我们在比较设备支持的Encoding Properties,需要手动去将它强制转换为 ImageEncodingProperties/VideoEncodingProperties对象。 此外还需要找到宽高比非常接近我们所期望的分辨率,误差范围在0.015之内。示例代码使用的宽高比为16:9,常见的还有4:3。

比较奇怪的IMediaEncodingProperties没有声明Width/Height属性,让代码写的有点啰嗦。

 实现代码如下:

 1  uint desiredWidth = 1920;
 2         uint desiredHeight = 1080;
 3 
 4         private async Task<uint[]> SetResolution(MediaStreamType streamType)
 5         {
 6             //Get the supported encoding properties. 
 7             var mediaStreamProperties = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(streamType);
 8             if (mediaStreamProperties == null || mediaStreamProperties.Count == 0)
 9                 return null;
10 
11             var imageEncodingProperty = mediaStreamProperties.Select(e => e as ImageEncodingProperties)
12                                                              .Where(e => e != null && e.Width <= desiredWidth
13                                                                         && e.Height < desiredHeight && IsMatchingRatio(e))
14                                                              .OrderByDescending(e => e.Width * e.Height)
15                                                              .FirstOrDefault();
16             if (imageEncodingProperty != null)
17             {
18                 await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(streamType, imageEncodingProperty);
19                 return new uint[] { imageEncodingProperty.Width, imageEncodingProperty.Height };
20             }
21 
22             var videoEncodingProperty = mediaStreamProperties.Select(e => e as VideoEncodingProperties)
23                                                            .Where(e => e != null && e.Width <= desiredWidth
24                                                                       && e.Height < desiredHeight && IsMatchingRatio(e))
25                                                            .OrderByDescending(e => e.Width * e.Height)
26                                                            .FirstOrDefault();
27             if (videoEncodingProperty != null)
28             {
29                 await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(streamType, videoEncodingProperty);
30                 return new uint[] { videoEncodingProperty.Width, videoEncodingProperty.Height };
31             }
32 
33             return null;
34         }
35 
36         private bool IsMatchingRatio(ImageEncodingProperties e)
37         {
38             double tolerance = 0.015;
39             return Math.Abs(GetAspectRatio(e.Height, e.Width) - GetAspectRatio(desiredHeight, desiredWidth)) < tolerance;
40         }
41 
42         private bool IsMatchingRatio(VideoEncodingProperties e)
43         {
44             double tolerance = 0.015;
45             return Math.Abs(GetAspectRatio(e.Height, e.Width) - GetAspectRatio(desiredHeight, desiredWidth)) < tolerance;
46         }
47 
48         private double GetAspectRatio(uint heiht, uint width)
49         {
50             return Math.Round((heiht != 0) ? (width / (double)heiht) : double.NaN, 2);
51         }


另外我决定采用的 LowLagPhotoCapture 来拍摄照片,可以调用 MediaCapture.PrepareLowLagPhotoCaptureAsync 初始化 LowLagPhotoCapture,初始化成功后就可以得到 LowLagPhotoCapture 对象。
然后使用 CaptureAsync 来捕获低快门滞后照片,拍照成功后得到一个 CapturedPhoto 对象,该对象包含两个 CapturedFrame 对象,其中一个返回的是缩略图,另外一个正是我们需要的。
最后使用 FinishAsync 释放 LowLagPhotoCapture 对象和资源,LowLagPhotoCapture 对象被释放后,再次拍照需要再次初始化。

 1 private LowLagPhotoCapture lowLagPhotoCapture;
 2 ...
 3 // Initialize MediaCapture
 4                 try
 5                 {
 6                     await mediaCapture.InitializeAsync(settings);
 7                     var imageEnCodingProperties = ImageEncodingProperties.CreatePng();
 8                     var resolution = await SetResolution(MediaStreamType.Photo);
 9                     if (resolution != null)
10                     {
11                         imageEnCodingProperties.Width = resolution[0];
12                         imageEnCodingProperties.Height = resolution[1];
13                     }
14                     lowLagPhotoCapture = await mediaCapture.PrepareLowLagPhotoCaptureAsync(imageEnCodingProperties);
15                     isInitialized = true;
16                 }
17                 catch (UnauthorizedAccessException)
18                 {
19                     await ShowMessage("Denied access to the camera.");
20                 }
21                 catch (Exception ex)
22                 {
23                     await ShowMessage("Exception when init MediaCapture. " + ex.Message);
24                 }
25 ...


下一节将介绍采用ZXing.UWP来实现扫描二维码的功能。

posted @ 2017-08-02 11:47  supperwu  阅读(332)  评论(0编辑  收藏  举报