Using GDI+ to draw barcodes

Author: Terry Voss

 

Introduction:

This solution does not use any components, controls, or fonts. The barcodes are drawn with code using the System.Drawing namespaces that support GDI+, so on one page you can have different barcodes existing if you want. I have coded Code39 and UPC-A. Doing other barcodes is straight forward once you have found the defining characteristics of the barcode you have need of. Ease of testing, debugging, and feature change will be shown to be attributes of this solution.

 

The source code:

In gdibarcodes.zip there are four files: webform1.aspx, webform1.aspx.vb, barcode.aspx, and barcode.aspx.vb.  Webform1.aspx has one image control on it with the imageurl = barcode.aspx?code=694038220006&height=14&width=1&mode=code39&text=1.  So the image is making a request to IIS for the page barcode.aspx with 5 parameters. Barcode.aspx has no controls, just code in its codebehind. Webform1.aspx.vb has no code. So all code is in barcode.aspx.vb.

 

The main flow:

When the webform1.aspx page loads, part of its loading is to load each control. The image control makes a request to the barcode.aspx page and the page_load event is processed.  I’m not using the width and height variables much, just to get the image wide enough for the barcodes I’m using, but you could make them work proportionally, or you could use a transform to cause scaling of your barcodes as a feature addition. After grabbing the parameters, I create an instance of the  bitmap type by specifying a width and height. The bitmap is what will sent back to the requesting image control for displaying. Then I create an instance named graph that is of type graphics using the bitmap.

I then print the proper barcode, and if text = 1 then I print the text underneath it. (Notice that with upc-a it is standard to print the text of the code overlapping the bottom of the barcode graphic, so I used two filled rectangles to do that and it helped me to color them lawngreen at first to get them lined up with the textcode. These rectangles are necessary to block the graph where the textcode will print) Lastly since the request is from the image control, not the whole webform1.aspx page, I save the bitmap to the response.outputstream in the proper GIF format.

 

Code listing 1 – Page load event

     Try

      _code = Request.QueryString.Item("code")

      _height = CType(Request.QueryString.Item("height"), Integer)

      _mode = Request.QueryString.Item("mode").ToLower

      _text = CType(Request.QueryString.Item("text"), Integer)

      _height = _height * 2 : _width = 105

      If Not _text = 0 And Not _text = 1 Then

        Throw New Exception("_text is out of range = 0-1")

      End If

      Dim bcBitMap As Bitmap

      If _mode.ToLower = "upc-a" Then

        bcBitMap = New Bitmap(_width, _height) ' default unit is pixels, barcode for upc-a is always 95 pixels wide

      Else

        bcBitMap = New Bitmap(_width * 2 + 20, _height + 10) ' default unit is pixels, barcode for upc-a is always 95 pixels wide

      End If

      Dim graph As Graphics = Graphics.FromImage(bcBitMap)

      graph.Clear(Color.White)

      ' handle barcode graphic

      Me.PrintBarCode(graph, _mode)

      ' handle text

      If _text = 1 Then

        If _mode.ToLower = "upc-a" Then

          Me.PrintUpcText(graph, _code)

        Else

          Me.PrintC39Text(graph, "*" & _code.Replace("*", "") & "*")

        End If

      End If

      Try

        Response.ContentType = "image/gif"

        bcBitMap.Save(Response.OutputStream, ImageFormat.Gif)

      Catch ex As Exception

        Dim errorMsg As String = ex.message

      End Try

    Catch ex As Exception

                  Dim errorMsg As String = ex.Message

    End Try

 

Printing a barcode:

Pass the graphics type instance graph into your procedure so you can paint on it. Create some objects to hold positioning. Origy and EndY and going to be constant over the printing, but curX is the main thing that will vary to make the barcode’s lines. We are printing or not printing every pixel, and since the pixel is the default unit of the image, this works nicely. Now we will get rid of any * = asterisks in our code since they should not be used in the text code ever, only on the ends. We loop through the letters of the code now including the asterisks.

 

Code Listing 2 – Printing the Code39 barcode

   Private Sub PrintCode39(ByVal graph As Graphics)

    Dim rHeight As Integer = _height - 7

    Dim curPattern As String

    Dim origx As Integer = 4

    Dim origy As Integer = 2

    Dim endY As Integer = origy + rHeight

    Dim curX As Integer

    curX = origx

    Dim pattern As String

    Dim code As String = "*" & Replace(_code, "*", "") & "*"

    For i As Integer = 0 To code.Length - 1

      pattern = Me.GetC39Pattern(code.Substring(i, 1))

      For Each patt As Char In pattern

        If patt = "1"c Then

          graph.DrawLine(Pens.Black, curX, origy, curX, endY)

          curX += 1

        Else

          curX += 1

        End If

      Next

    Next

  End Sub

 

We want to print the pattern associated with each letter of the code. To get the code is different for each barcode. For Code39 it is a simple matter of a select statement to get the right pattern. For UPC-A, notice that although we only print numbers so there are only 9 digits to be concerned with, there are separate sets of patterns for the left 6 digits, versus the right six digits, (UPC-A always has 12 digits in the code).

To print a pattern is a simple if-else-endif within a loop. If the first char type in the pattern is “1”c then print, otherwise just update the curX positon object to leave a blank space in your barcode’s printed pattern. The UPC-A has fixed constant patterns at front, middle, and end called “Guard bars” to make the barcode read easier, so those parts are constant printed patterns. Notice the same pattern loop is used though for both codes.


Image 1 – The barcodes


Links

This link shows how I figured out how to do the UPC-A code

 

Summary:

I feel this solution is a good one since relying on someone else’s font, component, control can sometimes be troublesome when you want to debug or change some features regarding your application. This solution is very easy to test by just printing your webpage and scanning the code to make sure it works. You can trace the code and look at each pattern easily, so debugging is a dream. Changing features with such simple code is straight forward.