Posts
417
Comments
233
Trackbacks
42
July 2012 Entries
Reading QR Codes In Your Windows Phone App

qrcode.6083951

I have recently been working on an application for a client that needs to read QR codes.  This has lead to some interesting findings.  There are a couple of approaches you can use.  One is to take a picture and evaluate it for a code and the other is more like the Bing Vision feature.  Both of them can be accomplished by leveraging theSilverlight ZXing library from Codeplex.

In order to have QR code images to test I would suggest going to QRStuff.com.  It is a site where you can freely generate QR images that you can prove out your app against.  This is how I generated the image at the top of this post.  If your code is working at the end you should be able to easily get back to this site.  Wink! Wink!

So how do we write this code?  I am going to take a quick look at both approaches and we can see which one we prefer at the end.  For full disclosure I actually borrowed the code for both from other sites, although I don’t have references to them.

Approach 1

The first approach opens a camera object and then you press the shutter button in order to focus and capture an image of code.  You will be asked to accept or retake the image.  The main component of this code is a CameraCaptureTask instance which you will then need an even to show.

private CameraCaptureTask camera = new CameraCaptureTask();

private void ScanButton_Click(object sender, RoutedEventArgs e)
{
camera.Completed += new EventHandler<PhotoResult>(camera_Completed);
camera.Show();
}

Your code then needs to capture the completed event for the CameraCaptureTask and then pass the image to code which will check it for a proper QR code.

void camera_Completed(object sender, PhotoResult e)         
{
camera.Completed -= new EventHandler<PhotoResult>(camera_Completed);

if (e.TaskResult == TaskResult.OK)
{
BitmapImage bmp = new BitmapImage();
bmp.CreateOptions = BitmapCreateOptions.None;

bmp.SetSource(e.ChosenPhoto);
textBlock1.Text = string.Empty;
WriteableBitmap wbmp = new WriteableBitmap(bmp);
string recognizedBarcode = string.Empty;

if (BarcodeHelper.TryToRecognizeQRcode(wbmp, out recognizedBarcode))
textBlock1.Text = recognizedBarcode;
else
textBlock1.Text = "Unrecognizable barcode! " + recognizedBarcode;
}
}

Below is the code within the BarcodeHelper which actually processes the image.

public static bool TryToRecognizeQRcode(WriteableBitmap wb, out string qrCode)         
{
var zxhints = new Dictionary<object, object>()
{
{ DecodeHintType.TRY_HARDER, true },
};
// create reader instance
var reader = new com.google.zxing.qrcode.QRCodeReader();
return TryToRecognize(wb, reader, null, out qrCode);
}

My experience with this code is that it doesn’t recognize the codes as often as it does.  This give the illusion of being less accurate since each time you accept an image it lets you know if it recognized it or not.

Approach 2

The second approach involves using the preview buffer for the phone’s camera.  To start you need to create a PhoneApplicationPage and strip it down to bare bones (no titles) and add rectangle object to the main grid with a VideoBrush fill.  It also needs a ListBox to display the results.

<Grid x:Name="LayoutRoot" Background="Transparent">
<Rectangle x:Name="_previewRect"
Margin="0"
Height="800"
Width="600"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Rectangle.Fill>
<VideoBrush x:Name="_previewVideo">
<VideoBrush.RelativeTransform>
<CompositeTransform
x:Name="_previewTransform" CenterX=".5" CenterY=".5" />
</VideoBrush.RelativeTransform>
</VideoBrush>
</Rectangle.Fill>
</Rectangle>
<ListBox Margin="10" x:Name="foundList" FontSize="30" FontWeight="ExtraBold" SelectionChanged="foundList_SelectionChanged" />
</Grid>

The page is then driven off of a PhotoCamera object and a DispatchTimer.  Below is the initial setup within the page.

private readonly DispatcherTimer _timer;
private readonly ObservableCollection<string> _matches;

private PhotoLuminanceSource _luminance;
private QRCodeReader _reader;
private PhotoCamera _photoCamera;

public ScanView()
{
InitializeComponent();

_matches = new ObservableCollection<string>();
foundList.ItemsSource = _matches;

_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(250);
_timer.Tick += (o, arg) => ScanPreviewBuffer();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
App app = Application.Current as App;
app.ScannedValue = string.Empty;

_photoCamera = new PhotoCamera();
_photoCamera.Initialized += OnPhotoCameraInitialized;
_previewVideo.SetSource(_photoCamera);

CameraButtons.ShutterKeyHalfPressed += (o, arg) => _photoCamera.Focus();

base.OnNavigatedTo(e);
}

private void OnPhotoCameraInitialized(object sender, CameraOperationCompletedEventArgs e)
{
int width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
int height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);

_luminance = new PhotoLuminanceSource(width, height);
_reader = new QRCodeReader();

Dispatcher.BeginInvoke(() =>
{
_previewTransform.Rotation = _photoCamera.Orientation;
_timer.Start();
});
}

Ultimately we get back down to the ZXing library again with a few improvements to the processing.  The code for the decoding is actually a simple native call to a QRCodeReader’s decode method and passing it the bitmap from the camera buffer.

private void ScanPreviewBuffer()
{
try
{
_photoCamera.GetPreviewBufferY(_luminance.PreviewBufferY);
var binarizer = new HybridBinarizer(_luminance);
var binBitmap = new BinaryBitmap(binarizer);
var result = _reader.decode(binBitmap);
Dispatcher.BeginInvoke(() => DisplayResult(result.Text));
}
catch
{
}
}

private void DisplayResult(string text)
{
if (!_matches.Contains(text))
_matches.Add(text);
}

In the end approach #2 gives a better user experience and can handle more garbage cluttering the media that is displaying the QR code.  When it comes down to it, both QR code interpretations could be used with either camera sampling.  The ZXing code from approach #1 is probably more flexible in the long run if you have more dynamic conditions to read the images under, but it is going to take more work and greater understanding of the libraries.  As usual pick the code sample that works best for your situation.

Posted On Monday, July 23, 2012 3:42 PM | Comments (2)
Why Social Metrics Are Only As Good As Their Input

As more and more social media sites come online people are looking to see what kind of influence you have on the community.  Some employers are even checking your Klout or PeerIndex scores before they go into an interview.  My problem is that these sites don’t even come close to telling the whole story of a person’s influence in the community.

The first thing  is that they can’t measure things such as user group interaction.  How many conferences do you attend or speak at?  Are you responding to forums and emails asking for help.  Granted, these are not part of the new social media environment, but people should be aware of this before putting to much emphasis on the importance of these ratings.

The other thing is that these sites are not consistent with what they measure.  While PeerIndex allows you to register a blog via a URL Klout only understands popular blog hosting sites like WordPress. This leaves this blog and ones like it high and dry since it isn’t counted at all.  Similarly Klout follows sites like Flickr and Tumbler which aren’t a main concern for PeerIndex.  With these differences you can have a huge difference in your ranking between the sites.

The main thing you find out with these sites is how many people think enough about what you post in to tell their friends and associates about it.  A lot of that is really how well you manage your connections and reciprocate as opposed to the quality of your content.  My advice is to check your rankings, but don’t dwell on them.  Use them as advisory tools instead of the end goal and you can improve you impact in the community you target.

Posted On Wednesday, July 18, 2012 10:36 AM | Comments (0)
Review: TypeMock Isolator 7

I was recently given an opportunity to review the TypeMock Isolator v7 framework.  This is a very feature rich add-in for Visual Studio which simplifies unit testing by putting all the features you need right at your finger tips.  Below is an abbreviated list of features found in the product.

Components

  • AutoRunner
  • Failed Test Analyzer
  • Coverage
  • Test Auto-Complete

The biggest productivity feature is the unit testing dashboard which drops down from the top of your Visual Studio code window. It provides helpful information about coverage and current state of tests that cover that portion of your code. You are able to drill down into the coverage for a particular method.  This is especially benefitial if there are multiple tests that cover the method.  It even give warnings that the test may be too long to be considered a unit test and should be broken down. From the dashboard you can even start debugging the unit test directly from the code window.  Speed and efficiency were definitely the driving factors here.

image

AutoRunner give you the features of continuous integration on your desktop.  After each build it runs any tests that cover code that was changed since the last build.  Of course that means that the flashing lights are only ever going off at your desk, but on the plus side you are the only one see that you broke the build.

The Failed Test Analyzer is like having the system monitor each of your tests and record the actual error messages that caused you test to fail.  This easily allows you to find where you may have left out fake code in your setup or identify actual bugs in your code.  It isn’t going to solve everything for you, but it will shorten the time it takes to look at your failed tests.  Your will no longer have to step through the test code for each case.

image 

While code coverage can be an over emphasized metric, it is a good feature for making you aware of where you may be missing tests.  The nice thing about the Coverage feature in Isolator is that you can plug in your favorite coverage tool to be leveraged.

Test Auto-Complete goes beyond the usual IDE capability of creating a shell of test and give you intellisense juiced up on mountains of caffeine.  If you a mock object the auto-complete will allow you to automatically generate statements that will fake many of the most common test conditions.

image

As I started investigating the tools I could see ways to do tests that involved difficult third party components and database calls that I had previously thought were nearly impossible.  This mainly comes from the power of the Isolate class which manages the faking features of the framework.  Being able to isolate a single condition in your code is always a challenge.  Defining

A good place to start when investigating TypeMock Isolator is the string of webinars and YouTube videos that they have available.  Roy Osherove of ISerializable fame presents several of them which I think gives them a lot of credibility. I would also suggest looking at the Mocking On Steroids link from the welcome page of the Developer’s Guide.

The one thing I would like to see improved with Isolator is the documentation.  It is note very verbose in it’s explanations of the product features.  This leaves you searching the we in many cases for answers.  If you are going to create a great product it should come with great documentation.

Overall I believe that Isolator is a great tool to have.  I could not justify the price for my personal projects that I don’t get paid for, but I think an IT shop would get a return on its money very quickly with the savings in time and reduction in application maintenance cost.  Be sure you take some time and check it out.

Posted On Monday, July 16, 2012 7:17 AM | Comments (1)
Features I’d Like To See In Windows Phone 8

With Windows Phone 8 around the corner I figured I would get the wish list out.  I am encouraged by what we have seen so far.  This is a short list of the things that have bugged me over the last two years of using and developing for the platform.  I realize that some of them are pure fantasy and will never happen, but we can dream.  So here we go.

  • Separate volume controls for phone and alerts
  • Videos can be taken in portrait and will be saved that way
  • Tweets created in the People Hub should be able to add pictures
  • Be able to group apps into folders or hubs on the phone
  • Native QR/Barcode/Tag library for development
  • Native JSON libraries for development
  • Ability to review missed toast messages

Please comment what you would add to the list.

Posted On Friday, July 13, 2012 1:40 PM | Comments (0)

Tim Murphy

Tim is a Solutions Architect for PSC Group, LLC. He has been an IT consultant since 1999 specializing in Microsoft technologies. Along with running the Chicago Information Technology Architects Group and speaking on Microsoft and architecture topics he was also contributing author on "The Definitive Guide to the Microsoft Enterprise Library".



I review for the O'Reilly Blogger Review Program



Technorati Profile

www.flickr.com
Tag Cloud