Click here to Skip to main content
Email Password   helpLost your password?

Introduction

On almost every product sold, there is typically a UPC barcode of some type which is used to identify the product. The most common barcode used, in the United States and Canada, is the UPC-A barcode. In this article, we will look at the UPC-A specification and examine some code that can produce UPC-A barcodes.

UPC-A Background

The UPC-A barcode is composed of 12 digits which are made up of the following sections:

Product Type

The product type is a one digit number which is used to describe the type of product.

Product Type Number Description
0 Regular UPC codes
1 Reserved
2 Weight items marked at the store.
3 National Drug/Health-related code.
4 No format restrictions, in-store use on non-food items.
5 Coupons
6 Reserved
7 Regular UPC codes
8 Reserved
9 Reserved

Manufacturer code and product code

The manufacturer code is assigned by the Uniform Code Council, and is used to uniquely identify the product's manufacturer. The product code is used to identify the product.

Checksum digit

The checksum digit is calculated using the product type, manufacturer's code, and the product code. The odd numbers are multiplied by 3 and added to the sum, while the even numbers are simply added to the sum. The modulus of 10 is then taken of the summed total. This is subtracted from 10 and the modulus of 10 is taken again.

For example: UPC-A 01234567890
Product Type : 0
Manufacturer's Code : 12345
Product Code : 67890

The first digit '0' is odd, so multiple it by 3, the second digit 1 is even so just add it, etc...

(0 * 3) + 1 + (2 * 3) + 3 + (4 * 3) + 5 + (6 * 3) + 7 + (8 * 3) + 9 + (0 * 3) = 85

85 % 10 = 5

( ( 10 - 5 ) % 10 ) = 5

Symbol size

The specifications for the UPC-A barcode specify the nominal size of a UPC symbol as 1.496" wide and 1.02" high. Based upon this nominal size the UPC symbol can be scaled by a magnification factor of 0.8 to 2.0. Scaling the barcode will produce a barcode between the minimal allowable size of 1.175" wide by .816" high and the maximum allowable size of 2.938" wide and 2.04" high.

Digit patterns

Each digit in a UPC-A bar code is composed of a series of two spaces and two bars. Each digit is drawn within a space that is 7 modules wide. In addition to the 12 digits, which make up a UPC-A barcode, the barcode symbol also has two quite zones, a lead block, a separator, and a trailing block. Each quite zone is 9 modules wide, the lead and trailing blocks are a series of lines and spaces in the format of bar, space, bar. The separator is signified by the sequence space/bar/space/bar/space.

Special Symbol Pattern
Quite Zone 000000000
Lead / Trailer 101
Separator 01010

where '0' represents space and '1' denotes a bar.

In addition to the special symbol patterns listed above, the UPC-A barcode symbol uses two distinct digit patterns as well, the Left Digit pattern and the Right Digit pattern. The Left Digit pattern is used to draw the product type and the manufacturer code. The Right Digit pattern is used to draw the product code and the checksum digit. The Left Digit pattern starts with spaces and the Right Digit pattern starts with bars (see table below).

Number Left Digits Right Digits
0 0001101 1110010
1 0011001 1100110
2 0010011 1101100
3 0111101 1000010
4 0100011 1011100
5 0110001 1001110
6 0101111 1010000
7 0111011 1000100
8 0110111 1001000
9 0001011 1110100

where a '0' denotes a space and '1' represents a bar.

Using the code

First, we will examine how to use the UpcA class, and then we'll examine how the UpcA class works.

Using the UpcA Class

The code excerpt below uses the UpcA class to draw a UPC-A barcode in a picture box control:

private void DrawUPC( )
{        
   System.Drawing.Graphics g = this.picBarcode.CreateGraphics( ); 

   g.FillRectangle(new System.Drawing.SolidBrush(
               System.Drawing.SystemColors.Control), 
                new Rectangle(0, 0, picBarcode.Width, picBarcode.Height)); 
        
   // Create an instance of the UpcA Class.        

   upc = new UpcA( ); 
    
   upc.ProductType = "0";
   upc.ManufacturerCode = "21200"; 
   upc.ProductCode = "10384"; 
   upc.Scale = 
     (float)Convert.ToDecimal( cboScale.Items [cboScale.SelectedIndex] ); 
    
   upc.DrawUpcaBarcode( g, new System.Drawing.Point( 0, 0 ) ); 
    
   g.Dispose( );
}

The first step for the DrawUPC function is to create an instance of the UpcA class, and then set the product type, manufacturer code, the product code, and the scale factor properties (the check sum will be calculated by the UpcA class). Once these properties are set, a call to the DrawUpcaBarcode function is made, passing a Graphics object and a Point, which indicates the starting position to draw at, this will cause the barcode to be drawn in the picture box starting at point (0, 0).

The UpcA Class

The most significant variables are listed below:

// This is the nomimal size recommended by the UCC.

private float _fWidth = 1.469f;
private float _fHeight = 1.02f;
private float _fFontSize = 8.0f;
private float _fScale = 1.0f;

// Left Hand Digits.

private string [] _aLeft = { "0001101", "0011001", "0010011", "0111101", 
                             "0100011", "0110001", "0101111", "0111011", 
                             "0110111", "0001011" };

// Right Hand Digits.

private string [] _aRight = { "1110010", "1100110", "1101100", "1000010", 
                              "1011100", "1001110", "1010000", "1000100", 
                              "1001000", "1110100" };

private string _sQuiteZone = "0000000000";
private string _sLeadTail = "101";
private string _sSeparator = "01010";

The _fWidth, _fHeight, and the _fScale variables are initialized with the nominal size recommended by the Uniform Code Council. When the barcode is rendered, its actual size will be determined by the nominal size, and the scale factor, as discussed in the Symbol Size section of this article. The variables _aLeft, _aRight, _sQuiteZone, _sLeadTail, and _sSeparator are all string representations of the bar/space graphics, which represent the various parts of a UPC-A barcode. Essentially, a '1' represents a bar and a '0' represents a space, so _sSeparator would cause a space-bar-space-bar-space to be rendered. An alternate method to using a string could be to use a binary representation, where a 0 bit would be space and a 1 bit is a bar.

There are three primary functions which provide the majority of the functionality for the UpcA class. The workhorse of these functions is DrawUpcaBarcode. DrawUpcaBarcode uses the other two functions as helper functions. The two helper functions are: CalculateChecksumDigit, ConvertToDigitPatterns and these will be discussed first. There is also a fourth function, CreateBitmap, which provides an easy means for creating a bitmap image.

The first helper function DrawUpcaBarcode calls the CalculateChecksumDigit function, which uses the product type, manufacturer code, and product code to calculate the barcode's check sum.

public void CalculateChecksumDigit( )
{
    string sTemp = this.ProductType + this.ManufacturerCode + this.ProductCode;
    int iSum = 0;
    int iDigit = 0;

    // Calculate the checksum digit here.

    for( int i = 1; i <= sTemp.Length; i++ )
    {
        iDigit = Convert.ToInt32( sTemp.Substring( i - 1, 1 ) );
        if( i % 2 == 0 )
        {    // even

            iSum += iDigit * 1;
        }
        else
        {    // odd

            iSum += iDigit * 3;
        }
    }

    int iCheckSum = ( 10 - ( iSum % 10 )  ) % 10;
    this.ChecksumDigit = iCheckSum.ToString( );

}

The CalculateChecksumDigit function calculates the check sum using the method discussed in the Checksum Digit section listed above.

The second helper function used is the ConvertToDigitPatterns function. This function takes the individual numbers of the manufacturer code, and the product number, and converts them to the string representation of the barcode graphics.

private string ConvertToDigitPatterns( string inputNumber, string [] patterns )
{
    System.Text.StringBuilder sbTemp = new StringBuilder( );
    int iIndex = 0;
    for( int i = 0; i < inputNumber.Length; i++ )
    {
        iIndex = Convert.ToInt32( inputNumber.Substring( i, 1 ) );
        sbTemp.Append( patterns[iIndex] );
    }
    return sbTemp.ToString( );
}

The ConvertToDigitPatterns function requires two parameters:

The inputNumber will be either the manufacturer number or the product number, and the patterns will either be the _aLeft or the _aRight array depending on whether the inputNumber is the manufacturer number or the product number.

Finally the workhorse; the DrawUpcaBarcode handles the rendering of the barcode graphics and requires two parameters:

This function begins by determining the width and height for the barcode, by scaling the nominal width and height by the scale factor. The lineWidth is based upon the total number of modules required to render a UPC-A barcode. The total number of modules, 113, is determined by the following: for example:

UPC-A code - 021900103841

Barcode Section Numeric Value Graphic Representation Number of Modules
Quite Zone N/A 000000000 9 modules
Lead N/A 101 3 modules
Product Type 1 digit - "0" 0001101 7 modules
Manufacturer Number 5 digits = "21900" 00100110011001000101100011010001101 5 digits * 7 modules = 35 modules
Separator N/A 01010 5 modules
Product Number 5 digits = "10384" 11001101110010100001010010001011100 5 digits * 7 modules = 35 modules
Check Sum 1 digit = "1" 1100110 7 modules
Trailer N/A 101 3 modules
Quite Zone N/A 000000000 9 modules

So, to determine the total module width, simply add the individual parts: 9 + 3 + 7 + 35 + 5 + 35 + 7 + 3 + 9 = 113.

public void DrawUpcaBarcode(System.Drawing.Graphics g,System.Drawing.Point pt)
{

    float width = this.Width * this.Scale;
    float height = this.Height * this.Scale;

    // A upc-a excluding 2 or 5 digit supplement information 

    // should be a total of 113 modules wide. 

    // Supplement information is typically 

    // used for periodicals and books.

    float lineWidth = width / 113f;

    // Save the GraphicsState.

    System.Drawing.Drawing2D.GraphicsState gs = g.Save( );

    // Set the PageUnit to Inch because all of 

    // our measurements are in inches.

    g.PageUnit = System.Drawing.GraphicsUnit.Inch;

    // Set the PageScale to 1, so an inch will represent a true inch.

    g.PageScale = 1;

    System.Drawing.SolidBrush brush = 
           new System.Drawing.SolidBrush( System.Drawing.Color.Black );

    float xPosition = 0;

    System.Text.StringBuilder strbUPC = new System.Text.StringBuilder( );

    float xStart = pt.X;
    float yStart = pt.Y;
    float xEnd = 0;

    System.Drawing.Font font = 
      new System.Drawing.Font( "Arial", this._fFontSize * this.Scale );

    // Calculate the Check Digit.

    this.CalculateChecksumDigit( );

    // Build the UPC Code.

    strbUPC.AppendFormat( "{0}{1}{2}{3}{4}{5}{6}{1}{0}",
                this._sQuiteZone, this._sLeadTail,
                ConvertToDigitPatterns( this.ProductType, this._aLeft ),
                ConvertToDigitPatterns( this.ManufacturerCode, this._aLeft ),
                this._sSeparator,
                ConvertToDigitPatterns( this.ProductCode, this._aRight ), 
                ConvertToDigitPatterns( this.ChecksumDigit, this._aRight ) );

    string sTempUPC = strbUPC.ToString( );

    float fTextHeight = g.MeasureString( sTempUPC, font ).Height;

    // Draw the barcode lines.

    for( int i = 0; i < strbUPC.Length; i++ )
    {
        if( sTempUPC.Substring( i, 1 ) == "1" )
        {
            if( xStart == pt.X )
                xStart = xPosition;

            // Save room for the UPC number below the bar code.

            if( ( i > 19 && i < 56 ) || ( i > 59 && i < 95 ) )
                // Draw space for the number

                g.FillRectangle( brush, xPosition, yStart, 
                                      lineWidth, height - fTextHeight );
            else
                // Draw a full line.

                g.FillRectangle( brush, xPosition, yStart, lineWidth, height );
        }

        xPosition += lineWidth;
        xEnd = xPosition;
    }

    // Draw the upc numbers below the line.

    xPosition = xStart - g.MeasureString( this.ProductType, font ).Width;
    float yPosition = yStart + ( height - fTextHeight );
    
    // Draw Product Type.

    g.DrawString( this.ProductType, font, brush, 
                   new System.Drawing.PointF( xPosition, yPosition ) );

    // Each digit is 7 modules wide, therefore the MFG_Number 

    // is 5 digits wide so

    // 5 * 7 = 35, then add 3 for the LeadTrailer 

    // Info and another 7 for good measure,

    // that is where the 45 comes from.

    xPosition += 
          g.MeasureString( this.ProductType, font ).Width + 45 * lineWidth - 
                     g.MeasureString( this.ManufacturerCode, font ).Width;

    // Draw MFG Number.

    g.DrawString( this.ManufacturerCode, font, brush, 
                         new System.Drawing.PointF( xPosition, yPosition ) );

    // Add the width of the MFG Number and 5 modules for the separator.

    xPosition += g.MeasureString( this.ManufacturerCode, font ).Width +
                        5 * lineWidth;

    // Draw Product ID.

    g.DrawString( this.ProductCode, font, brush, 
                          new System.Drawing.PointF( xPosition, yPosition ) );

    // Each digit is 7 modules wide, therefore 

    // the Product Id is 5 digits wide so

    // 5 * 7 = 35, then add 3 for the LeadTrailer 

    // Info, + 8 more just for spacing

    // that is where the 46 comes from.

    xPosition += 46 * lineWidth;

    // Draw Check Digit.

    g.DrawString( this.ChecksumDigit, font, brush, 
                          new System.Drawing.PointF( xPosition, yPosition ) );

    // Restore the GraphicsState.

    g.Restore( gs );

}

The function uses the CalculateChecksumDigit function to calculate the correct check sum digit, and then uses the ConvertToDigitPatterns function to convert the various numeric parts of the UPC-A barcode number to a string representation. Once the number has been converted over to a string representation, the code uses the string representation to render the barcode, 1 will cause a rectangle to be drawn, and 0 will cause the code to skip drawing a rectangle. If the code draws a rectangle, it also takes into consideration whether it needs to shorten the rectangle to allow space for the manufacturer's number and the product number. Once the barcode is completely rendered, the code then determines the position, and draws the product type number, the manufacturer's number, the product number, and the check sum digit.

The CreateBitmap function simply creates a Bitmap object, and uses the DrawUpcaBarcode function to render the barcode to the Bitmap object, and then it returns the Bitmap.

public System.Drawing.Bitmap CreateBitmap( )
{
    float tempWidth = ( this.Width * this.Scale ) * 100 ;
    float tempHeight = ( this.Height * this.Scale ) * 100;

    System.Drawing.Bitmap bmp = 
       new System.Drawing.Bitmap( (int)tempWidth, (int)tempHeight );

    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage( bmp );
    this.DrawUpcaBarcode( g, new System.Drawing.Point( 0, 0 ) );
    g.Dispose( );
    return bmp;
}

Points of interest

The United States and Canada are the only two countries that use the UPC-A barcode system, the rest of the world uses the EAN barcode system. So, as of January 1, 2005, the Uniform Code Council, UCC, has mandated that all U.S. and Canadian point-of-sale companies must be able to scan and process EAN-8, and EAN-13 barcodes, in addition to the UPC-A barcodes (this is called the 2005 Sunrise). The UCC has also began to push a new bar code system, known as the Global Trade Item Numbers (GTINs), basically a GTIN is a 14 digit number which conforms to the UPC-A, and EAN-13 symbol standards but uses additional digits to store country of origin information. If you want more information, go to UCC: 2005 Sunrise.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralBarcode does not show up if placed in Window directory
BHHNVB
8:01 18 Sep '09  
Thanks a lot for the good source code.

I am using Internet Explore 7.0 to render the label which has the barcode.

It works fine When I placed the barcode file in a IIS folder. Inn HTML file, I link to the barcode image using url as below:
<IMG SRC="http://localhost/UPCTypeA.BMP" >

But the barcode does not show up if I place the barcode file in Window directory and link to it using
<IMG SRC="C:\UPCTypeA.BMP">

Anybody has any idea?

Thanks
GeneralNOT PRODUCING AN ACCURATE BAR CODE! [modified]
Chris Marcan
8:43 16 Jul '09  
When scale is 1, bar codes will scan, but not very well.

When I compare with a bar code from a packaged product with the same upc created with this code, I notice that some of the lines have a different thickness. When looking at the binary string and comparing it to the lines in the bar code, some of the single lines (example: 010) are thicker than the others, even though the line width is the same value for every line. Some kinda rounding or scaling issue. When scale is changed to 2, all the single thickness lines are the same thickness and they scan perfectly.

How to fix this? I have no idea.

modified on Thursday, July 16, 2009 1:50 PM

AnswerRe: NOT PRODUCING AN ACCURATE BAR CODE! [modified]
Chris Marcan
9:36 16 Jul '09  
Fixed it. I found if I increased the resolution of the bitmap to 300dpi it worked fine. The default resolution of 100dpi is not enough to accurately display the barcode lines.

public System.Drawing.Bitmap CreateBitmap( )
{
//float tempWidth = ( this.Width * this.Scale ) * 100 ;
//float tempHeight = ( this.Height * this.Scale ) * 100;
float tempWidth = ( this.Width * this.Scale ) * 300 ; //changed from 100.
float tempHeight = ( this.Height * this.Scale ) * 300;

System.Drawing.Bitmap bmp = new System.Drawing.Bitmap( (int)tempWidth, (int)tempHeight );

bmp.SetResolution(300, 300); //new line

System.Drawing.Graphics g = System.Drawing.Graphics.FromImage( bmp );
this.DrawUpcaBarcode( g, new System.Drawing.Point( 0, 0 ) );
g.Dispose( );
return bmp;
}

modified on Thursday, July 16, 2009 4:43 PM

GeneralRe: NOT PRODUCING AN ACCURATE BAR CODE!
muppaluri
5:53 23 Oct '09  
Yep! I had the same issue with the original code and made the suggested changes to increase the resolution to 300. Thanks. Smile
Generalquistion
beeshooo
8:21 9 Feb '09  
what is the "upc"?
Generalhelp
lakshmi priya.t.n
18:33 29 Jan '09  
Hi,

i'm planning to do a project name library management system in which i hav to use barcodes . . . . .
i have to generate barcodes for student details and also for the bookdetails...
i'm new to this area of barcodes.can anyone pls tell me which type of barcode to use,which will be suitable and simple for this application...
i live in india..

pls help me..
GeneralThis saves me $$$
David Tum
6:53 27 Jan '07  
as some companies make money from it, you're giving it for free. Thank you for the kind contribution.

David
GeneralUPC-E
Bill Daugherty II
9:59 1 Jan '06  
Hello again,

Do you have any C#/VB.NET versions of the UPC-E?
GeneralRe: UPC-E
rainman_63
3:46 3 Jan '06  
Hey Bill,

No, I haven't done any UPC-E code.

SorryFrown ,

Raymond

GeneralRe: UPC-E
Bill Daugherty II
9:04 3 Jan '06  
That is ok. You inspired me to create the code39. I started by compairing to a font, but i ended up re-doing it all and came up with this:
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=4352&lngWId=10[^]
GeneralJust some inforamtion.
Bill Daugherty II
9:56 1 Jan '06  
Hello, i downloaded your application, you did a very nice job. I was going to create my own, but found this right when i was ready to start.

I think you did a very nice job.

Here is what i did to modify the code, and anyone can email me to get the code, billsecond at yahoo.com.

1. I converted it to VB.NET because i have an application where it was created in vb.net, and i don't want to use dll's just yet.
2. I made the minimum size 1.2 (scale), and this actually is the smallest reconized image for a bar code scanner application i found on the internet called "Clear Image", i just downladed the demo to make sure it worked, because the bar code didn't seem to match, but once i did increase the size it worked great.
3. I added another constructor that accepts the 11/12 digit bar code
4. I added an IsValid function that returns a boolean value to test weather or not the barcode is valid.

I also changed the way you can save it. See below..


======[code]
Dim g As Graphics = CreateGraphics()
Dim newBitmap As Bitmap = New Bitmap(picBarcode.Width, picBarcode.Height, Imaging.PixelFormat.Format32bppArgb)
g = Graphics.FromImage(newBitmap)
g.FillRectangle(New SolidBrush(Color.White), New Rectangle(0, 0, picBarcode.Width, picBarcode.Height))




upc.DrawUpcaBarcode(g)
newBitmap.Save("c:\test.jpg", Imaging.ImageFormat.Jpeg)
Me.picBarcode.Image = Image.FromHbitmap(newBitmap.GetHbitmap)
newBitmap.Dispose()
If Me.txtUPCA.Text.Length = 11 Then
Me.txtUPCA.Text += upc.ChecksumDigit()
ElseIf Me.txtUPCA.Text.Length = 12 Then
If Not Me.txtUPCA.Text.Substring(11, 1) = upc.ChecksumDigit() Then
Me.txtUPCA.Text = Me.txtUPCA.Text.Substring(0, 11) + upc.ChecksumDigit()
End If
End If
g.Dispose()[/code]
=====
(by the way, any coding suggestions, let me know, i know its probbly not the neatest.)

Here is the class file i created..

=====[code]
' Title: UPCA
' Description: Creates a graphic for the UPCA Barcode
' -------------------------------------------------------------------
' This code was taken and modified from the following link. I
' transfered the code from C#.NET to VB.NET so i could eleminate the
' DLL's, and just have a single EXE file.
' Code from: http://www.codeproject.com/csharp/upc_barcode.asp
' Here is a great resource for UPC's: http://www.activebarcode.com/codes/


Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Text

Public Class cUPC
Private globalName As String = "UPC-A"
Private globalMinimumAllowableScale As Single = 0.8F
Private globalMaximumAllowableScale As Single = 2.0F

' This is the nomimal size recommended by the UCC.
Private globalWidth As Single = 1.469F
Private globalHeight As Single = 1.02F
Private globalFontSize As Single = 8.0F
Private globalScale As Single = 1.5F 'Note i have tested this, and 1.2 is the minimum

' Left Hand Digits.
Private globalLeft() As String = {"0001101", "0011001", "0010011", "0111101", _
"0100011", "0110001", "0101111", "0111011", _
"0110111", "0001011"}

' Right Hand Digits.
Private globalRight() As String = {"1110010", "1100110", "1101100", "1000010", _
"1011100", "1001110", "1010000", "1000100", _
"1001000", "1110100"}

Private globalQuiteZone As String = "0000000000"

Private globalLeadTail As String = "101"

Private globalSeparator As String = "01010"

Private globalProductType As String = "0"
Private globalManufacturerCode As String
Private globalProductCode As String
Private globalChecksumDigit As String

Public Sub New()

End Sub

Public Sub New(ByVal barCode As String)
globalProductType = barCode.Substring(0, 1)
globalManufacturerCode = barCode.Substring(1, 5)
globalProductCode = barCode.Substring(6, 5)
If (barCode.Length > 11) Then
globalChecksumDigit = barCode.Substring(11, 1)
End If
End Sub

Public Sub New(ByVal mfgNumber As String, ByVal productId As String)
Me.globalProductType = "0"
Me.globalManufacturerCode = mfgNumber
Me.globalProductCode = productId
Me.CalculateChecksumDigit()
End Sub

Public Sub New(ByVal productType As String, ByVal mfgNumber As String, ByVal productId As String)
Me.globalProductType = productType
Me.globalManufacturerCode = mfgNumber
Me.globalProductCode = productId
Me.CalculateChecksumDigit()
End Sub

Public Sub New(ByVal productType As String, ByVal mfgNumber As String, ByVal productId As String, ByVal checkDigit As String)
Me.globalProductType = productType
Me.globalManufacturerCode = mfgNumber
Me.globalProductCode = productId
Me.globalChecksumDigit = checkDigit
End Sub

Public Function IsValid(ByVal barCode As String) As Boolean

Dim isTheBarCodeValid As Boolean = False
If barCode.Length = 12 Then
CalculateChecksumDigit()
If barCode.Substring(11, 1) = ChecksumDigit() Then
isTheBarCodeValid = True
End If
End If
Return isTheBarCodeValid

End Function

Public Sub DrawUpcaBarcode(ByVal g As System.Drawing.Graphics)
Dim pt As System.Drawing.Point = New System.Drawing.Point(0, 0)
Dim width As Single = Me.globalWidth * Me.globalScale
Dim height As Single = Me.globalHeight * Me.globalScale

' A upc-a excluding 2 or 5 digit supplement information
' should be a total of 113 modules wide. Supplement information is typically
' used for periodicals and books.
Dim lineWidth As Single = width / 113.0F

' Save the GraphicsState.
Dim gs As System.Drawing.Drawing2D.GraphicsState = g.Save()

' Set the PageUnit to Inch because all of our measurements are in inches.
g.PageUnit = System.Drawing.GraphicsUnit.Inch

' Set the PageScale to 1, so an inch will represent a true inch.
g.PageScale = 1

Dim brush As System.Drawing.SolidBrush = New System.Drawing.SolidBrush(System.Drawing.Color.Black)

Dim xPosition As Single = 0

Dim strbUPC As System.Text.StringBuilder = New System.Text.StringBuilder()
Dim xStart As Single = pt.X
Dim yStart As Single = pt.Y
Dim xEnd As Single = 0

Dim font As System.Drawing.Font = New System.Drawing.Font("MS Reference Sans Serif", (Me.globalFontSize + 1) * Me.globalScale)

' Calculate the Check Digit.
Me.CalculateChecksumDigit()

' Build the UPC Code.
strbUPC.AppendFormat("{0}{1}{2}{3}{4}{5}{6}{1}{0}", _
Me.globalQuiteZone, Me.globalLeadTail, _
ConvertToDigitPatterns(Me.globalProductType, Me.globalLeft), _
ConvertToDigitPatterns(Me.globalManufacturerCode, Me.globalLeft), _
Me.globalSeparator, _
ConvertToDigitPatterns(Me.globalProductCode, Me.globalRight), _
ConvertToDigitPatterns(Me.globalChecksumDigit, Me.globalRight))

Dim sTempUPC As String = strbUPC.ToString()

Dim fTextHeight As Single = g.MeasureString(sTempUPC, font).Height

' Draw the barcode lines.
Dim i As Integer = 0
For i = 0 To strbUPC.Length - 1

If (sTempUPC.Substring(i, 1) = "1") Then

If (xStart = pt.X) Then
xStart = xPosition
End If

' Save room for the UPC number below the bar code.
If ((i > 19 And i < 56) Or (i > 59 And i < 95)) Then
' Draw space for the number
g.FillRectangle(brush, xPosition, yStart, lineWidth, height - fTextHeight)
Else
' Draw a full line.
g.FillRectangle(brush, xPosition, yStart, lineWidth, height)
End If
End If
xPosition += lineWidth ' Taken out ";"
xEnd = xPosition ' Taken out ";"
Next

' Draw the upc numbers below the line.

xPosition = xStart - g.MeasureString(Me.globalProductType, font).Width
Dim yPosition As Single = yStart + (height - fTextHeight)
' Draw Product Type.
g.DrawString(Me.globalProductType, font, brush, New System.Drawing.PointF(xPosition, yPosition))

' Each digit is 7 modules wide, therefore the MFG_Number is 5 digits wide so
' 5 * 7 = 35, then add 3 for the LeadTrailer Info and another 7 for good measure,
' that is where the 45 comes from.
xPosition += g.MeasureString(Me.globalProductType, font).Width + 45 * lineWidth - _
g.MeasureString(Me.globalManufacturerCode, font).Width

' Draw MFG Number.
g.DrawString(Me.globalManufacturerCode, font, brush, New System.Drawing.PointF(xPosition, yPosition))

' Add the width of the MFG Number and 5 modules for the separator.
xPosition += g.MeasureString(Me.globalManufacturerCode, font).Width + 5 * lineWidth

' Draw Product ID.
g.DrawString(Me.globalProductCode, font, brush, New System.Drawing.PointF(xPosition, yPosition))

' Each digit is 7 modules wide, therefore the Product Id is 5 digits wide so
' 5 * 7 = 35, then add 3 for the LeadTrailer Info, + 8 more just for spacing
' that is where the 46 comes from.
xPosition += 46 * lineWidth

' Draw Check Digit.
g.DrawString(Me.globalChecksumDigit, font, brush, New System.Drawing.PointF(xPosition, yPosition))

' Restore the GraphicsState.
g.Restore(gs)

End Sub

Public Function CreateBitmap() As System.Drawing.Bitmap

Dim tempWidth As Single = (Me.globalWidth * Me.globalScale) * 100
Dim tempHeight As Single = (Me.globalHeight * Me.globalScale) * 100

Dim bmp As System.Drawing.Bitmap = New System.Drawing.Bitmap(CInt(tempWidth), CInt(tempHeight))

Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(bmp)
Me.DrawUpcaBarcode(g) ' Taken out ";"
g.Dispose() ' Taken out ";"
Return bmp ' Taken out ";"
End Function

Private Function ConvertToDigitPatterns(ByVal inputNumber As String, ByVal patterns() As String) As String

Dim sbTemp As System.Text.StringBuilder = New StringBuilder() ' Taken out ";"
Dim iIndex As Integer = 0 ' Taken out ";"
Dim i As Integer = 0
For i = 0 To inputNumber.Length - 1 '(int i = 0' Taken out ";" i < inputNumber.Length' Taken out ";" i++)
iIndex = Convert.ToInt32(inputNumber.Substring(i, 1)) ' Taken out ";"
sbTemp.Append(patterns(iIndex)) ' Taken out ";"
Next
Return sbTemp.ToString() ' Taken out ";"
End Function

Public Sub CalculateChecksumDigit()
Dim sTemp As String = Me.globalProductType + Me.globalManufacturerCode + Me.globalProductCode ' Taken out ";"
Dim iSum As Integer = 0 ' Taken out ";"
Dim iDigit As Integer = 0 ' Taken out ";"

' Calculate the checksum digit here.
Dim i As Integer = 0
For i = 1 To sTemp.Length '(int i = 1' Taken out ";" i <= sTemp.Length' Taken out ";" i++)

iDigit = Convert.ToInt32(sTemp.Substring(i - 1, 1)) ' Taken out ";"
If (i Mod 2 = 0) Then
iSum += iDigit * 1 ' Taken out ";"
Else
iSum += iDigit * 3 ' Taken out ";"
End If
Next

Dim iCheckSum As Integer = (10 - (iSum Mod 10)) Mod 10 ' Taken out ";"
Me.globalChecksumDigit = iCheckSum.ToString() ' Taken out ";"

End Sub

Public Property Name() As String
Get
Return globalName ' Taken out ";"
End Get
Set(ByVal value As String)
'
End Set
End Property

Public Property MinimumAllowableScale() As Single
Get
Return MinimumAllowableScale ' Taken out ";"
End Get
Set(ByVal value As Single)

End Set
End Property

Public Property MaximumAllowableScale() As Single
Get
Return MaximumAllowableScale ' Taken out ";"
End Get
Set(ByVal value As Single)

End Set
End Property

Public Property Width() As Single
Get
Return Width ' Taken out ";"
End Get
Set(ByVal value As Single)

End Set
End Property

Public Property Height() As Single
Get
Return Height ' Taken out ";"
End Get
Set(ByVal value As Single)

End Set
End Property

Public Property FontSize() As Single
Get
Return FontSize ' Taken out ";"
End Get
Set(ByVal value As Single)

End Set
End Property

Public Property Scale() As Single
Get
Return Scale ' Taken out ";"
End Get
Set(ByVal value As Single)
If (value < Me.globalMinimumAllowableScale Or value > Me.globalMaximumAllowableScale) Then
Throw New Exception("Scale value out of allowable range. Value must be between " + _
Me.globalMinimumAllowableScale.ToString() + " and " + _
Me.globalMaximumAllowableScale.ToString()) ' Taken out ";"
Else
globalScale = value ' Taken out ";"
End If
End Set
End Property



' ' System Description
' 0 - Regular UPC codes
' 1 - Reserved
' 2 - Weightitems marked at the store
' 3 - National Drug/Health-related code
' 4 - No format restrictions, in-store use on non-food items
' 5 - Coupons
' 6 - Reserved
' 7 - Regular UPC codes
' 8 - Reserved
' 9 - Reserved
'
'
Public Property ProductType() As String
Get
Return globalProductType ' Taken out ";"
End Get
Set(ByVal value As String)
' Check against what types are valid.
Dim iTemp As Integer = Convert.ToInt32(value) ' Taken out ";"
If (iTemp = 1 Or iTemp = 6 Or iTemp > 7) Then
' throw new Exception(value + " is a reserved Product Type. ")' Taken out ";"
Else
globalProductType = value ' Taken out ";"
End If
End Set
End Property



Public Property ManufacturerCode() As String
Get
Return globalManufacturerCode ' Taken out ";"
End Get
Set(ByVal value As String)
If Not value.Length = 5 Then
' throw new Exception("The manufacturer number must be 5 digits.")' Taken out ";"
Else
globalManufacturerCode = value ' Taken out ";"
End If
End Set
End Property

Public Property ProductCode() As String
Get
Return globalProductCode ' Taken out ";"
End Get
Set(ByVal value As String)
If Not value.Length = 5 Then
'throw new Exception("The product identification number must be 5 digits.")' Taken out ";"
Else
globalProductCode = value ' Taken out ";"
End If
End Set
End Property

Public Property ChecksumDigit() As String
Get
Return globalChecksumDigit ' Taken out ";"
End Get
Set(ByVal value As String)
Dim iValue As Integer = Convert.ToInt32(value) ' Taken out ";"
If (iValue < 0 Or iValue > 9) Then
' throw new Exception("The Check Digit must be between 0 and 9.")' Taken out ";"
Else
globalChecksumDigit = value ' Taken out ";"
End If
End Set
End Property

End Class[/code]
============
Generalrunnign code as webapp...
walkerla
16:26 27 Sep '05  
Great Article.

how difficult would it be to port this code over to run as a dotnet webapplication? I'm wondering if there is there is a control that has properties similiar to the System.Windows.Forms.PictureBox control. Any comments?
AnswerRe: runnign code as webapp...
rainman_63
5:37 28 Sep '05  
Hey walkerla,

To take a quick stab at it; yes you can use the code of the UPCA class to create a web application. Set the barcode data and then make a call to the CreateBitmap method which will return a bitmap that could be displayed on a web page.

HTH some,

rainman_63
QuestionRe: runnign code as webapp...
MadCoder81
4:46 7 Mar '08  
Heya there Rainman (or anyone with any advice),

I converted this to a web application and did indeed use the create bitmap method to save the image off so it could be displayed in an image control. The problem is, when I actually print out the barcode my scanner no longer recognizes it. If I draw the UPC into a picture box in a winforms application it works perfectly. I've been messing around with this for days now, so any advice would be greatly appreciated.

Confused and befuddled, Confused Confused Mad

Brandon

G'luck,

Brandon
brandon.osborne at gmail.com

GeneralModify to get EAN-8 codes
gRabbi2
12:29 4 Jul '05  
Very nice piece od code. But can anyone lett me how to convert modify this project to get EAN-8 codes? Thanks for any advises.
Generalconvert string to UPC-A
SpYflaX
10:34 4 May '05  
Your article is great, the explanation too. Though, i still have a problem. To generate the barcode, you use the 12 digits but i only have a mere string like A00300 for instance, and i don't know how to translate this string to the 12 digits hihi. If you have the solution, please tell me. Thanks a lot for your article and probably for the answer hehe Smile
GeneralRe: convert string to UPC-A
SpYflaX
11:06 4 May '05  
of course, if there is a special function to convert a string to UPC-A. Else, i'll code one myself =)
Bye !
GeneralRe: convert string to UPC-A
CPallini
2:50 10 Jul '07  
SpYflaX wrote:
mere string like A00300 for instance

Maybe it's an heaxadecimal number:
A00300 hexadecimal = 10486528 decimal
Smile

If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.

GeneralSuggestion for another article
Carl Mercier
6:26 18 Apr '05  
Your article and code is great! Thank you. I have a suggestion, though.

Why not make a code that READS barcodes from an image file (or bitmap object)?

For example, a document containing a barcode is scanned into the computer, passed through an application which automatically finds the barcode and decodes it in order to store it in the proper folder.

I think that would be a nice complement to your article.

Thanks!


This might help: http://www.generation5.org/content/2004/barCode.asp[^]
GeneralProblem Saving Memory Bitmap
Gary Vidal
9:42 15 Apr '05  
I would like to thank you on an Excellent article. I noticed that when I try to save the image to disk that I get a black image. Is there a possible workaround to this problem.


Gary Vidal
GeneralRe: Problem Saving Memory Bitmap
ivanvaliente
8:58 7 Aug '06  
Gary,

Try inserting this line of code at the begining of the 'DrawUpcaBarcode' method:

g.Clear(Color.White)

Good luck!

-Ivan.
GeneralEAN? GTIN?
MArmbruckner
0:24 13 Apr '05  
Hi!

Thanks for this article, it's very nice!
Do you plan to extend the code for EAN8/EAN13 and GTIN?

Regards,
Markus
GeneralRe: EAN? GTIN?
rainman_63
3:29 13 Apr '05  
Markus,

To be honest, I really haven't thought about it, but as soon as I get some free time, I'll start working on it.

Thanks,

Raymond
GeneralRe: EAN? GTIN?
MArmbruckner
4:00 13 Apr '05  
Would you post an answer in this thread, when you've finished it? So I would not have to poll this URL Smile .

Thanks,
Markus
GeneralRe: EAN? GTIN?
rainman_63
7:08 13 Apr '05  
Markus,

I just finished modifying the code to create EAN-13 barcodes, and I have the source code ready to post. However, I can’t add attachments to this post, and I would prefer not to add another set a downloads to this article (to many source downloads make me confused). Also, the EAN-13 has some slight differences from the UPC-A barcodes, and probably deserves its own explanation, but I don’t have the time to write a complete article right now. So, I’m going to start an article and post the source code, then I’ll finish the article later this week. I’ll post a link to the EAN-13 barcodes article here when I’m finished.


Raymond


Last Updated 13 Apr 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010