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)
{
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)
{
if (upcField.isCheckDigitValid ())
{
barcodeLabel.setUPC (upcField.getUPC());
barcodeLabel.validateUPC ();
barcodeLabel.generateBarcode ();
upcField.selectAll ();
}
else
{
barcodeLabel.setValid (false);
}
}
BarcodeLabel

Constants
We first start by defining the constants:
final String quiteZone = "000000000";
final String leftStartCode = "101";
final String rightEndCode = "101";
final String centerCode = "01010";
final String leftCodes[] = {"0001101", "0011001", "0010011", "0111101",
"0100011", "0110001", "0101111", "0111011",
"0110111", "0001011"};
final String rightCodes[] = {"1110010", "1100110", "1101100", "1000010",
"1011100", "1001110", "1010000", "1000100",
"1001000", "1110100"};
final int sliceNum = 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;
String barcode;
boolean valid;
Color barColor;
Color spaceColor;
Color errorColor;
int x;
int sliceWidth;
int width;
int height;
Methods
The constructor sets the color and size of the barcode label.
public BarcodeLabel (int sw, int sh, Color bc, Color sc, Color ec)
{
valid = false;
x = 0;
sliceWidth = sw;
width = sliceNum * sw;
height = sh;
barColor = bc;
spaceColor = sc;
errorColor = ec;
this.setBackground (spaceColor);
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.
public void paintComponent (Graphics page)
{
super.paintComponent (page);
page.setColor (getBackground ());
page.fillRect (0, 0, width, height);
if (isValid ())
drawBarcode (page);
}
This method takes care of drawing the vertical slices over the label.
public void drawBarcode (Graphics page)
{
int barcodeLength;
x = 0;
if (barcode != null)
{
barcodeLength = barcode.length ();
for (int i = 0; i < barcodeLength; i++)
{
if (barcode.charAt (i) == '0')
{
page.setColor (spaceColor);
}
else if (barcode.charAt (i) == '1')
{
page.setColor (barColor);
}
else
{
page.setColor (errorColor);
}
x += sliceWidth;
page.fillRect (x, 0, sliceWidth, height);
}
}
}
The UPC must be exactly 12 digits before we can generate the barcode from it.
public void validateUPC ()
{
valid = UPC.matches ("[0-9]{12}?");
}
The major method that generates the barcode from the UPC field.
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).
public UPCField (JButton MButton, JButton NButton)
{
<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.
public void generateCheckDigit ()
{
if (this.howManyDigits () == 11)
{
String upc = this.getText ();
int checksum = 0;
checksum = generateCheckDigit (upc);
this.setText (upc + checksum);
}
}
Generates the check digit from the first 11 digits of the UPC field.
public int generateCheckDigit (String upc)
{
int checksum = 0;
for (int i = 1; i <= upc.length (); i++)
{
if (i % 2 == 0)
checksum += charToInteger (upc.charAt (i - 1)) * 1;
else
checksum += charToInteger (upc.charAt (i - 1)) * 3;
}
return ( 10 - ( checksum % 10 ) ) % 10;
}
Tells whether the check digit is valid.
public boolean isCheckDigitValid ()
{
if (howManyDigits () == 12)
{
String upc = this.getText ();
int checkDigitEntered = charToInteger (upc.charAt (11));
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)
{
super (cols);
this.M = m;
this.N = n;
this.MComponentActor = new ComponentActor (mComp);
this.NComponentActor = new ComponentActor (nComp);
this.MComponentActor.setActionType (ComponentActor.ENABLE);
this.NComponentActor.setActionType (ComponentActor.ENABLE);
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;
if (currentLength + 1 > N)
return;
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
{
public void insertUpdate (DocumentEvent e)
{
decide (e);
}
public void removeUpdate (DocumentEvent e)
{
decide (e);
}
public void decide (DocumentEvent e)
{
Document doc = (Document)e.getDocument();
currentLength = doc.getLength ();
MComponentActor.<a href=""%22#public"">decide</a> (currentLength == M);
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:
public void doAction ()
{
if (component == null)
return;
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:
public void undoAction ()
{
if (component == null)
return;
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