If you’ve updated Windows Phone 7.5, you might have noticed that it has some nice built-in functionality for reading QR Codes using Bing Vision search.  After trying it out for a while, I pretty quickly started wondering how I could use this in an app, and equally quickly I was disappointed to find that there are no APIs available for 3rd party developers to access this feature.

After a short hunt online, I found an excellent library that can be used as an alternative, and I built a simple reader with it.  Here are the basic steps to create one yourself:

 

NOTE: To build and test this example you must use a physical phone rather than the emulator, as you will need access to the camera feed. 

 

Create a new Windows Phone Project in Visual Studio

I used Visual Studio Ultimate, but the Express version that ships with the Windows Phone SDK will do just fine.  Use the basic phone template for this example:

image

Be sure to select ‘Windows Phone 7.1’ as the target OS:

image

 

Update the App Manifest

If you plan to submit a camera-based app to the marketplace, then you must ensure that the WMAppManifest.xaml contains this capability element:

<Capability Name="ID_CAP_ISV_CAMERA"/>

A different element is required for the front-facing camera: ID_HW_FRONTCAMERA

Create the QR Reader Window and Output Area

Inside the content Grid in MainPage.xaml, add a Rectangle and a TextBlock:

 

<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
    <TextBlock x:Name="ApplicationTitle" Text="QR SCANNER"
                Style="{StaticResource PhoneTextNormalStyle}"/>
    <TextBlock x:Name="PageTitle" Text="scanner" Margin="9,-7,0,0"
                Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
 
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <!-- rectangle which acts as the 'camera window' -->
    <Rectangle Height="300" HorizontalAlignment="Left" Margin="82,61,0,0"
                Name="videoRectangle" Stroke="White" StrokeThickness="5"
                VerticalAlignment="Top" Width="300">
        <Rectangle.RenderTransform>
            <RotateTransform x:Name="videoRotateTransform"/>
        </Rectangle.RenderTransform>
        <Rectangle.Fill>
            <VideoBrush x:Name="viewfinderBrush"/>
        </Rectangle.Fill>
    </Rectangle>
            
    <!-- Textblock which will hold the output of the QR Code -->
    <TextBlock Height="171" HorizontalAlignment="Left" Margin="31,406,0,0"
                Name="resultText" Text="&lt;nothing to display&gt;"
                VerticalAlignment="Top" Width="399" TextWrapping="Wrap"
                TextAlignment="Center" />
</Grid>

 

This should result in a main page like this:

scanner

 

The Rectangle will act as the camera viewer – notice that it has a VideoBrush as its fill;  this will eventually contain the live feed from the camera.  The TextBlock will display the content read from the QR Code.

Directives and Variables

In MainPage.xaml.cs, add a few relevant using statements, such as for the Devices namespace so we can use the PhotoCamera type:

using Microsoft.Devices;
using System.IO;
using System.Windows.Media.Imaging;
 

Declare some variables inside the main app class:

private PhotoCamera camera;
private bool capturing = false;
   

Handle Navigation

It is recommended practice to initialise and dispose of the camera object when we navigate to and from our page, respectively, so we need to override these methods:

 

 
protected override void OnNavigatedTo(
           System.Windows.Navigation.NavigationEventArgs e)
{
    if (null == camera)
    {
        camera = new PhotoCamera();
 
        // filred when the camera is initialised
        camera.Initialized += camera_Initialised;
 
        // fired when the button is fully pressed
        CameraButtons.ShutterKeyPressed += camera_ButtonFullPress;
 
        // fired when an image is available.
        camera.CaptureImageAvailable += camera_CaptureImageAvailable;
 
        // set the VideoBrush source to the camera output
        videoRotateTransform.CenterX = videoRectangle.Width / 2;
        videoRotateTransform.CenterY = videoRectangle.Height / 2;
        videoRotateTransform.Angle = 90;
 
        viewfinderBrush.SetSource(camera);
    }
 
    base.OnNavigatedTo(e);
}
 
// user navigated away from page
protected override void OnNavigatedFrom(
           System.Windows.Navigation.NavigationEventArgs e)
{
    if (camera != null)
    {
        // unhook the event handlers
        CameraButtons.ShutterKeyPressed -= camera_ButtonFullPress;
        camera.CaptureImageAvailable -= camera_CaptureImageAvailable;
        camera.Initialized -= camera_Initialised;
 
        // dispose of the camera object
        camera.Dispose();
    }
 
    base.OnNavigatedFrom(e);
}

 

Here the PhotoCamera object is initialised to to use ‘primary’ camera, which is the rear-facing one. If you want to use the front-facing camera in an application, then you can call the alternate constructor like this:

camera = new PhotoCamera(CameraType.FrontFacing);

 

Add Camera Event Handlers

The event handlers are quite simple and simply initialise some settings and respond to the user taking a picture:

private void camera_Initialised(object sender, CameraOperationCompletedEventArgs e)
{
    // set the camera resolution
    if (e.Succeeded)
    {
        var res = from resolution in camera.AvailableResolutions
                    where resolution.Width == 640
                    select resolution;
 
        camera.Resolution = res.First();
    }
}
 
// user has pressed the camera button
private void camera_ButtonFullPress(object sender, EventArgs e)
{
    if (capturing) return;
 
    capturing = true;
 
    camera.CaptureImage();
}

We will add the ‘camera_CaptureImageAvailable’ handler later.

 

Download the Barcode Library

The library can be downloaded here:

http://twit88.com/platform/projects/show/mt-barcode

It ships with a sample Windows Phone 7 app, but this doesn’t read the data directly from the camera; instead it uses some hard-coded test images.  It also ships with an example desktop app for generating your own codes.

 

Add the Barcode Library to the Project

In MainPage.xaml.cs, add the following using statement:

 

using MessagingToolkit.Barcode;

 

Add a reference to the Windows Phone 7 version of the library:

 

image

Decode the QR Code Image

The camera_CaptureImageAvailable event handler is called once we have an image to process. This is where we try to decode any possible QR Code it contains:

 

private void camera_CaptureImageAvailable(
    object sender, 
    ContentReadyEventArgs e)
{
    capturing = false;
 
    Stream imageStream = (Stream)e.ImageStream;
    BarcodeDecoder barcodeDecoder = new BarcodeDecoder();
 
    Dictionary<DecodeOptions, object> decodingOptions = 
                        new Dictionary<DecodeOptions, object>();
    List<BarcodeFormat> possibleFormats = new List<BarcodeFormat>(1);
    Result result;
 
    Dispatcher.BeginInvoke(() =>
    {
 
        WriteableBitmap qrImage = new WriteableBitmap(
                                        (int)camera.Resolution.Width, 
                                        (int)camera.Resolution.Height);
        imageStream.Position = 0;
        qrImage.LoadJpeg(imageStream);
 
        possibleFormats.Add(BarcodeFormat.QRCode);
 
        decodingOptions.Add(
            DecodeOptions.PossibleFormats, 
            possibleFormats);
 
        try
        {
            result = barcodeDecoder.Decode(qrImage, decodingOptions);
 
            resultText.Text = result.Text;
        }
        catch (NotFoundException)
        {
            // this is expected if the image does not contain a valid
            // code, Or is too distorted to read
            resultText.Text = "<nothing to display>";
        }
        catch (Exception ex)
        {
            // something else went wrong, so alert the user
            MessageBox.Show(
                ex.Message, 
                "Error Decoding Image", 
                MessageBoxButton.OK);
        }
    });
}

Compile and Deploy

As mentioned at the top of this post, you will need to deploy the app to a real phone, since the Emulator generates its own test output which is useless in this case.

That’s it.  You should now have a basic QR Reader.  Test it by reading the code below:

qrsample