EAN条形码译码器代码.docx
- 文档编号:23167610
- 上传时间:2023-05-15
- 格式:DOCX
- 页数:37
- 大小:21.35KB
EAN条形码译码器代码.docx
《EAN条形码译码器代码.docx》由会员分享,可在线阅读,更多相关《EAN条形码译码器代码.docx(37页珍藏版)》请在冰豆网上搜索。
EAN条形码译码器代码
#include
#include
#include
#include
#include
#defineBI_RGB0L
#defineBI_RLE81L
#defineBI_RLE42L
#defineBI_BITFIELDS3L
typedefstruct{
unsignedcharrgbBlue;
unsignedcharrgbGreen;
unsignedcharrgbRed;
unsignedcharrgbReserved;
}RGBQUAD;
typedefstruct{
unsignedlongbiSize;
longbiWidth;
longbiHeight;
unsignedshortbiPlanes;
unsignedshortbiBitCount;
unsignedlongbiCompression;
unsignedlongbiSizeImage;
longbiXPelsPerMeter;
longbiYPelsPerMeter;
unsignedlongbiClrUsed;
unsignedlongbiClrImportant;
}BITMAPINFOHEADER;
typedefstruct{
BITMAPINFOHEADERbmiHeader;
RGBQUADbmiColors[1];
}BITMAPINFO;
#include
typedefstruct{
unsignedshortbfType;
unsignedlongbfSize;
unsignedshortbfReserved1;
unsignedshortbfReserved2;
unsignedlongbfOffBits;
}BITMAPFILEHEADER;
#include
/*
参考BMP文件格式
*/
intReadBMPToBuf(char*FileName,unsignedchar**RawImageData,int*ImageWidth,int*ImageHeight)
{
BITMAPFILEHEADERbmfileh;//BMP文件头变量
BITMAPINFOHEADERbminfoh;//位图信息头
FILE*fp;
intTotalPixelNumber;
fp=fopen(FileName,"rb");//读写打开一个二进制文件,允许读数据
if(fp==NULL)
{
return-1;
}
ints1=sizeof(bmfileh);//求文件头字节数,
ints2=sizeof(bminfoh);//求位图信息头字节数,
fread(&bmfileh,1,sizeof(bmfileh),fp);
fread(&bminfoh,1,sizeof(bminfoh),fp);
*ImageHeight=abs(bminfoh.biHeight);
*ImageWidth=bminfoh.biWidth;
//TotalPixelNumber=bmih.biHeight*(bmih.biWidth);
TotalPixelNumber=bmfileh.bfSize-bmfileh.bfOffBits;
fseek(fp,bmfileh.bfOffBits,SEEK_SET);//指针偏移bmfileh.bfoffbits。
//bfOffBitsSpecifiestheoffset,inbytes,fromtheBITMAPFILEHEADERstructureto
thebitmapbits.
*RawImageData=(unsignedchar*)calloc((TotalPixelNumber),sizeof(unsignedchar));//在内存
的动态存储区中分配连续空间。
fread(*RawImageData,1,TotalPixelNumber,fp);
fclose(fp);
///////////////////////////////////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////////////////////////////////
//
if(bminfoh.biHeight>0)
//SpecifiestheImageHeightofthebitmap,inpixels.IfbiHeightispositive,the
bitmapisabottom-upDIBanditsoriginisthelower-leftcorner.IfbiHeightisnegative,the
bitmapisatop-downDIBanditsoriginistheupper-leftcorner.
//IfbiHeightisnegative,indicatingatop-downDIB,biCompressionmustbeeither
BI_RGBorBI_BITFIELDS.Top-downDIBscannotbecompressed.
{
unsignedchar*RowBuffer=NULL;
RowBuffer=(unsignedchar*)calloc((*ImageWidth),sizeof(unsignedchar));
inti,j;
j=*ImageHeight/2;
unsignedchar*ptr1,*ptr2;
ptr1=*RawImageData;//第一行,
ptr2=*RawImageData+(*ImageHeight-1)*(*ImageWidth);//最后一行,
for(i=0;i { memcpy(RowBuffer,ptr1,*ImageWidth); memcpy(ptr1,ptr2,*ImageWidth); memcpy(ptr2,RowBuffer,*ImageWidth); ptr1+=*ImageWidth; ptr2-=*ImageWidth; } free(RowBuffer); RowBuffer=NULL; } return0; } /* *cell输入图像数据 nw输入图像宽度 nh输入图像高度 *edge_position输出边界坐标 *edge_num输出边界坐标个数 */ intGet_Bar_edge(unsignedchar*cellbuf,intnw,intnh,int*edge_position,int*edge_num) { inti,j; int*vertical=newint[nw];//垂直投影值 float*fvertical=newfloat[nw];//归一化后的投影值 intPmax,Pmin,T1,ration; enumEdgeType{wtb,btw};//定义边界的性质是聪白到黑,还是聪黑到白 EdgeType*edgetype=newEdgeType[nw]; intedgecount=0;//边界的个数 //投影 for(i=0;i { vertical[i]=0; for(j=0;j { vertical[i]+=cellbuf[j*nw+i]; } } //归一化处理 Pmax=Pmin=vertical[0]; for(i=0;i { if(vertical[i] if(vertical[i]>Pmax)Pmax=vertical[i]; } ration=Pmax-Pmin; for(i=0;i fvertical[i]=(float)(vertical[i]-Pmin)*nh/ration; //开始寻找边界,定义边界跳变的阈值 T1=nh/3; //第一个边界一定是从白到黑的 for(i=5;i if(fvertical[i-1]-fvertical[i+1]>T1) { edge_position[edgecount]=i; edgetype[edgecount]=wtb; edgecount++; break; } while(i { if(fabs(fvertical[i-1]-fvertical[i+1])>T1) { if(fvertical[i-1]>fvertical[i+1]&&edgetype[edgecount-1]==btw) { edge_position[edgecount]=i; edgetype[edgecount]=wtb; edgecount++; } if((fvertical[i-1] { edge_position[edgecount]=i; edgetype[edgecount]=btw; edgecount++; } } i++; } *edge_num=edgecount; ////////释放内存 delete[]vertical; delete[]fvertical; delete[]edgetype; return0; } ////////////////////////////////////////////////////////////////////// intsgn(floatx) { if(x>0)return (1); if(x<0)return(-1); return(0); } intGet_Bar_edge_a(unsignedchar*cellbuf,intnw,intnh,int*edge_position,int*edge_num) { inti,j,stdh=255,strx,endx,sign,ret; intPmax,Pmin,T1,ration,edgennum; enumEdgeType{wtb,btw}; EdgeType*edgetype=newEdgeType[nw]; intedgecount=0; int*edge=newint[nw]; int*vertical=newint[nw]; int*vertical1=newint[nw]; float*fvertical=newfloat[nw];//归一化后的投影值 int*vdis=newint[nw]; //投影 for(i=0;i { vertical[i]=0; for(j=0;j { vertical[i]+=cellbuf[j*nw+i]; } } memcpy(vertical1,vertical,nw*sizeof(int)); //对投影排序 for(i=0;i { for(j=i+1;j { if(vertical1[j] { inttmpv=vertical1[j]; vertical1[j]=vertical1[i]; vertical1[i]=tmpv; } } } intnmeant=nw/20; //取最小的%5的均值为下限 Pmin=0; for(i=0;i { Pmin+=vertical1[i]; } Pmin=Pmin/nmeant; //取最大的%5的均值为上限 Pmax=0; for(i=nw-nmeant;i { Pmax+=vertical1[i]; } Pmax=Pmax/nmeant; //Pmax=Pmin=vertical[0]; // //for(i=0;i //{ // //if(vertical[i] //if(vertical[i]>Pmax)Pmax=vertical[i]; //} ration=Pmax-Pmin; if(ration==0) { ret=-1; gotoENDPOINT; } //归一化操作 for(i=0;i { if(vertical[i] { fvertical[i]=0; } else if(vertical[i]>Pmax) { fvertical[i]=stdh; } else fvertical[i]=(float)(vertical[i]-Pmin)*stdh/ration; } edgecount=0; T1=stdh/5;//定义为边界的阈值,太大拒识率高,太低误识率高 strx=5; sign=1; i=5; while(i<(nw-5)) { vdis[i]=abs(fvertical[i+1]-fvertical[i-1]); intsigne=sgn(fvertical[i+1]-fvertical[i]); if(signe==sign||signe==0)//如果没有变化,说明是连续的增加或下降 { i++; continue; } //如果signe发生变化,说明出现了极值点(局部最大值为最小值) if(fabs(fvertical[i]-fvertical[strx])>T1)//如果变化的幅度超过阈值,说明可能是边界 { if((i-strx)<2) edge[edgecount]=i; else if((i-strx)<3) edge[edgecount]=strx+1; else { intmaxvdis=vdis[strx+1]; intmaxedge=strx+1; for(j=strx+1;j { if(vdis[j]>maxvdis)//找出边界投影值跳跃最大的地方,定义为 边界点 {//这个理论不总是正确 maxvdis=vdis[j]; maxedge=j; } } edge[edgecount]=maxedge; } if((fvertical[i]-fvertical[strx])>0)//定义边界点的性质 edgetype[edgecount]=btw; else edgetype[edgecount]=wtb; edgecount++; } strx=i; i++; sign=signe; } /////////////////////////////////////////// if(fabs(fvertical[i]-fvertical[strx])>T1)//最后一个边界点 { if((i-strx)<2) edge[edgecount]=i; else if((i-strx)<3) edge[edgecount]=strx+1; else { intmaxvdis=vdis[strx+1]; intmaxedge=strx+1; for(j=strx+1;j { if(vdis[j]>maxvdis) { maxvdis=vdis[j]; maxedge=j; } } edge[edgecount]=maxedge; } if((fvertical[i]-fvertical[strx])>0) edgetype[edgecount]=btw; else edgetype[edgecount]=wtb; edgecount++; } /////////////////////////////////////////////////// i=0; while (1) { if(i>=edgecount)break; if(edgetype[i]==wtb)//起始点一定是从空到条,即从白到黑 break; i++; } edgennum=0; for(;i { edge_position[edgennum]=edge[i]; edgennum++; } *edge_num=edgennum; ret=0; ENDPOINT: delete[]vdis; delete[]fvertical; delete[]vertical; delete[]vertical1; delete[]edge; delete[]edgetype; returnret; } /* 2代表为空 1代表为条 一个数字由两个条两个空组成,总长度为7个单元模块 每个条或者空的宽度最长为4个模块 */ #defineCELL_LEN7/*9barswithagap*/ /* 根据单元模块查找对应的数字 */ staticintlook_up(char*one_code) { typedefstruct{ charsymbol; charbarcode[20]; }LOOKUP_ENTRY; staticLOOKUP_ENTRYlookup_table_ean13[30]={ {'0',"2221121"},{'0',"2122111"},{'0',"1112212"}, {'1',"2211221"},{'1',"2112211"},{'1',"1122112"}, {'2',"2212211"},{'2',"2211211"},{'2',"1121122"}, {'3',"2111121"},{'3',"2122221"},{'3',"1222212"}, {'4',"2122211"},{'4',"2211121"},{'4',"1211122"}, {'5',"2112221"},{'5',"2111221"},{'5',"1221112"}, {'6',"2121111"},{'6',"2222121"},{'6',"1212222"}, {'7',"2111211"},{'7',"2212221"},{'7',"1222122"}, {'8',"2112111"},{'8',"2221221"},{'8',"1221222"}, {'9',"2221211"},{'9',"2212111"},{'9',"1112122"}, }; for(inti=0;i<30;i++) if(strncmp(lookup_table_ean13[i].barcode,one_code,CELL_LEN)==0) returnlookup_table_ean13[i].symbol; return(-1); } //////////////////////////////////////////////////////////////// /* 确定数字的奇偶性,在这里是指条在单元模块中的比例是奇数还是偶数,比如2221211,因为条的比例是 3,所以是奇数 */ staticcharCheck_OE(char*one_code) { intsum=0; charsymbol; for(inti=0;i { sum+=one_code[i]; } if(sum%2==0) symbol='E'; else symbol='O'; returnsymbol; } /////////////////////////////////////////////////////////////// /* 根据左边六个数字的奇偶性来确定最前面的那个字符 */ staticintlook_up_ean13_first(char*one_code) { typedefstruct{ charsymbol; charbarcode[20]; }LOOKUP_ENTRY; static
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- EAN 条形码 译码器 代码