Click here to Skip to main content
15,896,063 members
Articles / Desktop Programming / MFC

Drawing UPCA/E barcodes

Rate me:
Please Sign up or sign in to vote.
4.86/5 (18 votes)
2 Nov 20054 min read 64.2K   1.9K   55  
Drawing UPCA/E barcodes based on Neil Van Eps' and Rainman_63's articles.
// UPC.cpp: implementation of the CUPC class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "UPCAE.h"
#include "UPC.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CUPC::CUPC()
{
	m_nSymbology = UPCA;
}

CUPC::CUPC(int nSymbology)
{
	m_nSymbology = nSymbology;
}


CUPC::~CUPC()
{

}

void CUPC::LoadData(CString csMessage, double dNarrowBar, double dFinalHeight, long nGuardbarHeight, HDC hDC, int nStartingXPixel, int nStartingYPixel, double dRatio)
{
	m_nGuardbarHeight = nGuardbarHeight;

	//standardize the message
	int nLen = csMessage.GetLength();
	int i,nNumberOfAdditionZero = m_nSymbology == UPCA ? 11 - nLen : 7 - nLen;

	if (nNumberOfAdditionZero > 0){ // missing some numbers
		
		for (i = 0 ; i < nNumberOfAdditionZero ; i ++)
			csMessage = '0' + csMessage ;// just adding zeros at the head of message
	}
	else if (nNumberOfAdditionZero < 0){ 
		if (m_nSymbology == UPCA)
				csMessage.Delete(10,-nNumberOfAdditionZero);
		else
				csMessage.Delete(6,-nNumberOfAdditionZero);
	}
		
	CBarcode::LoadData(csMessage,dNarrowBar,dFinalHeight,hDC,nStartingXPixel,nStartingYPixel,dRatio);
}


long CUPC::CalculateCheckSumDigit()
{
	int i, nLen, nSum = 0, nItem;
	nLen = m_csMessage.GetLength();

	for (i = 0 ; i < nLen ; i++){
		nItem = i%2 ? ((int)m_csMessage.GetAt(i)-48)*1 : ((int)m_csMessage.GetAt(i)-48)*3;
		nSum += nItem;
	}

	nSum %= 10;
	return (10-nSum)%10;
}


CString CUPC::RetrieveSystemNumberPattern(int iSystemNumber /* = 0 */, int iNumber)
{
	CString strCharPattern;
	if (iSystemNumber == 0){
		switch (iNumber){
			case 0: 
				strCharPattern = "EEEOOO"; 
				break;
			case 1: 
				strCharPattern = "EEOEOO"; 
				break;
			case 2: 
				strCharPattern = "EEOOEO"; 
				break;
			case 3: 
				strCharPattern = "EEOOOE"; 
				break;
			case 4: 
				strCharPattern = "EOEEOO"; 
				break;
			case 5:
				strCharPattern = "EOOEEO"; 
				break;
			case 6: 
				strCharPattern = "EOOOEE"; 
				break;
			case 7:
				strCharPattern = "EOEOEO"; 
				break;
			case 8: 
				strCharPattern = "EOEOOE"; 
				break;
			case 9: 
				strCharPattern = "EOOEOE"; 
				break;
		}
	}
	else{
		switch(iNumber){
			case 0: 
				strCharPattern = "OOOEEE"; 
				break;
			case 1: 
				strCharPattern = "OOEOEE"; 
				break;
			case 2: 
				strCharPattern = "OOEEOE"; 
				break;
			case 3: 
				strCharPattern = "OOEEEO"; 
				break;
			case 4: 
				strCharPattern = "OEOOEE"; 
				break;
			case 5: 
				strCharPattern = "OEEOOE"; 
				break;
			case 6: 
				strCharPattern = "OEEEOO"; 
				break;
			case 7: 
				strCharPattern = "OEOEOE"; 
				break;
			case 8: 
				strCharPattern = "OEOEEO"; 
				break;
			case 9: 
				strCharPattern = "OEEOEO"; 
				break;
		}
	}
	return strCharPattern;
}


CString CUPC::RetrieveLeftOddParityPattern(int iNumber)
{
	CString strCharPattern;

	switch(iNumber){
		case 0: 
			strCharPattern = "sssbbsb"; 
			break;
		case 1: 
			strCharPattern = "ssbbssb";
			break;
		case 2: 
			strCharPattern = "ssbssbb"; 
			break;
		case 3: 
			strCharPattern = "sbbbbsb"; 
			break; 
		case 4: 
			strCharPattern = "sbsssbb"; 
			break; 
		case 5: 
			strCharPattern = "sbbsssb"; 
			break;
		case 6:
			strCharPattern = "sbsbbbb";
			break;
		case 7:
			strCharPattern = "sbbbsbb"; 
			break;
		case 8:
			strCharPattern = "sbbsbbb";
			break; 
		case 9:
			strCharPattern = "sssbsbb"; 
			break;
	}
	return strCharPattern;
}


CString CUPC::RetrieveLeftEvenParityPattern(int iNumber)
{
	CString strCharPattern;
	
	switch(iNumber){
		case 0: 
			strCharPattern = "sbssbbb";
			break;
		case 1: 
			strCharPattern = "sbbssbb";
			break; 
		case 2:
			strCharPattern = "ssbbsbb";
			break; 
		case 3: 
			strCharPattern = "sbssssb";
			break;
		case 4:
			strCharPattern = "ssbbbsb";
			break;
		case 5:
			strCharPattern = "sbbbssb";
			break;
		case 6: 
			strCharPattern = "ssssbsb";
			break; 
		case 7: 
			strCharPattern = "ssbsssb";
			break;
		case 8: 
			strCharPattern = "sssbssb"; 
			break;
		case 9:
			strCharPattern = "ssbsbbb";
			break;
	}
	return strCharPattern;
}



CString CUPC::RetrieveLeftPattern(int iNumber)
{
	CString strCharPattern;
	
	switch(iNumber){
		case 0: 
			strCharPattern = "sssbbsb";
			break; 
		case 1:
			strCharPattern = "ssbbssb";
			break; 
		case 2: 
			strCharPattern = "ssbssbb";
			break; 
		case 3:
			strCharPattern = "sbbbbsb"; 
			break; 
		case 4:
			strCharPattern = "sbsssbb"; 
			break; 
		case 5:
			strCharPattern = "sbbsssb";
			break; 
		case 6: 
			strCharPattern = "sbsbbbb";
			break; 
		case 7: 
			strCharPattern = "sbbbsbb";
			break; 
		case 8:
			strCharPattern = "sbbsbbb";
			break; 
		case 9: 
			strCharPattern = "sssbsbb"; 
			break;
	}

	return strCharPattern;
}


CString CUPC::RetrieveRightPattern(int iNumber)
{
	CString strCharPattern;
	
	switch(iNumber){
		case 0: 
			strCharPattern = "bbbssbs";
			break; 
		case 1:
			strCharPattern = "bbssbbs";
			break; 
		case 2: 
			strCharPattern = "bbsbbss";
			break; 
		case 3:
			strCharPattern = "bssssbs"; 
			break; 
		case 4:
			strCharPattern = "bsbbbss"; 
			break; 
		case 5:
			strCharPattern = "bssbbbs";
			break; 
		case 6: 
			strCharPattern = "bsbssss";
			break; 
		case 7: 
			strCharPattern = "bsssbss";
			break; 
		case 8:
			strCharPattern = "bssbsss";
			break; 
		case 9: 
			strCharPattern = "bbbsbss"; 
			break;
	}

	return strCharPattern;
}

void CUPC::DrawPattern(CString csPattern)
{
	int			i,nXPixel,nYPixel;
	CDC			oDC;

	// attach to the device context
	oDC.Attach(m_hDC);

	// initialize X pixel value
	nXPixel = m_nStartingXPixel;
	
	for (i=0;i<csPattern.GetLength();i++)
	{
		// X value for loop
		for (nXPixel=m_nStartingXPixel;nXPixel<m_nStartingXPixel+m_nNarrowBarPixelWidth;nXPixel++)
		{
			// Y value for loop
			for (nYPixel=m_nStartingYPixel;nYPixel<m_nStartingYPixel+m_nPixelHeight+m_nGuardbarHeight;nYPixel++)
			{
				// if this is a bar
				if (csPattern.GetAt(i)=='b')
					oDC.SetPixelV(nXPixel,nYPixel,COLORBLACK);

			//	else
				//	oDC.SetPixelV(nXPixel,nYPixel,COLORWHITE);
			}
		}

		// advance the starting position
		m_nStartingXPixel+= m_nNarrowBarPixelWidth;
	}

	// detach from the device context
	oDC.Detach();
	
	return;

}

void CUPC::DrawUPCA()
{
	int i, tmpGuardBarHeight;
	
	DrawPattern("sssssssss"); // draw quite zone	
	DrawPattern("bsb"); // draw lead

	DrawPattern(RetrieveLeftPattern((int)m_csMessage.GetAt(0)-48)); // draw number system
	
	tmpGuardBarHeight = m_nGuardbarHeight;
	m_nGuardbarHeight = 0;

	for (i = 1 ; i < 6 ; i++)// draw manufacturer code
		DrawPattern(RetrieveLeftPattern((int)m_csMessage.GetAt(i)-48));

	m_nGuardbarHeight = tmpGuardBarHeight;

	DrawPattern("sbsbs"); // draw separator bars

	tmpGuardBarHeight = m_nGuardbarHeight;
	m_nGuardbarHeight = 0;

	for (i = 6 ; i < 11 ; i ++) // draw product code
		DrawPattern(RetrieveRightPattern((int)m_csMessage.GetAt(i)-48));

	m_nGuardbarHeight = tmpGuardBarHeight;
	DrawPattern(RetrieveRightPattern(CalculateCheckSumDigit())); //draw check sum digits
 
	
	DrawPattern("bsb"); // draw trailer bars
	DrawPattern("sssssssss"); // draw quite zone 

}

void CUPC::DrawUPCE()
{
	
	int i,nCheckDigit, nSystemNumber, tmpGuardBarHeight;

	nSystemNumber = (int)m_csMessage.GetAt(0)-48;
	nCheckDigit = CalculateCheckSumDigit();
	
	CString strSystemNumberPattern = RetrieveSystemNumberPattern(nSystemNumber,nCheckDigit);

	DrawPattern("sssssssss"); // draw quite zone	
	DrawPattern("bsb"); // draw lead
	
	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"); // draw separator bars
	DrawPattern("b"); // draw trailer bars
	DrawPattern("sssssssss"); // draw quite zone 

}


void CUPC::DrawBitmap()
{
	if (m_nSymbology == UPCA)
		DrawUPCA();
	else
		DrawUPCE();
}

void CUPC::BitmapToClipboard()
{
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
Vietnam Vietnam
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.

Comments and Discussions