Algorithms - How to read a barcode from an image

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:

 NameDescriptionExample
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.

Algorithms Overview