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.
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.
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.
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.
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
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
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
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();
Conclusion
I am an inexperienced student in coding. Although I started to study Barcode
solutions since last year, this is the first time I am applying it. The barcode
has been commonly used everywhere, but it is so fresh a topic in my country (Vietnam).
I would like to thank Van Neil Eps and rainman_63 again.
I would appreciate getting your feedback.
I joined CodeProject since working in MFC/C++ applications. For some personal reasons, I switched to Flash/Flex web applications and joined Pyramid Consulting Vietnam. I left Pyramid Consulting Vietnam in 2009 and started my free-lance jobs. Now I am a professional multimedia developer with specialized in Flash/Flex technologies and intend to turn back this community as a chance to contribute my knowledge in Flash/Flex technologies.