Example #1
0
		/// <summary>
		/// Continuously look for a QR code
		/// NOTE: this method won't work if recording is enabled ('hey Cortana, start recording' thing).
		/// </summary>
		public static async Task<string> ReadAsync(CancellationToken token = default(CancellationToken))
		{
			var mediaCapture = new MediaCapture();
			await mediaCapture.InitializeAsync();
			await mediaCapture.AddVideoEffectAsync(new MrcVideoEffectDefinition(), MediaStreamType.Photo);

			var reader = new BarcodeReader();
			reader.Options.TryHarder = false;

			while (!token.IsCancellationRequested)
			{
				var imgFormat = ImageEncodingProperties.CreateJpeg();
				using (var ras = new InMemoryRandomAccessStream())
				{
					await mediaCapture.CapturePhotoToStreamAsync(imgFormat, ras);
					var decoder = await BitmapDecoder.CreateAsync(ras);
					using (var bmp = await decoder.GetSoftwareBitmapAsync())
					{
						Result result = await Task.Run(() =>
							{
								var source = new SoftwareBitmapLuminanceSource(bmp);
								return reader.Decode(source);
							});
						if (!string.IsNullOrEmpty(result?.Text))
							return result.Text;
					}
				}
				await Task.Delay(DelayBetweenScans);
			}
			return null;
		}
        public async Task StartScanningAsync(Action<ZXing.Result> scanCallback, MobileBarcodeScanningOptions options = null)
        {
            if (stopping)
                return;

            isAnalyzing = true;
            ScanCallback = scanCallback;
            ScanningOptions = options ?? MobileBarcodeScanningOptions.Default;

            topText.Text = TopText ?? string.Empty;
            bottomText.Text = BottomText ?? string.Empty;

            if (UseCustomOverlay)
            {
                gridCustomOverlay.Children.Clear();
                if (CustomOverlay != null)
                    gridCustomOverlay.Children.Add(CustomOverlay);

                gridCustomOverlay.Visibility = Visibility.Visible;
                gridDefaultOverlay.Visibility = Visibility.Collapsed;
            }
            else
            {
                gridCustomOverlay.Visibility = Visibility.Collapsed;
                gridDefaultOverlay.Visibility = Visibility.Visible;
            }

            // Find which device to use
            var preferredCamera = await this.GetFilteredCameraOrDefaultAsync(ScanningOptions);            
            mediaCapture = new MediaCapture();
            
            // Initialize the capture with the settings above
            await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings()
            {
                StreamingCaptureMode = StreamingCaptureMode.Video,
                VideoDeviceId = preferredCamera.Id
            });

            // Set the capture element's source to show it in the UI
            captureElement.Source = mediaCapture;

            // Start the preview
            await mediaCapture.StartPreviewAsync();
            
            // Get all the available resolutions for preview
            var availableProperties = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
            var availableResolutions = new List<CameraResolution>();
            foreach (var ap in availableProperties)
            {
                var vp = (VideoEncodingProperties)ap;
                System.Diagnostics.Debug.WriteLine("Camera Preview Resolution: {0}x{1}", vp.Width, vp.Height);
                availableResolutions.Add(new CameraResolution { Width = (int)vp.Width, Height = (int)vp.Height });                
            }
            CameraResolution previewResolution = null;
            if (ScanningOptions.CameraResolutionSelector != null)
                previewResolution = ScanningOptions.CameraResolutionSelector(availableResolutions);

            // If the user did not specify a resolution, let's try and find a suitable one
            if (previewResolution == null)
            {
                // Loop through all supported sizes
                foreach (var sps in availableResolutions)
                {
                    // Find one that's >= 640x360 but <= 1000x1000
                    // This will likely pick the *smallest* size in that range, which should be fine
                    if (sps.Width >= 640 && sps.Width <= 1000 && sps.Height >= 360 && sps.Height <= 1000)
                    {
                        previewResolution = new CameraResolution
                        {
                            Width = sps.Width,
                            Height = sps.Height
                        };
                        break;
                    }
                }
            }

            if (previewResolution == null)
                previewResolution = availableResolutions.LastOrDefault();

            System.Diagnostics.Debug.WriteLine("Using Preview Resolution: {0}x{1}", previewResolution.Width, previewResolution.Height);

            // Find the matching property based on the selection, again
            var chosenProp = availableProperties.FirstOrDefault(ap => ((VideoEncodingProperties)ap).Width == previewResolution.Width && ((VideoEncodingProperties)ap).Height == previewResolution.Height);
            
            // Set the selected resolution
            await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, chosenProp);

            await SetPreviewRotationAsync();

            captureElement.Stretch = Stretch.UniformToFill;

            // Get our preview properties
            var previewProperties = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
            
            // Setup a frame to use as the input settings
            var destFrame = new VideoFrame(Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height);

            var zxing = ScanningOptions.BuildBarcodeReader();

            timerPreview = new Timer(async (state) => {
                if (stopping)
                    return;                               
                if (mediaCapture == null || mediaCapture.CameraStreamState != Windows.Media.Devices.CameraStreamState.Streaming)
                    return;
                if (processing)
                    return;
                if (!isAnalyzing)
                    return;

                processing = true;

                SoftwareBitmapLuminanceSource luminanceSource = null;

                try
                {

                    // Get preview 
                    var frame = await mediaCapture.GetPreviewFrameAsync(destFrame);

                    // Create our luminance source
                    luminanceSource = new SoftwareBitmapLuminanceSource(frame.SoftwareBitmap);

                } catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("GetPreviewFrame Failed: {0}", ex);
                }

                ZXing.Result result = null;

                try
                {
                    // Try decoding the image
                    if (luminanceSource != null)
                        result = zxing.Decode(luminanceSource);
                }
                catch (Exception ex)
                {
                    
                }

                // Check if a result was found
                if (result != null && !string.IsNullOrEmpty (result.Text))
                {
                    if (!ContinuousScanning)
                        await StopScanningAsync();
                    LastScanResult = result;
                    ScanCallback(result);                    
                }

                processing = false;
                         
            }, null, TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(200));           
        }
        async private void beginCapture()
        {
            ZXing.Mobile.MobileBarcodeScanningOptions ScanningOptions = MobileBarcodeScanningOptions.Default;
            var zxing = ScanningOptions.BuildBarcodeReader();
            SoftwareBitmapLuminanceSource luminanceSource = null;

            // Capture the preview frame, analyzem repeat until a result or cancel
            while (result == null && !hasBeenCancelled)
            {
                var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)capturePreview.ActualWidth, (int)capturePreview.ActualHeight);
                using (var frame = await mediaCapture.GetPreviewFrameAsync(videoFrame))
                {
                    try
                    {
                        // Create our luminance source
                        luminanceSource = new SoftwareBitmapLuminanceSource(frame.SoftwareBitmap);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine("GetPreviewFrame Failed: {0}", ex);
                    }

                    try
                    {
                        zxing.Options.TryHarder = true;
                        // Try decoding the image
                        if (luminanceSource != null)
                            result = zxing.Decode(luminanceSource);
                    }
                    catch (Exception ex)
                    {

                    }
                }

                if (result != null)
                {
                    if(App.APP_SETTINGS.UPCFormatsEnabled.Where(f => f == result.BarcodeFormat).Count() > 0 || App.APP_SETTINGS.UPCFormatsEnabled.Where(f => f == ZXing.BarcodeFormat.All_1D).Count() > 0)
                        alert.Play();                            
                }
            }
        }
        public async Task StartScanningAsync(Action <ZXing.Result> scanCallback, MobileBarcodeScanningOptions options = null)
        {
            if (stopping)
            {
                var error = "Camera is closing";
                OnScannerError?.Invoke(new[] { error });
                return;
            }


            displayRequest.RequestActive();

            isAnalyzing     = true;
            ScanCallback    = scanCallback;
            ScanningOptions = options ?? MobileBarcodeScanningOptions.Default;

            topText.Text    = TopText ?? string.Empty;
            bottomText.Text = BottomText ?? string.Empty;

            if (UseCustomOverlay)
            {
                gridCustomOverlay.Children.Clear();
                if (CustomOverlay != null)
                {
                    gridCustomOverlay.Children.Add(CustomOverlay);
                }

                gridCustomOverlay.Visibility  = Visibility.Visible;
                gridDefaultOverlay.Visibility = Visibility.Collapsed;
            }
            else
            {
                gridCustomOverlay.Visibility  = Visibility.Collapsed;
                gridDefaultOverlay.Visibility = Visibility.Visible;
            }

            // Find which device to use
            var preferredCamera = await GetFilteredCameraOrDefaultAsync(ScanningOptions);

            if (preferredCamera == null)
            {
                var error = "No camera available";
                System.Diagnostics.Debug.WriteLine(error);
                isMediaCaptureInitialized = false;
                OnScannerError?.Invoke(new[] { error });
                return;
            }

            if (preferredCamera.EnclosureLocation == null || preferredCamera.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Unknown)
            {
                // No information on the location of the camera, assume it's an external camera, not integrated on the device.
                externalCamera = true;
            }
            else
            {
                // Camera is fixed on the device.
                externalCamera = false;

                // Only mirror the preview if the camera is on the front panel.
                mirroringPreview = preferredCamera.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front;
            }

            mediaCapture = new MediaCapture();

            // Initialize the capture with the settings above
            try
            {
                await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings
                {
                    StreamingCaptureMode = StreamingCaptureMode.Video,
                    VideoDeviceId        = preferredCamera.Id
                });

                isMediaCaptureInitialized = true;
            }
            catch (UnauthorizedAccessException)
            {
                System.Diagnostics.Debug.WriteLine("Denied access to the camera");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Exception when init MediaCapture: {0}", ex);
            }

            if (!isMediaCaptureInitialized)
            {
                var error = "Unexpected error on Camera initialisation";
                OnScannerError?.Invoke(new[] { error });
                return;
            }


            // Set the capture element's source to show it in the UI
            captureElement.Source        = mediaCapture;
            captureElement.FlowDirection = mirroringPreview ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;

            try
            {
                // Start the preview
                await mediaCapture.StartPreviewAsync();
            }
            catch (Exception ex)
            {
                var error = "Unexpected error on Camera initialisation";
                OnScannerError?.Invoke(new[] { error });
                return;
            }

            if (mediaCapture.CameraStreamState == CameraStreamState.Streaming)
            {
                OnCameraInitialized?.Invoke();
            }

            // Get all the available resolutions for preview
            var availableProperties  = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
            var availableResolutions = new List <CameraResolution>();

            foreach (var ap in availableProperties)
            {
                var vp = (VideoEncodingProperties)ap;
                System.Diagnostics.Debug.WriteLine("Camera Preview Resolution: {0}x{1}", vp.Width, vp.Height);
                availableResolutions.Add(new CameraResolution {
                    Width = (int)vp.Width, Height = (int)vp.Height
                });
            }
            CameraResolution previewResolution = null;

            if (ScanningOptions.CameraResolutionSelector != null)
            {
                previewResolution = ScanningOptions.CameraResolutionSelector(availableResolutions);
            }

            if (availableResolutions == null || availableResolutions.Count < 1)
            {
                var error = "Camera is busy. Try to close all applications that use camera.";
                OnScannerError?.Invoke(new[] { error });
                return;
            }

            // If the user did not specify a resolution, let's try and find a suitable one
            if (previewResolution == null)
            {
                // Loop through all supported sizes
                foreach (var sps in availableResolutions)
                {
                    // Find one that's >= 640x360 but <= 1000x1000
                    // This will likely pick the *smallest* size in that range, which should be fine
                    if (sps.Width >= 640 && sps.Width <= 1000 && sps.Height >= 360 && sps.Height <= 1000)
                    {
                        previewResolution = new CameraResolution
                        {
                            Width  = sps.Width,
                            Height = sps.Height
                        };
                        break;
                    }
                }
            }

            if (previewResolution == null)
            {
                previewResolution = availableResolutions.LastOrDefault();
            }

            if (previewResolution == null)
            {
                System.Diagnostics.Debug.WriteLine("No preview resolution available. Camera may be in use by another application.");
                return;
            }

            MobileBarcodeScanner.Log("Using Preview Resolution: {0}x{1}", previewResolution.Width, previewResolution.Height);

            // Find the matching property based on the selection, again
            var chosenProp = availableProperties.FirstOrDefault(ap => ((VideoEncodingProperties)ap).Width == previewResolution.Width && ((VideoEncodingProperties)ap).Height == previewResolution.Height);

            // Pass in the requested preview size properties
            // so we can set them at the same time as the preview rotation
            // to save an additional set property call
            await SetPreviewRotationAsync(chosenProp);

            // *after* the preview is setup, set this so that the UI layout happens
            // otherwise the preview gets stuck in a funny place on screen
            captureElement.Stretch = Stretch.UniformToFill;

            await SetupAutoFocus();

            var zxing = ScanningOptions.BuildBarcodeReader();

            timerPreview = new Timer(async(state) =>
            {
                var delay = ScanningOptions.DelayBetweenAnalyzingFrames;

                if (stopping || processing || !isAnalyzing ||
                    (mediaCapture == null || mediaCapture.CameraStreamState != Windows.Media.Devices.CameraStreamState.Streaming))
                {
                    timerPreview.Change(delay, Timeout.Infinite);
                    return;
                }

                processing = true;

                SoftwareBitmapLuminanceSource luminanceSource = null;

                try
                {
                    // Get preview
                    var frame = await mediaCapture.GetPreviewFrameAsync(videoFrame);

                    // Create our luminance source
                    luminanceSource = new SoftwareBitmapLuminanceSource(frame.SoftwareBitmap);
                }
                catch (Exception ex)
                {
                    MobileBarcodeScanner.Log("GetPreviewFrame Failed: {0}", ex);
                }

                ZXing.Result result = null;

                try
                {
                    // Try decoding the image
                    if (luminanceSource != null)
                    {
                        result = zxing.Decode(luminanceSource);
                    }
                }
                catch (Exception ex)
                {
                    MobileBarcodeScanner.Log("Warning: zxing.Decode Failed: {0}", ex);
                }

                // Check if a result was found
                if (result != null && !string.IsNullOrEmpty(result.Text))
                {
                    if (!ContinuousScanning)
                    {
                        delay = Timeout.Infinite;
                        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => { await StopScanningAsync(); });
                    }
                    else
                    {
                        delay = ScanningOptions.DelayBetweenContinuousScans;
                    }

                    LastScanResult = result;
                    ScanCallback(result);
                }

                processing = false;

                timerPreview.Change(delay, Timeout.Infinite);
            }, null, ScanningOptions.InitialDelayBeforeAnalyzingFrames, Timeout.Infinite);
        }
Example #5
0
        public async Task StartScanningAsync(Action <ZXing.Result> scanCallback, MobileBarcodeScanningOptions options = null)
        {
            if (stopping)
            {
                return;
            }

            isAnalyzing     = true;
            ScanCallback    = scanCallback;
            ScanningOptions = options ?? MobileBarcodeScanningOptions.Default;

            topText.Text    = TopText ?? string.Empty;
            bottomText.Text = BottomText ?? string.Empty;

            if (UseCustomOverlay)
            {
                gridCustomOverlay.Children.Clear();
                if (CustomOverlay != null)
                {
                    gridCustomOverlay.Children.Add(CustomOverlay);
                }

                gridCustomOverlay.Visibility  = Visibility.Visible;
                gridDefaultOverlay.Visibility = Visibility.Collapsed;
            }
            else
            {
                gridCustomOverlay.Visibility  = Visibility.Collapsed;
                gridDefaultOverlay.Visibility = Visibility.Visible;
            }

            // Find which device to use
            var preferredCamera = await this.GetFilteredCameraOrDefaultAsync(ScanningOptions);

            mediaCapture = new MediaCapture();

            // Initialize the capture with the settings above
            await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings()
            {
                StreamingCaptureMode = StreamingCaptureMode.Video,
                VideoDeviceId        = preferredCamera.Id
            });

            // Set the capture element's source to show it in the UI
            captureElement.Source = mediaCapture;

            // Start the preview
            await mediaCapture.StartPreviewAsync();

            // Get all the available resolutions for preview
            var availableProperties  = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
            var availableResolutions = new List <CameraResolution>();

            foreach (var ap in availableProperties)
            {
                var vp = (VideoEncodingProperties)ap;
                System.Diagnostics.Debug.WriteLine("Camera Preview Resolution: {0}x{1}", vp.Width, vp.Height);
                availableResolutions.Add(new CameraResolution {
                    Width = (int)vp.Width, Height = (int)vp.Height
                });
            }
            CameraResolution previewResolution = null;

            if (ScanningOptions.CameraResolutionSelector != null)
            {
                previewResolution = ScanningOptions.CameraResolutionSelector(availableResolutions);
            }

            // If the user did not specify a resolution, let's try and find a suitable one
            if (previewResolution == null)
            {
                // Loop through all supported sizes
                foreach (var sps in availableResolutions)
                {
                    // Find one that's >= 640x360 but <= 1000x1000
                    // This will likely pick the *smallest* size in that range, which should be fine
                    if (sps.Width >= 640 && sps.Width <= 1000 && sps.Height >= 360 && sps.Height <= 1000)
                    {
                        previewResolution = new CameraResolution
                        {
                            Width  = sps.Width,
                            Height = sps.Height
                        };
                        break;
                    }
                }
            }

            if (previewResolution == null)
            {
                previewResolution = availableResolutions.LastOrDefault();
            }

            System.Diagnostics.Debug.WriteLine("Using Preview Resolution: {0}x{1}", previewResolution.Width, previewResolution.Height);

            // Find the matching property based on the selection, again
            var chosenProp = availableProperties.FirstOrDefault(ap => ((VideoEncodingProperties)ap).Width == previewResolution.Width && ((VideoEncodingProperties)ap).Height == previewResolution.Height);

            // Set the selected resolution
            await mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, chosenProp);

            await SetPreviewRotationAsync();

            captureElement.Stretch = Stretch.UniformToFill;

            // Get our preview properties
            var previewProperties = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;

            // Setup a frame to use as the input settings
            var destFrame = new VideoFrame(Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height);

            var zxing = ScanningOptions.BuildBarcodeReader();

            timerPreview = new Timer(async(state) => {
                var delay = ScanningOptions.DelayBetweenAnalyzingFrames;

                if (stopping || processing || !isAnalyzing ||
                    (mediaCapture == null || mediaCapture.CameraStreamState != Windows.Media.Devices.CameraStreamState.Streaming))
                {
                    timerPreview.Change(delay, Timeout.Infinite);
                    return;
                }

                processing = true;

                SoftwareBitmapLuminanceSource luminanceSource = null;

                try
                {
                    // Get preview
                    var frame = await mediaCapture.GetPreviewFrameAsync(destFrame);

                    // Create our luminance source
                    luminanceSource = new SoftwareBitmapLuminanceSource(frame.SoftwareBitmap);
                } catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("GetPreviewFrame Failed: {0}", ex);
                }

                ZXing.Result result = null;

                try
                {
                    // Try decoding the image
                    if (luminanceSource != null)
                    {
                        result = zxing.Decode(luminanceSource);
                    }
                }
                catch (Exception ex)
                {
                }

                // Check if a result was found
                if (result != null && !string.IsNullOrEmpty(result.Text))
                {
                    if (!ContinuousScanning)
                    {
                        delay = Timeout.Infinite;
                        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => { await StopScanningAsync(); });
                    }
                    else
                    {
                        delay = ScanningOptions.DelayBetweenContinuousScans;
                    }

                    LastScanResult = result;
                    ScanCallback(result);
                }

                processing = false;

                timerPreview.Change(delay, Timeout.Infinite);
            }, null, ScanningOptions.InitialDelayBeforeAnalyzingFrames, Timeout.Infinite);
        }
        public async Task StartScanningAsync(Action<ZXing.Result> scanCallback, MobileBarcodeScanningOptions options = null)
        {
            if (stopping)
                return;

            displayRequest.RequestActive();

            isAnalyzing = true;
            ScanCallback = scanCallback;
            ScanningOptions = options ?? MobileBarcodeScanningOptions.Default;

            topText.Text = TopText ?? string.Empty;
            bottomText.Text = BottomText ?? string.Empty;

            if (UseCustomOverlay)
            {
                gridCustomOverlay.Children.Clear();
                if (CustomOverlay != null)
                    gridCustomOverlay.Children.Add(CustomOverlay);

                gridCustomOverlay.Visibility = Visibility.Visible;
                gridDefaultOverlay.Visibility = Visibility.Collapsed;
            }
            else
            {
                gridCustomOverlay.Visibility = Visibility.Collapsed;
                gridDefaultOverlay.Visibility = Visibility.Visible;
            }

            // Find which device to use
            var preferredCamera = await GetFilteredCameraOrDefaultAsync(ScanningOptions);
            if (preferredCamera == null)
            {
                System.Diagnostics.Debug.WriteLine("No camera available");
                isMediaCaptureInitialized = false;
                return;
            }

            if (preferredCamera.EnclosureLocation == null || preferredCamera.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Unknown)
            {
                // No information on the location of the camera, assume it's an external camera, not integrated on the device.
                externalCamera = true;
            }
            else
            {
                // Camera is fixed on the device.
                externalCamera = false;

                // Only mirror the preview if the camera is on the front panel.
                mirroringPreview = preferredCamera.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front;
            }

            mediaCapture = new MediaCapture();

            // Initialize the capture with the settings above
            try
            {
                await mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings
                {
                    StreamingCaptureMode = StreamingCaptureMode.Video,
                    VideoDeviceId = preferredCamera.Id
                });
                isMediaCaptureInitialized = true;
            }
            catch (UnauthorizedAccessException)
            {
                System.Diagnostics.Debug.WriteLine("Denied access to the camera");
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("Exception when init MediaCapture: {0}", ex);
            }

            if (!isMediaCaptureInitialized)
                return;

            // Set the capture element's source to show it in the UI
            captureElement.Source = mediaCapture;

            // Start the preview
            await mediaCapture.StartPreviewAsync();


            // Get all the available resolutions for preview
            var availableProperties = mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
            var availableResolutions = new List<CameraResolution>();
            foreach (var ap in availableProperties)
            {
                var vp = (VideoEncodingProperties)ap;
                System.Diagnostics.Debug.WriteLine("Camera Preview Resolution: {0}x{1}", vp.Width, vp.Height);
                availableResolutions.Add(new CameraResolution { Width = (int)vp.Width, Height = (int)vp.Height });                
            }
            CameraResolution previewResolution = null;
            if (ScanningOptions.CameraResolutionSelector != null)
                previewResolution = ScanningOptions.CameraResolutionSelector(availableResolutions);

            // If the user did not specify a resolution, let's try and find a suitable one
            if (previewResolution == null)
            {
                // Loop through all supported sizes
                foreach (var sps in availableResolutions)
                {
                    // Find one that's >= 640x360 but <= 1000x1000
                    // This will likely pick the *smallest* size in that range, which should be fine
                    if (sps.Width >= 640 && sps.Width <= 1000 && sps.Height >= 360 && sps.Height <= 1000)
                    {
                        previewResolution = new CameraResolution
                        {
                            Width = sps.Width,
                            Height = sps.Height
                        };
                        break;
                    }
                }
            }

            if (previewResolution == null)
                previewResolution = availableResolutions.LastOrDefault();

            MobileBarcodeScanner.Log("Using Preview Resolution: {0}x{1}", previewResolution.Width, previewResolution.Height);

            // Find the matching property based on the selection, again
            var chosenProp = availableProperties.FirstOrDefault(ap => ((VideoEncodingProperties)ap).Width == previewResolution.Width && ((VideoEncodingProperties)ap).Height == previewResolution.Height);

            // Pass in the requested preview size properties
            // so we can set them at the same time as the preview rotation
            // to save an additional set property call
            await SetPreviewRotationAsync(chosenProp);
            
            // *after* the preview is setup, set this so that the UI layout happens
            // otherwise the preview gets stuck in a funny place on screen
            captureElement.Stretch = Stretch.UniformToFill;
            
            await SetupAutoFocus();
                        
            var zxing = ScanningOptions.BuildBarcodeReader();

            timerPreview = new Timer(async (state) => {

                var delay = ScanningOptions.DelayBetweenAnalyzingFrames;

                if (stopping || processing || !isAnalyzing
                || (mediaCapture == null || mediaCapture.CameraStreamState != Windows.Media.Devices.CameraStreamState.Streaming))
                {
                    timerPreview.Change(delay, Timeout.Infinite);
                    return;
                }

                processing = true;

                SoftwareBitmapLuminanceSource luminanceSource = null;

                try
                {
                    // Get preview 
                    var frame = await mediaCapture.GetPreviewFrameAsync(videoFrame);

                    // Create our luminance source
                    luminanceSource = new SoftwareBitmapLuminanceSource(frame.SoftwareBitmap);

                } catch (Exception ex)
                {
                    MobileBarcodeScanner.Log ("GetPreviewFrame Failed: {0}", ex);
                }

                ZXing.Result result = null;

                try
                {
                    // Try decoding the image
                    if (luminanceSource != null)
                        result = zxing.Decode(luminanceSource);
                }
                catch (Exception ex)
                {
                    MobileBarcodeScanner.Log("Warning: zxing.Decode Failed: {0}", ex);
                }

                // Check if a result was found
                if (result != null && !string.IsNullOrEmpty (result.Text))
                {
                    if (!ContinuousScanning)
                    {
                        delay = Timeout.Infinite;
                        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { await StopScanningAsync(); });
                    }
                    else
                    {
                        delay = ScanningOptions.DelayBetweenContinuousScans;
                    }

                    LastScanResult = result;
                    ScanCallback(result);
                }

                processing = false;

                timerPreview.Change(delay, Timeout.Infinite);
                         
            }, null, ScanningOptions.InitialDelayBeforeAnalyzingFrames, Timeout.Infinite);
        }