⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stddataobject.cpp

📁 对位图文件中的点阵数据进行模式判别,找出其中的完整PDF417条码,并按照GB/T 17172-1997规范来解释读出对应的数据.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				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:x<xend)
		{
			if(x<600)
			{
				x++;
				x--;
			}
			if(x>xend) 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;i<rheight;i+=dj)
	{
		//得到一行数据
		UINT tx=PointArray[i].x+dx,ty=PointArray[i].y+dy;
		if(tx<0) tx=0;
		if(tx>dImageWidth-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;k<rwidth;k++)
			if(BWArray[k]>8) break;
		//得出一个模块宽
		double onewidth = (double)(BWArray[k]+1)/8;
		rwidth=(rwidth>9?9:rwidth);
		for(int j=k;j<rwidth;j++)
		{
			if(abs((int)(((double)BWArray[j]/onewidth)-TailShape[j-k]))>=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:y<yend)
		{
			if(y>yend) 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:x<xend)
		{
			if(x>xend) 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<struct _Region,struct _Region &> 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(&reg))	//判断是否为条码起始符
		{
			RegionList.GetAt(pos) = reg;
			RegionList.GetAt(pos).RegionType='H';	//区域类型为HEADER
		}
		else if(IsBarTail(&reg))	//判断是否为条码结束符
		{
			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;i<rheight;i++)
		{
			//得到一行数据
			UINT tx=PointArray[i].x+dx,ty=PointArray[i].y+dy;
			//进行有效性判断
			if(tx<0) tx=0;
			if(tx>dImageWidth-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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -