Test case failed for CODE39

Mar 28, 2013 at 3:51 AM
I continued to test the CODE39 decoder. I have several success cases but the following one failed. Here is the link to the test image:

https://www.dropbox.com/s/zjgc4t1r8ke9ycd/BadImage.TIF

Since I know the image format is CODE39, I'm trying to use the Code39Reader directly. Code snippet as following. Am I missing something in the following piece of code?
        ZXing.OneD.Code39Reader c39 = new ZXing.OneD.Code39Reader();
        BinaryBitmap bBitmap = new BinaryBitmap(new ZXing.Common.GlobalHistogramBinarizer(new BitmapLuminanceSource(image)));
        IDictionary<DecodeHintType, object> hints = new Dictionary<DecodeHintType, object>();
        List<BarcodeFormat> possibleFormats = new List<BarcodeFormat>();
        possibleFormats.Add(BarcodeFormat.CODE_39);
        
        hints[DecodeHintType.POSSIBLE_FORMATS] = possibleFormats;
        hints[DecodeHintType.TRY_HARDER] = true;
        Result r = c39.decode(bBitmap, hints);  // <-- Several success cases. Result r is null for the above failed case.
Coordinator
Mar 28, 2013 at 8:40 PM
It can be decoded, but that is tricky. The image is a little bit disturbed. The algorithm behind doesn't look at the whole image to find a barcode (for performance reasons). If you set TryHarder = true it will look through the whole image, but with a step width greater than 1. If your barcode is shifted a little bit more up or down, the algorithm can find a line which can be decoded without errors. Another solution would be cropping.

Within the source code the decoder can be modified to look at more lines with a smaller step width. I'm not sure if I should generally change that. More lines to scan means more cpu cycles for processing the image.

But if you want you can try it out. Open the file OneDReader.cs. Look for the line
int rowStep = Math.Max(1, height >> (tryHarder ? 8 : 5));
Change it to
int rowStep = Math.Max(1, height >> (tryHarder ? 10 : 5));

Perhaps we need an option like TryItReallyHarder. :)

Btw. I would change the code above a little bit:
var reader = new ZXing.BarcodeReader { TryHarder = true, PossibleFormats = new List<BarcodeFormat> { BarcodeFormat.CODE_39 } };
var result = reader.Decode(image);
Or like that
var reader = new ZXing.BarcodeReader(new ZXing.OneD.Code39Reader(), null, null) { TryHarder = true };
var result = reader.Decode(image);
Mar 30, 2013 at 3:17 AM
I tried to change that magic number controlling the step width from 8 to 10, it can recognize the bar code in my test image. Great work!

A little suggestion: we may want to make that magic number (8 or 10) configurable. As you can see from the name of my test image (BadImage.tif), I'm purposely make the image have bad quality. In real life scenario, the incoming image may have very bad quality and the user may want to sacrifice cpu cycles for accuracy. Making the step width configurable, the user of ZXing.Net will have more flexibility. Just my 2 cents.

Many thanks to your great work!
Jul 26, 2013 at 8:05 AM
Wonderful, many thanks.
Solved my problem, too!