条形码基础
一、条形码概述
   条形码是由美国的N.T.Woodland在1949年首先提出的。近年来,随着计算机应用的不断普及,条形码的应用得到了很大的发展。条形码可以标出 商品的生产国、制造厂家、商品名称、生产日期、图书分类号、邮件起止地点、类别、日期等信息,因而在商品流通、图书管理、邮电管理、银行系统等许多领域都 得到了广泛的应用。
  条形码是由宽度不同、反射率不同的条和空,按照一定的编码规则(码制)编制成的,用以表达一组数字或字母符号信息的图 形标识符,即条形码是一组粗细不同,按照一定的规则安排间距的平行线条图形,常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称空)组成的。

二、条形码识别系统的组成
  为了阅读出条形码所代表的信息,需要一套条形码识别系统,它由条形码扫描器、放大整形电路、译码接口电路和计算机系统等部分组成。

三、条形码的识别原理
   由于不同颜色的物体,其反射的可见光的波长不同,白色物体能反射各种波长的可见光,黑色物体则吸收各种波长的可见光,所以当条形码扫描器光源发出的光经 光阑及凸透镜1后,照射到黑白相间的条形码上时,反射光经凸透镜2聚焦后,照射到光电转换器上,于是光电转换器接收到与白条和黑条相应的强弱不同的反射光 信号,并转换成相应的电信号输出到放大整形电路,白条、黑条的宽度不同,相应的电信号持续时间长短也不同。但是,由光电转换器输出的与条形码的条和空相应 的电信号一般仅10mV左右,不能直接使用,因而先要将光电转换器输出的电信号送放大器放大,放大后的电信号仍然是一个模拟电信号,为了避免由条形码中的 疵点和污点导致错误信号,在放大电路后需加一整形电路,把模拟信号转换成数字电信号,以便计算机系统能准确判读。
  整形电路的脉冲数字信号 经译码器译成数字、字符信息。它通过识别起始、终止字符来判别出条形码符号的码制及扫描方向;通过测量脉冲数字电信号0、1的数目来判别出条和空的数目. 通过测量0、1信号持续的时间来判别条和空的宽度,这样便得到了被辩读的条形码符号的条和空的数目及相应的宽度和所用码制,根据码制所对应的编码规则,便 可将条形符号换成相应的数字、字符信息,通过接口电路送给计算机系统进行数据处理与管理,便完成了条形码辨读的全过程。

  以下是中华人民共和国国家标准 GB/T 12905-2000 中的术语:
    1、条码 bar code 由一组规则排列的条、空及其对应字符组成的标记,用以表示一定的信息。
    2、条码系统 bar code system 由条码符号设计、制作及扫描识读组成的系统。
    3、反射率 reflectance;reflectivity 反射光强度与入射光强度的比值。
    4、漫反射 deffuse reflection 投射在粗糙表面的光向各个方向反射的现象。
    5、镜反射 specular reflection 投射在光滑表面的光向各个方向反射的现象。
    6、条 bar;dark bar;black bar 条码中反射率较低的部分。
    7、空 space;light bar 条码中反射率较高的部分。
    8、起始符 start character;start cipher;start code 位于条码起始位置的若干条与空。
    9、终止符 stop character;stop cipher;start code 位于条码终止位置的若干条与空。
    10、空白区 clear area;quiet zone;quiet area;clear zone 条码起始符、终止符两端外侧与空的反射率相同的限定区域。
    11、条码符号 bar code symbol 包括空白区的条码。
    12、字符集 character seet 条码符号可以表示的字母、数字和符号的集合。
    13、中间分隔符 central seperating character 位于条码中间位置用来分隔数据段的若干条与空。
    14、分隔字符 separator 编码字符集中的一种起分隔作用的特殊字符。
    15、条码字符 bar code character 表示一个字符或符号的若干条与空。
    16、条码字符集 bar code character set 某种条码所能表示的条码字符的集合。
    17、条码数据符 bar code data character 表示特定信息的条码字符。
    18、条码校验符 bar code check character 表示校验码的条码字符。
    19、条码填充符 bar code filler character 不表示特定信息的条码字符。
    20、单元 element 构成条码字符的条或空。
    21、条高 bar height 垂直于单元宽度方向的条的高度尺寸。
    22、条宽 bar width 条码字符中条的的宽度尺寸。
    23、空宽 space width 条码字符的空的宽度尺寸。
    24、条宽比 bar width ratio 条码中最宽条与最窄条的宽度比。
    25、空宽比 space width ratio 条码中最宽空与最窄空的宽度比。
    26、X尺寸 X dimension X 条码符号中窄单元的标称尺寸。
    27、Z尺寸 Z dimension Z 条码符号中窄单元的实际尺寸。
    28、宽窄比 width to narrow ratio N 平均宽条的条宽与平均宽空的空宽之和(条码字符间隔不计在内)除以两倍Z尺寸。它是宽度调节编码法中的技术参数。计算公式:N=(平均宽条的条宽+平均宽空的空宽)/2Z
    29、条码长度 bar code length 从条码起始符前缘到终止符后缘的长度。
    30、条码符号的长度 bar code symbol length;symbol length 包括空白去的条码长度。
    31、纵横比 aspect ratio 条码长度与条高的比。
    32、条码密度 bar code density 单位长度条码所表示的条码字符的个数。注:通常用CPI表示,即每英寸内能表示的条码字符的个数。
    33、条码字符间隔 inter-character gap 相邻条码字符间不表示特定信息且与空的反射率相同的区域。
    34、模块 module 模块组配编码法组成条码字符的基本单位。
    35、保护框 bearer bar 围绕条码且与条反射率相同的边或框。
    36、连续型条码 continuos bar code 没有条码字符间隔的条码。
    37、非连续型条码 discrete bar code 有条码字符间隔的条码。
    38、双向条码 bi-directional bar code 条码符号两端均可作为扫描起点的条码。
    39、附加条码 add-on 表示附加信息的条码。
    40、奇偶校验 odd-even check 根据二进制数位中0或1的个数为奇数或偶数而进行校验的方法。
    41、自校验条码 self-checking bar code 条码字符本身具有校验功能的条码。
    42、定长条码 fixed length of bar code 条码字符个数固定的条码。
    43、非定长条码 unfixed length of bar code 条码字符个数不固定的条码。
    44、宽度调节编码法 width encode 条码符号中的条和空由宽、窄两种单元组成的条码编码方法。
    45、模块组配编码法 module combination encode 条码符号的字符由规定的若干个模块组成的条码编码方法。
    46、二元码 binary-edge-code 两种单元宽度条码,由两种宽度单元组成的条码字符。
    47、多元码 four-edge-code 多种单元宽度条码,由三种或三种以上的宽度单元组成的条码字符。
    48、奇排列 odd permutation;odd parity 模块组配编码法中,一个条码字符所含条的模块数的和为奇数的排列。
    49、偶排列 even permutation;even parity 模块组配编码法中,一个条码字符所含条的模块数的和为偶数的排列。
    50、条码逻辑式 bar code logic value 用二进制“0”和“1”表示条码字符的表示式。
    51、编码容量 encoded volume 条码字符集中所能表示的字符数的最大值。
    52、条码原版胶片 bar code film master 条码胶片的母片。
    53、一维条码 linear bar code;one-dimentional bar code 只在一维方向上表示信息的条码符号。
    54、二维条码 two-dimentional bar code 在二维方向上表示信息的条码符号。
    55、特种条码 special bar code 特殊材料制成的条码。
    56、条码字符的值 character value 一维条码由条码逻辑式向字符集转换的中间值。
    57、码字 codeword 二维条码字符的值。由条码逻辑式象字符集转换的中间值。
    58、纠错字符 error correction character 二维条码中,错误检测和错误纠正的字符。
    59、纠错码字 error correction codeword 二维条码中,纠错字符的值。

四 条形码的一些基本概念

◆码制
条码的码制是指条码符号的类型,每种类型的条码符号都是由符合特定编码规则的条和空组合而成。每种码制都具有固定的编码容量和所规定 的条码字符集。条码字符中字符总数不能大于该种码制的编码容量。常用的一维码的码制包括:EAN码、39码、交插25码、UPC码、128码、93码,及 Codabar(库德巴码)等。

◆条码字符集
条码字符集是指某种码制所表示的全部字符的集合。有些码制仅能表示10个数字字 符:0到9,如EAN/UPC码,25条码;有些码制除了能表示10个数字字符外,还可以表示几个特殊字符,如库德巴条码。39条码可表示数字字 符:0~9,26个英文字母:A~Z以及一些特殊符号。

◆连续性与非连续性
条码符号的连续性是指每个条码字符之间不存在间 隔,相反,非连续性是指每个条码字符之间存在间隔。从某种意义上讲,由于连续性条码不存在条码字符间隔,即密度相对较高,而非连续性条码的密度相对较 低。但非连续性条码字符间隔引起误差较大,一般规范不给出具体指标限制。而对连续性条码除了控制尺寸误差外,还需控制相邻条与条,空与空的相同边缘间的尺 寸误差及每一条码字符的尺寸误差。

◆定长条码与非定长条码
定长条码是指仅能表示固定字符个数的条码。非定长条码是指能表示可变字符个数的条码。例如:EAN/UPC码是定长条码,它们的标准版仅能表示12个字符,39码为非定长条码。
定 长条码由于限制了表示字符的个数,即密码的无视率相对较低,因为就一个完整的条码符号而言,任何信息的丢失总会导致密码的失败。非定长条码具有灵活、方便 等优点,但受扫描器及印刷面积的控制,它不能表示任意多个字符,并且在扫描阅读过程中可能产生因信息丢失而引起错误密码,这些缺点在某些码制(如交插25 码)中出现的概率相对较大,这个缺点可通过识读器或计算机系统的校验程度而克服。

◆双向可读性
条码符号的双向可读性,是指从左、 右两侧开始扫描都可被识别的特性。绝大多数码制都可双向识读,所以都具有双向可读性。事实上,双向可读性不仅仅是条码符号本身的特性,它是条码符号和扫描 设备的综合特性。对于双向可读的条码,识读过程中译码器需要判别扫描方向。有些类型的条码符号,其扫描方向的判定是通过起始符与终止符来完成。例如39 码、交插25码、库德巴码。有些类型的条码,由于从两个方向扫描起始符和终止符所产生的数字脉冲信号完全相同,所以无法用它们来判别扫描方向。例 如:EAN和UPC码。在这种情况下,扫描方向的判别则是通过条码数据符的特定组合来完成的。对于某些非连续性条码符号,例如:39条码,由于其字符集 中存在着条码字符的对称性(例如字符“*”与“P”,“M”与“—”等),在条码字符间隔较大时,很可能出现因信息丢失而引起的译码错误。

◆自校验特性
条 码符号的自校验特性是指条码字符本身具有校验特性。若在一条码符号中,一个印刷缺陷(例如,因出现污点把一个窄条错认为宽条,而相邻宽空错认为窄空)不会 导致替代错误,那么这种条码就具有自校验功能。例如39条码、库德巴条码、交插25条码都具有自校验功能;EAN和UPC条码、93条码等都没有自校验功 能。自校验功能也能校验出一个印刷缺陷。对于大于一个的印刷缺陷,任何自校验功能的条码都不可能完全校验出来。对于某种码制,是否具有自校验功能是由其编 码结构决定的。码制设置者在设置条码符号时,均须考虑自校验功能。

五 一维条码

条形码知识-编程知识网
(图1: 标准版商品条码符号结构)

条形码知识-编程知识网
(图2:标准版商品条码符号构成示意图)


  ★左侧空白区:
牋 位于条码符号最左侧的与空的反射率相同的区域,其最小宽度为11个模块宽。
  ★起始符:
牋 位于条码符号左侧空白区的右侧,表示信息开始的特殊符号,由3个模块组成。
  ★左侧数据符:
牋 位于起始符号右侧,是平分字符的特殊符号,由5个模块组成。
  ★中间分隔符:
牋 位于左侧数据符的右侧,是平分条码字符的特殊符号,由5个模块组成。
  ★右侧数据符:
牋 位于中间分隔符右侧,表示5位数字信息的一组条码字符,由35个模块组成。
  ★校验符:
牋 位于右侧数据符的右侧,表示校验码的条码字符,由7个模块组成。
  ★终止符:
牋 位于条码符号校验符的右侧,表示信息结束的特殊符号,由3个模块组成。
  ★右侧空白区:
  位于条码符号最右侧的与空的反射率相同的区域,其最小宽度为7个模块宽。为保护右侧空白区的宽度,可在条码符号右下角加 ">" 符号, "<" 符号的位置见图3。

条形码知识-编程知识网
(图3:标准版条码符号右空白区中“>”的位置及尺寸)


  ★供人识别字符:
  位于条码符号的下方,与条码相对应的13位数字。供人识别字符优先选用GB/T 12508中规定的OCR-B字符集;字符顶部和条码字符底部的最小距离为0.5个模块宽。EAN-13商品条码供人识别字符中的前置码印制在条码符号起始符的左侧。


(1)EAN码:
EAN码是国际物品编码协会制定的一种商品用条码,通用于全世界。EAN码符号有标准版(EAN-13)和缩短版(EAN-8)两种,我国的通用商品条码与其等效,日常购买的商品包装上所印的条码一般就是EAN码。如图所示:
    

(2)UPC码:
UPC码是美国统一代码委员会制定的一种商品用条码,主要用于美国和加拿大地区,我们在美国进口的商品上可以看到。如图所示:
      条形码知识-编程知识网                         条形码知识-编程知识网
        UPC-A码                                   UPC-E码
(3)39码:
39码是一种可表示数字、字母等信息的条码,主要用于工业、图书及票证的自动化管理,目前使用极为广泛。如图所示:
                     条形码知识-编程知识网
                                 39码

(4)Code 93码:
Code 93码与39码具有相同的字符集,但它的密度要比39码高,所以在面积不足的情况下,可以用93码代替39码。
                    条形码知识-编程知识网
                               Code 93码

(5)库德巴码:
库德巴码也可表示数字和字母信息,主要用于医疗卫生、图书情报、物资等领域的自动识别。如图所示:
                   条形码知识-编程知识网
                              库德巴码
(6)Code 128 码:
    128可表示ASCII 0 到 ASCII 127 共计128个ASCII字符。如图所示:
                   条形码知识-编程知识网
                              Code128码

(7)ITF 25 条码:
交插25码是一种条和空都表示信息的条码,交插25码有两种单元宽度,每一个条 码字符由五个单元组成,其中二个宽单元,三个窄单元。在一个交插25码符号中,组成条码符号的字符个数为偶数,当字符是奇数个时,应在左侧补0变为偶数。 条码字符从左到右,奇数位置字符用条表示,偶数位字符用空表示。交插25码的字符集包括数字0到9。如图示:
                  条形码知识-编程知识网
                           ITF 25 条码

(8)Industrial 25 条码:
Industrial 25码只能表示数字,有两种单元宽度。每个条码字符由五个条组成,其中两个宽条,其余为窄条。这种条码的空不表示信息,只用来分隔条,一般取与窄条相同的宽宽度。如图示:
                 条形码知识-编程知识网
                       Industrial 25 条码

(9)Matrix 25 条码:
     Matrix 25码只能表示数字0到9。当采用Matrix25码的编码规范,而采用ITF25码的启始符和终止符时,生成的条码就是中国邮政码。我公司的LabelShop条码标签打印软件可打印中国邮政码!
                条形码知识-编程知识网
                        Matrix 25码

六 二维条码

       一维条码所携带的信息量有限,如商品上的条码仅能容纳13位(EAN-13码)阿拉伯数字,更多的信息只能依赖商品数据库的支持,离开了预先建立的数据 库,这种条码就没有意义了,因此在一定程度上也限制了条码的应用范围。基于这个原因,在90年代发明了二维条码。二维条码除了具有一维条码的优点外,同时 还有信息量大、可靠性高,保密、防伪性强等优点。 
       目前二维条码主要有PDF417码、Code49码、Code 16K码、Data Matrix码、MaxiCode码等,主要分为堆积或层排式和棋盘或矩阵式两大类。
      二维条码作为一种新的信息存储和传递技术,从诞生之时就受到了国际社会的广泛关注。经过几年的努力,现已应用在国防、公共安全、交通运输、医疗保健、工业、商业、金融、海关及政府管理等多个领域。
      二维条码依靠其庞大的信息携带量,能够把过去使用一维条码时存储于后台数据库中的信息包含在条码中,可以直接通过阅读条码得到相应的信息,并且二维条码还有错误修正技术及防伪功能,增加了数据的安全性。
      二维条码可把照片、指纹编制于其中,可有效地解决证件的可机读和防伪问题。因此,可广泛应用于护照、身份证、行车证、军人证、健康证、保险卡等。

(1)PDF417 二维条码
       PDF417是一种堆叠式二维条码,目前应用最为广泛。PDF417条码是由美国SYMBOL公司发明的,PDF(Portable Data File)意为"便携数据文件"。组成条码的每一个条码字符由4个条和4个空,共17个模块构成,故称为PDF417条码。
       PDF417条码可表示数字、字母或二进制数据,也可表示汉字。一个PDF417条码最多可容纳1850个字符或1108 个字节的二进制数据,如果只表示数字则可容纳2710个数字。PDF417的纠错能力分为9级,级别越高,纠正能力越强。由于这种纠错功能,使得污损的 417条码也可以正确读出。我国目前已制定了PDF417码的国家标准。 PDF417条码需要有417解码功能的条码阅读器才能识别。
       PDF417条码最大的优势在于其庞大的数据容量和极强的纠错能力。当PDF417条码用于防伪时,并不是PDF417条码不能被复制,而是由于使用PDF417条码可以将大量的数据快速读入计算机,使得大规模的防伪检验成为可能。
             条形码知识-编程知识网
                              PDF417条码


(2)QR Code 二维条码
      QR Code码是由日本Denso公司于1994年9月研制的一种矩阵二维码符号,它除具有一维条码及其它二维条码所具有的信息容量大、可靠性高、可表示汉字及图象多种文字信息、保密防伪性强等优点外,还具有如下主要特点:
               条形码知识-编程知识网

七  商品条码(EAN条码)的编码结构
  包括标准版商品条码(EAN—13条码)和缩短版商品条码(EAN—8条码)。
  1、标准版商品条码:EAN—13
  标准版商品条码所表示的代码由13位数字组成,其结构如下:
  结构一:X13X12X11X10X9X8X7 X6X5X4X3X2 X1, 其中:X13 ⋯⋯X7厂商识别代码;X6 ⋯⋯X2表示商品项目代码;X1校验码。
   结构二:X13X12X11X10X9X8X7 X6 X5X4X3X2 X1。其中:X13 ⋯⋯X6厂商识别代码;X5 ⋯⋯X2表示商品项目代码;X1校验码。当X13X12X11为690、691时,其代码结构同结构一;当X13X12X11为692时,其代码结构同结 构二。
  2、缩短版商品条码:EAN-8
  缩短版商品条码由8位数字组成,其结构如下:
  X8X7 X6 X5X4X3X2 X1;其中:X8X7 X6:其含义同标准版商品条码的X13X12X11;X5X4X3X2:表示商品项目代码,由EAN编码组织统一分配。在我国,由中国物品编码中心统一分 配;X1:校验码。计算时,需在缩短版商品条码代码前加5个“0”,然后按标准版商品条码校验码的计算方法计算。

八 EAN-13 商品条码的符号结构
牋 EAN-13商品条码由左侧空白区、起始符、左侧数据符、中间分隔符、右侧数据符、校验符、终止符、右侧空白区及供人识别字符组成。见图1和图2。

九 EAN码校验位的计算方法

    下面的算法来自互联网,不是最方便的,但可以使用

/**
   EAN码校验位的计算方法
   从代码位置序号2开始,所有偶数位的数字代码求和为a。
   将上步中的a乘以3为a。
   从代码位置序号3开始,所有奇数位的数字代码求和为b。
   将a和b相加为c。
   取c的个位数d。
   用10减去d即为校验位数值。

   例:234235654652的校验码的计算如下表:

   数据码 校验码
   代码位置序号 13 12 11 10 9 8 7 6 5 4 3 2 1
   数字码 2 3 4 2 3 5 5 5 4 6 5 2 ?
   偶数位     3 + 2 + 5 + 5 + 6 + 2
   奇数位 2 + 4 + 3 + 5 + 4 + 5

   步骤1:3+2+5+5+6+2=23
   步骤2:23*3=69
   步骤3:2+4+3+5+4+5=23
   步骤4:69+23=92
   步骤5:10-2=8
   步骤6:校验码为 8

   数据码 校验码
   代码位置序号 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
   数字码 2 0 0 0 0 0 5 0 0 2 2 0 0 0 1 4 7 ?
   偶数位 2 + 0 + 0 + 5 + 0 + 2 + 0 + 1 + 7
   奇数位      0 + 0 + 0 + 0 + 2 + 0 + 0 + 4

   步骤1:2+0+0+5+0+2+0+1+7=17
   步骤2:17*3=51
   步骤3:0+0+0+0+2+0+0+4=6
   步骤4:51+6=57
   步骤5:10-7=3
   步骤6:校验码为 3

  */

/// <summary>
  /// EAN码校验位的计算
  /// </summary>
  /// <param name="szCode"></param>
  /// <returns></returns>
  private bool GetVerifyBit(ref string szCode)
  {
   int nNum1 = 0;
   int nNum2 = 0;
   int nNum3 = 0;
   int szLen = 0;
   if ( szCode == null )
    return false;
  
   szLen = szCode.Length;    
   if(szLen <=12 || szLen >= 17)
        return true;
   for ( int i=0; i<szLen; i++)
   {  

    if ( i%2 == 0 )
    {
     nNum2 += int.Parse(szCode[i].ToString()); //偶数    
    }
    else
    {
     nNum1 += int.Parse(szCode[i].ToString()); //奇数    
    }
   }
   nNum3 = (Operator.DiscountLabelBarLength % 2 ==0) ? nNum1 + nNum2 * 3 : nNum1 * 3 + nNum2 ;
  
   int t ;
   if(nNum3%10>0) t= 10- (nNum3 % 10) ;
   else t=0;
   szCode+=t;

   return true
  }

/// <summary>
  /// EAN码校验位的计算
  /// </summary>
  /// <param name="szCode"></param>
  /// <returns></returns>
  private bool GetVerifyBit(ref string szCode)
  {
   int nNum1 = 0;
   int nNum2 = 0;
   int nNum3 = 0;
   int szLen = 0;
   if ( szCode == null )
    return false;
  
   szLen = szCode.Length;    
   if(szLen <=12 || szLen >= 17)
        return true;
   for ( int i=0; i<szLen; i++)
   {  

    if ( i%2 == 0 )
    {
     nNum2 += int.Parse(szCode[i].ToString()); //偶数    
    }
    else
    {
     nNum1 += int.Parse(szCode[i].ToString()); //奇数    
    }
   }
   nNum3 = (Operator.DiscountLabelBarLength % 2 ==0) ? nNum1 + nNum2 * 3 : nNum1 * 3 + nNum2 ;
  
   int t ;
   if(nNum3%10>0) t= 10- (nNum3 % 10) ;
   else t=0;
   szCode+=t;

   return true
  }