Click here to Skip to main content
Click here to Skip to main content

The Asti Spumante Bar Code

, 3 Jun 2008
Rate this:
Please Sign up or sign in to vote.
An interesting article to learn how UPC-A bar coding works

Introduction

I've decided to write this article after reading the novel 'THE ASTI SPUMANTE CODE' by Toby Clements, which is a parody of 'THE DA VINCI CODE' by Dan Brown. I'm not that obsessed with any of these books, but just thought it would be more interesting to introduce UPC-A barcoding from such a perspective; though sarcastic.

Almost every item we buy or own has a barcode printed on it. We see those barcodes every day, but still we don't understand what they really mean or how to generate them. The major benefit of using barcodes is to automate and improve the speed and accuracy of data collection. That's why we see them on most sellable items.

One other way to look at barcodes is to think of them as one other form of cryptography that's so easy to decipher using barcode scanners. For example, a UPC-A barcode is a simple encoding of a 12 digit number into its bit representation, where 1 is represented as black vertical line and 0 represented as white vertical line. We will be creating a Java program that just does that.

Note: Image Cropped From 'THE ASTI SPUMANTE CODE' Book Cover

Background

In 'The Da Vinci Code', the secret that Robert Langdon and Sophie were searching for was the Holy Grail, which the Priory of Sion has hidden for centuries. However, in 'The ASTI SPUMANTE CODE', the secret that James Crack and Emily were searching for was the greatest book that will ever be written. According to Toby Clements, 'the secret ingredients of this book - characterization, plot, setting, and so forth - what para-literalists call the Asti Spumante Code - are contained on something called the Mure-de-Paume, the legendary keystone.'

While searching for the code, James Crack and Emily find a prolix, or simply what I concluded, a book. They discover under the book's red leather cover 'a rectangle of paper approximately five centimeters by three, laminated to the back of the prolix. On the piece of paper were a set of lines of differing widths and heights that could be read from right to left, or left to right, or not at all. It was a code. A barcode.' As sarcastic as this can get, it does describe what a barcode looks like.

In order to be able to read the barcode, James Crack escapes to London to a bookstore owned by Donnie Dogs. Clark asks Dogs about barcodes, and Dogs explains that barcodes are named by scholars as UPC, or Universal Product Code. Manufactures buy those barcodes from UCC, or Uniform Code Council. The UPC is made up of exactly 12 digits. Each digit is represented as a stream of 7 bits, and each bit corresponds to a slice (1 for black slices and 0 for white ones). The first 6 digits for the 12-digit UPC correspond to the manufacturer code, and they are handed down by UCC. The next 5 digits correspond to the product code, and they are filled by the manufacturer. The last digit is a check digit used to help the barcode scanner make sure that it read the right code number. And as we've all seen, in a bookstore or super market, a scanner reads the barcode through red laser beams (i.e. barcode reader). In 'The ASTI SPUMANTE CODE', it is this check digit that James and Emily have to calculate in order to reach the hidden secret. Wow, what an impossible mission!

The check digit is calculated by first adding the odd-spaced digits (6 characters), multiplying them by three, then adding them to the sum of the even-spaced digits (5 characters since we exclude the check digit). Then subtract from the next higher multiple of 10.

For example, let's say we want to find the check digit for the following code: 31415926535.

3 * (3 + 4 + 5 + 2 + 5 + 5) + (1 + 1 + 9 + 6 + 3) = 3 * (24) + (20) = 92 
==> Check code = 100 - 92 = 8.

Overview

There are many kinds of barcodes:

  • Codabar
  • Code 128
  • Code 3 of 9
  • Code 93
  • EAN 13
  • EAN 8
  • Interleabed 2/5
  • MSI/Plessey
  • Postal/Postnet
  • UPC-A
  • UPC-E

The kind that Toby Clements refers to in his parody is UPC-A. In the UPC code, only the digits [0-9] are allowed. However, in other types of barcoding, you might have characters, symbols, or even images!

UPC-A

In addition to the information that Dogs mentioned, there remains some useful information that we need to know about the UPC-A barcode.

Structure of UPC-A Barcode

We can divide the 12 digit UPC code into two parts: the left 6 digits and the right 6 digits. Every digit has its predefined stream of bits based on whether it is a left or a right digit.

Digit Bits for Left Digits Bits for 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

For example, the left 3 in the following code 314159265358 would be converted into 0111101, while the right 3 would be converted into 1000010.

The left, middle, and right codes are used to help the scanner (or reader) identify where the code starts and ends. The number system is a single digit which identifies the type of the product.

Number System Description

0

Regular UPC codes

1

Reserved

2

Weight items marked at the store

3

National Drug/Health-related code

4

Non-Food items

5

Coupons

6

Reserved

7

Regular UPC codes

8

Reserved

9

Reserved

The remaining digits should be well known by now, as explained by Dogs and as shown in the figure.

The Program

This program converts a 12 digit code into a barcode. The whole idea is very simple: read a digit, convert it to its corresponding 7 bits based on whether it is on the left or the right, and then draw a vertical line for every 1, and skipping space for every 0. The program also includes a feature to let you calculate the check digit. In case you have entered a wrong check digit, the program doesn't display a barcode.

Program View

UPC is the number entered by the user, and barcode is the alternating black and white lines (or slices) that we want to generate.

How To Run The Program

I have used BlueJ as the environment to implement this program. So if you have BlueJ, you can easily open it, view the UML diagram, and run the Main class. Otherwise, you can always run the *.jar file or execute the Run.bat file.

Using the Code

As shown in the figure above, the Main class uses the ASBarcode class, which is the major class that contains all the program's logic. The ASBarcode uses the UPCField and BarcodeLabel classes. The UPCField class inherits from the MNDigitField class, which represents a text field that allows only digits and up to maximum of N digits. This class also has two component actors (MComponentActor and NComponentActor) which act on two components (MComponent and NComponent). In our case, the MComponent is the 'Generate Check Digit' button, the NComponent is the 'Generate Barcode' button, and the action that the MComponentActor and NComponentActor do is enable or disable the buttons.

GUI Behavior

We have a panel (ASBarcode) containing a text field (UPCField) where the user can enter UPC-A code, a barcode label (BarcodeLabel) generated when the user clicks "Generate Bar Code" button, a label ("Enter UPC"), and two buttons ("Generate check Digit" and "Generate bar Code"). The two buttons are initially disabled. Once the user types 11 characters in the UPC-A field (UPCField), the "Generate Check Digit" button becomes enabled. The user will then click this button, and the check digit will be generated. As a result, the UPC field will now contain 12 characters, and thus the "Generate Check Digit" buttons gets disabled and the "Generate Bar Code" button gets enabled. Now, the user would click on the "Generate Bar Code" button, and the barcode will be generated based on the UPC-A code specified in the UPC field. However, before generating the barcode label, the program checks if the UPC-A code entered by the user is valid (UPC-A is valid if it is a 12 digit number and the value of the check digit is valid). In case the UPC-A code is invalid, nothing is displayed on the barcode label.

Class Deign

ASBarcode

  • The codeProjectOrange variable represents the orange color used at The Code Project, whose RGB components are Red = 255, Green = 153, and Blue = 0.
  • The barcodeLabel is a reference to the BarcodeLabel object that will display the generated barcode.
  • The barcodePanel is the panel that will hold the BarcodeLabel component.
  • The two variables generateCheckDigitButton and generateBarcodeButton are references to JButton objects, and will both fire an ActionEvent when the user clicks them. The CheckDigitListener and BarcodeListener classes will handle those events.
  • The buttonPanel is a panel that will hold the two buttons.
  • The upcField is a reference to the field where the user enters the UPC code.
  • The upcPanel is the panel that will hold this field.

The logic of the program is found in the ASBarcode() constructor, and the main method is used to test the ASBarcode class.

Initialization
  • Create the Barcode Label with a slice width of 2 pixels and a slice height of 150 pixels. Let the color of slices (1) be black and of empty space (0) be orange. In case there is any other number (other than 0 or 1), then draw the red color to reflect that something went wrong. Add the barcode label to its panel.

    barcodeLabel = new BarcodeLabel 
                (2, 150, Color.black, codeProjectOrange, Color.red);
  • Create the 'Generate Check Digit' and 'Generate Bar Code' and add them to their panel. Also, add action listeners (CheckDigitListener and BarcodeListener) to them, and make them initially disabled.
  • Create the UPC field and pass to it as arguments the generateCheckDigitButton and generateBarcodeButton buttons. Those will be the components on which the MComponentActor and NComponentActor will act on. Don't get confused, this will be explained in more details under the UPCField and MNDigitField classes.
  • At last, add all those components to the ASBarcode panel.

CheckDigitListener

The method below is called when the 'Generate Check Digit' button is clicked.

void actionPerformed (ActionEvent e)
{
     // Generate the check digit and append it at the end of the 11-digit UPC field
     upcField.generateCheckDigit ();
}

BarcodeListener

The method below is called when the 'Generate Bar Code' button is clicked. If the check digit is valid, the barcode is generated and displayed.

public void actionPerformed (ActionEvent e)
{
    // Generate the barcode only if the check digit is valid
    if (upcField.isCheckDigitValid ())
    {
        // Set the UPC of the barcode label
        barcodeLabel.setUPC (upcField.getUPC());

        // Validate the UPC of the barcode label
        barcodeLabel.validateUPC ();

        // Generate the barcode
        barcodeLabel.generateBarcode ();

        // Select the text in the UPC field
        upcField.selectAll ();
    }
    else
    {
        // Make the barcode as invalid so that nothing would be drawn on 
        // the barcode panel.
        // Check BarcodeLabel.paintComponent
        barcodeLabel.setValid (false);
    }
}

BarcodeLabel

Constants

We first start by defining the constants:

// Put in front and at end of every barcode
final String quiteZone = "000000000";

// Put after quite zone at the front - <a href="%22#Structure">See Figure</a>
final String leftStartCode = "101";

// Put before quite zone at the end - <a href="%22#Structure">See Figure</a>
final String rightEndCode = "101";

// Put in the center of every barcode - <a href="%22#Structure">See Figure</a>
final String centerCode = "01010";

// Represent the <a href="%22#Bits">left UPC bits</a> for the digits
final String leftCodes[] = {"0001101", "0011001", "0010011", "0111101",
"0100011", "0110001", "0101111", "0111011",
"0110111", "0001011"};

// Represent the <a href="%22#Bits">right UPC bits</a> for the digits
final String rightCodes[] = {"1110010", "1100110", "1101100", "1000010",
"1011100", "1001110", "1010000", "1000100",
"1001000", "1110100"};

// represents the number of slices in a UPC-A
final int sliceNum = 113; // 3 + 3 + 5 + (12 * 7) + (9 * 2) = 113

The quite zone, left, center, and right codes will be added to every barcode we are going to generate.

We would care to know the number of slices we have in order to define the widths of the slices and of the panel that will hold them. The sliceNum is a constant equal to 113. This is the sum of the left, center, right codes (3 + 5 + 3), the 12 digits, where each digit is made up of 7 slices or bits (12 * 7), and the quite zone (9 * 2).

Instance Variables
String UPC;         // UPC to be converted into barcode
String barcode;     // the barcode
boolean valid;      // UPC is valid or not?
Color barColor;     // The color of the slice corresponding to bit 1
Color spaceColor;   // The color of the slice corresponding to bit 0
Color errorColor;   // In case the bit is neither 0 or 1 (something wrong)
int x;              // Represents the current x coordinate of the slice
int sliceWidth;     // Represents the width of the slice
int width;          // Width of barcode label
int height;         // height of barcode label
Methods

The constructor sets the color and size of the barcode label.

//---------------------------------------------------------------------
//  Constructor...
//
//  sw is the slice width and sh is the slice height.
//  bc is the bar color, sc is the space color, and ec is error color.
//---------------------------------------------------------------------
public BarcodeLabel (int sw, int sh, Color bc, Color sc, Color ec)
{
    //  Upc is initially invalid
    valid = false;

    //  Set x initially to zero
    x = 0;

    //  Set the slicewidth
    sliceWidth = sw;

    //  Set the width of barcode label
    width = sliceNum * sw;

    //  Set the height of barcode label
    height = sh;

    //  Set the colors
    barColor = bc;
    spaceColor = sc;
    errorColor = ec;

    //  Set the background color to space color
    this.setBackground (spaceColor);

    //  Set the preferred size of the barcode label
    this.setPreferredSize (new Dimension (width, height));
}

The paintComponent() method draws the barcode label by first clearing the background and then only drawing the slices if the UPC code is valid.

//---------------------------------------------------------------------
//  Paints the barcode only if it is valid...
//---------------------------------------------------------------------
public void paintComponent (Graphics page)
{
    super.paintComponent (page);

    //  Clear the barcode before drawing
    page.setColor (getBackground ());
    page.fillRect (0, 0, width, height);

    //  Draw the barcode only if the UPC is valid
    if (isValid ())
        drawBarcode (page);
}

This method takes care of drawing the vertical slices over the label.

//---------------------------------------------------------------------
//  Draws the barcode if it is not null.
//---------------------------------------------------------------------
public void drawBarcode (Graphics page)
{
    int barcodeLength;

    //  Set x to zero
    x = 0;

    if (barcode != null)
    {
        //  Get the barcode length
        barcodeLength = barcode.length ();

        //  Loop over every character (0 or 1)
        for (int i = 0; i < barcodeLength; i++)
        {
            //  Draw a white slice for the 0
            if (barcode.charAt (i) == '0')
            {
                page.setColor (spaceColor);
            }
            //  Draw a black slice for the '1'
            else if (barcode.charAt (i) == '1')
            {
                page.setColor (barColor);
            }
            //  Draw a red slice to show something graphically
            else
            {
                page.setColor (errorColor);
            }

            //  Update the coordinates
            x += sliceWidth;

            //  Draw the slices at the specified coordinates
            page.fillRect (x, 0, sliceWidth, height);
        }
    }
}

The UPC must be exactly 12 digits before we can generate the barcode from it.

//---------------------------------------------------------------------
//  Checks if the UPC is valid. a UPC is valid if it consists
//  of exactly 12 digits.
//---------------------------------------------------------------------
public void validateUPC ()
{
    valid = UPC.matches ("[0-9]{12}?");
}

The major method that generates the barcode from the UPC field.

//---------------------------------------------------------------------
//  Generate the barcode from the UPC...
//---------------------------------------------------------------------
public void generateBarcode ()
{
    if (isValid ())
    {
        barcode = quiteZone + leftStartCode +
                  leftCodes[charToInteger (UPC.charAt (0))] +
                  leftCodes[charToInteger (UPC.charAt (1))] +
                  leftCodes[charToInteger (UPC.charAt (2))] +
                  leftCodes[charToInteger (UPC.charAt (3))] +
                  leftCodes[charToInteger (UPC.charAt (4))] +
                  leftCodes[charToInteger (UPC.charAt (5))] +
                  centerCode +
                  rightCodes[charToInteger (UPC.charAt (6))] +
                  rightCodes[charToInteger (UPC.charAt (7))] +
                  rightCodes[charToInteger (UPC.charAt (8))] +
                  rightCodes[charToInteger (UPC.charAt (9))] +
                  rightCodes[charToInteger (UPC.charAt (10))] +
                  rightCodes[charToInteger (UPC.charAt (11))] +
                  rightEndCode + quiteZone;

        repaint ();
    }
}

UPCField

Methods

Calls the parent (MNDigitField) constructor to create a text field that only accepts digits with a maximum of N (12) digits. When exactly M (11) digits are entered, the MComponent ('Generate Check Digit' button) is acted upon (enabled). Otherwise, the action is undone (button disabled). When exactly N (12) digits are entered, the NComponent ('Generate Bar Code' button) is acted upon (enabled). Otherwise, the action is undone (button disabled).

//---------------------------------------------------------------------
//  Create a field where user enters UPC code.
//---------------------------------------------------------------------
public UPCField (JButton MButton, JButton NButton)
{
    //  Create a 12 digit field having width of 8 cols
    //  M = 11, N = 12, MComponent = MButton, NComponent = NButton
    //  cols = 8.
    <a href="%22#MNDigitField"">super</a> (11, 12, MButton, NButton, 8);
}

If the UPC is 11 digits long, then generate the check digit, and append it to the end of the UPC to form the 12 digit valid UPC.

//---------------------------------------------------------------------
//  Generates check digit and appends it to the upc field.
//---------------------------------------------------------------------
public void generateCheckDigit ()
{
    //  Generate check digit only if there are 11 characters
    if (this.howManyDigits () == 11)
    {
        String upc = this.getText ();
        int checksum = 0;

        checksum = generateCheckDigit (upc);

        //  Append the check digit to the end of hte UPC
        this.setText (upc + checksum);
    }
}

Generates the check digit from the first 11 digits of the UPC field.

//---------------------------------------------------------------------
//  Generates check digit.
//---------------------------------------------------------------------
public int generateCheckDigit (String upc)
{
    int checksum = 0;

    for (int i = 1; i <= upc.length (); i++)
    {
        // even
        if (i % 2 == 0)
            checksum += charToInteger (upc.charAt (i - 1)) * 1;
        //  odd
        else
            checksum += charToInteger (upc.charAt (i - 1)) * 3;
    }

    return ( 10 - ( checksum % 10 )  ) % 10;
}

Tells whether the check digit is valid.

//---------------------------------------------------------------------
//  Makes sure that the check digit is valid.
//---------------------------------------------------------------------
public boolean isCheckDigitValid ()
{
    if (howManyDigits () == 12)
    {
        String upc = this.getText ();

        //  The check digit entered by the user
        //  character 12 (start at 0)
        int checkDigitEntered = charToInteger (upc.charAt (11));

        //  the generate (valid) check digit
        int validCheckDigit = this.generateCheckDigit (upc.substring (0, 11));

        return checkDigitEntered == validCheckDigit;
    }

    return false;
}

MNDigitField

This is a class that allows you to create a text field with only digits and with a maximum of N digits. Once the number of digits becomes M, an MAction is performed on the MComponent. And once the number of digits is not M anymore, an MReaction is performed. The same is true for N. Once the number of digits becomes N, an NAction is performed on the NComponent, and once the number of digits is not N anymore, an NReaction is performed.

public MNDigitField (int m, int n, JComponent mComp, JComponent nComp, int cols)
{
    //  Specify the width of the text field in terms of columns
    super (cols);

    //  Set M and N
    this.M = m;
    this.N = n;

    //  create component actors
    this.MComponentActor = new ComponentActor (mComp);
    this.NComponentActor = new ComponentActor (nComp);


    //  Set the action type to ENABLE (This is default type, but I'm
    //  resetting to emphasize the idea)
    this.MComponentActor.setActionType (ComponentActor.ENABLE);
    this.NComponentActor.setActionType (ComponentActor.ENABLE);

    //  Add document listener to the text field
    this.getDocument().addDocumentListener (new MNDocumentListener ());
}

The NDigitDocument class is responsible for not allowing characters other than digits to be entered, and for not allowing the number of characters to exceed N.

static class NDigitDocument extends PlainDocument
{
    public void insertString (int offs, String str, AttributeSet a)
    throws BadLocationException
    {
        if (str == null)
            return;

        //  Don't allow number of characters to exceed N
        //  (The +1 is because insertString is called before insertupdate)
        if (currentLength + 1 > N)
            return;

        //  Validate that the characters of the string are digits
        for (int i = 0; i < str.length(); i++)
        {
            if (!Character.isDigit (str.charAt (i)))
                return;
        }

        super.insertString(offs, str, a);
    }
}

The MNDocumentListener class listens to the user's interaction with the textfield, and decides what to do based on the number of characters in the text field.

class MNDocumentListener implements DocumentListener
{
    //-----------------------------------------------------------------
    //  Called when users insert characters.
    //-----------------------------------------------------------------
    public void insertUpdate (DocumentEvent e)
    {
        decide (e);
    }

    //-----------------------------------------------------------------
    //  Called when users remove characters (DEL or Back Space).
    //-----------------------------------------------------------------
    public void removeUpdate (DocumentEvent e)
    {
        decide (e);
    }

    //-----------------------------------------------------------------
    //  Do an action based on the values of M and N. In our case, the
    //  action is to enable or disable (reaction) the MComponent
    //  and NComponent.
    //-----------------------------------------------------------------
    public void decide (DocumentEvent e)
    {
        Document doc = (Document)e.getDocument();
        currentLength = doc.getLength ();

        //  Enable MComponent if M digits reached
        //  Otherwise, disable it.
        MComponentActor.<a href="%22#public">decide</a> (currentLength == M);

        //  Enable NComponent if N digits reached
        //  Otherwise, disable it.
        NComponentActor.<a href="%22#public">decide</a> (currentLength == N);
    }
}

Actor

This is an abstract class that performs an action and reverses this action based on a condition. The action performed is based on the actionType.

public void decide (boolean condition)
{
    if (condition)
        doAction ();
    else
        undoAction ();
}

ComponentActor

This class inherits from the Actor abstract class. It acts on a Java GUI component. If the actionType is ENABLE, then this class would enable or disable a JComponent based on a condition.

The method called in our program to enable the 'Generate Check Digit' and 'Generate Bar Code' buttons is:

//---------------------------------------------------------------------
//  Perform an action.
//---------------------------------------------------------------------
public void doAction ()
{
    //  Do nothing if no component is supplied
    if (component == null)
        return;

    //  Perform action based on action type
    switch (actionType)
    {
        case ENABLE:
            component.setEnabled (true);
            break;
        case MAKE_VISIBLE:
            component.setVisible (true);
            break;
    }
}

The method called in our program to disable the 'Generate Check Digit' and 'Generate Bar Code' buttons is:

//---------------------------------------------------------------------
//  Reverse the action..
//---------------------------------------------------------------------
public void undoAction ()
{
    //  Do nothing if no component is supplied
    if (component == null)
        return;

    //  Perform reaction based on action type
    switch (actionType)
    {
        case ENABLE:
            component.setEnabled (false);
            break;
        case MAKE_VISIBLE:
            component.setVisible (false);
            break;
    }
}

Conclusion

I created this program and wrote the article in 2005. I got it submitted to Code Project, but at that time Java was not supported on this site. I guess now I got back the opportunity to share it with the community. I hope it would be fun... Enjoy!

Just in case you wondered what ASTI SPUMANTE means. It is a "semi-dry sparkling wine produced from the Moscato di Canelli grape in the village of Asti, in the Piedmont region of Italy".

Revision History

  • 06/01/2008: Original article submitted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ali BaderEddin
Software Developer Microsoft
United States United States
http://mycodelog.com/about/

Comments and Discussions

 
Questionbarcode library PinmemberTertalu12-Mar-13 17:31 
Generalthat's good Pinmembersonnykwe10-Jun-08 11:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 3 Jun 2008
Article Copyright 2008 by Ali BaderEddin
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid