📄 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 <math.h>
#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<struct _Region,struct _Region &>& 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;i<pCell->CellItemCount;i++)
{
if((tmp1=pCell->CellArray[i].x)>dCIAWidth)
dCIAWidth=tmp1;
if((tmp1=pCell->CellArray[i].y)>dCIAHeight)
dCIAHeight=tmp1;
}
dCIAWidth++;
dCIAHeight++;
for(H=0;H<dImageHeight-dCIAHeight;H+=8)
for(W=0;W<dImageWidth-dCIAWidth;W+=8)
{
//如果点为BLACK,则判断由该点开始的一个区域是否满足Cell
if(StdIsBlack(W,H))
{
bIsOk=true;
for(i=0;i<pCell->CellItemCount;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+1<dImageWidth && StdIsBlack(++xx,yy))
Whitten(xx,yy);
ex=xx-1;
if(sx<mleft) mleft=sx;
if(ex>mright) mright=ex;
if(yy<mtop) mtop=yy;
else if(yy>mroot) mroot=yy;
//判断是否为LEFT点
/*
if(yy<pRegion->Left.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 && yy<pRegion->Left.y)
{ pRegion->Left.x=sx; pRegion->Right.x=ex; }
*/
if(sx<pRegion->Left.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 && yy<pRegion->Left.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(yy<pRegion->Top.y && abs(pRegion->Top.x-ex)<=EMPTYLIMIT)
{ pRegion->Top.y=yy; pRegion->Top.x=ex; };
*/
if(yy<pRegion->Top.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 && sx<pRegion->Root.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+1<dImageHeight)
{
for(xx=sx;xx<=ex;xx++)
{
if(StdIsBlack(xx,yy+1))
{
EmptyRegionInXY(xx,yy+1,pRegion);
flags=false;
}
}
}
}
//判断一个区域是否为矩形
BOOL CStdDataObject::IsRect(Region r)
{
//判断两直角边是否相等
if(abs((int)(r.Top.x-r.Left.x-r.Right.x+r.Root.x))>ERRORLIMIT)
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;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>8?8:rwidth);
for(int j=k;j<rwidth;j++)
{
if(abs((int)(((double)BWArray[j]/onewidth)-HeaderShape[j-k]))>=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:y<yend)
{
if(y>yend) y--;
else y++;
if(pp<0)
pp+=twodx;
else{
if(xb>xa) x++;
else x--;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -