Windows Phone 8.1

Sep 8, 2014 at 1:21 PM
Hello,
I have created an QR-Code Scanner for WP 8.1.
My Problem is that it needs about 8 seconds to complete the process.
I've used your WindowsRT example to get rid of QR-Code scanning.

The process inside the while loop is currently running really slow! Any suggestions how i can improve the process?
Code Snippets:
await _mediaCapture.StartPreviewAsync();

int i = 0;
var barcodeReader = new BarcodeReader
{
    TryHarder = true,
    AutoRotate = true
};

while (_result == null)
{
    photoStorageFile = await KnownFolders.PicturesLibrary.CreateFileAsync("scan.jpg", CreationCollisionOption.ReplaceExisting);
    await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), photoStorageFile);

    var stream = await photoStorageFile.OpenReadAsync();

    var writeableBmp = new WriteableBitmap(1, 1);
    writeableBmp.SetSource(stream);

    writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
    stream.Seek(0);
    writeableBmp.SetSource(stream);
    _result = barcodeReader.Decode(writeableBmp);
    if (_result != null)
    {
        CaptureImage.Source = writeableBmp;
    }

    i += 1;
    ScanResult.Text = "Nummer " + i;
}
await _mediaCapture.StopPreviewAsync();
VideoCapture.Visibility = Visibility.Collapsed;
CaptureImage.Visibility = Visibility.Visible;
ScanResult.Text = _result.Text;
}
Sep 9, 2014 at 8:04 AM
Edited Sep 9, 2014 at 8:04 AM
Ok i just did it!

I've just initialized the camera asynchronous and added some settings
FocusSettings focusSetting = new FocusSettings()
            {
                Mode = FocusMode.Continuous,
                AutoFocusRange = AutoFocusRange.Normal,
                DisableDriverFallback = false,
                WaitForFocus = true
            };
Now it does work fast!
Oct 7, 2014 at 8:48 PM
I'm having the same issue where it's running completely slow. I've tried the code you have here. Set the initialize to be async and added the focus settings.

Currently have
writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
                    stream.Seek(0);
                    writeableBmp.SetSource(stream);
                    _result = barcodeReader.Decode(writeableBmp);
                    if (_result != null)
                    {
                        CaptureImage.Source = writeableBmp;
                    }

                    i += 1;
                    ScanResult.Text = "Nummer " + i;
                }

                await _mediaCapture.StopPreviewAsync();
                VideoCapture.Visibility = Visibility.Collapsed;
                CaptureImage.Visibility = Visibility.Visible;
                ScanResult.Text = _result.Text;

            }
            catch (Exception ex)
            {
                Error.Text = ex.Message;
            }            
        }
It is taking about 15 seconds for it to get passed
_result = barcodeReader.Decode(writeableBmp);
Oct 15, 2014 at 1:23 PM
I wanted to use ZXing for Windows Phone 8.1 but i doesn't know how to include the library in my project, someone could help me with that ?
Oct 20, 2014 at 8:48 PM
Its a NUGET package just run Install-Package ZXing.Net from the Package Manager Console
Oct 21, 2014 at 7:03 AM
Yes i found since my post ! Thanks !
Nov 4, 2014 at 12:20 PM
Hi all, where can I found a barebone ZXing Windows Phone example?.
Dec 23, 2014 at 4:15 PM
Hi all! I'm working on an app which needs barcode reader feature. It is very important to me to have it included, so please help me. Setting the FocusSettings causes an exception with the message: "Value does not fall within the expected range". Any idea what is wrong? Also, how can I set the mediaCapture preview to appear full screan and portrait mode? Thank you!
Coordinator
Jan 14, 2015 at 7:54 PM
Reteservizi
You can find a simple demo app here:
https://zxingnet.svn.codeplex.com/svn/trunk/Clients/SimpleWindowsPhone8Demo

wpAhmee
Please check the capabilities of the camera of the device before setting the FocusSettings. If the setting you want to use is not supported by the device you will get that error.
Jan 15, 2015 at 9:03 AM
micjanh

Many thanks!.
Jan 20, 2015 at 12:31 PM
Hi all, i am facing the same issue, even after setting the FocusSettings the whole loop takes 8 seconds to complete its process, because of that i guess i am getting decode sucessfully only once in 10 times, most of the time while i am decoding i am gettting null value. My whole code is below.
private readonly MediaCapture _mediaCapture = new MediaCapture();
        private Result _result;
        private bool _navBack;
        public Scan1xaml()
        {
            this.InitializeComponent();
            this.NavigationCacheMode = NavigationCacheMode.Required;
        }

        /// <summary>
        /// Invoked when this page is about to be displayed in a Frame.
        /// </summary>
        /// <param name="e">Event data that describes how this page was reached.
        /// This parameter is typically used to configure the page.</param>
        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            InitCameraPreviewAction();

            //await DecodeStaticResource();
            //return;
        }

        private async void InitCameraPreviewAction()
        {
#if _TestCatpureImage_
  await DecodeStaticResource();
            return;
#endif
            var canUseCamera = true;
            try
            {
                var cameras = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
                if (cameras.Count < 1)
                {
                    Error.Text = "No camera found, decoding static image";
                    await DecodeStaticResource();
                    return;
                }
                MediaCaptureInitializationSettings settings;
                if (cameras.Count == 1)
                {
                    settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameras[0].Id }; // 0 => front, 1 => back
                }
                else
                {
                    settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameras[1].Id }; // 0 => front, 1 => back
                }
                await _mediaCapture.InitializeAsync(settings);


                FocusSettings focusSetting = new FocusSettings()
                {
                    Mode = FocusMode.Continuous,                   
                    AutoFocusRange = AutoFocusRange.Normal,
                    DisableDriverFallback = false,                    
                    WaitForFocus = true
                };

                _mediaCapture.VideoDeviceController.FocusControl.Configure(focusSetting);
                await _mediaCapture.VideoDeviceController.ExposureControl.SetAutoAsync(true);


                SetResolution();
                VideoCapture.Source = _mediaCapture;
                try
                {
                    //should update CurrentOrientation
                    _mediaCapture.SetPreviewRotation(VideoRotationLookup(DisplayProperties.CurrentOrientation, false));
                    //set flash close
                    _mediaCapture.VideoDeviceController.FlashControl.Enabled = false;
                }
                catch (Exception e)
                {
                    App.WpLog(e);
                }

                await _mediaCapture.StartPreviewAsync();
                var count = 0;

                while (_result == null && !_navBack)
                {
                    count++;
                    App.WpLog(count);
                    var photoStorageFile = await KnownFolders.PicturesLibrary.CreateFileAsync("scan.jpg", CreationCollisionOption.GenerateUniqueName);
                    await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), photoStorageFile);

                    var stream = await photoStorageFile.OpenReadAsync();
                    // initialize with 1,1 to get the current size of the image
                    var writeableBmp = new WriteableBitmap(1, 1);
                    writeableBmp.SetSource(stream);
                    // and create it again because otherwise the WB isn't fully initialized and decoding
                    // results in a IndexOutOfRange
                    writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
                    stream.Seek(0);
                    writeableBmp.SetSource(stream);

                    _result = ScanBitmap(writeableBmp);

                    await photoStorageFile.DeleteAsync(StorageDeleteOption.PermanentDelete);
                }

                await _mediaCapture.StopPreviewAsync();
                VideoCapture.Visibility = Visibility.Collapsed;
                CaptureImage.Visibility = Visibility.Visible;
                ScanResult.Text = _result.Text;

            }
            catch (Exception ex)
            {
                Error.Text = ex.Message;
                App.WpLog("use camera fail: " + ex);
                canUseCamera = false;
            }

            if (canUseCamera || _navBack) return;
            //tips error 
        }

        private async System.Threading.Tasks.Task DecodeStaticResource()
        {
#if _TestCatpureImage_
            var file = await KnownFolders.PicturesLibrary.GetFileAsync("scan_test.jpg");
            var image = new BitmapImage();
            image.SetSource(await file.OpenAsync(FileAccessMode.Read));
            CaptureImage.Source = image;
            CaptureImage.Visibility = Visibility.Visible; 
            return;
#else
            var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@"Assets\bar.png");
            //var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@"Assets\TestZXing.png");
            var stream = await file.OpenReadAsync();
            // initialize with 1,1 to get the current size of the image
            var writeableBmp = new WriteableBitmap(1, 1);
            writeableBmp.SetSource(stream);
            // and create it again because otherwise the WB isn't fully initialized and decoding
            // results in a IndexOutOfRange
            writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
            stream.Seek(0);
            writeableBmp.SetSource(stream);
            CaptureImage.Source = writeableBmp;
            VideoCapture.Visibility = Visibility.Collapsed;
            CaptureImage.Visibility = Visibility.Visible;

            _result = ScanBitmap(writeableBmp);
            if (_result != null)
            {
                ScanResult.Text += _result.Text;
            }
            return;
#endif
        }

        private Result ScanBitmap(WriteableBitmap writeableBmp)
        {
            try
            {
                var barcodeReader = new BarcodeReader
                {
                    TryHarder = true,
                    AutoRotate = true
                };
                var result = barcodeReader.Decode(writeableBmp);

                if (result != null)
                {
                    CaptureImage.Source = writeableBmp;
                }

                return result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private Windows.Media.Capture.VideoRotation VideoRotationLookup(
         Windows.Graphics.Display.DisplayOrientations displayOrientation,
         bool counterclockwise)
        {
            switch (displayOrientation)
            {
                case Windows.Graphics.Display.DisplayOrientations.Landscape:
                    return Windows.Media.Capture.VideoRotation.None;

                case Windows.Graphics.Display.DisplayOrientations.Portrait:
                    return (counterclockwise) ? Windows.Media.Capture.VideoRotation.Clockwise270Degrees :
                        Windows.Media.Capture.VideoRotation.Clockwise90Degrees;

                case Windows.Graphics.Display.DisplayOrientations.LandscapeFlipped:
                    return Windows.Media.Capture.VideoRotation.Clockwise180Degrees;

                case Windows.Graphics.Display.DisplayOrientations.PortraitFlipped:
                    return (counterclockwise) ? Windows.Media.Capture.VideoRotation.Clockwise90Degrees :
                        Windows.Media.Capture.VideoRotation.Clockwise270Degrees;
                default:
                    return Windows.Media.Capture.VideoRotation.None;
            }
        }

        //This is how you can set your resolution
        public async void SetResolution()
        {
            System.Collections.Generic.IReadOnlyList<IMediaEncodingProperties> res;
            res = this._mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
            uint maxResolution = 0;
            int indexMaxResolution = 0;

            if (res.Count >= 1)
            {
                for (int i = 0; i < res.Count; i++)
                {
                    var vp = (VideoEncodingProperties)res[i];
                    App.WpLog(vp.Width + " _ " + vp.Height);
                    if (vp.Width > maxResolution)
                    {
                        indexMaxResolution = i;
                        maxResolution = vp.Width;
                        Debug.WriteLine("Resolution: " + vp.Width);
                    }
                }
                await this._mediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, res[res.Count - 1]);
            }
        }

        protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            try
            {
                _navBack = true;
                VideoCapture.Visibility = Visibility.Collapsed;
                await _mediaCapture.StopPreviewAsync();
                VideoCapture.Source = null;
            }
            catch (Exception exception)
            {
                App.WpLog(exception);
            }
        }
Jan 29, 2015 at 11:27 AM
Hi Nambukarthy,

Hve you Resolved this issue , Because I am also looking for Barcode Scanner in Windows phone 8.1 , I found your Postings i too tried but it is taking too much time to scan

if you completed please let me know to this mail ID charyvgk@gmail.com
Jan 31, 2015 at 5:40 AM
bastik wrote:
Hello,
I have created an QR-Code Scanner for WP 8.1.
My Problem is that it needs about 8 seconds to complete the process.
I've used your WindowsRT example to get rid of QR-Code scanning.

The process inside the while loop is currently running really slow! Any suggestions how i can improve the process?
Code Snippets:
await _mediaCapture.StartPreviewAsync();

int i = 0;
var barcodeReader = new BarcodeReader
{
    TryHarder = true,
    AutoRotate = true
};

while (_result == null)
{
    photoStorageFile = await KnownFolders.PicturesLibrary.CreateFileAsync("scan.jpg", CreationCollisionOption.ReplaceExisting);
    await _mediaCapture.CapturePhotoToStorageFileAsync(ImageEncodingProperties.CreateJpeg(), photoStorageFile);

    var stream = await photoStorageFile.OpenReadAsync();

    var writeableBmp = new WriteableBitmap(1, 1);
    writeableBmp.SetSource(stream);

    writeableBmp = new WriteableBitmap(writeableBmp.PixelWidth, writeableBmp.PixelHeight);
    stream.Seek(0);
    writeableBmp.SetSource(stream);
    _result = barcodeReader.Decode(writeableBmp);
    if (_result != null)
    {
        CaptureImage.Source = writeableBmp;
    }

    i += 1;
    ScanResult.Text = "Nummer " + i;
}
await _mediaCapture.StopPreviewAsync();
VideoCapture.Visibility = Visibility.Collapsed;
CaptureImage.Visibility = Visibility.Visible;
ScanResult.Text = _result.Text;
}
Hi ,Could you please share your application i need to scan the all bar code may be your way approach gives some idea
Feb 9, 2015 at 2:13 PM
Hey Guys!

I found a way for performance improvment. Instead of calling the CapturePhotoToStorage method of the MediaCapture API, you should call CapturePhotoToStreamAsync, which takes an ImageEncodingProperties and an IRandomAccessStream as parameters.

Here's my snippet:
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();

            await _mediaCapture.CapturePhotoToStreamAsync(imgProp, stream);
            
            stream.Seek(0);

            WriteableBitmap wbm = new WriteableBitmap(600, 800);

            await wbm.SetSourceAsync(stream);
Although the scanning is now fast, I'm facing another problem. After scanning about 20 codes, the program crashes with OutOfMemoryException, which seems to be a leak in the new MediaCapture API, or an incompatibility with some Lumia drivers, as Microsoft support said:
...that the only work-around is to write this as a Windows Phone 8.0 targeted application.
As I understand it: The problem is an incompatibility between the new MediaCapture API’s (…used by SL8.1 and WP8.1/Universal apps) and a camera driver used on most of the Lumia devices. An updated driver is expected for some of the newer devices but unfortunately many of the older devices may not receive updated drivers so this will continue to be a problem for a while.
Feb 10, 2015 at 7:19 AM
bastik wrote:
Ok i just did it!

I've just initialized the camera asynchronous and added some settings
FocusSettings focusSetting = new FocusSettings()
            {
                Mode = FocusMode.Continuous,
                AutoFocusRange = AutoFocusRange.Normal,
                DisableDriverFallback = false,
                WaitForFocus = true
            };
Now it does work fast!
Hi people,

Becareful with the Continuous mode of Autofocus : Most of Phone doesn't support it ! My Lumia 925 for example isn't compatible with this function.
Feb 10, 2015 at 7:23 AM
Edited Feb 10, 2015 at 9:48 AM
wpAhmee wrote:
Hey Guys!

I found a way for performance improvment. Instead of calling the CapturePhotoToStorage method of the MediaCapture API, you should call CapturePhotoToStreamAsync, which takes an ImageEncodingProperties and an IRandomAccessStream as parameters.

Here's my snippet:
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();

            await _mediaCapture.CapturePhotoToStreamAsync(imgProp, stream);
            
            stream.Seek(0);

            WriteableBitmap wbm = new WriteableBitmap(600, 800);

            await wbm.SetSourceAsync(stream);
Although the scanning is now fast, I'm facing another problem. After scanning about 20 codes, the program crashes with OutOfMemoryException, which seems to be a leak in the new MediaCapture API, or an incompatibility with some Lumia drivers, as Microsoft support said:
...that the only work-around is to write this as a Windows Phone 8.0 targeted application.
As I understand it: The problem is an incompatibility between the new MediaCapture API’s (…used by SL8.1 and WP8.1/Universal apps) and a camera driver used on most of the Lumia devices. An updated driver is expected for some of the newer devices but unfortunately many of the older devices may not receive updated drivers so this will continue to be a problem for a while.
Maybe you could freeing memory after a complete decode with the method "Dispose" of the InMemoryRandomAccessStream API. I think it could be solve your problem

Also, I tried your solution, but I have an exception " 'System.IndexOutOfRangeException' occurred in ZXing.winmd "
Do you had the same ? Or maybe I use a bad Zxing conversion function ?

_result = ScanBitmap(wbm);
Feb 12, 2015 at 3:01 PM
I have a very little problem :

I'm using the decoder with phone in portrait mode (not landscape). The camera preview is 90° turned ! So i'm using the parameter :

" captureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees); "

And it's perfect ! ... Until image decoded : I stop the preview and display the image scanned ... And the displayed image is turned 90° ! how can I correct this proble ?
Coordinator
Feb 27, 2015 at 4:30 PM
In the windows phone 8 sample client app I used some manual rotation of the preview buffer before decoding.
Take a look at the methods DetectBarcodeAsync and RotateClockwise:
https://zxingnet.svn.codeplex.com/svn/trunk/Clients/WindowsPhone8Demo/ViewModels/CaptureViewModel.cs
Feb 28, 2015 at 11:16 AM
Hey guys! Here's the solution for reading barcodes/QR codes using Zxing on Windows Phone 8.1 RUNTIME apps using the MediaCapture APi, and Matthieu Maitre's VideoEffect project, install the NuGet package: PM> Install-Package MMaitre.VideoEffects and you're ready to go. Here's the sample app
The point is that with his VideoEffect library you can access the preview frame asynchronously, so decoding the barcode won't cause delaying the frames inside the video stream. No need for capturing photo to stream or anything. It is crazy fast. Please vote my solution up on stackoverflow.
Mar 3, 2015 at 1:53 PM
Wonderfull solution wpAhmee, I integrate it in my project,and the result is incredibly fast !
It only missing an autofocus function, I will try to add it.
Apr 3, 2015 at 9:25 AM
autofocus function have been resolvet ?
Apr 3, 2015 at 11:45 AM
Yes, I solved the problem on my Lumia 925 which don't have the autofocus Continuous mode.

I create a timer which are make focus every seconds :
       #region Timer

        FocusControl focusControl;

        /// <summary>
        /// Timer for displaying dummy QR Code analysis
        /// </summary>
        DispatcherTimer dispatcherAnalyzeTimer;
        bool dispatcherAnalyzeTimerState = false;

        public void DispatcherTimer_Create()
        {
            dispatcherAnalyzeTimer = new DispatcherTimer();
            dispatcherAnalyzeTimer.Tick += dispatcherTimer_Analyze_Tick;
            dispatcherAnalyzeTimer.Interval = new TimeSpan(0, 0, 2);
        }

        public void DispatcherTime_Start()
        {
            dispatcherAnalyzeTimerState = true;
            dispatcherAnalyzeTimer.Start();
        }

        public void DispatcherTimer_Stop()
        {
            if ((dispatcherAnalyzeTimer != null) && (dispatcherAnalyzeTimerState == true))
            {
                dispatcherAnalyzeTimerState = false;
                dispatcherAnalyzeTimer.Stop();
            }
        }


        async void  dispatcherTimer_Analyze_Tick(object sender, object e)
        {
            try
            {
                if (focusControl.Supported == true)
                {
                    await focusControl.FocusAsync();
                }
            }
            catch
            {
                DisposeCapture();
            }
        }

        #endregion
And I configure Focus and Timer just after launching the preview :
                await capture.StartPreviewAsync();

                isAnalyzing = true;

                focusControl = capture.VideoDeviceController.FocusControl;

                if (focusControl.Supported == true)
                {
                    FocusSettings focusSetting = new FocusSettings()
                    {
                        AutoFocusRange = AutoFocusRange.Normal,
                        Mode = FocusMode.Auto,
                        WaitForFocus = false,
                        DisableDriverFallback = false
                    };

                    focusControl.Configure(focusSetting);
                    await capture.VideoDeviceController.ExposureControl.SetAutoAsync(true);
                    await focusControl.FocusAsync();

                    DispatcherTimer_Create();
                    DispatcherTime_Start();
                }

Don't forget to stop timer after finishing decode or at the page change ;)
Apr 10, 2015 at 11:13 PM
@xNius: Do you mind if I pull that autofocus code into VideoEffect's sample app? That will make detection a lot more reliable on low-end phones like the 520.
May 18, 2015 at 7:44 AM
Hi mmaitre ! Sorry for the delay of my answer.

Yes, I think it could be improve decoding, but only if the Autofocus is supported by thus phones.
I think the better is to test it.
Jun 16, 2016 at 8:21 PM
Hi . I'm trying to create a bar code scanner with auto focus or tap to focus function for Windows phone 8.1. Could someone send me working code? Thanks!!!
Sep 26, 2016 at 10:17 AM
Hi . I'm trying to create a bar code scanner with auto focus or tap to focus function for Windows phone 8.1. Could someone send me working code? Thanks!!!
Sep 26, 2016 at 10:19 AM
u got any working code , can you please share ?