Have you ever wondered, how to detect a barcode on an image? The following article describes an algorithm in VB NET to detect 2 of 5 interleaved barcodes, which are widely used in industrial applications like document management (DMS). The algorithm can be easily extended to detect every other two-width barcode like 2 of 5 standard and Code 39. The full code can be downloaded here.
If you do not want to code it yourself or if you need additional symbologies like EAN 13, EAN 8, Code 128, Code 11 including image processing functions feel free to download GMSE Imaging.
The algorithm
The algorithm uses a bitmap in 1bpp format as input. It detects all 2 of 5 interleaved barcodes. 2 of 5 belongs to the category of two-width barcodes. Two-width barcodes are represented with only two bar types: a narrow bar (represented as n) and a wide bar (represented as w). The basic format is NNNNWNN. (For further information see Barcode Island.)
The algorithm works with 4 different representations of the image data:
| Name | Description | Example | |
|---|---|---|---|
| 1 | Bitmap in 1bpp format | .NET Bitmap | ![]() |
| 2 | Row pixeldata (ScanRow() As Byte) | Array of Pixel in 1bpp format | |
| 3 | Barwidth: cBarWidth() As Integer | Width of the bars in ScanRow. | (53, 2, 2, 2, 2, 6, 2, 2, 6, 7, 6, 2, 2, 2, 2, 2, 7, 2, 2, 2, 2, 6, 6, 6, 2, 6, 2, 3, 2, 2, 2, 2, 6, 7, 6, 6, 2, 3, 5, 7, 6, 2, 2, 3, 2, 6, 2, 2, 379) |
| 4 | NW representation (as String) | Representation of a subset of bars in ScanRow in n/w notation. | nnnnwnnww wnnnnnwnnnnw wwnwnnnnnnw wwwnnwwwn nnnwnn |
| 5 | Text | The result | 56781756 |
To decode the barcode the data is transformed beginning from the bitmap:

(Diagram created with Trigos GPA)
The interesting part in the algorithm is how to find a candidate for a valid barcode. This is mainly done in the function gmseNWScanner.CalcNWWidth. The task is to test, if a subset of cBarWidth can be represented as narrow and wide bars. This is done by computing the minimum =n and maximum =m of barwidth in the subset. The subset is a candidate if the following criteria are met:
- The difference of n and m is not too big.
- The barwidth are not to far away from n and m
If a candidate is identified, the algorithm reads all following bars until the read barcode is to big or small to be represented as n or w and created the nw representation nwrep. Now the algorithm tries to decode the nw representation nwrep. First of all the length of nwrep must be 10*count+7. If so, the decoding starts:
- nwrep must start with nnnn (Startcode of 2 of 5 interleaved)
- The data section is decoded with a hashtable.
- Nwrep must end with wnn (Stopcode of 2 og 5 interleaved)
How to use it
Scanning the barcodes is as simple as
Dim bmp As New Bitmap("d:\sample2of5.bmp")
Dim scanner As New gmseNWScanner(New gmseBarcodeDef2of5interleaved)
Scanner.Scan(bmp)
For your convenience: a sub to handle Button1.Click:
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim bmp As Bitmap
Dim scanner As New gmseNWScanner(New gmseBarcodeDef2of5interleaved)
Dim sb As New System.Text.StringBuilder
Dim result As gmseNWResult
bmp = New Bitmap("d:\sample2of5.bmp")
Try
scanner.Scan(bmp)
For Each result In scanner.Result
sb.Append(Format(result.Count, "000") & ": " & result.Text)
sb.Append(vbCrLf)
Next
MsgBox(sb.ToString)
Catch ex As Exception
MsgBox(ex.ToString)
Finally
bmp.Dispose()
End Try
End Sub
Implementation
The main class is gmseNWScanner. It contains a generic scanning algorithm for two-width barcodes and does the transforming steps 1-4. The symbology scecific parameters are defined in the abstract class gmseNWBarcodeDef. The class gmseBarcodeDef2of5interleaved implements gmseNWBarcodeDef to decode 2 of 5 interleaved. The detected barcodes are saved in class gmseNWResult and class gmseNWResultCollection.
