Win10/UWP 扫描二维码

在Win10开发中,扫描二维码以及拍照都和以前的Windows 8.1 相同,是使用MediaCapture对象来获取图片或者视频预览数据,通过MediaCapture的CapturePhotoToStreamAsync()方法就可以拿到IRandomAccessStream流进行二维码解析或者做其他的图片操作,MediaCapture也提供了CapturePhotoToStorageFileAsync()方法来获取到IStorageFile流进行文件的操作。 
 
下面贴下代码展示下Win10中的扫描二维码,就不一一讲解了,和以前的Windows8.1的方法类似,解析二维码用的 zxing.NET 。

前台(需要注意的是用了Behaviors,记得添加 Behaviors SDK 的引用):

[csharp] view plain copy
 
  1. <Page.Resources>  
  2.     <Storyboard x:Name="LineStoryboard" AutoReverse="True" RepeatBehavior="Forever">  
  3.         <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="recScanning">  
  4.             <EasingDoubleKeyFrame KeyTime="0" Value="0"/>  
  5.             <EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="-269.94"/>  
  6.         </DoubleAnimationUsingKeyFrames>  
  7.     </Storyboard>  
  8. </Page.Resources>  
  9.    
  10. <Interactivity:Interaction.Behaviors>  
  11.     <Core:EventTriggerBehavior EventName="Loaded">  
  12.         <Media:ControlStoryboardAction Storyboard="{StaticResource LineStoryboard}"/>  
  13.     </Core:EventTriggerBehavior>  
  14. </Interactivity:Interaction.Behaviors>  
  15.    
  16. <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">  
  17.     <Grid x:Name="LayoutRoot" >  
  18.         <Grid x:Name="ContentPanel" >  
  19.    
  20.             <!--视频流预览-->  
  21.             <CaptureElement x:Name="VideoCapture"/>  
  22.    
  23.             <!--Tips-->  
  24.             <TextBlock x:Name="tbkTip" Foreground="White" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="36" Text="提示:请将二维码图案放置在取景框内"/>  
  25.    
  26.             <Grid Width="306" Height="306">  
  27.                 <Rectangle Width="3" Height="50" Fill="Red" HorizontalAlignment="Left" VerticalAlignment="Top"/>  
  28.                 <Rectangle Width="3" Height="50" Fill="Red" HorizontalAlignment="Right" VerticalAlignment="Top"/>  
  29.                 <Rectangle Width="3" Height="50" Fill="Red" HorizontalAlignment="Left" VerticalAlignment="Bottom"/>  
  30.                 <Rectangle Width="3" Height="50" Fill="Red" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>  
  31.                 <Rectangle Width="50" Height="3" Fill="Red" HorizontalAlignment="Left" VerticalAlignment="Top"/>  
  32.                 <Rectangle Width="50" Height="3" Fill="Red" HorizontalAlignment="Right" VerticalAlignment="Top"/>  
  33.                 <Rectangle Width="50" Height="3" Fill="Red" HorizontalAlignment="Left" VerticalAlignment="Bottom"/>  
  34.                 <Rectangle Width="50" Height="3" Fill="Red" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>  
  35.    
  36.                 <Rectangle x:Name="recScanning"  Margin="12,0,12,16" Height="2" RenderTransformOrigin="0.5,0.5" VerticalAlignment="Bottom" d:LayoutOverrides="Height">  
  37.                     <Rectangle.RenderTransform>  
  38.                         <CompositeTransform/>  
  39.                     </Rectangle.RenderTransform>  
  40.                     <Rectangle.Projection>  
  41.                         <PlaneProjection/>  
  42.                     </Rectangle.Projection>  
  43.                     <Rectangle.Fill>  
  44.                         <LinearGradientBrush EndPoint="0,0.5" StartPoint="1,0.5">  
  45.                             <GradientStop Color="#331CF106" Offset="0.15"/>  
  46.                             <GradientStop Color="#331CF106" Offset="0.85"/>  
  47.                             <GradientStop Color="#FF1CF106" Offset="0.5"/>  
  48.                         </LinearGradientBrush>  
  49.                     </Rectangle.Fill>  
  50.    
  51.                 </Rectangle>  
  52.             </Grid>  
  53.         </Grid>  
  54.         <!--扫描结果-->  
  55.         <TextBlock x:Name="tbkResult" Grid.Row="1" Foreground="White" VerticalAlignment="Top" TextWrapping="Wrap"  Margin="12,18" FontSize="25" Text="扫描结果:"/>  
  56.     </Grid>  
  57. </Grid>  
 
后台:
[csharp] view plain copy
 
  1. public sealed partial class MainPage : Page  
  2.   {  
  3.       private Result _result;  
  4.       private readonly MediaCapture _mediaCapture = new MediaCapture();  
  5.       private DispatcherTimer _timer;  
  6.       private bool IsBusy;  
  7.       public MainPage()  
  8.       {  
  9.           this.InitializeComponent();  
  10.       }  
  11.    
  12.       protected override void OnNavigatedTo(NavigationEventArgs e)  
  13.       {  
  14.           base.OnNavigatedTo(e);  
  15.           InitVideoCapture();  
  16.           InitVideoTimer();  
  17.       }  
  18.    
  19.       private void InitVideoTimer()  
  20.       {  
  21.           _timer = new DispatcherTimer();  
  22.           _timer.Interval = TimeSpan.FromSeconds(3);  
  23.           _timer.Tick += _timer_Tick;  
  24.           _timer.Start();  
  25.       }  
  26.    
  27.       private async void _timer_Tick(object sender, object e)  
  28.       {  
  29.           try  
  30.           {  
  31.               Debug.WriteLine(@"[INFO]开始扫描 -> " + DateTime.Now.ToString());  
  32.               if (!IsBusy)  
  33.               {  
  34.                   IsBusy = true;  
  35.                   IRandomAccessStream stream = new InMemoryRandomAccessStream();  
  36.                   await _mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);  
  37.    
  38.                   var writeableBmp = await ReadBitmap(stream, ".jpg");  
  39.    
  40.                   await Task.Factory.StartNew(async () => { await ScanBitmap(writeableBmp); });  
  41.               }  
  42.               IsBusy = false;  
  43.               await Task.Delay(50);  
  44.           }  
  45.           catch (Exception)  
  46.           {  
  47.               IsBusy = false;  
  48.           }  
  49.       }  
  50.    
  51.       /// <summary>  
  52.       /// 保存照片  
  53.       /// </summary>  
  54.       /// <param name="stream"></param>  
  55.       /// <param name="fileName"></param>  
  56.       /// <param name="photoOrientation"></param>  
  57.       /// <returns></returns>  
  58.       private static async Task ReencodeAndSavePhotoAsync(IRandomAccessStream stream, string fileName, PhotoOrientation photoOrientation = PhotoOrientation.Normal)  
  59.       {  
  60.           using (var inputStream = stream)  
  61.           {  
  62.               var decoder = await BitmapDecoder.CreateAsync(inputStream);  
  63.    
  64.               var file = await KnownFolders.PicturesLibrary.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);  
  65.    
  66.               using (var outputStream = await file.OpenAsync(FileAccessMode.ReadWrite))  
  67.               {  
  68.                   var encoder = await BitmapEncoder.CreateForTranscodingAsync(outputStream, decoder);  
  69.    
  70.                   // Set the orientation of the capture  
  71.                   var properties = new BitmapPropertySet { { "System.Photo.Orientation", new BitmapTypedValue(photoOrientation, PropertyType.UInt16) } };  
  72.                   await encoder.BitmapProperties.SetPropertiesAsync(properties);  
  73.    
  74.                   await encoder.FlushAsync();  
  75.               }  
  76.           }  
  77.       }  
  78.    
  79.       static Guid DecoderIDFromFileExtension(string strExtension)  
  80.       {  
  81.           Guid encoderId;  
  82.           switch (strExtension.ToLower())  
  83.           {  
  84.               case ".jpg":  
  85.               case ".jpeg":  
  86.                   encoderId = BitmapDecoder.JpegDecoderId;  
  87.                   break;  
  88.               case ".bmp":  
  89.                   encoderId = BitmapDecoder.BmpDecoderId;  
  90.                   break;  
  91.               case ".png":  
  92.               default:  
  93.                   encoderId = BitmapDecoder.PngDecoderId;  
  94.                   break;  
  95.           }  
  96.           return encoderId;  
  97.       }  
  98.          
  99.       public static Size MaxSizeSupported = new Size(4000, 3000);  
  100.    
  101.       /// <summary>  
  102.       /// 读取照片流 转为WriteableBitmap给二维码解码器  
  103.       /// </summary>  
  104.       /// <param name="fileStream"></param>  
  105.       /// <param name="type"></param>  
  106.       /// <returns></returns>  
  107.       public async static Task<WriteableBitmap> ReadBitmap(IRandomAccessStream fileStream, string type)  
  108.       {  
  109.           WriteableBitmap bitmap = null;  
  110.           try  
  111.           {  
  112.               Guid decoderId = DecoderIDFromFileExtension(type);  
  113.    
  114.               BitmapDecoder decoder = await BitmapDecoder.CreateAsync(decoderId, fileStream);  
  115.               BitmapTransform tf = new BitmapTransform();  
  116.    
  117.               uint width = decoder.OrientedPixelWidth;  
  118.               uint height = decoder.OrientedPixelHeight;  
  119.               double dScale = 1;  
  120.    
  121.               if (decoder.OrientedPixelWidth > MaxSizeSupported.Width || decoder.OrientedPixelHeight > MaxSizeSupported.Height)  
  122.               {  
  123.                   dScale = Math.Min(MaxSizeSupported.Width / decoder.OrientedPixelWidth, MaxSizeSupported.Height / decoder.OrientedPixelHeight);  
  124.                   width = (uint)(decoder.OrientedPixelWidth * dScale);  
  125.                   height = (uint)(decoder.OrientedPixelHeight * dScale);  
  126.    
  127.                   tf.ScaledWidth = (uint)(decoder.PixelWidth * dScale);  
  128.                   tf.ScaledHeight = (uint)(decoder.PixelHeight * dScale);  
  129.               }  
  130.    
  131.    
  132.               bitmap = new WriteableBitmap((int)width, (int)height);  
  133.    
  134.    
  135.    
  136.               PixelDataProvider dataprovider = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, tf,  
  137.                   ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage);  
  138.               byte[] pixels = dataprovider.DetachPixelData();  
  139.    
  140.               Stream pixelStream2 = bitmap.PixelBuffer.AsStream();  
  141.    
  142.               pixelStream2.Write(pixels, 0, pixels.Length);  
  143.               //bitmap.SetSource(fileStream);  
  144.           }  
  145.           catch  
  146.           {  
  147.           }  
  148.    
  149.           return bitmap;  
  150.       }  
  151.    
  152.       /// <summary>  
  153.       /// 解析二维码图片  
  154.       /// </summary>  
  155.       /// <param name="writeableBmp">图片</param>  
  156.       /// <returns></returns>  
  157.       private async Task ScanBitmap(WriteableBitmap writeableBmp)  
  158.       {  
  159.           try  
  160.           {  
  161.               var barcodeReader = new BarcodeReader  
  162.               {  
  163.                   AutoRotate = true,  
  164.                   Options = new ZXing.Common.DecodingOptions { TryHarder = true }  
  165.               };  
  166.               await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>  
  167.               {  
  168.                   _result = barcodeReader.Decode(writeableBmp);  
  169.               });  
  170.    
  171.    
  172.    
  173.               if (_result != null)  
  174.               {  
  175.                   Debug.WriteLine(@"[INFO]扫描到二维码:{result}   ->" + _result.Text);  
  176.                   await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>  
  177.                   {  
  178.                       tbkResult.Text = _result.Text;  
  179.                   });  
  180.               }  
  181.           }  
  182.           catch (Exception)  
  183.           {  
  184.           }  
  185.       }  
  186.    
  187.       private async void InitVideoCapture()  
  188.       {  
  189.           ///摄像头的检测  
  190.           var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Back);  
  191.    
  192.           if (cameraDevice == null)  
  193.           {  
  194.               Debug.WriteLine("No camera device found!");  
  195.               return;  
  196.           }  
  197.           var settings = new MediaCaptureInitializationSettings  
  198.           {  
  199.               StreamingCaptureMode = StreamingCaptureMode.Video,  
  200.               MediaCategory = MediaCategory.Other,  
  201.               AudioProcessing = Windows.Media.AudioProcessing.Default,  
  202.               VideoDeviceId = cameraDevice.Id  
  203.           };  
  204.           await _mediaCapture.InitializeAsync(settings);  
  205.           VideoCapture.Source = _mediaCapture;  
  206.           await _mediaCapture.StartPreviewAsync();  
  207.       }  
  208.    
  209.       private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)  
  210.       {  
  211.           var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);  
  212.    
  213.           DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);  
  214.    
  215.           return desiredDevice ?? allVideoDevices.FirstOrDefault();  
  216.       }  
  217.   }  
效果:
 

本文出自:53078485群大咖Aran

posted @ 2016-10-04 11:07  天涯海角路  阅读(405)  评论(0)    收藏  举报