Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
929 lines (697 sloc) 53.3 KB

Table of contents

Windows Phone PDF417 integration instructions

The package contains Visual Studio 2012 solution(can open in VS 2013) that contains everything you need to get you started with PDF417 library. Demo project PDF417Demo for Windows Phone 8.0 is included in solution containing the example use of PDF417 library.

PDF417 is supported on Windows Phone 8.0. Windows Phone 8.1 can be supported with minor changes and Windows Phone 10 is expected to be supported soon.

Quick Start

Quick start with demo app

In Visual Studio 2012

  1. In FILE menu choose Open Project....
  2. In Open project dialog select PDF417Demo.sln in PDF417Demo folder.
  3. Wait for project to load.

In Visual Studio 2013

  1. In FILE menu choose Open then Project/Solution.
  2. In Open project dialog select PDF417Demo.sln in PDF417Demo folder.
  3. Wait for project to load.

Quick integration of PDF417 into your app

This works the same in both Visual Studio 2012 or Visual Studio 2013

  1. In File Explorer (NOT in VS) copy the WPLibDebug and WPLibRelease folders from PDF417 SDK to your project's folder
  2. Copy (INSIDE VS) the WPLibAssets folder from PDF417 SDK into your project (it is important to preserve folder structure)
  3. Set the properties Build Action to None and Copy to Output Directory to Copy if newer to all the files in WPLibAssets folder
  4. Right click to your project's References and choose Add Reference...
  5. Click the Browse... button on the bottom
  6. In Select the files to reference... dialog select PDF417.dll and Microblink.winmd from WPLibDebug folder (you created in first step) if you want to link to debug version of PDF417 library (select files from WPLibRelease if you want to link to release version of PDF417 library)

Performing your first scan

  1. Add RecognizerControl to main page of your application. Your .xaml file should contain something like these lines:

    xmlns:UserControls="clr-namespace:Microblink.UserControls;assembly=PDF417"

    and RecognizerControl tag itself:

    <UserControls:RecognizerControl x:Name="mRecognizer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
  2. You should setup RecognizerControl in containing page constructor like this:

    // sets license key
    // obtain your licence key at http://microblink.com/login or
    // contact us at http://help.microblink.com            
    mRecognizer.LicenseKey = "Add your licence key here";
    
    // setup array of recognizer settings
    Microblink.PDF417RecognizerSettings pdf417Settings = new Microblink.PDF417RecognizerSettings();
    Microblink.ZXingRecognizerSettings zxingSettings = new Microblink.ZXingRecognizerSettings() { QRCode = true };
    Microblink.BarDecoderRecognizerSettings bardecSettings = new Microblink.BarDecoderRecognizerSettings() { ScanCode128 = true };
    Microblink.USDLRecognizerSettings usdlSettings = new Microblink.USDLRecognizerSettings();
    mRecognizer.RecognizerSettings = new Microblink.IRecognizerSettings[] { pdf417Settings, zxingSettings, bardecSettings, usdlSettings };        
    
    // these three events must be handled
    mRecognizer.OnCameraError += mRecognizer_OnCameraError;            
    mRecognizer.OnScanningDone += mRecognizer_OnScanningDone;
    mRecognizer.OnInitializationError += mRecognizer_OnInitializationError;
  3. You should implement OnNavigatedTo and OnNavigatedFrom of your main page to initialize and terminate RecognizerControl respectively so RecognizerControl will be initialized when the user activates the page and will terminate when the user navigates away from the page. You should do it like this:

    protected override void OnNavigatedTo(NavigationEventArgs e) {
        // call default behaviour
        base.OnNavigatedTo(e);
        // initialize the recognition process
        mRecognizer.InitializeControl(this.Orientation);
    }
        
    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) {
        // terminate the recognizer
        mRecognizer.TerminateControl();
        // call default behaviour
        base.OnNavigatingFrom(e);
    }
  4. You should also implement OnOrientationChanged of your main page and forward the orientation change info to RecognizerControl like this:

    protected override void OnOrientationChanged(OrientationChangedEventArgs e) {
        // call default behaviour
        base.OnOrientationChanged(e);            
        // orientation change events MUST be forwarded to RecognizerControl
        mRecognizer.OnOrientationChanged(e);            
    }
  5. After scan finishes it will trigger OnScanningDone event. You can obtain the scanning results by implementing the event handler something like this:

    void mRecognizer_OnScanningDone(IList<Microblink.IRecognitionResult> resultList, RecognitionType recognitionType) {
        // display results if scan was successful
        if (recognitionType == RecognitionType.SUCCESSFUL) {
            StringBuilder b = new StringBuilder();
            // process all results in result list
            foreach (var result in resultList) {
                // process all result elements
                if (result.Valid && !result.Empty) {
                    foreach (var key in result.Elements.Keys) {
                        // append key-value pairs to StringBuilder
                        b.Append(key);
                        b.Append(" = ");
                        b.Append(result.Elements[key]);
                        b.Append("\n");
                    }
                }
            }
            // display message box with scanned results
            MessageBox.Show("Results:\n" + b.ToString());
        }
        // resume scanning
        mRecognizer.ResumeScanning();
    }

    For more information about defining recognition settings and obtaining scan results see Recognition settings and results.

Advanced PDF417 integration instructions

This section will cover more advanced details in PDF417 integration. First part will discuss the methods for checking whether PDF417 is supported on current device. Second part will show how to embed RecognizerControl into custom application page. Third part is a brief RecognizerControl reference.

Checking if PDF417 is supported

PDF417 requirements

Even before starting the scanning process, you should check if PDF417 is supported on current device. In order to be supported, device needs to have a camera.

Windows Phone 8.0 is the minimum version on which PDF417 is supported. It is supported on Windows Phone 8.1 with minor adjustments and we expect Windows Phone 10.0 to be supported soon.

Camera video preview resolution also matters. In order to perform successful scans, camera preview resolution cannot be too low. PDF417 requires minimum 480p camera preview resolution in order to perform scan. It must be noted that camera preview resolution is not the same as the video record resolution, although on most devices those are the same. However, there are some devices that allow recording of HD video (720p resolution), but do not allow high enough camera preview resolution. PDF417 does not work on those devices.

However, some recognizers require camera with autofocus. If you try to start recognition with those recognizers on a device that does not have camera with autofocus, you will get an error. To determine whether does recognizer require camera with autofocus or not you can call bool requiresAutofocus() method of Microblink.IRecognitionSettings interface.

Embedding RecognizerControl into custom application page

This section will discuss how to embed RecognizerControl into your windows phone application page and perform scan. Note that this example is for Windows Phone 8.0.

Here is the minimum example of integration of RecognizerControl as the only control in your page:

.xaml file

<phone:PhoneApplicationPage
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:UserControls="clr-namespace:Microblink.UserControls;assembly=PDF417"
    xmlns:local="clr-namespace:MyApp"
    x:Class="MyApp.MyPage"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
    
    <Grid Background="Transparent">        
                        
        <UserControls:RecognizerControl x:Name="mRecognizer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
                
    </Grid>

</phone:PhoneApplicationPage>

.xaml.cs file

public partial class MyPage : PhoneApplicationPage
    {
    
    private void InitializeRecognizer() {            
        // sets license key
		// obtain your licence key at http://microblink.com/login or
		// contact us at http://help.microblink.com            
		mRecognizer.LicenseKey = "Add your licence key here";
		
		// setup array of recognizer settings
		Microblink.PDF417RecognizerSettings pdf417Settings = new Microblink.PDF417RecognizerSettings();
        Microblink.ZXingRecognizerSettings zxingSettings = new Microblink.ZXingRecognizerSettings() { QRCode = true };
        Microblink.BarDecoderRecognizerSettings bardecSettings = new Microblink.BarDecoderRecognizerSettings() { ScanCode128 = true };
        Microblink.USDLRecognizerSettings usdlSettings = new Microblink.USDLRecognizerSettings();
        mRecognizer.RecognizerSettings = new Microblink.IRecognizerSettings[] { pdf417Settings, zxingSettings, bardecSettings, usdlSettings };        
		
		// these three events must be handled
		mRecognizer.OnCameraError += mRecognizer_OnCameraError;            
		mRecognizer.OnScanningDone += mRecognizer_OnScanningDone;
		mRecognizer.OnInitializationError += mRecognizer_OnInitializationError;
    }
    
    void mRecognizer_OnInitializationError(InitializationErrorType errorType) {
        // handle licensing error by displaying error message and terminating the application
        if (errorType == InitializationErrorType.INVALID_LICENSE_KEY) {
            MessageBox.Show("Could not unlock API! Invalid license key!\nThe application will now terminate!");
            Application.Current.Terminate();
        } else {
            // there are no other error types
            throw new NotImplementedException();
        }           
    }
    
    void mRecognizer_OnScanningDone(IList<Microblink.IRecognitionResult> resultList, RecognitionType recognitionType) {
        // display results if scan was successful
        if (recognitionType == RecognitionType.SUCCESSFUL) {
            StringBuilder b = new StringBuilder();
            // process all results in result list
            foreach (var result in resultList) {
                // process all result elements
                if (result.Valid && !result.Empty) {
	                foreach (var key in result.Elements.Keys) {
	                    // append key-value pairs to StringBuilder
	                    b.Append(key);
	                    b.Append(" = ");
	                    b.Append(result.Elements[key]);
	                    b.Append("\n");
	                }
            	}
            }
            // display message box with scanned results
            MessageBox.Show("Results:\n" + b.ToString());
        }
        // resume scanning
        mRecognizer.ResumeScanning();
    }
    
    void mRecognizer_OnCameraError(Microblink.UserControls.CameraError error) {
        MessageBox.Show("Could not initialize the camera!\nThe application will now terminate!");
        Application.Current.Terminate();
    }        
    
    public MyPage()
    {
        InitializeComponent();
        // set up recognizer
        InitializeRecognizer();
    }
   
    protected override void OnNavigatedTo(NavigationEventArgs e) {
        // call default behaviour
        base.OnNavigatedTo(e);
        // initialize the recognition process
        mRecognizer.InitializeControl(this.Orientation);
    }
    
    protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) {
        // terminate the recognizer
        mRecognizer.TerminateControl();
        // call default behaviour
        base.OnNavigatingFrom(e);
    }    

    protected override void OnOrientationChanged(OrientationChangedEventArgs e) {
        // call default behaviour
        base.OnOrientationChanged(e);        
        // orientation change events MUST be forwarded to RecognizerControl
        mRecognizer.OnOrientationChanged(e);            
    }    
               
}

RecognizerControl reference

The usage example for RecognizerControl is provided in PDF417Demo demo app provided with SDK. This section just gives a quick overview of RecognizerControl's most important features.

Methods

InitializeControl(PageOrientation)

This method will initialize RecognizerControl's internal fields and will initialize camera control thread. This method must be called after all other settings are already defined, such as event handlers and recognition settings.

ResumeScanning()

This method resumes scanning loop. Scanning loop is usually paused when results have arrived and OnScanningDone event is raised. You can also pause scanning loop by yourself by calling PauseScanning.

PauseScanning()

This method pauses scanning loop. Scanning loop is resumed by calling ResumeScanning.

TerminateControl()

This method terminates RecognizerControl internal state, stops the recognizers and shuts down camera control thread. Call this method when you are finished with scanning and want to free resources used up by PDF417 library. You can reinitialize RecognizerControl by calling InitializeControl method.

OnOrientationChanged(OrientationChangedEventArgs)

This method should be called to forward the OnOrientationChanged event to RecognizerControl so it can handle the orientation change.

SetROI(Windows.Foundation.Rect)

You can use this method to define the scanning region of interest.

Region of interest is defined as Windows.Foundation.Rect. First parameter of rectangle is x-coordinate represented as percentage of view width, second parameter is y-coordinate represented as percentage of view height, third parameter is region width represented as percentage of view width and fourth parameter is region height represented as percentage of view height.

View width and height are defined in current context, i.e. they depend on screen orientation.

Note that scanning region of interest only reflects to native code - it does not have any impact on user interface. You are required to create a matching user interface that will visualize the same scanning region you set here.

TransformPointCoordinateRelative(Point)

Method to transform a point from a position in image to a position in a control relative to current preview size.

TransformPointCoordinateAbsolute(Point)

Method to transform a point from a position in image to absolute position in a control.

TransformPointCoordinateROI(Point)

Method to transform a point from a position in image to a position in a control relative to Region of Interest.

Properties

GenericRecognizerSettings

With this property you can set the generic settings that will affect all enabled recognizers or the whole recognition process. For more information about generic settings, see Generic settings. This property must be set before InitializeControl().

RecognizerSettings

Array of IRecognizerSettings objects. Those objects will contain information about what will be scanned and how will scan be performed. For more information about recognition settings and results see Recognition settings and results. This property must be set before InitializeControl().

PreviewScale

Defines the aspect mode of camera. If set to Uniform (default), then camera preview will be fit inside available view space. If set to UniformToFill, camera preview will be zoomed and cropped to use the entire view space.

MacroMode

When set to true, camera will be optimized for near object scanning. It will focus on near objects more easily and will not be able to focus on far objects. Use this only if you plan to hold your device very near to the object you are scanning. Also, feel free to experiment with both true and false to see which better suits your use case.

IsTorchSupported

This property is set to true if camera supports torch flash mode. Note that if camera is not loaded it will be set to false.

TorchOn

If torch flash mode is supported on camera, this property can be used to enable/disable torch flash mode. When set to true torch is turned on. Note that camera has to be loaded for this to work.

Licensee and LicenseKey

With these properties you can set the license key for PDF417. You can obtain your license key from Microblink website or you can contact us at http://help.microblink.com. Once you obtain a license key, you can set it with following snippet:

// set the license key
mRecognizer.LicenseKey = "Enter_License_Key_Here";

License key is bound to your application ID. For example, if you have license key that is bound to PDF417Demo application ID, you cannot use the same key in other applications. However, if you purchase Premium license, you will get license key that can be used in multiple applications. This license key will then not be bound to application ID. Instead, it will be bound to the licensee string that needs to be provided to the library together with the license key. To provide licensee string, use something like this:

// set the license key
mRecognizer.Licensee = "Enter_Licensee_Here";
mRecognizer.LicenseKey = "Enter_License_Key_Here";

Events

OnAutofocusFailed

This event is raised when camera fails to perform autofocus even after multiple attempts. You should inform the user to try using camera under different light.

OnCameraError

This event is triggered on camera related errors. This event must be handled or the PDF417 library will throw an exception. Camera errors come in four different types:

  • NoCameraAtSelectedSensorLocation - There is no camera at selected location(front or right)
  • CameraNotReady - Camera is not ready
  • PreviewSizeTooSmall - Camera preview size is smaller than required
  • NotSupported - Required camera is not supported
OnScanningDone

This event is raised when scanning finishes and scan data is ready. This event must be handled or the PDF417 library will throw an exception. After recognition completes, RecognizerControl will pause its scanning loop and to continue the scanning you will have to call ResumeScanning method.

OnInitializationError

This event is raised when an error occurs during RecognizerControl initialization. At the moment only licensing errors trigger this event. This event must be handled or the PDF417 library will throw an exception.

OnControlInitialized

Triggered after canvas is initialized and camera is ready for receiving frames.

OnSuccessfulScanImage

Handle this event to obtain images that are currently being processed by the native library. This event will return images that resulted in a successful scan. Please take notice that installing this event handler introduces a large performance penalty.

OnOriginalImage

Handle this event to obtain images that are currently being processed by the native library. This event will return original images passed to recognition process. Please take notice that installing this event handler introduces a large performance penalty.

OnDewarpedImage

Handle this event to obtain images that are currently being processed by the native library. This event will return dewarped images from the recognition process. Please take notice that installing this event handler introduces a large performance penalty.

OnDisplayDefaultTarget

This event is raised when recognizer wants to put viewfinder in its default position (for example if detection has failed).

OnDisplayNewTarget

This event is raised when recognizer detects an object and wants to put viewfinder in position of detected object.

OnDisplayOcrResult

This event is raised when recognizer has OCR support enabled and has OCR result ready for displaying / using. You can handle this event to display real-time OCR results in preview.

OnDisplayPointSet

This event is raised when recognizer detects a non-rectangular object (e.g. 1D barcode, QR code, etc), instead of raising OnDisplayNewTarget. Handler will be provided with a list of detected object's feature points (in image coordinates). You can handle this event to display real-time detected object's feature points in preview.

Image coordinates refer to coordinates in video frame that has been analyzed. Usually the video frame is in landscape right mode, i.e. (0,0) represents the upper right corner and x coordinate rises downwards and y coordinate rises leftward.

OnShakingStartedEvent

Event is triggered when device shaking starts.

Using direct API for recognition of Android Bitmaps

This section will describe how to use direct API to recognize Windows Phone images without the need for camera.

  1. First, you need to obtain reference to Recognizer singleton.
  2. Second, you need to initialize the recognizer.
  3. After initialization, you can use the singleton to process images. You cannot process multiple images in parallel.
  4. Do not forget to terminate the recognizer after usage (it is a shared resource).

Here is the minimum example of usage of direct API for recognizing an image:

void InitDirectAPI() {
	// setup direct API
    Recognizer directRecognizer = Recognizer.GetSingletonInstance();                   
    if (directRecognizer.CurrentState == RecognizerDirectAPIState.OFFLINE) { 
    	// register event handler
        directRecognizer.OnScanningDone += recognizer_OnScanningDone;
        // unlock direct API
        try {
            directRecognizer.LicenseKey = "Enter license key here";
        }
        catch (InvalidLicenseKeyException exception) {
            // handle license key exception
        }
    }
    // recognize image
    BitmapImage image = new BitmapImage(new Uri("/path/to/some/file.jpg", UriKind.Absolute));
    directRecognizer.Recognize(image);
}

void recognizer_OnScanningDone(IList<Microblink.IRecognitionResult> resultList, RecognitionType recognitionType) {
    bool resultFound = false;
    if (recognitionType == RecognitionType.SUCCESSFUL) {                
        foreach (var result in resultList) {
            if (result.Valid && !result.Empty) {
				// display recognition results                                       
            }
        }                
    }
}

void TerminateDirectAPI() {
	// terminate direct API
    Recognizer.GetSingletonInstance().Terminate();
}

Understanding DirectAPI's state machine

DirectAPI's Recognizer singleton is actually a state machine which can be in one of 4 states: OFFLINE, UNLOCKED, READY and WORKING.

  • When you obtain the reference to Recognizer singleton, it will be in OFFLINE state.
  • First you need to unlock the Recognizer by providing a valid licence key using LicenseKey property(Licensee property can also be used if needed). If you attempt to set LicenseKey while Recognizer is not in OFFLINE state, you will get InvalidOperationException.
  • After successful unlocking, Recognizer singleton will move to UNLOCKED state.
  • Once in UNLOCKED state, you can initialize Recognizer by calling Initialize method. If you call Initialize method while Recognizer is not in UNLOCKED state, you will get InvalidOperationException.
  • After successful initialization, Recognizer will move to READY state. Now you can call Recognize method.
  • When starting recognition with Recognize methods, Recognizer will move to WORKING state. If you attempt to call these methods while Recognizer is not in READY state, you will get InvalidOperationException
  • Recognition is performed on background thread so it is safe to call all Recognizer's method from UI thread
  • When recognition is finished, Recognizer first moves back to READY state and then returns the result by fireing OnScanningDone event.
  • By calling Terminate method, Recognizer singleton will release all its internal resources and will request processing thread to terminate. Note that even after calling Terminate you might receive onScanningDone event if there was work in progress when Terminate was called.
  • Terminate method can be called from any Recognizer singleton's state
  • You can observe Recognizer singleton's state via CurrentState property

Using DirectAPI while RecognizerControl is active

Both RecognizerControl and DirectAPI recognizer use the same internal singleton that manages native code. This singleton handles initialization and termination of native library and propagating recognition settings to native library. If both RecognizerControl and DirectAPI attempt to use the same singleton, a race condition will occur. This race condition is always solved in RecognizerControl's favor, i.e.:

  • if RecognizerControl initializes the internal singleton before DirectAPI, DirectAPI's method Initialize will detect that and will make sure that its settings are applied immediately before performing recognition and after recognition RecognizerControl's settings will be restored to internal singleton
  • if DirectAPI initializes the internal singleton before RecognizerControl, RecognizerControl will detect that and will overwrite internal singleton's settings with its own settings. The side effect is that next call to Recognize on DirectAPI's Recognizer will not use settings given to Initialize method, but will instead use settings given to RecognizerControl.

If this raises too much confusion, we suggest not using DirectAPI while RecognizerControl is active, instead use RecognizerControl's methods Recognize or RecognizeWithSettings which will require no race conditions to be resolved.

Recognition settings and results

This chapter will discuss various recognition settings used to configure different recognizers and scan results generated by them.

Generic settings

Generic settings affect all enabled recognizers and the whole recognition process. Here is the list of properties that are most relevant:

bool AllowMultipleScanResults

Sets whether or not outputting of multiple scan results from same image is allowed. If that is true, it is possible to return multiple recognition results from same image. By default, this option is false, i.e. the array of IRecognitionResults will contain at most 1 element. The upside of setting that option to false is the speed - if you enable lots of recognizers, as soon as the first recognizer succeeds in scanning, recognition chain will be terminated and other recognizers will not get a chance to analyze the image. The downside is that you are then unable to obtain multiple results from single image.

int RecognitionTimeout

Number of miliseconds PDF417 will attempt to perform the scan before it exits with timeout error. On timeout returned array of IRecognitionResults might be null, empty or may contain only elements that are not valid (Valid is false) or are empty (Empty is true).

Scanning PDF417 barcodes

This section discusses the settings for setting up PDF417 recognizer and explains how to obtain results from PDF417 recognizer.

Setting up PDF417 recognizer

To activate PDF417 recognizer, you need to create a PDF417RecognizerSettings and add it to IRecognizerSettings array. You can do this using following code snippet:

using Microblink;

private IRecognizerSettings[] setupSettingsArray() {
	PDF417RecognizerSettings sett = new PDF417RecognizerSettings();
	
	// disable inverse scan mode
	sett.InverseScanMode = false;
	// enable null quiet zone
	sett.NullQuietZoneAllowed = true;
	// enable uncertain scan mode
    sett.UncertainScanMode = true	
	
	// now add sett to recognizer settings array that is used to configure
	// recognition
	return new IRecognizerSettings[] { sett };
}            

As can be seen from example, you can tweak PDF417 recognition parameters with properties of PDF417RecognizerSettings.

UncertainScanMode

By setting this property to true, you will enable scanning of non-standard elements, but there is no guarantee that all data will be read. This option is used when multiple rows are missing (e.g. not whole barcode is printed). Default is false.

NullQuietZoneAllowed

By setting this property to true, you will allow scanning barcodes which don't have quiet zone surrounding it (e.g. text concatenated with barcode). This option can significantly increase recognition time. Default is false.

InverseScanMode

By setting this to true, you will enable scanning of barcodes with inverse intensity values (i.e. white barcodes on dark background). This option can significantly increase recognition time. Default is false.

Obtaining results from PDF417 recognizer

PDF417 recognizer produces PDF417RecognitionResult. You can use is operator to check if element in results array is instance of PDF417RecognitionResult class. See the following snippet for an example:

using Microblink;

public void OnScanningDone(IList<IRecognitionResult> resultList, RecognitionType recognitionType) {   
    if (recognitionType == RecognitionType.SUCCESSFUL) {        
        foreach (var result in resultList) {
        	if (result is PDF417RecognitionResult) {			    
			    PDF417RecognitionResult pdf417Result = (PDF417RecognitionResult)result;
			    // you can use properties of PDF417RecognitionResult class to 
		        // obtain scanned information
		        if(result.Valid && !result.Empty) {
		        	bool uncertain = pdf417Result.Uncertain;
		        	string stringData = pdf417Result.StringData;
		        	BarcodeDetailedData rawData = pdf417Result.RawData;				    				    				    
			    } else {
		        	// not all relevant data was scanned, ask user
		        	// to try again
		        }   
			}            
        }                 
    }
}

Available properties are:

bool Valid

Set to true if scan result is valid, i.e. if all required elements were scanned with good confidence and can be used. If false is returned that indicates that some crucial data fields are missing. You should ask user to try scanning again. If you keep getting false (i.e. invalid data) for certain document, please report that as a bug to help.microblink.com. Please include high resolution photographs of problematic documents.

bool Empty

Set to true if scan result is empty, i.e. nothing was scanned. All getters should return null for empty result.

bool Uncertain

Indicates if scanned barcode is uncertain. This can be true only if scanning of uncertain barcodes is allowed, as explained earlier.

string StringData

This property holds string representation of barcode contents. Note that PDF417 barcode can contain binary data so sometimes it makes little sense to obtain only string representation of barcode data.

BarcodeDetailedData RawData

This property contains information about barcode's binary layout. If you only need to access containing byte array, you can call method GetAllData of BarcodeDetailedData object.

Scanning one dimensional barcodes with PDF417's implementation

This section discusses the settings for setting up 1D barcode recognizer that uses PDF417's implementation of scanning algorithms and explains how to obtain results from that recognizer. Henceforth, the 1D barcode recognizer that uses PDF417's implementation of scanning algorithms will be refered as "Bardecoder recognizer".

Setting up Bardecoder recognizer

To activate Bardecoder recognizer, you need to create a BarDecoderRecognizerSettings and add it to IRecognizerSettings array. You can do this using following code snippet:

using Microblink;

private IRecognizerSettings[] setupSettingsArray() {
	BarDecoderRecognizerSettings sett = new BarDecoderRecognizerSettings();
		
	// activate scanning of Code39 barcodes
	sett.ScanCode39 = true;
	// activate scanning of Code128 barcodes
	sett.ScanCode128 = true;
	// disable inverse scan mode
	sett.InverseScanMode = false;
	// disable slower algorithm for low resolution barcodes
	sett.TryHarder = false;
	// disable autodetection of image scale
	sett.AutoScaleDetection = false;
		
	// now add sett to recognizer settings array that is used to configure
	// recognition
	return new IRecognizerSettings[] { sett };
}            

As can be seen from example, you can tweak Bardecoder recognition parameters with properties of BarDecoderRecognizerSettings.

ScanCode128

Activates or deactivates the scanning of Code128 1D barcodes. Default (initial) value is false.

ScanCode39

Activates or deactivates the scanning of Code39 1D barcodes. Default (initial) value is false.

InverseScanMode

By setting this to true, you will enable scanning of barcodes with inverse intensity values (i.e. white barcodes on dark background). This option can significantly increase recognition time. Default is false.

AutoScaleDetection

Setting this property to true will enable autodetection of image scale when scanning barcodes. This enables correct reading of barcodes on high resolution images but slows down the recognition process.

TryHarder

By setting this to true, you will enabled scanning of lower resolution barcodes at cost of additional processing time. This option can significantly increase recognition time. Default is false.

Obtaining results from Bardecoder recognizer

Bardecoder recognizer produces BarDecoderRecognitionResult. You can use is operator to check if element in results array is instance of BarDecoderRecognitionResult class. See the following snippet for example:

using Microblink;

public void OnScanningDone(IList<IRecognitionResult> resultList, RecognitionType recognitionType) {   
    if (recognitionType == RecognitionType.SUCCESSFUL) {        
        foreach (var result in resultList) {
        	if (result is BarDecoderRecognitionResult) {			    
			    BarDecoderRecognitionResult bardecoderResult = (BarDecoderRecognitionResult)result;
			    // you can use properties of BarDecoderRecognitionResult class to 
		        // obtain scanned information
		        if(result.Valid && !result.Empty) {
		        	BarcodeType type = bardecoderResult.BarcodeType		        	
		        	string stringData = pdf417Result.StringData;
		        	BarcodeDetailedData rawData = pdf417Result.RawData;
		        	if (BarcodeType.CODE39.Equals(type)) {
			        	string stringDataExt = pdf417Result.ExtendedStringData;
			        	BarcodeDetailedData rawDataExt = pdf417Result.ExtendedRawData;
		        	}
			    } else {
		        	// not all relevant data was scanned, ask user
		        	// to try again
		        }   
			}            
        }                 
    }
}

As you can see from the example, obtaining data is rather simple. You just need to call several methods of the BarDecoderScanResult object:

bool Valid

Set to true if scan result is valid, i.e. if all required elements were scanned with good confidence and can be used. If false is returned that indicates that some crucial data fields are missing. You should ask user to try scanning again. If you keep getting false (i.e. invalid data) for certain document, please report that as a bug to help.microblink.com. Please include high resolution photographs of problematic documents.

bool Empty

Set to true if scan result is empty, i.e. nothing was scanned. All getters should return null for empty result.

string StringData

This property holds string representation of barcode contents.

BarcodeDetailedData RawData

This property contains information about barcode's binary layout. If you only need to access containing byte array, you can call method GetAllData of BarcodeDetailedData object.

string ExtendedStringData

This property holds string representation of extended barcode contents. This is available only if barcode that supports extended encoding mode was scanned (e.g. code39).

BarcodeDetailedData ExtendedRawData

This property contains information about barcode's binary layout when decoded in extended mode. If you only need to access containing byte array, you can call method GetAllData of BarcodeDetailedData object. This is available only if barcode that supports extended encoding mode was scanned (e.g. code39).

BarcodeType

This property is an enum that defines the type of barcode scanned.

Scanning barcodes with ZXing implementation

This section discusses the settings for setting up barcode recognizer that use ZXing's implementation of scanning algorithms and explains how to obtain results from it. PDF417 uses ZXing's c++ port to support barcodes for which we still do not have our own scanning algorithms. Also, since ZXing's c++ port is not maintained anymore, we also provide updates and bugfixes to it inside our codebase.

Setting up ZXing recognizer

To activate ZXing recognizer, you need to create a ZXingRecognizerSettings and add it to IRecognizerSettings array. You can do this using the following code snippet:

using Microblink;

private IRecognizerSettings[] setupSettingsArray() {
	ZXingRecognizerSettings sett = new ZXingRecognizerSettings();
	
	// disable inverse scan mode
	sett.InverseScanMode = false;
	// enable scanning of QR code
	sett.QRCode = true;
	// enable scanning of ITF barcode
	sett.ITFCode = true;
	
	// now add sett to recognizer settings array that is used to configure
	// recognition
	return new IRecognizerSettings[] { sett };
}            

As can be seen from example, you can tweak ZXing recognition parameters with properties of ZXingRecognizerSettings. Note that some barcodes, such as Code 39 are available for scanning with PDF417's implementation. You can choose to use only one implementation or both (just put both settings objects into IRecognizerSettings array). Using both implementations increases the chance of correct barcode recognition, but requires more processing time. Of course, we recommend using the PDF417's implementation for supported barcodes.

AztecCode

Activates or deactivates the scanning of Aztec 2D barcodes. Default (initial) value is false.

Code128

Activates or deactivates the scanning of Code128 1D barcodes. Default (initial) value is false.

Code39

Activates or deactivates the scanning of Code39 1D barcodes. Default (initial) value is false.

DataMatrixCode

Activates or deactivates the scanning of Data Matrix 2D barcodes. Default (initial) value is false.

EAN13Code

Activates or deactivates the scanning of EAN 13 1D barcodes. Default (initial) value is false.

EAN8Code

Activates or deactivates the scanning of EAN 8 1D barcodes. Default (initial) value is false.

ITFCode

Activates or deactivates the scanning of ITF 1D barcodes. Default (initial) value is false.

QRCode

Activates or deactivates the scanning of QR 2D barcodes. Default (initial) value is false.

UPCACode

Activates or deactivates the scanning of UPC A 1D barcodes. Default (initial) value is false.

UPCECode

Activates or deactivates the scanning of UPC E 1D barcodes. Default (initial) value is false.

InverseScanMode

By setting this to true, you will enable scanning of barcodes with inverse intensity values (i.e. white barcodes on dark background). This option can significantly increase recognition time. Default is false.

Obtaining results from ZXing recognizer

Bardecoder recognizer produces ZXingRecognitionResult. You can use is operator to check if element in results array is instance of ZXingRecognitionResult class. See the following snippet for example:

using Microblink;

public void OnScanningDone(IList<IRecognitionResult> resultList, RecognitionType recognitionType) {   
    if (recognitionType == RecognitionType.SUCCESSFUL) {        
        foreach (var result in resultList) {
        	if (result is ZXingRecognitionResult) {			    
			    ZXingRecognitionResult zxingResult = (ZXingRecognitionResult)result;
			    // you can use properties of ZXingRecognitionResult class to 
		        // obtain scanned information
		        if(result.Valid && !result.Empty) {
		        	bool uncertain = pdf417Result.Uncertain;
		        	string stringData = pdf417Result.StringData;
		        	BarcodeDetailedData rawData = pdf417Result.RawData;				    				    				    
			    } else {
		        	// not all relevant data was scanned, ask user
		        	// to try again
		        }   
			}            
        }                 
    }
}

As you can see from the example, obtaining data is rather simple. You just need to call several methods of the ZXingScanResult object:

bool Valid

Set to true if scan result is valid, i.e. if all required elements were scanned with good confidence and can be used. If false is returned that indicates that some crucial data fields are missing. You should ask user to try scanning again. If you keep getting false (i.e. invalid data) for certain document, please report that as a bug to help.microblink.com. Please include high resolution photographs of problematic documents.

bool Empty

Set to true if scan result is empty, i.e. nothing was scanned. All getters should return null for empty result.

string StringData

This property holds string representation of barcode contents.

BarcodeDetailedData RawData

This property contains information about barcode's binary layout. If you only need to access containing byte array, you can call method GetAllData of BarcodeDetailedData object.

string ExtendedStringData

This property holds string representation of extended barcode contents. This is available only if barcode that supports extended encoding mode was scanned (e.g. code39).

BarcodeDetailedData ExtendedRawData

This property contains information about barcode's binary layout when decoded in extended mode. If you only need to access containing byte array, you can call method GetAllData of BarcodeDetailedData object. This is available only if barcode that supports extended encoding mode was scanned (e.g. code39).

BarcodeType

This property is an enum that defines the type of barcode scanned.

Scanning US Driver's licence barcodes

This section discusses the settings for setting up USDL recognizer and explains how to obtain results from it.

Setting up USDL recognizer

To activate USDL recognizer, you need to create a USDLRecognizerSettings and add it to IRecognizerSettings array. You can do this using following code snippet:

using Microblink;

private IRecognizerSettings[] setupSettingsArray() {
	USDLRecognizerSettings sett = new USDLRecognizerSettings();
	
	// enable null quiet zone
	sett.NullQuietZoneAllowed = true;
	// enable uncertain scan mode
    sett.UncertainScanMode = true	
	
	// now add sett to recognizer settings array that is used to configure
	// recognition
	return new IRecognizerSettings[] { sett };
}            

As can be seen from example, you can tweak USDL recognition parameters with properties of USDLRecognizerSettings.

UncertainScanMode

By setting this property to true, you will enable scanning of non-standard elements, but there is no guarantee that all data will be read. This option is used when multiple rows are missing (e.g. not whole barcode is printed). Default is false.

NullQuietZoneAllowed

By setting this property to true, you will allow scanning barcodes which don't have quiet zone surrounding it (e.g. text concatenated with barcode). This option can significantly increase recognition time. Default is false.

Obtaining results from USDL recognizer

USDL recognizer produces USDLRecognitionResult. You can use is operator to check if element in results array is instance of USDLRecognitionResult. See the following snippet for an example:

using Microblink;

public void OnScanningDone(IList<IRecognitionResult> resultList, RecognitionType recognitionType) {   
    if (recognitionType == RecognitionType.SUCCESSFUL) {        
        foreach (var result in resultList) {
        	if (result is USDLRecognitionResult) {			    
			    USDLRecognitionResult usdlResult = (USDLRecognitionResult)result;
			    // you can use properties of USDLRecognitionResult class to 
		        // obtain scanned information
		        if(result.Valid && !result.Empty) {
		        	bool uncertain = usdlResult.Uncertain;
		        	string stringData = usdlResult.StringData;
		        	BarcodeDetailedData rawData = usdlResult.RawData;

		        	// if you need specific parsed driver's license element, you can
					// use GetField method
					// for example, to obtain AAMVA version, you should use:
					string aamvaVersion = usdlResult.GetField(USDLRecognitionResult.kAamvaVersionNumber);				    				    				    
			    } else {
		        	// not all relevant data was scanned, ask user
		        	// to try again
		        }   
			}            
        }                 
    }
}

Available properties are:

bool Valid

Set to true if scan result is valid, i.e. if all required elements were scanned with good confidence and can be used. If false is returned that indicates that some crucial data fields are missing. You should ask user to try scanning again. If you keep getting false (i.e. invalid data) for certain document, please report that as a bug to help.microblink.com. Please include high resolution photographs of problematic documents.

bool Empty

Set to true if scan result is empty, i.e. nothing was scanned. All getters should return null for empty result.

bool Uncertain

Indicates if scanned barcode is uncertain. This can be true only if scanning of uncertain barcodes is allowed, as explained earlier.

string StringData

This property holds string representation of barcode contents. Note that PDF417 barcode can contain binary data so sometimes it makes little sense to obtain only string representation of barcode data.

BarcodeDetailedData RawData

This property contains information about barcode's binary layout. If you only need to access containing byte array, you can call method GetAllData of BarcodeDetailedData object.

Method for retrieving specific driver's license element is:

string GetField(string)

This method will return a parsed US Driver's licence element. The method requires a key that defines which element should be returned and returns either a string representation of that element or null if that element does not exist in barcode. To see a list of available keys, refer to Keys for obtaining US Driver's license data

Troubleshooting

Integration problems

If you have followed Windows Phone integration instructions and are still having integration problems, please contact us at help.microblink.com.

SDK problems

In case of problems with using the SDK, you should do as follows:

Licensing problems

If you are getting "invalid license key" error or having other license-related problems (e.g. some feature is not enabled that should be or there is a watermark on top of camera), first check the log. All license-related problems are logged to error log so it is easy to determine what went wrong.

When you have determined what is the license-related problem or you simply do not understand the log, you should contact us help.microblink.com. When contacting us, please make sure you provide following information:

  • exact ID of your app (Product ID from your WMAppManifest.xml file)
  • license key that is causing problems
  • please stress out that you are reporting problem related to Windows Phone version of PDF417 SDK
  • if unsure about the problem, you should also provide excerpt from log containing license error

Other problems

If you are having problems with scanning certain items, undesired behaviour on specific device(s), crashes inside PDF417 or anything unmentioned, please do as follows:

  • enable logging to get the ability to see what is library doing. To enable logging, put this line in your application:

     Microblink.Log.Level = Microblink.Log.LogLevel.Verbose;	

    After this line, library will display as much information about its work as possible. Please save the entire log of scanning session to a file that you will send to us. It is important to send the entire log, not just the part where crash occured, because crashes are sometimes caused by unexpected behaviour in the early stage of the library initialization.

  • Contact us at help.microblink.com describing your problem and provide following information:

    • log file obtained in previous step
    • high resolution scan/photo of the item that you are trying to scan
    • information about device that you are using - we need exact model name of the device.
    • please stress out that you are reporting problem related to Windows Phone version of PDF417 SDK

Additional info

For any other questions, feel free to contact us at help.microblink.com.