×
Namespaces

Variants
Actions

Generating and scanning barcodes using ZXing on Windows Phone

From Nokia Developer Wiki
Jump to: navigation, search
Featured Article
04 Aug
2013

This article explains how to add barcode reading and scanning capabilities to your Windows Phone application using the ZXing library.

Tip.pngTip: Developers should consider the Optical Reader Library for Windows Phone 8. This delivers an Optical Reader Task that can easily be embedded in Windows Phone 8 apps. It uses ZXing (by default) "under the hood" but is pre-configured and optimised for the camera capabilities of Nokia devices. It is also extensible to use other decoders and image enhancement routines. ZXing is still required directly for image generation.

WP Metro Icon Multimedia.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata
Code ExampleTested with
Devices(s): Nokia Lumia 800, Windows Phone 8 Emulator, Nokia Lumia 920
CompatibilityPlatform Security
Capabilities: ID_CAP_ISV_CAMERA
Article
Created: PedroQ (21 Jul 2013)
Last edited: hamishwillee (12 Feb 2014)
See Also

Contents

Introduction

A barcode is a way to represent data in a way that can be read by a machine. Everyday you see barcodes in the world around you. In every food package, every book, every CD, you'll notice that every single item has a barcode, which is used to identify the item it is attached to. There are a lot of formats and types of barcodes. Some are simply group of vertical lines parallel to each other. By varying the width of each line, data can be encoded in them. These are called 1D (one-dimensional) barcodes. Others encode data using a set of geometrical patterns. These are called 2D barcodes, or matrix codes and are able to store more data. A common example of a 2D barcode is a format called QR Code. With the smartphone revolution, QR Codes became really popular. In advertisements, for example, you can quickly go to the product website by scanning a QR Code. Or you can share your contact information using a QR Code.

By default, both Windows Phone 7 and Windows Phone 8 are able to read some types of barcodes (QR Code, EAN-13, Microsoft Tag) using the Bing Vision app (to use it, tap the search button and select the eye icon in the Application Bar). However sometimes you'll need to read a barcode that Bing Vision does not support, or you'll want to be able to add barcode functionality into your application (for example, in an app to keep track of the DVD's your friends borrowed from you). Libraries like this usually support a lot of barcode types and can help you in these tasks.

In this article you'll learn how you can add the ability of generating and scanning barcodes using the phone camera to your Windows Phone application. In this example. we'll create a simple app that generates a QR Code containing a phone number you want to share and is able to scan barcodes and display the data stored in them.

Libraries

We'll use a library called ZXing.Net, which is a .Net port of the popular ZXing open-source library that gives developers the ability to read and generate barcodes. ZXing.Net is avaliable as NuGet package, so we'll use this method to add this reference to our project.

Go to the Solution Explorer, right click the project file and select Manage NuGet Packages. Search for ZXing.Net and click Install. You can also use the Package Manager Console to install packages. Run the following command to install ZXing.Net using this method: PM> Install-Package ZXing.Net.

Generate barcodes

In this example we'll generate a QR Code containing a telephone number. We'll user the PhoneNumberChooserTask to launch the Contacts application and to obtain the phone number of a contact selected by the user.

PhoneNumberChooserTask phoneNumberChooserTask;
phoneNumberChooserTask = new PhoneNumberChooserTask();
phoneNumberChooserTask.Completed += phoneNumberChooserTask_Completed;


Now we'll generate the QR Code with the selected phone number:

private static WriteableBitmap GenerateQRCode(string phoneNumber)
{
BarcodeWriter _writer = new BarcodeWriter();
 
_writer.Renderer = new ZXing.Rendering.WriteableBitmapRenderer()
{
Foreground = System.Windows.Media.Color.FromArgb(255, 0, 0, 255) // blue
};
 
_writer.Format = BarcodeFormat.QR_CODE;
 
 
_writer.Options.Height = 400;
_writer.Options.Width = 400;
_writer.Options.Margin = 1;
 
var barcodeImage = _writer.Write("tel:" + phoneNumber); //tel: prefix for phone numbers
 
return barcodeImage;
}

The BarcodeWriter has some properties that allow a lot of customization:

  • The Renderer property is used to change the appearance of the barcode, such as the background and foreground colors, font size, weight and family. In this example we'll set blue as the Foreground color, which will create a blue QR Code in a white Background.
  • The Format property is used to select the barcode format to generate. For this example we'll generate an QR Code.
  • The Options property allows us to specify the dimensions of the barcode to generate, as well as define its margins.

You'll notice that in this case we prefix the encoded data with tel:. This is to allow the QR Code readers to understand that the content of this barcode is a telephone number. This particular type of barcodes, the QR Code, supports a lot of this prefixes. You can find a detailed list of this standards here.

Here is an example of a generated QR Code:

A sample QR Code with a phone number

These are some other examples of barcodes that can be generated:

Scan barcodes

Adding barcode scanning capabilities to your app can sometimes be very useful. For example, a price search application would be much more easy to use if you could just point your phone's camera at the barcode and click search.

In our example application, we'll add the scanning feature in a different page called Scan.xaml. This page contains a viewfinder so the user can see what the phone camera is capturing and an area to display informations about the barcode. Portions of this example were taken from these articles: How to create a base camera app for Windows Phone and How to use camera focus in an app for Windows Phone.

This is the XAML code for the page:

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
 
<Canvas x:Name="viewfinderCanvas">
 
<!--Camera viewfinder -->
<Canvas.Background>
 
<VideoBrush x:Name="viewfinderBrush">
<VideoBrush.RelativeTransform>
<CompositeTransform
x:Name="viewfinderTransform"
CenterX="0.5"
CenterY="0.5"
Rotation="90"/>
</VideoBrush.RelativeTransform>
</VideoBrush>
</Canvas.Background>
<TextBlock
x:Name="focusBrackets"
Text="[ ]"
FontSize="40"
Visibility="Collapsed"/>
</Canvas>
<!--Used for debugging >-->
<StackPanel Grid.Row="1" Margin="20, 0">
<TextBlock x:Name="tbBarcodeType" FontWeight="ExtraBold" />
<TextBlock x:Name="tbBarcodeData" FontWeight="ExtraBold" TextWrapping="Wrap" />
</StackPanel>
</Grid>

This is the code behind:

public partial class Scan : PhoneApplicationPage
{
private PhotoCamera _phoneCamera;
private IBarcodeReader _barcodeReader;
private DispatcherTimer _scanTimer;
private WriteableBitmap _previewBuffer;
 
public Scan()
{
InitializeComponent();
}
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
// Initialize the camera object
_phoneCamera = new PhotoCamera();
_phoneCamera.Initialized += cam_Initialized;
_phoneCamera.AutoFocusCompleted += _phoneCamera_AutoFocusCompleted;
 
CameraButtons.ShutterKeyHalfPressed += CameraButtons_ShutterKeyHalfPressed;
 
//Display the camera feed in the UI
viewfinderBrush.SetSource(_phoneCamera);
 
 
// This timer will be used to scan the camera buffer every 250ms and scan for any barcodes
_scanTimer = new DispatcherTimer();
_scanTimer.Interval = TimeSpan.FromMilliseconds(250);
_scanTimer.Tick += (o, arg) => ScanForBarcode();
 
viewfinderCanvas.Tap += new EventHandler<GestureEventArgs>(focus_Tapped);
 
base.OnNavigatedTo(e);
}
 
void _phoneCamera_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
focusBrackets.Visibility = Visibility.Collapsed;
});
}
 
void focus_Tapped(object sender, GestureEventArgs e)
{
if (_phoneCamera != null)
{
if (_phoneCamera.IsFocusAtPointSupported == true)
{
// Determine the location of the tap.
Point tapLocation = e.GetPosition(viewfinderCanvas);
 
// Position the focus brackets with the estimated offsets.
focusBrackets.SetValue(Canvas.LeftProperty, tapLocation.X - 30);
focusBrackets.SetValue(Canvas.TopProperty, tapLocation.Y - 28);
 
// Determine the focus point.
double focusXPercentage = tapLocation.X / viewfinderCanvas.ActualWidth;
double focusYPercentage = tapLocation.Y / viewfinderCanvas.ActualHeight;
 
// Show the focus brackets and focus at point.
focusBrackets.Visibility = Visibility.Visible;
_phoneCamera.FocusAtPoint(focusXPercentage, focusYPercentage);
}
}
}
 
void CameraButtons_ShutterKeyHalfPressed(object sender, EventArgs e)
{
_phoneCamera.Focus();
}
 
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
//we're navigating away from this page, we won't be scanning any barcodes
_scanTimer.Stop();
 
if (_phoneCamera != null)
{
// Cleanup
_phoneCamera.Dispose();
_phoneCamera.Initialized -= cam_Initialized;
CameraButtons.ShutterKeyHalfPressed -= CameraButtons_ShutterKeyHalfPressed;
}
}
 
void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
{
if (e.Succeeded)
{
this.Dispatcher.BeginInvoke(delegate()
{
_phoneCamera.FlashMode = FlashMode.Off;
_previewBuffer = new WriteableBitmap((int)_phoneCamera.PreviewResolution.Width, (int)_phoneCamera.PreviewResolution.Height);
 
_barcodeReader = new BarcodeReader();
 
// By default, BarcodeReader will scan every supported barcode type
// If we want to limit the type of barcodes our app can read,
// we can do it by adding each format to this list object
 
//var supportedBarcodeFormats = new List<BarcodeFormat>();
//supportedBarcodeFormats.Add(BarcodeFormat.QR_CODE);
//supportedBarcodeFormats.Add(BarcodeFormat.DATA_MATRIX);
//_bcReader.PossibleFormats = supportedBarcodeFormats;
 
_barcodeReader.TryHarder = true;
 
_barcodeReader.ResultFound += _bcReader_ResultFound;
_scanTimer.Start();
});
}
else
{
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Unable to initialize the camera");
});
}
}
 
void _bcReader_ResultFound(Result obj)
{
// If a new barcode is found, vibrate the device and display the barcode details in the UI
if (!obj.Text.Equals(tbBarcodeData.Text))
{
VibrateController.Default.Start(TimeSpan.FromMilliseconds(100));
tbBarcodeType.Text = obj.BarcodeFormat.ToString();
tbBarcodeData.Text = obj.Text;
}
}
 
private void ScanForBarcode()
{
//grab a camera snapshot
_phoneCamera.GetPreviewBufferArgb32(_previewBuffer.Pixels);
_previewBuffer.Invalidate();
 
//scan the captured snapshot for barcodes
//if a barcode is found, the ResultFound event will fire
_barcodeReader.Decode(_previewBuffer);
 
}
 
}

After having a functioning camera application, scanning for barcodes is actually quite simple. The ZXing.Net library contains a class called BarcodeReader. You use the method Decode to scan a WriteableBitmap for barcodes. If any barcode is found, the ResultFound event will fire.

In this example a DispatcherTimer _scanTimer is used to grab a snapshot of what the camera is capturing and feed it to the BarcodeReader class.

By default, the BarcodeReader class will scan for every supported barcode format in an image. If you want to constraint this process to just a few formats, all you need to do is set the PossibleFormats on the BarcodeReader object. If you're having trouble scanning some barcodes, specially 1D codes, you can try to set the TryHarder property to true. Note that this will have some impact on performance, but at least on my Lumia 800 it is not that noticeable.

Here are some examples of scanned barcodes:

Summary

In this article we covered the scanning and generation of barcodes on the Windows Phone platform using the ZXing.Net library. It supports a wide range of platforms, which may be useful if you're targeting not only Windows Phone. As this is a port from a commonly used library in Android applications, you'll find a lot of documentation that can help you. Feel free to download the example application (File:WPBarcodes.zip) and play with it!

There are other libraries that offer the same functionality, for example the Telerik RadControls for Windows Phone suite. If you are member of the Nokia Premium Developer Program for Lumia, you can access it for free.

This page was last modified on 12 February 2014, at 03:46.
1846 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×