Skip to main content

Barcode Scanner | Windows Barcode Scanner

The SDK offers various ways to extract barcodes from a live camera feed or still images.

Scanner UI

For live detection, you can use our so-called Ready-To-Use UI Component (RTU UI) or implement a custom scanner UI by using our Classic Component.

Ready-To-Use UI Component

This UI component is a final and ready-to-use Page component and is meant for the simplest interactions, with the fewest customizations possible, but can be implemented within a couple of minutes.

To launch Scanbot SDK's barcode scanner Page, run the following:

var scanner = new BarcodeScanner();
var configuration = new BarcodeScannerConfiguration();
BarcodeResult result = await scanner.Start(Frame, configuration);
Debug.WriteLine(result.Barcodes);

This approach returns a BarcodeResult object and then closes and properly disposes the scanner Page itself.

This BarcodeResult object contains a list of barcodes, each with a SoftwareBitmap containing a crop of the detected barcode, and, if something went wrong, a Scanbot.Model.ScanbotSdkException object with a message.

Classic Component

If you wish to build your own layout, we advise you to use BarcodeScannerComponent. It's a XAML-compliant camera component that offers endless recognition and handles all initialization and error-handling for you. This approach allows you full customization of the UI and workflow. Since you have full control over the lifecycle of this component, you can implement continuous scanning.

Add the component to your view:

<Grid x:Name="Root">
<scanbot:BarcodeScannerComponent x:Name="BarcodeScanner"/>
</Grid>

Implement lifecycle functions:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);

var configuration = new BarcodeScannerConfiguration();
await BarcodeScanner.Initialize(configuration);

BarcodeScanner.Recognized += OnRecognized;
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);

BarcodeScanner.Dispose();

BarcodeScanner.Recognized -= OnRecognized;
}

In this example we're presuming that your barcode scanner would be a separate Page, but you're free to initialize the scanner in any form or fashion, just don't forgot to dispose it when you're done, or else memory leaks are expected.

The result will either be an error or a list of barcodes, as follows:

private void OnRecognized(BarcodeResult result)
{
if (result.IsEmpty)
return;

Debug.WriteLine(result.Barcodes);
}

If you wish to do any additional processing after receiving a barcode result, there is an option to temporarily pause the scanner:

BarcodeScannerComponent.IsPaused = true;

If something went wrong initializing the component itself (e.g. permission issues, camera missing entirely), then BarcodeScannerComponent.Error event will be invoked.

User Guidance

In order to improve both the end user's experience and scanning quality, you can add visual guidance to the scanning UI.

This will help the user understand the desired positioning, orientation, and size of the scanned document or the QR/barcodes in the camera preview and take care of the preliminary processing to improve the results.

ViewFinder

In your layout, add the finder control alongside the barcode scanner within the same parent:

<Grid x:Name="Root">
<scanbot:BarcodeScannerComponent x:Name="BarcodeScanner"/>
<scanbot:FinderControl x:Name="Finder"/>
</Grid>

When calling Initialize on the BarcodeScannerComponent, the finder control is automatically detected.

For complex layouts, or if you want to explictly specify the finder control to use, it can be passed as a parameter to Initialize.

Customisation

FinderControl supported properties for styling the overlay:

  • HintText - The hint text shown underneath the hole.
  • HoleShape:
    • The shape of the hole made in the overlay.
    • Supported values are:
      • ShapeType.Rectangle
      • ShapeType.RoundedRectangle
      • ShapeType.Ellipse
      • ShapeType.Square
      • ShapeType.RoundedSquare
      • ShapeType.Circle
    • Defaults to ShapeType.RoundedRectangle.
  • HoleCornerRadius:
    • The size of the radius of each corner of a rounded rectangle or rounded square.
    • This property has no effect on other shape types.
  • HoleStrokeThickness - The thickness of the stroke around the hole.
  • HoleStrokeColor - The color of the stroke around the hole.
  • RelativeHoleWidth - The width of the hole, as a percentage of the overall control width.
  • RelativeHoleHeight - The height of the hole, as a percentage of the overall control width.
  • OverlayColor - The color of the overlay outside the area of the hole.

Additionally, the following read-only properties are available:

  • HoleBounds:
    • Represents the bounding box of the hole.
    • The dimensions are used internally to crop an area out of a camera snapshot.

XAML example:

<!-- All properties are explicitly set below, however each are optional (except for x:Name, which may be required). -->
<views:FinderControl
x:Name="Finder"
HintText="My hint text"
HoleShape="RoundedSquare"
HoleCornerRadius="10 30 10 30"
HoleStrokeThickness="20"
HoleStrokeColor="LightBlue"
RelativeHoleWidth="33"
RelativeHoleHeight="33"
OverlayColor="#aabbccdd"
/>

Code example:

var finder = new FinderControl();
finder.HintText = "My hint text";
finder.HoleShape = ShapeType.RoundedSquare;
finder.HoleCornerRadius = new CornerRadius(10, 30, 10, 30);
finder.HoleStrokeThickness = 20;
finder.HoleStrokeColor = Windows.UI.Colors.LightBlue;
finder.RelativeHoleWidth = 33;
finder.RelativeHoleHeight = 33;
finder.OverlayColor = Windows.UI.Color.FromArgb(0xdd, 0xaa, 0xbb, 0xcc);

Root.Children.Add(finder);

AR Overlay (or Barcode Overlay)

In addition to the ViewFinder, the barcode overlay can be enabled to display and select recognized barcodes in an augmented-reality fashion. Each recognized barcode will be presented on the barcode overlay by a colored frame and text.

The Selection Overlay works similarily to the Finder. First, you define it in XAML adjacent to the BarcodeScannerComponent (and/or FinderControl):

<Grid x:Name="Root">
<scanbot:BarcodeScannerComponent x:Name="BarcodeScanner"/>
<!-- The finder control can also be used in combination with the selection overlay, if desired. -->
<!-- <scanbot:FinderControl x:Name="Finder"/> -->

<scanbot:SelectionOverlayControl x:Name="SelectionOverlay" />
</Grid>

When calling Initialize on the BarcodeScannerComponent, the selection overlay control is automatically detected.

For complex layouts, or if you want to explictly specify the selection overlay control to use, it can be passed as a parameter to Initialize.

Customisation

SelectionOverlayControl supported properties for styling the overlay:

  • PolygonColor - The color of the polygon which covers a detected barcode.
  • TextColor - The color of the text which appears underneath the detection polygon.
  • TextBackgroundColor - The color of the background which surrounds the text under the detection polygon.
  • HighlightedPolygonColor - The color of the detection polygon, when a barcode is marked as highlighted.
  • HighlightedTextColor - The color of the text, when a barcode is marked as highlighted.
  • HighlightedTextBackgroundColor - The color of the background which surrounds the text, when a barcode is marked as highlighted.
  • HighlightedBarcodes - The barcodes marked as highlighted.
    • If a barcode is marked as highlighted, then the highlighted family of color properties are used instead of the regular ones when the detected barcode comes into view.
  • PolygonTapped - A callback which is triggered if a barcode polygon is tapped.
    • If no callback is added, the default implementation will add/remove barcodes to the HighlightedBarcodes collection and set the appropriate colors.
    • If a callback is added, the callback assumes responsibility for setting the colors for the barcode as well as adding/removing barcodes to/from HighlightedBarcodes. An example of this is present in the code example below.
  • FormatText - A callback which allows the barcode text to be modified before being shown on screen. The text alignment can also be set.
    • If no callback is added, the default implementation leaves the barcode data as-is and aligns it to the left.

XAML example:

<!-- All properties are explicitly set below, however each are optional (except for x:Name, which may be required). -->
<scanbot:SelectionOverlayControl
x:Name="SelectionOverlay"
PolygonColor="Red"
TextColor="White"
TextBackgroundColor="Red"
HighlightedPolygonColor="Green"
HighlightedTextColor="Black"
HighlightedTextBackgroundColor="Green"
PolygonTapped="OnPolygonTapped"
FormatText="OnFormatText"
/>

Code example:

// All properties are explicitly set below, however each are optional.
var selectionOverlay = new SelectionOverlayControl();
selectionOverlay.PolygonColor = Windows.UI.Colors.Red;
selectionOverlay.TextColor = Windows.UI.Colors.White;
selectionOverlay.TextBackgroundColor = Windows.UI.Colors.Red;
selectionOverlay.HighlightedPolygonColor = Windows.UI.Colors.Green;
selectionOverlay.HighlightedTextColor = Windows.UI.Colors.Black;
selectionOverlay.HighlightedTextBackgroundColor = Windows.UI.Colors.Green;
selectionOverlay.PolygonTapped += OnPolygonTapped;
selectionOverlay.FormatText += OnFormatText;

Root.Children.Add(selectionOverlay);

Below is a example for a PolygonTapped callback:

private void OnPolygonTapped(object sender, BarcodeFigure e)
{
var selectionOverlay = sender as SelectionOverlayControl;

if (selectionOverlay == null)
{
return;
}

if (!selectionOverlay.HighlightedBarcodes.Contains(e.Barcode))
{
e.PolygonStroke = selectionOverlay.HighlightedPolygonColor.Brush();
e.PolygonFill = selectionOverlay.HighlightedPolygonColor.Brush(0.3);
e.TextBackground = selectionOverlay.HighlightedTextBackgroundColor.Brush(0.7);
e.TextColor = selectionOverlay.HighlightedTextColor.Brush();
selectionOverlay.HighlightedBarcodes.Add(e.Barcode);
}
else
{
// removing the barcode will cause it to reset to the default colors
// specified via the `PolygonColor`, `TextBackgroundColor` and `HighlightedTextColor` properties,
// thus no need to specify them manually.
selectionOverlay.HighlightedBarcodes.Remove(e.Barcode);
}

// Any additional processing of the barcode itself, or close the scanner etc.
}

Here is another example for the FormatText callback which formats a string with the barcode type and the barcode value:

private Tuple<string, TextAlignment> OnFormatText(Scanbot.Model.Barcode arg)
{
return Tuple.Create($"{arg.Type}: {arg.Text}", TextAlignment.Left);
}

Configuration

Any barcode scanning option, be it still image detection, RTU UI, or Classic Component, accepts a BarcodeScannerConfiguration parameter. This config parameter is optional, and all properties within the configuration object are optional as well.

The following configuration parameters are available:

  • AcceptedTypes – List of barcode formats that acts as a detection filter. By default, the most common supported formats will be detected.
  • Engine - The engine used to detect barcodes, see specific enumeration values for description. Defaults to EngineMode.Balanced.
  • DecodingOptions - Additional decoding options for specific barcode types.
    • UseIATA2OF5Checksum:
      • Determines if the checksum of an IATA 2 of 5 barcode should be checked.
      • The barcode may not be recognised if the flag is true and the barcode doesn't have the checksum encoded.
      • Defaults to true.
  • Camera - Additional options for customising the camera and also how frames are captured. See below for more details.

Camera Configuration

The Camera has several properties:

  • Direction - Whether the front or back camera is preferred. Defaults to CameraDirection.Back
  • FocusMode - Focus mode of the Camera.
  • Mirrored:
    • Determines whether the preview stream should be horizontally mirrored.
    • If unset, mirrored flow is used for the front camera and natural flow for the back camera.
    • Defaults to null.
  • Resolution - Additional resolution settings relating how frames are captured (with all values defaulting to null):
    • ConstrainedWidth:
      • The intended width of the output frame.
      • The height is scaled to the aspect ratio of the camera.
      • Takes precedence over the other parameters if it is set.
    • ConstrainedHeight:
      • The intended height of the output frame.
      • Has no effect when ConstrainedWidth is set.
    • ResolutionScale:
      • A scale value to multiply the camera width and height by.
      • 1.0 is treated as 100%, thus 0.5 will be half and 2.0 will be double the resolution.
      • Has no effect if either ConstrainedWidth or ConstrainedHeight is set.

Additional FocusMode Notes

Numerous laptop makes and models have a fixed-focus camera hardware component, meaning configuration is severely limited. Scanbot provides the following advanced options for controlling focus mode (please note that only some, or maybe none of them, may be supported by your target device):

"A photographic lens for which the focus is not adjustable is called a fixed-focus lens or sometimes focus-free. The focus is set at the time of lens design, and remains fixed. It is usually set to the hyperfocal distance, so that the depth of field ranges all the way down from half that distance to infinity, which is acceptable for most cameras used for capturing images of humans or objects larger than a meter".

If you would like to know more, check out this Wikipedia article.

Continuous Focus

Continuous focus is functionally the simplest option. You tell the camera to just try and keep focusing all the time:

await BarcodeScanner.Camera.ConfigureContinuousFocus();

Support can be queried via:

BarcodeScanner.Camera.IsContinuousFocusSupported;

Manual Focus

To configure manual focus, make a call similar to continuous focus:

await BarcodeScanner.Camera.ConfigureManualFocus(value);

Support can be queried via:

BarcodeScanner.Camera.IsManualFocusSupported;

To find out what the min, max and default focus values are, call:

BarcodeScanner.Camera.FocusControl.Min;
BarcodeScanner.Camera.FocusControl.Max;
BarcodeScanner.Camera.FocusControl.Value;

Regional Focus

In addition to using continuous focus or configuring it manually, the Scanbot Windows SDK provides the option to set the focus in a so-called tap-to-focus fashion.

var position = e.GetPosition(sender as UIElement);
var height = BarcodeScanner.HoleRect.Height / 4;
var size = new Size(height, height);

await BarcodeScanner.Camera.UpdateTapToFocusRegion(position, size, new RegionalFocusOptions());

The e is the TappedRoutedEventArgs callback argument of either of these two tap event listeners:

BarcodeScanner.CaptureElement.Tapped += OnCaptureElementTap;
BarcodeScanner.ViewFinder.Tapped += OnViewFinderTap;

Use them accordingly, whether you want to display the ViewFinder or not.

Regional focus contains the following options:

public bool AutoFocus { get; set; }
public bool AutoExposure { get; set; }
public bool AutoWhiteBalance { get; set; }

Before setting these values, be sure to check whether updating them is permitted via the api as such:

BarcodeScanner.MediaCapture.VideoDeviceController.RegionsOfInterestControl.AutoFocusSupported

Please note that updating these values, whether to true or false, may lead to crashes if the feature is not supported.

Utilities

In addition to numerous view and image processing functions, the Scanbot Windows SDK also features utility functions. These are available under Scanbot.Utils namespace:

  • BarcodeType.Description() to get a formatted string of a certain barcode type
  • VideoFrame.Crop(Windows.Foundation.Rect) to crop a frame to the specified Rect

Advanced Features

In addition to these convenience functions offered by Scanbot, you are free to use the native MediaCapture features accessible via BarcodeScanner.MediaCapture.VideoDeviceController.

VideoDeviceController offers degrees of configuration over various controls such as WhiteBalanceControl, ExposureControl, IsoSpeedControl and much more.

Find out more on Microsoft's official documentation page here.

Want to scan longer than one minute?

Generate your free "no-strings-attached" Trial License and properly test the Scanbot SDK.

Get your free Trial License

What do you think of this documentation?