1、EAN条形码译码器代码#include #include #include #include #include #define BI_RGB 0L#define BI_RLE8 1L#define BI_RLE4 2L#define BI_BITFIELDS 3Ltypedef struct unsigned char rgbBlue; unsigned char rgbGreen; unsigned char rgbRed; unsigned char rgbReserved; RGBQUAD;typedef struct unsigned long biSize; long biWidth
2、; long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; long biXPelsPerMeter; long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; BITMAPINFOHEADER;typedef struct BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColor
3、s1; BITMAPINFO;#include /typedef struct unsigned short bfType; unsigned long bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits; BITMAPFILEHEADER;#include /* 参考BMP文件格式*/int ReadBMPToBuf(char *FileName,unsigned char *RawImageData,int *ImageWidth,int *ImageHeight)
4、BITMAPFILEHEADER bmfileh;/BMP文件头变量 BITMAPINFOHEADER bminfoh;/位图信息头 FILE *fp; int TotalPixelNumber; fp = fopen(FileName, rb);/读写打开一个二进制文件,允许读数据 if (fp = NULL) return -1; int s1=sizeof(bmfileh);/求文件头字节数, int s2=sizeof(bminfoh);/求位图信息头字节数, fread(&bmfileh, 1, sizeof(bmfileh), fp); fread(&bminfoh, 1, siz
5、eof(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。 /bfOffBits Specifies the offset, in bytes, fro
6、m the BITMAPFILEHEADER structure to the bitmap bits. *RawImageData = (unsigned char *) calloc(TotalPixelNumber),sizeof(unsigned char);/在内存的动态存储区中分配连续空间。 fread(*RawImageData, 1,TotalPixelNumber,fp); fclose(fp); / / if(bminfoh.biHeight0) /Specifies the ImageHeight of the bitmap, in pixels. If biHeight
7、 is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner. /If biHeight is negative, indicating a top-down DIB, biCompression must be either BI_RGB or BI_BITFIELDS. Top-down DIBs
8、cannot be compressed. unsigned char *RowBuffer=NULL; RowBuffer = (unsigned char *) calloc(*ImageWidth),sizeof(unsigned char); int i,j; j = *ImageHeight/2; unsigned char *ptr1,*ptr2; ptr1 = *RawImageData;/第一行 , ptr2 = *RawImageData + (*ImageHeight-1)*(*ImageWidth);/最后一行, for(i=0;ij;i+) memcpy(RowBuff
9、er,ptr1,*ImageWidth); memcpy(ptr1,ptr2,*ImageWidth); memcpy(ptr2,RowBuffer,*ImageWidth); ptr1 += *ImageWidth; ptr2 -= *ImageWidth; free(RowBuffer); RowBuffer = NULL; return 0;/* *cell 输入 图像数据 nw 输入 图像宽度 nh 输入 图像高度 *edge_position 输出 边界坐标 *edge_num 输出 边界坐标个数*/int Get_Bar_edge(unsigned char *cellbuf,in
10、t nw,int nh,int *edge_position,int* edge_num) int i,j; int *vertical=new intnw; /垂直投影值 float *fvertical=new floatnw; /归一化后的投影值 int Pmax,Pmin,T1,ration; enum EdgeTypewtb,btw; /定义边界的性质是聪白到黑,还是聪黑到白 EdgeType *edgetype=new EdgeTypenw; int edgecount=0; /边界的个数 / 投影 for (i=0;inw;i+) verticali=0; for (j=0;jn
11、h;j+) verticali+=cellbufj*nw+i; /归一化处理 Pmax=Pmin=vertical0; for (i=0;inw;i+) if (verticaliPmax) Pmax=verticali; ration=Pmax-Pmin; for (i=0;inw;i+) fverticali=(float)(verticali-Pmin)*nh/ration; / 开始寻找边界,定义边界跳变的阈值 T1=nh/3; / 第一个边界一定是从白到黑的 for (i=5;iT1) edge_positionedgecount=i; edgetypeedgecount=wtb;
12、edgecount+; break; while (iT1) if (fverticali-1fverticali+1&edgetypeedgecount-1=btw) edge_positionedgecount=i; edgetypeedgecount=wtb; edgecount+; if (fverticali-10) return (1); if (x0) return(-1); return(0);int Get_Bar_edge_a(unsigned char *cellbuf,int nw,int nh,int *edge_position,int* edge_num) int
13、 i,j,stdh=255,strx,endx,sign,ret; int Pmax,Pmin,T1,ration,edgennum; enum EdgeTypewtb,btw; EdgeType *edgetype=new EdgeTypenw; int edgecount=0; int *edge=new intnw; int *vertical=new intnw; int *vertical1=new intnw; float *fvertical=new floatnw; /归一化后的投影值 int *vdis=new intnw; /投影 for (i=0;inw;i+) vert
14、icali=0; for (j=0;jnh;j+) verticali+=cellbufj*nw+i; memcpy(vertical1,vertical,nw*sizeof(int); /对投影排序 for (i=0;inw-1;i+) for (j=i+1;jnw;j+) if (vertical1jvertical1i) int tmpv=vertical1j; vertical1j=vertical1i; vertical1i=tmpv; int nmeant=nw/20; / 取最小的5的均值为下限 Pmin=0; for (i=0;inmeant;i+) Pmin+=vertica
15、l1i; Pmin=Pmin/nmeant; / 取最大的5的均值为上限 Pmax=0; for (i=nw-nmeant;inw;i+) Pmax+=vertical1i; Pmax=Pmax/nmeant;/ Pmax=Pmin=vertical0;/ / for (i=0;inw;i+)/ / / if (verticaliPmax) Pmax=verticali;/ ration=Pmax-Pmin; if (ration=0) ret=-1; goto ENDPOINT; /归一化操作 for (i=0;inw;i+) if (verticaliPmax) fverticali=st
16、dh; else fverticali=(float)(verticali-Pmin)*stdh/ration; edgecount=0; T1=stdh/5; /定义为边界的阈值,太大拒识率高,太低误识率高 strx=5; sign=1; i=5; while (iT1) /如果变化的幅度超过阈值,说明可能是边界 if (i-strx)2) edgeedgecount=i; else if (i-strx)3) edgeedgecount=strx+1; else int maxvdis=vdisstrx+1; int maxedge=strx+1; for (j=strx+1;jmaxvd
17、is) /找出边界投影值跳跃最大的地方,定义为边界点 /这个理论不总是正确 maxvdis=vdisj; maxedge=j; edgeedgecount=maxedge; if (fverticali-fverticalstrx)0) /定义边界点的性质 edgetypeedgecount=btw; else edgetypeedgecount=wtb; edgecount+; strx=i; i+; sign=signe; / if (fabs(fverticali-fverticalstrx)T1) /最后一个边界点 if (i-strx)2) edgeedgecount=i; else
18、 if (i-strx)3) edgeedgecount=strx+1; else int maxvdis=vdisstrx+1; int maxedge=strx+1; for (j=strx+1;jmaxvdis) maxvdis=vdisj; maxedge=j; edgeedgecount=maxedge; if (fverticali-fverticalstrx)0) edgetypeedgecount=btw; else edgetypeedgecount=wtb; edgecount+; / i=0; while (1) if (i=edgecount) break; if (e
19、dgetypei=wtb) /起始点一定是从空到条,即从白到黑 break; i+; edgennum=0; for (;iedgecount;i+) edge_positionedgennum=edgei; edgennum+; *edge_num=edgennum; ret=0;ENDPOINT: delete vdis; delete fvertical; delete vertical; delete vertical1; delete edge; delete edgetype; return ret;/* 2 代表为空 1 代表为条 一个数字由两个条两个空组成,总长度为7个单元模块
20、 每个条或者空的宽度最长为4个模块*/#define CELL_LEN 7 /*9 bars with a gap*/* 根据单元模块查找对应的数字*/static int look_up(char *one_code) typedef struct char symbol; char barcode20; LOOKUP_ENTRY; static LOOKUP_ENTRY lookup_table_ean1330 = 0, 2221121, 0, 2122111, 0, 1112212, 1, 2211221, 1, 2112211, 1, 1122112, 2, 2212211, 2, 2
21、211211, 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 (int i = 0; i 30; i +)
22、 if (strncmp(lookup_table_ean13i.barcode, one_code, CELL_LEN) = 0) return lookup_table_ean13i.symbol; return(-1);/* 确定数字的奇偶性,在这里是指条在单元模块中的比例是奇数还是偶数,比如2221211,因为条的比例是 3,所以是奇数*/static char Check_OE(char *one_code) int sum=0; char symbol; for (int i=0;iCELL_LEN;i+) sum+=one_codei; if (sum%2=0) symbol=E; else symbol=O; return symbol;/*根据左边六个数字的奇偶性来确定最前面的那个字符*/static int look_up_ean13_first(char *one_code) typedef struct char symbol; char barcode20; LOOKUP_ENTRY; static
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1