www.pudn.com > pdf417.rar > StdDataObject.cpp


// StdDataObject.cpp: implementation of the CStdDataObject class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "pdf417.h" 
#include "StdDataObject.h" 
#include "Afx.h" 
#include "data.h" 
#include "MainFrm.h" 
#include  
 
#define ERRORLIMIT	10	//错误范围限制 
#define EMPTYLIMIT  4 
#define JUDGETIMES	10 
 
//条码组合模式 
#define TEXTMODE	1	//文本压缩模式 
#define BYTEMODE	2	//字节压缩模式 
#define NUMBERMODE	3	//数字压缩模式 
 
//文本压缩子模式 
#define ALPHA		1	//大写字母子模式 
#define LOWERCASE	2	//小写字母子模式 
#define MIXED		3	//混合子模式 
#define PUNCTUATION 4	//标点子模式 
 
//文本压缩子模式锁定/转移码 
#define LL			2	//锁定为小定字母型子模式 
#define PS			4	//转移为标点型子模式 
#define ML			5	//锁定为混合型子模式 
#define AL			6	//锁定为大写字母型子模式 
#define PL			7	//锁定为标点型子模式 
#define AS			8	//转移为大写字母型子模式 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CStdDataObject::CStdDataObject() 
{ 
 
} 
 
CStdDataObject::~CStdDataObject() 
{ 
 
} 
 
//从一个BMP对象中得到数据,并化为标准格式后存入类的pArrayMemory中 
//标准化格式为:一个字节存放一个像素点 
void CStdDataObject::GetStdData(CBmpObject* pObj) 
{ 
	//设定图像高度,宽度,行长 
	dImageWidth = pObj->dImageWidth; 
	dImageHeight = pObj->dImageHeight; 
 
	//每行所需要的字节数目 
	dBytesPerLine = dImageWidth;	//每个像素对应于一个字节 
 
	//为像素点阵申请内存空间 
	pArrayMemory = new UCHAR[dBytesPerLine*dImageHeight]; 
 
	//矩阵内存空间初始化为0 
	::memset(pArrayMemory,0,dBytesPerLine*dImageHeight); 
 
	//根据点像素来设置矩阵数据 
	for(UINT H=0;H < dImageHeight;H++) 
	{ 
		for(UINT W=0;W < dImageWidth;W++) 
		{ 
			if(pObj->IsBlack(W,H)) 
				pArrayMemory[dBytesPerLine*H+W] = 1; 
		} 
	} 
} 
 
//判断像素点是否为黑色 
inline BOOL CStdDataObject::StdIsBlack(UINT x, UINT y) 
{ 
	return pArrayMemory[dBytesPerLine*y+x]; 
} 
 
//转换像素点为白色 
inline void CStdDataObject::Whitten(UINT x, UINT y) 
{ 
	pArrayMemory[dBytesPerLine*y+x] = 0; 
} 
 
//得到所有包括Cell的区域,并存入到类的RegionList中 
void CStdDataObject::FindAllCell(Cell* pCell,CList& RegionList) 
{ 
	UINT dCIAWidth=0,dCIAHeight=0; 
	UINT tmp1,i,W,H; 
	BOOL bIsOk; 
	Region tmp; 
	//申请空间以保存原始数据 
	UCHAR* tmpbuffer=new UCHAR[dBytesPerLine*dImageHeight]; 
	memcpy(tmpbuffer,pArrayMemory,dBytesPerLine*dImageHeight); 
	//得到Cell数组的高度和宽度于dCIAWidth,dCIAHeight中 
	for(i=0;iCellItemCount;i++) 
	{ 
		if((tmp1=pCell->CellArray[i].x)>dCIAWidth)  
			dCIAWidth=tmp1; 
		if((tmp1=pCell->CellArray[i].y)>dCIAHeight) 
			dCIAHeight=tmp1; 
	} 
	dCIAWidth++; 
	dCIAHeight++; 
 
	for(H=0;HCellItemCount;i++) 
				{ 
					if(!StdIsBlack(W+pCell->CellArray[i].x,H+pCell->CellArray[i].y)) 
					{	bIsOk=false; break;  } 
				} 
				//如满足,则穷尽此区域,得到区域的上下左右各点坐标,并存入RegionList中 
				if(bIsOk) 
				{ 
					tmp.Left.x = W; 
					tmp.Left.y = H; 
					tmp.Right.x = W; 
					tmp.Right.y = H; 
					tmp.Top.y = H; 
					tmp.Top.x = W; 
					tmp.Root.y = H; 
					tmp.Root.x = W; 
					mleft = mright = W; 
					mroot = mtop = H; 
					EmptyRegionInXY(W,H,&tmp); 
					if(IsRect(tmp)) 
					{ 
						if(RegionList.GetCount()==0) RegionList.AddHead(tmp); 
						else RegionList.AddTail(tmp); 
					} 
				} 
			} 
		} 
	//恢复原数据 
	memcpy(pArrayMemory,tmpbuffer,dBytesPerLine*dImageHeight); 
	delete[] tmpbuffer; 
} 
 
//使用递归运算来穷尽整个区域,并返回区域的坐标值 
void CStdDataObject::EmptyRegionInXY(UINT x, UINT y, Region* pRegion) 
{ 
	UINT xx,yy,sx,ex; 
	BOOL flags; 
	xx=x,yy=y; 
	//处理点(x,y)左边的数据 
	do{ 
		Whitten(xx,yy); 
	}while(xx>=1 && StdIsBlack(--xx,yy)); 
	sx=xx+1; 
 
	//处理点(x,y)右边的数据 
	xx=x; 
	while(xx+1mright) mright=ex; 
	if(yymroot) mroot=yy; 
 
	//判断是否为LEFT点 
/* 
	if(yyLeft.y && abs(sx-pRegion->Left.x)<=2 && pRegion->Left.y-yy>=2) 
	{ pRegion->Left.x=sx; pRegion->Left.y=yy; } 
	if(yy>pRegion->Left.y && sx<=pRegion->Left.x-2) 
	{ pRegion->Left.x=sx; pRegion->Left.y=yy; } 
	if(yy==pRegion->Left.y) 
	{ pRegion->Left.x=sx; pRegion->Right.x=ex; } 
	if(ex==pRegion->Left.x && yyLeft.y) 
	{ pRegion->Left.x=sx; pRegion->Right.x=ex; } 
*/ 
	if(sxLeft.x && (pRegion->Left.x-sx >=2 || pRegion->Left.x-sx>abs(yy-pRegion->Left.y))) 
	{ pRegion->Left.x=sx; pRegion->Left.y=yy; } 
	if(abs(sx-mleft)<=1 && yyLeft.y) 
	{ pRegion->Left.x=sx; pRegion->Left.y=yy; } 
 
	//判断是否为TOP点 
/* 
	if(pRegion->Top.y>=yy+2) 
	{ pRegion->Top.y=yy; pRegion->Top.x=ex; } 
	if(pRegion->Top.y>=yy && ex>=pRegion->Top.x) 
	{ pRegion->Top.y=yy; pRegion->Top.x=ex; } 
	else if(yyTop.y && abs(pRegion->Top.x-ex)<=EMPTYLIMIT) 
	{ pRegion->Top.y=yy; pRegion->Top.x=ex; }; 
*/ 
	if(yyTop.y) 
	{ pRegion->Top.y=yy; pRegion->Top.x=ex; } 
	if(abs(mtop-yy)<=1 && ex>pRegion->Top.x) 
	{ pRegion->Top.y=yy; pRegion->Top.x=ex; } 
		 
 
	//判断是否为RIGHT点 
	if(ex>pRegion->Right.x) 
	{ pRegion->Right.x=ex; pRegion->Right.y=yy; } 
	if(yy> pRegion->Right.y && abs(ex-mright)<=1) 
	{ pRegion->Right.x=ex; pRegion->Right.y=yy; } 
 
	//判断是否为ROOT点 
	if(yy>pRegion->Root.y) 
	{ pRegion->Root.y=y; pRegion->Root.x=sx; } 
	if(abs(mroot-yy)<=1 && sxRoot.x) 
	{ pRegion->Root.y=y; pRegion->Root.x=sx; } 
 
	//处理上一行 
	if(y>0) 
	{ 
		for(xx=sx;xx<=ex;xx++) 
		{ 
			if(StdIsBlack(xx,yy-1)) 
			{ 
				EmptyRegionInXY(xx,yy-1,pRegion); 
				flags=false; 
			} 
		} 
	} 
 
	//处理下一行 
	if(y+1ERRORLIMIT) 
		return false; 
	if(abs((int)(r.Left.y-r.Top.y-r.Root.y+r.Right.y))>ERRORLIMIT) 
		return false; 
 
	//判断两对角线是否相等 
	double tmp1=sqrt((r.Top.x-r.Left.x)*(r.Top.x-r.Left.x)+ 
		(r.Root.y-r.Top.y)*(r.Root.y-r.Top.y)); 
	double tmp2=sqrt((r.Right.x-r.Left.x)*(r.Right.x-r.Left.x)+ 
		(r.Right.y-r.Left.y)*(r.Right.y-r.Left.y)); 
//	if(abs(tmp1-tmp2)> tmp1>1000?10*ERRORLIMIT:ERRORLIMIT) 
//		return false; 
	return true; 
} 
 
BOOL CStdDataObject::IsBarHeader(Region* pReg) 
{ 
	Region tmpreg,reg; 
	UCHAR HeaderShape[]={8,1,1,1,1,1,1,3}; 
	//此变量进行两个方向的判断 
	BOOL firstjudge=true; 
	UPOINT* PointArray; 
	UCHAR BWArray[1000]; 
	//把原矩形化为可供判断的标准矩形 
	reg = *pReg; 
	tmpreg = reg; 
	if((reg.Top.x-reg.Left.x)*(reg.Top.x-reg.Left.x)+(reg.Left.y-reg.Top.y)*(reg.Left.y-reg.Top.y) >  
		(reg.Right.x-reg.Top.x)*(reg.Right.x-reg.Top.x)+(reg.Right.y-reg.Top.y)*(reg.Right.y-reg.Top.y)) 
	{ 
		tmpreg.Left=reg.Top; 
		tmpreg.Root=reg.Left; 
		tmpreg.Top=reg.Right; 
		tmpreg.Right=reg.Root; 
	} 
loop: 
	if(!firstjudge) 
	{ 
		//进行第二次判断时,改变方向 
		Region tmpreg1 = tmpreg; 
		tmpreg.Top = tmpreg1.Root; 
		tmpreg.Left = tmpreg1.Right; 
		tmpreg.Right = tmpreg1.Left; 
		tmpreg.Root = tmpreg1.Top; 
	} 
	//计算点的总数 
	int _height = (int)(sqrt((tmpreg.Left.x-tmpreg.Root.x)*(tmpreg.Left.x-tmpreg.Root.x)+ 
		(tmpreg.Left.y-tmpreg.Root.y)*(tmpreg.Left.y-tmpreg.Root.y))+1.5); 
	//申请一空间以存入纵向的点(起始点) 
	PointArray = new UPOINT[_height]; 
	int rheight = GetLineDataA(tmpreg.Left.x,tmpreg.Left.y,tmpreg.Root.x,tmpreg.Root.y,PointArray); 
	//确定dx,dy值 
	int tx=tmpreg.Top.x,ty=tmpreg.Top.y,lx=tmpreg.Left.x,ly=tmpreg.Left.y,z; 
	z=(tx>lx)?1:-1; 
	int dx=(int)((tx==lx)?0:(18*(tx-lx+z)/7+0.5)); 
	z=(ty>ly)?1:-1; 
	int dy=(int)((ty==ly)?0:(18*(ty-ly+z)/7+0.5)); 
	//申请空间以存放横向的点(一行数据),宽度为_width 
	int _width = (int)(sqrt(dx*dx+dy*dy)+1.5); 
	if(_width>1000)	//如一条模宽度大于1000,则认为数据出错 
	{ 
		delete PointArray; 
		return false; 
	} 
	int dj=(int)(rheight/JUDGETIMES+0.5); 
	if(dj<1) dj=1; 
	for(int i=rheight/(2*JUDGETIMES),rightnum=0;idImageWidth-1) tx=dImageWidth-1; 
		if(ty<0) ty=0; 
		if(ty>dImageHeight-1) ty=dImageHeight-1; 
		int rwidth=GetLineDataB(PointArray[i].x,PointArray[i].y,tx,ty,BWArray); 
		//得到起始符位置 
		for(int k=0;k8) break; 
		//得出一个模块宽 
		double onewidth = (double)(BWArray[k]+1)/8; 
		rwidth=(rwidth>8?8:rwidth); 
		for(int j=k;j=1) 
				break; 
		} 
		if(j==rwidth&&rwidth>=8) rightnum++;	//如果满足要求,则加一 
		if(rightnum > JUDGETIMES/2) break; 
	} 
	delete[] PointArray; 
	if(rightnum > JUDGETIMES/2) //如果正确的数据超过总判断数的1/2,则认为正确 
	{ 
		*pReg = tmpreg; 
		return true; 
	} 
	else if(firstjudge) 
	{ 
		firstjudge = false; 
		goto loop; 
	} 
	else 
		return false; 
} 
 
//BWArray以BWBWBWBW的序列存放,如第一点不为B,则存入0 
//所返回的数组中的每一元素均代表B/W的数目 
UINT CStdDataObject::GetLineDataB(UINT xa, UINT ya, UINT xb, UINT yb, UCHAR* BWArray) 
{ 
	int num=0; 
	int dx=abs(xa-xb),dy=abs(ya-yb); 
	int p=2*dy-dx; 
	int pp=2*dx-dy; //++ 
	int twody=2*dy,twody_dx=2*(dy-dx); 
	int twodx=2*dx,twodx_dy=2*(dx-dy);	//++ 
	int x,y,xend,yend; 
	int count=0,flags='B',ArrNum=0; //ArrNum指示当前数组中所用元素的位置 
									//count指示当前计数的B/W的数目 
									//flags指示当前对什么进行计数B/W 
	x=xa;y=ya; 
	xend=xb;yend=yb; 
	if(StdIsBlack(x,y)) 
		count++; 
	else { 
		flags='W'; 
		BWArray[ArrNum++]=count; 
		count=1; 
	} 
	num++; 
	if(dy>dx) 
	{ 
		while(y>yend?y>yend:yyend) y--; 
			else y++; 
			if(pp<0) 
				pp+=twodx; 
			else{ 
				if(xb>xa) x++; 
				else x--; 
				pp+=twodx_dy; 
			} 
			if(StdIsBlack(x,y)) 
			{ 
				if(flags=='B') count++;	//如果当前标志为B,则继续计数 
				else{ 
					flags='B';			//否则改变标志,并把数据存入; 
					BWArray[ArrNum++]=count; 
					count=1; 
				} 
			} 
			else { 
				if(flags=='W')count++; 
				else{ 
					flags='W'; 
					BWArray[ArrNum++]=count; 
					count=1; 
				} 
			} 
			num++; 
		} 
	} 
	else 
	{ 
		while(x>xend?x>xend:xxend) x--; 
			else x++; 
			if(p<0) 
				p+=twody; 
			else{ 
				if(yb>ya) y++; 
				else y--; 
				p+=twody_dx; 
			} 
			if(StdIsBlack(x,y)) 
			{ 
				if(flags=='B') count++;	//如果当前标志为B,则继续计数 
				else{ 
					flags='B';			//否则改变标志,并把数据存入; 
					BWArray[ArrNum++]=count; 
					count=1; 
				} 
			} 
			else { 
				if(flags=='W')count++; 
				else{ 
					flags='W'; 
					BWArray[ArrNum++]=count; 
					count=1; 
				} 
			} 
			num++; 
		} 
	}	 
	BWArray[ArrNum]=count; 
	BWArray[ArrNum+1]='\0'; 
	return ArrNum+1;	 
} 
 
BOOL CStdDataObject::IsBarTail(Region* pReg) 
{ 
	Region tmpreg,reg; 
	UCHAR TailShape[]={7,1,1,3,1,1,1,2,1}; 
	//此变量进行两个方向的判断 
	BOOL firstjudge=true; 
	UPOINT* PointArray; 
	UCHAR BWArray[1000]; 
	//把原矩形化为可供判断的标准矩形 
	reg = *pReg; 
	tmpreg = reg; 
	if((reg.Top.x-reg.Left.x)*(reg.Top.x-reg.Left.x)+(reg.Left.y-reg.Top.y)*(reg.Left.y-reg.Top.y) >  
		(reg.Right.x-reg.Top.x)*(reg.Right.x-reg.Top.x)+(reg.Right.y-reg.Top.y)*(reg.Right.y-reg.Top.y)) 
	{ 
		tmpreg.Left=reg.Top; 
		tmpreg.Root=reg.Left; 
		tmpreg.Top=reg.Right; 
		tmpreg.Right=reg.Root; 
	} 
loop: 
	if(!firstjudge) 
	{ 
		//进行第二次判断时,改变方向 
		Region tmpreg1 = tmpreg; 
		tmpreg.Top = tmpreg1.Root; 
		tmpreg.Left = tmpreg1.Right; 
		tmpreg.Right = tmpreg1.Left; 
		tmpreg.Root = tmpreg1.Top; 
	} 
	//计算点的总数 
	int _height = (int)(sqrt((tmpreg.Left.x-tmpreg.Root.x)*(tmpreg.Left.x-tmpreg.Root.x)+ 
		(tmpreg.Left.y-tmpreg.Root.y)*(tmpreg.Left.y-tmpreg.Root.y))+1.5); 
	//申请一空间以存入纵向的点(起始点) 
	PointArray = new UPOINT[_height]; 
	int rheight = GetLineDataA(tmpreg.Left.x,tmpreg.Left.y,tmpreg.Root.x,tmpreg.Root.y,PointArray); 
	//确定dx,dy值 
	int tx=tmpreg.Top.x,ty=tmpreg.Top.y,lx=tmpreg.Left.x,ly=tmpreg.Left.y,z; 
	z=(tx>lx)?1:-1; 
	int dx=(int)((tx==lx)?0:(19*(tx-lx+z)/7+0.5)); 
	z=(ty>ly)?1:-1; 
	int dy=(int)((ty==ly)?0:(19*(ty-ly+z)/7+0.5)); 
	//申请空间以存放横向的点(一行数据),宽度为_width 
	int _width = (int)(sqrt(dx*dx+dy*dy)+1.5); 
	if(_width>1000)	//如一条模宽度大于1000,则认为数据出错 
	{ 
		delete PointArray; 
		return false; 
	} 
	int dj=(int)(rheight/JUDGETIMES+0.5); 
	if(dj<1) dj=1; 
	for(int i=rheight/(2*JUDGETIMES),rightnum=0;idImageWidth-1) tx=dImageWidth-1; 
		if(ty<0) ty=0; 
		if(ty>dImageHeight-1) ty=dImageHeight-1; 
		int rwidth=GetLineDataB(PointArray[i].x,PointArray[i].y,tx,ty,BWArray); 
		//得到起始符位置 
		for(int k=0;k8) break; 
		//得出一个模块宽 
		double onewidth = (double)(BWArray[k]+1)/8; 
		rwidth=(rwidth>9?9:rwidth); 
		for(int j=k;j=1) 
				break; 
		} 
		if(j==rwidth&&rwidth>=9) rightnum++;	//如果满足要求,则加一 
		if(rightnum > JUDGETIMES/2) break; 
	} 
	delete[] PointArray; 
	if(rightnum > JUDGETIMES/2) //如果正确的数据超过总判断数的1/2,则认为正确 
	{ 
		*pReg = tmpreg; 
		return true; 
	} 
	else if(firstjudge) 
	{ 
		firstjudge = false; 
		goto loop; 
	} 
	else 
		return false; 
} 
 
//把从点(xa,ya)到点(xb,yb)的直线段上所有的点均存入数组,并返回点的数目 
UINT CStdDataObject::GetLineDataA(UINT xa, UINT ya, UINT xb, UINT yb, UPOINT* PointArray) 
{ 
	int num=0; 
	int dx=abs(xa-xb),dy=abs(ya-yb); 
	int p=2*dy-dx; 
	int pp=2*dx-dy; 
	int twody=2*dy,twody_dx=2*(dy-dx); 
	int twodx=2*dx,twodx_dy=2*(dx-dy); 
	int x,y,xend,yend; 
	x=xa;y=ya; 
	xend=xb;yend=yb; 
	 
	PointArray[num].x=x; 
	PointArray[num].y=y; 
	num++; 
	if(dy>dx) 
	{ 
		while(y>yend?y>yend:yyend) y--; 
			else y++; 
			if(pp<0) 
				pp+=twodx; 
			else{ 
				if(xb>xa) x++; 
				else x--; 
				pp+=twodx_dy; 
			} 
			PointArray[num].x=x; 
			PointArray[num].y=y; 
			num++; 
		} 
	} 
	else 
	{ 
		while(x>xend?x>xend:xxend) x--; 
			else x++; 
			if(p<0) 
				p+=twody; 
			else{ 
				if(yb>ya) y++; 
				else y--; 
				p+=twody_dx; 
			} 
			PointArray[num].x=x; 
			PointArray[num].y=y; 
			num++; 
		} 
	}	 
	return num-1; 
} 
 
//执行数据分析操作 
//1.定义Cell,调用FindAllCell来找出所有匹配的区域,存入类成员RegionList; 
//2.根据找出的每一个区域,进行判断 
BOOL CStdDataObject::Act() 
{ 
	//定义Cell(8*8矩阵) 
	Cell m_cell; 
	CellItem CellItems[] =  {{0,0},{1,0},{2,0},{3,0},{4,0},{5,0},{6,0},{7,0}, 
							{0,7},{1,7},{2,7},{3,7},{4,7},{5,7},{6,7},{7,7}, 
							{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7}, 
							{7,1},{7,2},{7,3},{7,4},{7,5},{7,6},{7,7}}; 
	m_cell.CellArray=CellItems; 
	m_cell.CellItemCount=30; 
 
	//调用成员函数来找出所有包含m_cell的区域于RegionList中 
	CList RegionList; 
	FindAllCell(&m_cell,RegionList); 
 
	//判断是否有数据,如无则退出 
	if(RegionList.IsEmpty())	 
		return false; 
	 
	//遍历对列,找出条码起始,结束符,并删除无用数据顶 
	POSITION tmppos,pos; 
	Region tmpreg,reg;	//用于临时存储变量 
	pos = RegionList.GetHeadPosition();	//得到对列头 
	do 
	{ 
		reg = RegionList.GetAt(pos); 
		tmppos = pos;	//保存对列指针 
		RegionList.GetNext(tmppos);	//保存下一数据POSITION 
		if(IsBarHeader(®))	//判断是否为条码起始符 
		{ 
			RegionList.GetAt(pos) = reg; 
			RegionList.GetAt(pos).RegionType='H';	//区域类型为HEADER 
		} 
		else if(IsBarTail(®))	//判断是否为条码结束符 
		{ 
			RegionList.GetAt(pos) = reg; 
			RegionList.GetAt(pos).RegionType='T';	//区域类型为TAIL 
		} 
		else RegionList.RemoveAt(pos);	//无效数据则删除 
		pos = tmppos; 
	}while(pos!=NULL); 
 
	//判断对列中是否有数据,如无则退出 
	if(RegionList.IsEmpty())	 
		return false; 
 
	//再次遍历对列,找出相匹配的HEAD和TAIL,如匹配,则译出数据,并返回true 
	BOOL bHaveOneBar=false; 
	for(pos=RegionList.GetHeadPosition();pos!=NULL;RegionList.GetNext(pos)) 
	{ 
		reg = RegionList.GetAt(pos); 
		if(reg.RegionType == 'H') 
		{ 
			for(tmppos=RegionList.GetHeadPosition();tmppos!=NULL;RegionList.GetNext(tmppos)) 
			{ 
				tmpreg = RegionList.GetAt(tmppos); 
				//查看两者是否匹配,如匹配,则返回数据于列表中 
				if(tmpreg.RegionType=='T'&&IsMatch(reg,tmpreg)) 
				{ 
					//如果已匹配,则设置标志为'O' 
					RegionList.GetAt(pos).RegionType = 'O';	 
					RegionList.GetAt(tmppos).RegionType = 'O'; 
					//得到一个数据后就返回true; 
					bHaveOneBar=true;	 
					return true;	//目前只处理一个图形数据 
				} 
			} 
		} 
	} 
 
	//删除数列 
	if(RegionList.GetCount() != 0) 
		RegionList.RemoveAll();	 
	return bHaveOneBar; 
} 
 
//根据两区域的Top,Left,Right,Root的坐标以及由两者的组合区域是否为一矩阵 
//来查看两区域(条码起始符/条码结束符)是否匹配 
BOOL CStdDataObject::IsMatch(Region reg1, Region reg2) 
{ 
	Region reg; 
	int arraylen,tmp; 
 
	//合并两矩形 
	reg.Left = reg1.Left; 
	reg.Root = reg1.Root; 
	reg.Top = reg2.Top; 
	reg.Right = reg2.Right; 
 
	//判断组合区域是否为一矩阵 
	if(IsRect(reg)) 
	{ 
		CClientDC dc(((CMainFrame*)(AfxGetMainWnd()->GetActiveWindow()))->m_wndSplitter.GetPane(0,0)); 
		dc.MoveTo(reg.Left.x,reg.Left.y); 
		dc.LineTo(reg.Top.x,reg.Top.y); 
		//计算纵向点的总数 
		int _height = (int)(sqrt((reg.Left.x-reg.Root.x)*(reg.Left.x-reg.Root.x)+ 
			(reg.Left.y-reg.Root.y)*(reg.Left.y-reg.Root.y))+1.5); 
 
		//得到每一行的起始点坐标,PointArray用于存放此点数组 
		UPOINT* PointArray = new UPOINT[_height]; 
		int rheight = GetLineDataA(reg.Left.x,reg.Left.y,reg.Root.x,reg.Root.y,PointArray); 
 
		//tx,ty为每一行的目标点坐标 
		//dx,dy为起始与目标点的坐标差 
		int tx=reg.Top.x,ty=reg.Top.y,lx=reg.Left.x,ly=reg.Left.y,z; 
		z=(tx>lx)?1:-1; 
		int dx=(tx==lx)?0:(tx-lx+z); 
		z=(ty>ly)?1:-1; 
		int dy=(ty==ly)?0:(ty-ly+z); 
		int _width = (int)(sqrt(dx*dx+dy*dy)+1.5); 
 
		//用于存放每一条/空的点数,经IsValidData判断后,存放每一条/空的模块数 
		UCHAR* BWArray = new UCHAR[_width]; 
		//用于保存刚进行判断的数据,以防止存入两相同的行 
		UCHAR *tmpCurArray = new UCHAR[_width]; 
		//对应条码的当前行 
		int CurrentRow=0; 
		//对条码的每一行进行判断 
		for(int i=0,rightnum=0;idImageWidth-1) tx=dImageWidth-1; 
			if(ty<0) ty=0; 
			if(ty>dImageHeight-1) ty=dImageHeight-1; 
			int rwidth=GetLineDataB(PointArray[i].x,PointArray[i].y,tx,ty,BWArray); 
			//判断是否为正确数据,如是,则对其转换 
			if(IsValidData(BWArray,rwidth,CurrentRow))	 
			{ 
				i+=2; 
				//比较两行数据是否相同 
				tmp = strcmp((char*)BWArray,(char*)tmpCurArray); 
				if(tmp!=0) 
				{ 
					if(BarDataList.GetCount() == 0) 
						arraylen = strlen((char*)BWArray); 
					if(arraylen == strlen((char*)BWArray)) 
					{ 
						//如不同,则存入对象的BarDataList中 
						UCHAR* tmparray = new UCHAR[rwidth]; 
						memcpy(tmparray,BWArray,rwidth); 
						if(BarDataList.GetCount() == 0) 
						{ 
							BarDataList.AddHead(tmparray); 
							arraylen = strlen((char*)tmparray); 
						} 
						else  
							BarDataList.AddTail(tmparray); 
						memcpy(tmpCurArray,BWArray,rwidth); 
						i+=2; 
						CurrentRow++; 
					} 
				} 
			} 
			else memset(tmpCurArray,0,_width); 
		} 
		delete[] PointArray; 
		delete[] BWArray; 
		delete[] tmpCurArray; 
	} 
 
	//根据列表是否为空,返回true/false 
	if(BarDataList.IsEmpty()) 
		return false; 
	else 
		return true; 
} 
 
//判断数据是否有效 
//入口: 
//pStr---指向条/空信息串,每一个数据表示对应的条/空为多少点数 
//len ---信息串长度 
//返回: 
//   true:表示数据正确,pStr中的数据改为条/空的模块数(已不含条码起始和结束符) 
//   false:数据不符合 
BOOL CStdDataObject::IsValidData(UCHAR *pStr, UINT len,int CurrentRow) 
{ 
	UINT j,ii; 
	UCHAR HeaderShape[]={8,1,1,1,1,1,1,3}; 
	double onewidth,tmpsum,tmpsum1; 
 
	if(len<8) return false; 
 
	//找第一个大于8的数(头标志),如无,则返回false 
	for(UINT i=0;i=8) break; 
 
	//如果无数据,则返回false 
	if(i==len) return false; 
 
	ii=i; 
	//申请一变量用于存放 
	UCHAR* tmpstr = new UCHAR[8]; 
	while(ii+7= 8) return false; 
 
	//如果数据正确,则化为标准ASCII码 
	pStr[ii]='\0'; 
 
	//ii=i+8:除去条码起始符 
	for(ii=i+8,j=0;pStr[ii]!='\0';ii++,j++) 
	{ 
		pStr[j]=pStr[ii]; 
		pStr[j]+=48;	//化为ASCII码 
	} 
	pStr[j]='\0'; 
	return true; 
} 
 
//把条码的条空信息转换成条码的数据值,如“31231121”转换成其对的数据127等 
//入口数据:类成员数据BarDataList; 
//返回:	类成员数据p417Data中; 
BOOL CStdDataObject::BarTo417Data() 
{ 
	POSITION pos= BarDataList.GetHeadPosition(); 
	char* str = (char*)(BarDataList.GetNext(pos)); 
	int w = strlen(str)/8,h=BarDataList.GetCount(),dCount=0; 
	int i,tmp,hno=0; 
	char tmpstr[10]; 
 
	//为p417Data申请数据空间 
	p417Data = new UINT[w*h]; 
 
	//得到条码矩阵的长度和宽度 
	this->Height = h; 
	this->Width = w; 
 
	//为每一个条空信息调用FindData来查找数据 
	pos= BarDataList.GetHeadPosition(); 
	while(pos!=NULL) 
	{ 
		str = (char*)(BarDataList.GetNext(pos)); 
		hno++; 
		for(i=0;i10?no-10:0;i<=no+10 && i<928;i++) 
	{ 
	if(pArray[i][0] == sum) 
	 return pArray[i][1]; 
	} 
	return 0; 
} 
 
BOOL CStdDataObject::D417ToEnd() 
{ 
	int w,h,dCount,dSourcePoint,dTargetPoint,tmpmode,tmpsum; 
	UINT tmp,tmp1; 
	int CurSubMode=AL,CurSubChgMode=0,CurMode=ALPHA,CurChgMode=0; 
 
	//临时数据,用于存储去了左右标志字节的数据 
	//数据数目保存在dCount中 
	UINT* tmpdata = new UINT[Height*(Width-2)]; 
	for(h=0,dCount=0;hHeight*(Width-2)) 
		tmpsum = Height*(Width-2); 
	while(dSourcePoint < tmpsum) 
	{ 
		tmp = tmpdata[dSourcePoint]; 
		switch(tmp) 
		{ 
			case 900:  
				CurMode = TEXTMODE; 
				CurSubMode=AL; 
				CurSubChgMode=0; 
				break; 
			case 901: 
				CurMode = BYTEMODE; 
				break; 
			case 924:  
				CurMode = BYTEMODE; 
				break; 
			case 902:  
				CurMode = NUMBERMODE; 
				break; 
			case 913:  
				CurChgMode = BYTEMODE; 
				break; 
			default: 
				tmpmode = CurMode; 
				if(CurChgMode) {CurMode = CurChgMode; CurChgMode = 0;} 
				if(CurMode == TEXTMODE) 
				{ 
					tmp1 = TextModeTrans(tmp/30,&CurSubMode,&CurSubChgMode); 
					if(tmp1) pEndData[dTargetPoint++] = tmp1; 
					tmp1 = TextModeTrans(tmp%30,&CurSubMode,&CurSubChgMode); 
					if(tmp1) pEndData[dTargetPoint++] = tmp1; 
				} 
				if(CurMode == BYTEMODE) 
				{ 
					UCHAR targetdata[7]; 
					int i=0,tmp; 
					do{ 
						tmp=tmpdata[dSourcePoint+i]; 
						if(tmp>=900) break; 
						i++; 
					}while(i<5 && dSourcePoint+i0) 
						ByteModeTrans(&tmpdata[dSourcePoint],targetdata,i); 
					dSourcePoint+=i-1; 
					for(i=0;i=0;i--) 
						pEndData[dTargetPoint++]=target[i]; 
				} 
				CurMode = tmpmode; 
		} 
		dSourcePoint++; 
	} 
	pEndData[dTargetPoint]='\0'; 
	delete[] tmpdata; 
	return true; 
} 
 
//字符模式下转换 
//入口: 
// data---数据 
// cursubmode---当前子模式 
// cursubchgmode---当前转移子模式 
int CStdDataObject::TextModeTrans(int data, int *cursubmode, int *cursubchgmode) 
{ 
	int tmpmode,retcode; 
	UCHAR Alpha[]={' ',LL,ML,PS}; 
	UCHAR LowerCase[]={' ',AS,ML,PS}; 
	UCHAR Mixed[]={38,13,9,44,58,35,45,46,36,47,43,37,42,61,94,PL,32,LL,AL,PS}; 
	UCHAR Punctuation[]={59,60,62,64,91,92,93,95,96,126,33,13,9,44,58,10,45,46,36,47,34,124,42,40,41,63,123,125,39,AL}; 
	tmpmode = *cursubmode; 
	if(*cursubchgmode == PS) { *cursubmode = PL; *cursubchgmode = 0; } 
	if(*cursubchgmode == AS) { *cursubmode = AL; *cursubchgmode = 0; } 
	switch(*cursubmode) 
	{ 
	case AL: 
		if(data>25) retcode=Alpha[data-26]; 
		else retcode=65+data; 
		break; 
	case LL: 
		if(data>25) retcode=LowerCase[data-26]; 
		else retcode=97+data; 
		break; 
	case ML: 
		if(data<=9) retcode=48+data; 
		else retcode=Mixed[data-10]; 
		break; 
	case PL: 
		retcode=Punctuation[data]; 
		break; 
	} 
	if(retcode==LL || retcode==ML || retcode==AL || retcode==PL) 
	{ tmpmode = retcode; retcode = 0; } 
	else if(retcode==PS || retcode==AS)  
	{ *cursubchgmode=retcode; retcode = 0; } 
	*cursubmode = tmpmode; 
	return retcode; 
} 
 
void CStdDataObject::NumberModeTrans(UINT *sourcedata, char *targetdata, int num) 
{ 
	int i,j,tmp,d,l; 
 
	//把数据初始化为0 
	for(i=0;i<46;i++) 
	targetdata[i]=0; 
	for(i=0;i=2;j--) 
	targetdata[j] = targetdata[j-2]; 
	targetdata[0]=0; 
	targetdata[1]=0; 
 
	//数据*9 
	tmp=0; 
	for(j=2;j<44;j++) 
	{ 
	d=targetdata[j]*9+tmp; 
	targetdata[j]=d%10; 
	tmp=d/10; 
	} 
	} 
 
	//加上最后一位数据 
	d=sourcedata[num-1]; 
	j=0; 
	tmp=0; 
	while(d || tmp) 
	{ 
	l=targetdata[j]+d%10+tmp; 
	targetdata[j]=l%10; 
	tmp=l/10; 
	d/=10; 
	j++; 
	} 
 
	//变成ASCII字符 
	tmp=0; 
	for(j=45;j>=0;j--) 
	{ 
	if(targetdata[j]) tmp=0x30; 
	targetdata[j]+=tmp; 
	} 
} 
 
void CStdDataObject::ByteModeTrans(UINT *sourcedata, UCHAR *targetdata,int len) 
{ 
	//位数不足五位 
	if(len!=5) 
	{ 
		for(int i=0;i