How to use zxing in WinRT application

Aug 28, 2012 at 12:16 PM

Hello Team,

I have Downloaded latest zxing  - 81165 library which contains two project in solution .
1. zxing-vs2012 and 2.zxing.winrt.

I want to user winrt solution in my windows metro style project but it gives me compilation errors and all are related to WriteableBitmap Class.

ex error is in BitmapLuminanceSource.Silverlight.cs file Line no 53.

Could you please guide me for this ? Also need some sample of encoding and decoding image.

I have read one post from forum which says this in working phase. Its really urgent for us so please guide me..


 

 

Coordinator
Aug 28, 2012 at 8:35 PM

The WinRT port is not finished yet. I'm working on it and will hopefully finish it this week.

Different samples are provided through the source code repository and the source archive download.
The way of decoding and encoding barcodes is similar for every .net target platform.

* create an instance of BarcodeReader or BarcodeWriter
* call the Decode or Encode/Write method with the necessary arguments

That's it. A short snippet is shown at the main page here.

Coordinator
Aug 28, 2012 at 9:40 PM

I fixed the build errors but I could not test the WinRT port yet.

Aug 29, 2012 at 5:23 AM
Edited Aug 31, 2012 at 5:40 AM
Hi micjahn,
Thanks for your instance reply. I have fix build errors by using WritableBitmap nudget Package from codeplex.
But I want to save that encoded QRCode ByteMatrix in jpeg/bmp/png form in my winRT app just like earlier zxing .net framework library does.
 
Can you PLEASE suggest any solution for this ?
 
Thanks in advance.
 
Aug 29, 2012 at 5:37 AM
Edited Aug 31, 2012 at 5:40 AM
Hi mic,
I have tried code pasted in home page for decoding. this is
 
// create a barcode reader instance
IBarcodeReader reader = new BarcodeReader();
// load a bitmap
var barcodeBitmap = (Bitmap)Bitmap.LoadFrom("C:\\sample-barcode-image.png");
// detect and decode the barcode inside the bitmap
var result = reader.Decode(barcodeBitmap);
But as Bitmap is not supportive class in winRT (windows style) application. Its is giving error.
Also I know how to call encod class but as its returning ByteMatrix; please guide if you have any snipet for creating and saving image from this ByteMatrix.
 
Thanks in advance.
 
 
 
  
Coordinator
Aug 29, 2012 at 8:02 PM

Ok, here some steps for encoding some content to a barcode image (which you can find in the sample clients in the source code repository, too):

var writer = new BarcodeWriter { Format = BarcodeFormat.QR_CODE };
var writeableBitmap = writer.Write("some content");
// do something with the bitmap e.g. save it as a file using .net framework functionality or other image tools

Btw. the BarcodeWriter has a second method called Encode which gives a BitMatrix (not ByteMatrix as you mentioned) instead of a WriteableBitmap. You can use it if you want to render the BitMatrix to an image by yourself. Or you write your own renderer implementing the IRender interface and give an instance to BarcodeWriter. But that is only necessary if you want to draw the barcode with your own algorithm. Normaly the snippet above is enough to get a barcode bitmap. Saving as a file depends on your environment and is not in the scope of zxing.net.

The decoding snippet is written for the winforms client. But the steps are the same for all target platforms.
You have to replace the call for loading an image with a similar call depending on your environment.
It should look similar like this here:

var writeableBitmap = new WriteableBitmap(0, 0);
using (var stream = File.OpenRead("path to an barcode image file"))
{
   writeableBitmap.SetSource(stream);
}
IBarcodeReader reader = new BarcodeReader();
var result = reader.Decode(writeableBitmap);
Please look into the documentation of WinRT how to load an image from disk.
Michael
Aug 30, 2012 at 10:26 AM
Edited Aug 30, 2012 at 10:27 AM

Hi micjahn,

I have tested the 81253 drop using the following code and the WriteableBitmapEx (http://writeablebitmapex.codeplex.com/) library:

    WriteableBitmap writeableBmp = await BitmapFactory.New(1, 1).FromContent(new Uri(BaseUri, "///img.png"));
    TheImage.Source = writeableBmp;

    var barcodeReader = new QRCodeReader();
    var rgb = new RGBLuminanceSource(writeableBmp.ToByteArray(), writeableBmp.PixelWidth, writeableBmp.PixelHeight);
    var hybrid = new HybridBinarizer(rgb);
    BinaryBitmap binBitmap = new BinaryBitmap(hybrid);
    var result = barcodeReader.decode(binBitmap, zxingHints);

The result comes up null (img.png is the Wikipedia's sample QR code image http://en.wikipedia.org/wiki/File:Wikipedia_mobile_en.svg in 500x500px resolution)

I have traced the execution flow:

  • In the barcodeReader.decode method, the DetectorResult detectorResult = new Detector(image.BlackMatrix).detect(hints)line returns null
  • Inside Detector.detect(...) method, the FinderPatternInfo info = finder.find(hints) returns null 
  • Inside FinderPatternFinder.find(...) method, the foundPatternCross(stateCount) method never returns true (no winner), so when the execution flow goes down to FinderPattern[] patternInfo = selectBestPatterns() the patternInfo array comes up null again.

I hope it will help you find the problem...

Manos

Aug 30, 2012 at 11:02 AM
Edited Aug 30, 2012 at 11:54 AM

Hi mic,

Even I tried with latest build 81253 in my winRT application. And use code as u mentioned earlier for decoding.

FileOpenPicker imagePicker = new FileOpenPicker 
{ 	ViewMode = PickerViewMode.List, SuggestedStartLocation = PickerLocationId.PicturesLibrary, 
	FileTypeFilter = { ".jpg", ".png", ".bmp", ".gif", ".tif" } 
}; 
StorageFile imageFile = await imagePicker.PickSingleFileAsync(); 
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{ 	WriteableBitmap writeableBitmap = new WriteableBitmap(0, 0); // Getting Error Here
 	writeableBitmap.SetSource(fileStream); IBarcodeReader reader = new BarcodeReader(); 
	var result = reader.Decode(writeableBitmap); 
}
 I am getting error WriteableBitmap writeableBitmap = new WriteableBitmap(0, 0);   this line as "Additional information: The parameter is incorrect."; So I have tried by setting hardcoded value as new WriteableBitmap(150,150). Even though final result is null.
 
Also can we get configuration (What is ErrorCorrectionLevel, CharacterSet, Margin etc) of encoded image while decoding ?

Please guide ..

 

 


Coordinator
Aug 30, 2012 at 9:39 PM

@mkelaiditis

I think the problem is the alpha channel of the svg/png barcode image. The barcode is a fully black image with transparent pixels for the white parts.
The method ToByteArray gives an array of BGRA32 pixel format back (32 bits per pixel or 4 byte elements from the array per pixel).
The RGBLuminanceSource only supports the RGB24 pixel format (24 bits per pixel or 3 byte elements from the array per pixel).
Please try the following code:

WriteableBitmap writeableBmp = await BitmapFactory.New(1, 1).FromContent(new Uri(BaseUri, "///img.png"));
TheImage.Source = writeableBmp;

var barcodeReader = new BarcodeReader { PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE } };
var result = barcodeReader.Decode(writeableBmp);

You should try this with the current revision 81286 or above because I fixed an error related to the alpha channel.

off topic:
Nice to see that you use the library writeablebitmapex from my friend and former colleague René. :)
Best wishes to Rene, if you read that here someday.

 

 

Coordinator
Aug 30, 2012 at 9:47 PM

@vivekdeshmukh

Please send me a sample picture which doesn't work for you.

You can find the error correction level in the dictionary of the property result.ResultMetadata. The key for the dictionary is ResultMetadataType.ERROR_CORRECTION_LEVEL. The type of the value is string.

Aug 30, 2012 at 10:18 PM

Hi micjahn, thanx for your reply.

I have tried it on rev 81286 but it doesn't work either. Still the result comes up null. I also used the same image in jpeg format to avoid any transparency issues but to no avail.

Coordinator
Aug 30, 2012 at 10:21 PM

Did you use my code snippet or your code with the RGBLuminanceSource?

- Michael

Aug 30, 2012 at 10:37 PM

I used your code...

 

 

Aug 31, 2012 at 6:54 AM
Edited Aug 31, 2012 at 7:44 AM

Hi Mic,

Really appreciate your instant reply for encoding image forecolor. I tried with new build and works as expected. Thanks....

But for decode; even I also tried with code for decoding which u have pasted here(with just one change . insteadt of from file I tried with from stream) on latest build 81287.

FileOpenPicker imagePicker = new FileOpenPicker
{
ViewMode = PickerViewMode.List,
SuggestedStartLocation = PickerLocationId.PicturesLibrary,
FileTypeFilter = { ".jpg", ".png", ".bmp", ".gif", ".tif" }
};
StorageFile imageFile = await imagePicker.PickSingleFileAsync();
using (IRandomAccessStream fileStream = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
WriteableBitmap writeableBmp = await BitmapFactory.New(1, 1).FromStream(fileStream);
var barcodeReader = new BarcodeReader { PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.QR_CODE } };
var result = barcodeReader.Decode(writeableBmp);
}

But is returning null.

Any suggestion ?

 

Coordinator
Aug 31, 2012 at 10:47 PM

@mkelaiditis
@
vivekdeshmukh

The calculation of the luminance values wasn't correct. I fixed it in revision 81326.
Please try again with the current source.

Aug 31, 2012 at 11:11 PM

OK, now it works correctly.

Thanx Michael!

 

Sep 3, 2012 at 10:56 AM
Edited Sep 3, 2012 at 10:57 AM

Hello mic,

Its works perfect ... Truly Appreciable..

Thanks for your instant replies and support.

 

Mic I have one more query here, While decoding we are getting ErrorCorrection level in result metadata as ResultMetadataType.ERROR_CORRECTION_LEVEL.

Is here any way for getting its encoded version number also ? i.e. in which version it is encoded ?

Thanks in Advance.

 

 

 

Coordinator
Sep 4, 2012 at 8:31 PM

Do you mean the number for the 4 error correction levels?

If so you can statically map them: M -> 0, L -> 1, H -> 2, Q -> 3

Sep 5, 2012 at 7:19 PM
Edited Sep 5, 2012 at 7:20 PM

Hello Michael,

I have followed this discussion and try to decode a barcode in WinRT application.
I get index out of bound exception in BitmapLuminanceSource.SilverLight.cs at line 56

System.IndexOutOfRangeException was unhandled by user code
  HResult=-2146233080
  Message=Index was outside the bounds of the array.
  Source=zxing.winrt

I'm kind of new to C# and WinRT. Maybe I do something wrong. I use your barcode sample (upcean-extension-1).
I will appreciate if you can give me some suggestion.

I use build 81376

 FileOpenPicker openPicker = new FileOpenPicker
            {
                ViewMode = PickerViewMode.Thumbnail,
                SuggestedStartLocation = PickerLocationId.PicturesLibrary,
                FileTypeFilter = { ".jpg", ".png", ".bmp", ".gif", ".tif" }
            };
            StorageFile imageFile = await openPicker.PickSingleFileAsync();
            IRandomAccessStream fileStream = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);

            var writeableBitmap = new WriteableBitmap(1, 1);

            writeableBitmap.SetSource(fileStream);

            IBarcodeReader reader = new BarcodeReader();
            reader.TryHarder = false;
            var result = reader.Decode(writeableBitmap);
Coordinator
Sep 5, 2012 at 9:29 PM

The important difference of your example compared to that one from vivekdeshmukh

WriteableBitmap writeableBmp = await BitmapFactory.New(1, 1).FromStream(fileStream);

The SetSource isn't immediately finished. It is internally async as I know. That means, the class BitmapLuminanceSource uses a not fully initialized bitmap and crashs.

Please look here for some solutions for that:
http://stackoverflow.com/questions/10197170/in-winrt-how-do-i-load-an-image-and-then-wait-only-as-long-as-is-needed-for-it

I see no chance to work around it internally of zxing.net.

Sep 6, 2012 at 1:56 AM

Thanks Michael,

It seems that vivekdeshmukh uses BitmapFactory from WriteableBitmapEx library which in turn initializes WriteableBitmap in same way also.

The solution from stackoverflow has some problem converting MemoryStream to IRandomAccessStream.

 I'll try to figure it out.

Coordinator
Sep 7, 2012 at 7:44 PM

It isn't exactly the same. The key word "await" is very important. It ensures that the bitmap is fully loaded before the next method is called.

Sep 10, 2012 at 8:27 PM

When I try with  a sample jpeg for barcode from internet it works on winRT. But whenever I capture the image using web cam the decode methods fails with return value == null. Any idea? This all on WINRT . Also I am using

WriteableBitmap writeableBmp = await BitmapFactory.New(1, 1).FromStream(fileStream);

 

Coordinator
Sep 10, 2012 at 9:09 PM

Can you provide a more complete example?

What kind of webcam do you use? What is the resolution? Do other barcode reader applications work with your webcam?

Can you test the decoding with your webcam and the winforms sample client?

Sep 11, 2012 at 6:35 AM

Windows.Media.Capture.CameraCaptureUI ccu = new Windows.Media.Capture.CameraCaptureUI();
            ccu.PhotoSettings.Format = Windows.Media.Capture.CameraCaptureUIPhotoFormat.Jpeg;
            ccu.PhotoSettings.MaxResolution = Windows.Media.Capture.CameraCaptureUIMaxPhotoResolution.HighestAvailable;
            Windows.Storage.StorageFile x = await ccu.CaptureFileAsync(Windows.Media.Capture.CameraCaptureUIMode.Photo);
            //FileOpenPicker fop = new FileOpenPicker();
            //fop.FileTypeFilter.Add(".jpg");
            //StorageFile x = await fop.PickSingleFileAsync();
            if (x != null)
            {
                ZXing.BarcodeReader br = new ZXing.BarcodeReader();
                WriteableBitmap wrb;
                BitmapImage img = new BitmapImage();
                img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                using (IRandomAccessStream fileStream = await x.OpenAsync(FileAccessMode.Read))
                {
                    //fileStream.
                    wrb = await BitmapFactory.New(1, 1).FromStream(fileStream);
                }
                var res = br.Decode(wrb);
                testImage.Source = wrb;
                //System.Diagnostics.Debug.WriteLine("ISBN = " + res.ToString());
            }

This is the code. I also crop the image to select only the barcode section. I haven't tried with winform application with same web cam yet. Web cam is integrated and does not support auto focus. Could focus be an issue here?

Coordinator
Sep 11, 2012 at 8:30 PM

Your code looks good to me. Can you save a capture image and send it to me please?
The missing auto focus can be a problem. I have a Microsoft VX-2000. I can't scan barcodes of normal size with it because it doesn't focus the image.
For tests I show big barcodes on the screen and scan it with the cam.
Please send me a sample picture which was captured by the cam and try the web cam with the winforms client.

Sep 11, 2012 at 8:46 PM

Ok, the Win form too did not work. It crashed after few retries... I have bunch of saved images.. how can I attach here?

Sep 12, 2012 at 8:47 AM

Ok , I tried the big barcodes printed on paper and it worked... Just wondering how to optimize this for barcodes printed small..

Coordinator
Sep 12, 2012 at 8:41 PM

You cannot attach the images here. I send you my email address through the contact form.
Basically your webcam (like mine) is not suitable for barcode scanning (missing focus feature).

Sep 13, 2012 at 6:58 AM

Yes, its seems to be. I tried the bigger barcode images [printed on a A4 sheet] and it worked great. I have sent you the images that did not get scanned on the email.
Also I was wondering what would be the approach on showing the scanning rectangle by detecting that there is a barcode. Just like Bing search on Windows phone does..

I see a WhiteRectangleDetector class. Can that be used to find the pixel locations and overlay a rectangle on top of the web cam ?

 

Coordinator
Sep 13, 2012 at 7:50 PM

There are no needs to do it your own with the WhiteRectangleDetector class.
The result from the Decode method has a property ResultPoints which you can use for it.

May 21, 2014 at 11:30 AM
hello
I am developing Windows 8.1 tablet application to read barcode scanner output.
  • I also want to scan barcodes using camera
    I could able to do that using the code snippet given above.
    but there is problem for I can scan for small barcodes. only barcodes with very high resolution and printed on A4 pages I can read.
    but in reality no barcodes will be like that.
    so how can I focus on barcodes?
    how can I read barcode batch(actual barcode strips)?
  • I also want to show rectangular white triangle around barcodes, is there any way?
thanks in advance.
Coordinator
May 21, 2014 at 8:14 PM
You need a good camera for your tablet. You have to write your own application to use the focus features of the camera.
ZXing.Net doesn't control that by itself. It only uses the image data which is given by an application. The library isn't
responsible for the quality of the image.
If you need a batch scanning functionality you have to implement it by yourself. It should be easy but it is not a feature
of the library.
You can implement the painting of an rectangle yourself inside of your application. When the library finds
a barcode it gives a result object back to the application which contains the corner points of the barcode in the image.