Introduction
I had introduced how to
draw an
EAN13
barcode in
my last article. This
article is about UPC
barcodes, with two
instances:
UPCA and
UPCE.
UPCA barcode
UPCA and
UPCE background
UPCA is
the most commonly
symbology (at least in
the US), you can find
them at supermarkets,
bookstores�
UPCA uses
11 digits (0 through 9)
to encode its message
data, the 12th
character is the check
digit.
UPCA can
be divided into 4 parts:
system number,
manufacturer code,
product code, and check
digit. We also follow
this structure to
draw the
barcode.
The
UPCE is a
variation of
UPCA. By
removing some continued
zeros, the
UPCE
compresses the message
data, so it is about
half the size of a
UPCA barcode.
UPCE is
used on small packaging,
where
UPCA could
not fit well.
UPCE also
consists of 4 parts, but
you can only see 3
parts, as in the picture
below:
UPCE Barcode
�0� is the number
system, �123456� is the
manufacturer code and
product code compressed
and joined into one, and
the last number is the
check digit and it can
be calculated from the
original
UPCA
message data. �can be�,
this means the
compressed message is
used to generate the
check digit (just my
opinion, should be wrong
?).
UPCE
compresses the
manufacturer code and
product code only. In
this article, I have not
discussed how to convert
message data from
UPCA to
UPCE yet,
but I promise to work on
that after my
examination.
Encoding UPCA and UPCE
Actually,
UPCA is a
subset of
EAN13 that
the first number is set
to zero. That is you can
use the
EAN13
encoding method to
encode
UPCA.
UPCA uses
two different patterns,
the left pattern used to
encode the number system
and the manufacturer
code, and the right
pattern used to encode
the product code and
check digits. Please see
the table below.
Number |
Left Digits |
Right Digits |
0 |
sssbbsb |
bbbssbs |
1 |
ssbbssb |
bbssbbs |
2 |
ssbssbb |
bbsbbss |
3 |
sbbbbsb |
bssssbs |
4 |
sbsssbb |
bsbbbss |
5 |
sbbsssb |
bssbbbs |
6 |
sbsbbbb |
bsbssss |
7 |
sbbbsbb |
bsssbss |
8 |
sbbsbbb |
bssbsss |
9 |
sssbsbb |
bbbsbss |
Table 1
�s� represents space and
�b� represents bar.
UPCE uses
the Left Digits Odd
Parity and the Right
Digits Even Parity
characters set from the
EAN13
encoding standard.
Please see the table
below:
Number |
Left Digits |
Odd Parity |
Even Parity |
0 |
sssbbsb |
sbssbbb |
1 |
ssbbssb |
sbbssbb |
2 |
ssbssbb |
ssbbsbb |
3 |
sbbbbsb |
sbssssb |
4 |
sbsssbb |
ssbbbsb |
5 |
sbbsssb |
sbbbssb |
6 |
sbsbbbb |
ssssbsb |
7 |
sbbbsbb |
ssbsssb |
8 |
sbbsbbb |
sssbssb |
9 |
sssbsbb |
ssbsbbb |
Table 2
Additionally,
UPCE may
only be used if the
system is 0 or 1. The
encoded characters are
encoded with odd and
even parity by the Left
Digits Odd and the Left
Digits Even from the
table above. The parity
used for each character
depends on the number
system and the check
digit. See the table
below.
Check Digit |
Number System |
0 |
1 |
0 |
EEEOOO |
OOOEEE |
1 |
EEOEOO |
OOEOEE |
2 |
EEOOEO |
OOEEOE |
3 |
EEOOOE |
OOEEEO |
4 |
EOEEOO |
OEOOEE |
5 |
EOOEEO |
OEEOOE |
6 |
EOOOEE |
OEEEOO |
7 |
EOEOEO |
OEOEOE |
8 |
EOEOOE |
OEOEEO |
9 |
EOOEOE |
OEEOEO |
Table 3
Example
An example may be useful
here. I will show you
how to encode the
UPCA
message data:
�01234567890�. The
message consists of
three parts (remember
that the check digit is
not available at this
time):
-
0 - System number
-
12345 � Manufacturer
code
-
67890 � Product code
We calculate the check
digit by scanning from
the beginning to the end
of the message. With
each character, if its
position in the string
is odd, multiply it by
3. Otherwise, just add
it into the sum.
Collapse |
Copy Code
0*3 + 1 + 2*3 + 3 + 4*3 + 5 + 6*3 + 7 + 8*3 + 9 + 0*3 = 85
In this case, the next
number following 85 that
is divisible by 10 is
90. We need to add 5 to
85 to get 90, and 5 is
our check digit. Modulus
of 10 is taken from 85,
and this is subtracted
by 10 again to get 5.
Collapse |
Copy Code
10 � (85%10) = 5
And now, our result is
�0 12345 67890 5�.
The same method is used
to calculate the check
digit for the
UPCE
message data, but the
length of the
UPCE
message data is shorter
than that for
UPCA. In
fact, the check digit
for
UPCE must
be calculated from the
original
UPCA
message data
(non-compressed
message).
UPC Class
My UPC is based on the
CBarcode
class that has been
introduced in Neil Van
Eps' series of articles.
It�s necessary to
introduce this class
again.
Collapse |
Copy Code
class CBarcode
{
public:
CBarcode();
void LoadData(CString csMessage, double dNarrowBar, double dFinalHeight,
HDC pDC, int nStartingXPixel, int nStartingYPixel,
double dRatio = 1.0);
virtual void DrawBitmap() = 0;
virtual void BitmapToClipboard() = 0;
virtual ~CBarcode();
long GetBarcodePixelWidth();
long GetBarcodePixelHeight();
protected:
CString m_csMessage;
HDC m_hDC;
long m_nFinalBarcodePixelWidth;
long m_nNarrowBarPixelWidth;
long m_nPixelHeight;
long m_nStartingXPixel;
long m_nStartingYPixel;
long m_nSymbology;
long m_nWideBarPixelWidth;
virtual void DrawPattern(CString csPattern) = 0;
};
And here is the
CUPC
class declaration. It's
implemented to draw UPCA
and UPCE barcodes.
Collapse |
Copy Code
class CUPC : public CBarcode
{
public:
CUPC();
CUPC(int nSymbology);
virtual ~CUPC();
void LoadData(CString csMessage, double dNarrowBar,
double dFinalHeight, long nGuardbarHeight,
HDC hDC, int nStartingXPixel,
int nStartingYPixel, double dRatio);
void DrawBitmap();
void BitmapToClipboard();
private:
long m_nGuardbarHeight;
long CalculateCheckSumDigit();
CString RetrieveSystemNumberPattern(int iSystemNumber, int iNumber);
CString RetrieveLeftOddParityPattern(int iNumber);
CString RetrieveLeftEvenParityPattern(int iNumber);
CString RetrieveLeftPattern(int iNumber);
CString RetrieveRightPattern(int iNumber);
void DrawPattern(CString csPattern);
void DrawUPCA();
void DrawUPCE();
};
Drawing a UPC Barcode
Collapse |
Copy Code
void CUPC::DrawUPCA()
{
int i, tmpGuardBarHeight;
DrawPattern("sssssssss"); DrawPattern("bsb");
DrawPattern(RetrieveLeftPattern((int)m_csMessage.GetAt(0)-48));
tmpGuardBarHeight = m_nGuardbarHeight;
m_nGuardbarHeight = 0;
for (i = 1 ; i < 6 ; i++) DrawPattern(RetrieveLeftPattern((int)m_csMessage.GetAt(i)-48));
m_nGuardbarHeight = tmpGuardBarHeight;
DrawPattern("sbsbs");
tmpGuardBarHeight = m_nGuardbarHeight;
m_nGuardbarHeight = 0;
for (i = 6 ; i < 11 ; i ++) DrawPattern(RetrieveRightPattern((int)m_csMessage.GetAt(i)-48));
m_nGuardbarHeight = tmpGuardBarHeight;
DrawPattern(RetrieveRightPattern(CalculateCheckSumDigit()));
DrawPattern("bsb"); DrawPattern("sssssssss");
}
void CUPC::DrawUPCE()
{
int i,nCheckDigit, nSystemNumber, tmpGuardBarHeight;
nSystemNumber = (int)m_csMessage.GetAt(0)-48;
nCheckDigit = CalculateCheckSumDigit();
CString strSystemNumberPattern =
RetrieveSystemNumberPattern(nSystemNumber,nCheckDigit);
DrawPattern("sssssssss"); DrawPattern("bsb");
tmpGuardBarHeight = m_nGuardbarHeight;
m_nGuardbarHeight = 0;
for (i = 1 ; i < 7 ; i ++){
if (strSystemNumberPattern[i-1] == 'O')
DrawPattern(RetrieveLeftOddParityPattern((int)m_csMessage.GetAt(i)-48));
if (strSystemNumberPattern[i-1] == 'E')
DrawPattern(RetrieveLeftEvenParityPattern((int)m_csMessage.GetAt(i)-48));
}
m_nGuardbarHeight = tmpGuardBarHeight;
DrawPattern("sbsbs"); DrawPattern("b"); DrawPattern("sssssssss");
}
Using the code
Drawing UPCA
Collapse |
Copy Code
CUPC upc(UPCA); HDC hDC = m_staticBitmap.GetDC()->m_hDC;
upc.LoadData("01234567890",0.018,1.0,10,hDC,0,0,3.0);
upc.DrawBitmap();
Drawing UPCE
Collapse |
Copy Code
CUPC upc(UPCE); HDC hDC = m_staticBitmap.GetDC()->m_hDC;
upc.LoadData("1123456",0.018,1.0,10,hDC,0,0,3.0);
upc.DrawBitmap();