QR Decoding with Mono For Android always returns null

Feb 5, 2013 at 1:57 AM
I have created a simple app with Mono For Android, SDK v.8 that can never decode a QR Code successfully. I created a QR Code image (PNG) with my name and added it as an asset to my project. After adding ZXing.Net- as a reference I added the following code to the OnClick event of one of my buttons:
using (var str = Assets.Open("image.png")) {
            var reader = new ZXing.MultiFormatReader();
            using (Android.Graphics.Bitmap androidBmp = Android.Graphics.BitmapFactory.DecodeStream(str)) {
                var binarizer = new ZXing.Common.GlobalHistogramBinarizer(new BitmapLuminanceSource(androidBmp));
                //var binarizer = new ZXing.Common.HybridBinarizer(new BitmapLuminanceSource(androidBmp));
                //var binarizer = new ZXing.Common.HybridBinarizer(new RGBLuminanceSource(StreamToByteArray(str), 250, 250));

            var binbmp = new BinaryBitmap(binarizer);

                ZXing.Result res = reader.decode(binbmp);

                if (res == null)
As the title says, "res" is always null, i.e. no Qr code is ever decoded successfully.
As you can see, I have tried other binarizers and other luminance sources, but nothing has worked. I have also tried instantiating ZXing.QrCode.QrCodeReader directly, but that still didn't work. Other image formats didn't do anything either (actually, the Bitmap had both its Height and Width properties set properly after reading from the stream).

What am I doing wrong?
Thanks in advance.
Feb 5, 2013 at 7:41 AM
Edited Feb 5, 2013 at 7:47 AM
I need your sample image for testing. I will send you a message through codeplex with my email address. After that you can send me your qr code.

I can't send you a message because you don't want to be contacted.
Feb 5, 2013 at 12:25 PM
Sorry, I have updated my preferences to be contacted. You can find the QR Code in http://upload.wikimedia.org/wikipedia/commons/thumb/9/9b/Wikipedia_mobile_en.svg/200px-Wikipedia_mobile_en.svg.png

However, I tried running the code again and very strangely I am now getting a NullReferenceException.
After adding the ZXing.Net- as a project and debugging, I noticed that the exception is being thrown because estimateBlackPoint(int[] buckets, out int blackPoint) from GlobalHistogramBinarizer.cs is returning false, with both secondPeak and firstPeak equal to 0 (zero), as per:
if (secondPeak - firstPeak <= numBuckets >> 4)
            return false;
And after that the following snippet returns null for the BitMatrix of the histogram (in the overridden BlackMatrix getter in GlobalHistogramBinarizer.cs):
if (!estimateBlackPoint(localBuckets, out blackPoint))
               return null;
After that, null gets passed around and everything goes wrong. This is the stack trace of my app when it throws (after trying to access image.Height with image == null):
System.NullReferenceException: Object reference not set to an instance of an object
  at ZXing.QrCode.Internal.FinderPatternFinder.find (System.Collections.Generic.IDictionary`2<ZXing.DecodeHintType, object>) [0x0000f] in c:\Users\mzabani\Documents\Projects\ZXing.Net.Source.\Source\lib\qrcode\detector\FinderPatternFinder.cs:97

  at ZXing.QrCode.Internal.Detector.detect (System.Collections.Generic.IDictionary`2<ZXing.DecodeHintType, object>) [0x00034] in c:\Users\mzabani\Documents\Projects\ZXing.Net.Source.\Source\lib\qrcode\detector\Detector.cs:89

  at ZXing.QrCode.QRCodeReader.decode (ZXing.BinaryBitmap,System.Collections.Generic.IDictionary`2<ZXing.DecodeHintType, object>) [0x00051] in c:\Users\mzabani\Documents\Projects\ZXing.Net.Source.\Source\lib\qrcode\QRCodeReader.cs:81

  at ZXing.MultiFormatReader.decodeInternal (ZXing.BinaryBitmap) [0x00058] in c:\Users\mzabani\Documents\Projects\ZXing.Net.Source.\Source\lib\MultiFormatReader.cs:204

  at ZXing.MultiFormatReader.decode (ZXing.BinaryBitmap) [0x00009] in c:\Users\mzabani\Documents\Projects\ZXing.Net.Source.\Source\lib\MultiFormatReader.cs:54

  at QRReader.Read.From (System.IO.Stream) [0x00022] in c:\Users\mzabani\Documents\Visual Studio 2010\Projects\AndroidTicketValidator\QRReader\Read.cs:98

  at AndroidTicketValidator.MainActivity/<>c__DisplayClass5.<OnCreate>b__3 (object,System.EventArgs) [0x00018] in c:\Users\mzabani\Documents\Visual Studio 2010\Projects\AndroidTicketValidator\AndroidTicketValidator\MainActivity.cs:85

  at Android.Views.View/IOnClickListenerImplementor.OnClick (Android.Views.View) [0x0000b] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Android.Views.View.cs:631

  at Android.Views.View/IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (intptr,intptr,intptr) [0x00010] in /Users/builder/data/lanes/monodroid-mac-monodroid-4.4-series/6418373f/source/monodroid/src/Mono.Android/platforms/android-8/src/generated/Android.Views.View.cs:602

  at (wrapper dynamic-method) object.a7634cba-e489-47f5-9ec5-aa0e8e8ba31d (intptr,intptr,intptr) <IL 0x00017, 0x00043>
I would really like to learn exactly what are Luminance Sources, Binarizers and other concepts involved in QR/Barcode decoding. Can you point me to any online material?

Thanks a lot for your attention,
Marcelo Zabani.
Feb 5, 2013 at 8:06 PM
I'm not sure but I think there is no online material which describes the concepts behind the scenes.
Perhaps there is more to find at the homepage of the java based, original version of zxing: http://code.google.com/p/zxing/

But I can give you a short explanation of the basics:
  • luminance sources are classes which convert the original image to a gray scale image. it represents every pixel as a value between 0 and 255
  • binarizers try to convert the gray scale image into a bit matrix. it calculates the black point of the image which is used to decide which pixel would be black and which would be white.
  • the resulting black and white matrix of the binarizer is than used by the different detector and decoder classes. They use slightly different ways to find a bar code. But basically they look for black-white patterns.
And now to your sample image. The image uses an alpha channel which wasn't supported by the bitmap luminance source.
I changed it with revision 84936 in the source code repository. If you want to try it out you have grab the current source from the repository.