概念
一维条码即指条码条和空的排列规则,常用的一维码的码制包括:EAN码、39码、交叉25码、UPC码、128码、93码,ISBN码,及Codabar(库德巴码)等。
条形码起源于 20 世纪 40 年代,应用于 70 年代,普及于 80 年代。条码技术是在计算机应用和实践中产生并发展起来的广泛应用于商业、邮政、图书管理、仓储、工业生产过程控制、交通等领域的一种自动识别技术,具有输入速度快、准确度高、成本低、可靠性强等优点,在当今的自动识别技术中占有重要的地位。
不同的码制有它们各自的应用领域:
EAN 码:是国际通用的符号体系,是一种长度固定、无含意的条码,所表达的
信息全部为数字,主要应用于商品标识。
39码和128码:为目前国内企业内部自定义码制,可以根据需要确定条码的长度和信息,它编码的信息可以是数字,也可以包含字母,主要应用于工业生产线领域、图书管理等。Code 39 码,是目前 用途广泛的一种条形码,可表示数字、英文字母以及“−”、“.”、“/”、“+”、“%”、“$”、 “”(空格)和“*”共 44 个符号,其中“*”仅作为起始符和终止符。既能用数字,也能用 字母及有关符号表示信息。
93码:是一种类似于39码的条码,它的密度较高,能够替代39码。
25码:主要应用于包装、运输以及国际航空系统的机票顺序编号等。
Codabar码:应用于血库、图书馆、包裹等的跟踪管理。
ISBN:用于图书管理。
识别原理:
由于不同颜色的物体,其反射的可见光的波长不同,白色物体能反射各种波长的可见光,黑色物体则吸收各种波长的可见光,所以当条码扫描器光源发出的光经光阑及凸透镜1后,照射到黑白相间的条码上时,反射光经凸透镜2聚焦后,照射到光电转换器上,于是光电转换器接收到与白条和黑条相应的强弱不同的反射光信号,并转换成相应的电信号输出到放大整形电路.白条、黑条的宽度不同,相应的电信号持续时间长短也不同.但是,由光电转换器输出的与条码的条和空相应的电信号一般仅10mV左右,不能直接使用,因而先要将光电转换器输出的电信号送放大器放大.放大后的电信号仍然是一个模拟电信号,为了避免由条码中的疵点和污点导致错误信号,在放大电路后需加一整形电路,把模拟信号转换成数字电信号,以便计算机系统能准确判读.
整形电路的脉冲数字信号经译码器译成数字、字符信息.它通过识别起始、终止字符来判别出条码符号的码制及扫描方向;通过测量脉冲数字电信号0、1的数目来判别出条和空的数目.通过测量0、1信号持续的时间来判别条和空的宽度.这样便得到了被辩读的条码符号的条和空的数目及相应的宽度和所用码制,根据码制所对应的编码规则,便可将条形符号换成相应的数字、字符信息,通过接口电路送给计算机系统进行数据处理与管理,便完成了一维条码辨读的全过程。
源码与实现
code39的实现
////// 生成条码 Bitmap,自定义条码高度,自定义文字对齐样式 /// /// /// /// /// public Bitmap GetCode39(string sourceCode, int barCodeHeight, StringFormat sf) { BarCodeText = sourceCode.ToUpper(); int leftMargin = 5; int topMargin = 0; int thickLength = 2; int narrowLength = 1; int intSourceLength = sourceCode.Length; string strEncode = "010010100" ; //添加起始码“ *”. var font = new System.Drawing.Font( "Segoe UI", 5); string AlphaBet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*" ; string[] Code39 = { /* 0 */ "000110100" , /* 1 */ "100100001" , /* 2 */ "001100001" , /* 3 */ "101100000" , /* 4 */ "000110001" , /* 5 */ "100110000" , /* 6 */ "001110000" , /* 7 */ "000100101" , /* 8 */ "100100100" , /* 9 */ "001100100" , /* A */ "100001001" , /* B */ "001001001" , /* C */ "101001000" , /* D */ "000011001" , /* E */ "100011000" , /* F */ "001011000" , /* G */ "000001101" , /* H */ "100001100" , /* I */ "001001100" , /* J */ "000011100" , /* K */ "100000011" , /* L */ "001000011" , /* M */ "101000010" , /* N */ "000010011" , /* O */ "100010010" , /* P */ "001010010" , /* Q */ "000000111" , /* R */ "100000110" , /* S */ "001000110" , /* T */ "000010110" , /* U */ "110000001" , /* V */ "011000001" , /* W */ "111000000" , /* X */ "010010001" , /* Y */ "110010000" , /* Z */ "011010000" , /* - */ "010000101" , /* . */ "110000100" , /*' '*/ "011000100" , /* $ */ "010101000" , /* / */ "010100010" , /* + */ "010001010" , /* % */ "000101010" , /* * */ "010010100" }; sourceCode = sourceCode.ToUpper(); Bitmap objBitmap = new Bitmap(((thickLength * 3 + narrowLength * 7) * (intSourceLength + 2)) + (leftMargin * 2), barCodeHeight + (topMargin * 2)); Graphics objGraphics = Graphics.FromImage(objBitmap); objGraphics.FillRectangle( Brushes.White, 0, 0, objBitmap.Width, objBitmap.Height); for (int i = 0; i < intSourceLength; i++) { //非法字符校验 if (AlphaBet.IndexOf(sourceCode[i]) == -1 || sourceCode[i] == '*' ) { objGraphics.DrawString( "Invalid Bar Code", SystemFonts.DefaultFont, Brushes .Red, leftMargin, topMargin); return objBitmap; } //编码 strEncode = string.Format("{0}0{1}" , strEncode, Code39[AlphaBet.IndexOf(sourceCode[i])]); } strEncode = string.Format("{0}0010010100" , strEncode); //添加结束码“*” int intEncodeLength = strEncode.Length; int intBarWidth; for (int i = 0; i < intEncodeLength; i++) //绘制 Code39 barcode { intBarWidth = strEncode[i] == '1' ? thickLength : narrowLength; objGraphics.FillRectangle(i % 2 == 0 ? Brushes.Black : Brushes .White, leftMargin, topMargin, intBarWidth, barCodeHeight); leftMargin += intBarWidth; } //绘制明码 Font barCodeTextFont = new Font( "黑体" , 10F); RectangleF rect = new RectangleF(2, barCodeHeight - 20, objBitmap.Width - 4, 20); objGraphics.FillRectangle( Brushes.White, rect); //文本对齐 objGraphics.DrawString(BarCodeText, barCodeTextFont, Brushes.Black, rect, sf); return objBitmap; }
Demo2
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Printing; using System.Threading; namespace BarCodeTest { public partial class Form1 : Form { string inputString = ""; code128 barcode = new code128(); Thread thre; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //label14.Location = new Point((panel1.Width - label14.Width) / 2, 92); /* label6.Font = new Font("宋体", 12); label8.Font = new Font("宋体", 12); label9.Font = new Font("宋体", 12); label11.Font = new Font("宋体", 12); label12.Font = new Font("宋体", 12); label13.Font = new Font("宋体", 12); label14.Font = new Font("宋体", 12); label10.Font = new Font("宋体", 26, FontStyle.Bold); */ PaintEventArgs pe = new PaintEventArgs(panel1.CreateGraphics(), panel1.ClientRectangle); DrawLine(pe); } public void DrawLine(PaintEventArgs e) { /* //画边框 Rectangle rc = e.ClipRectangle; rc.Width = rc.Width - 1; rc.Height = rc.Height - 1; e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Red)), rc); */ barcode.width = Convert.ToSingle(Mwidth.Text); Graphics gh = e.Graphics; if (dataToEncode.Text != "") { inputString = barcode.getCodeB(dataToEncode.Text); //drawCodePic(); //把之前显示的用白色覆盖掉 //gh.DrawRectangle(new Pen(Color.Black), new Rectangle(new Point(0, 0), new Size(413, 40))); gh.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(1, 70), new Size(411, 38))); Brush br = new SolidBrush(Color.Black); Pen p = new Pen(br, barcode.width); Brush br1 = new SolidBrush(Color.White); Pen p1 = new Pen(br1, barcode.width); inputString = inputString.Trim(); float x = 10;//这里是距离left //这里想把条码置中,已经画好了,怎么移动位置呢? //先计算条码的width float w = 0; for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { w = w + barcode.width; } else { w = w + barcode.width; } } } x = (panel1.Width - (int)w) / 2; for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { //这里的2是距离top,30是条码高 gh.DrawLine(p, x, 70, x, 90); x = x + barcode.width; } else { gh.DrawLine(p1, x, 70, x, 90); x = x + barcode.width; } } } } if (textBox1.Text != "") { inputString = barcode.getCodeB(textBox1.Text); //drawCodePic2(); //把之前显示的用白色覆盖掉 //gh.DrawRectangle(new Pen(Color.Black), new Rectangle(new Point(0, 0), new Size(413, 40))); gh.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(200, 0), new Size(350, 50))); e.Graphics.DrawString("P/N :" + "102401", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 12, 8); e.Graphics.DrawString("单位:" + "EA", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 12, 26); e.Graphics.DrawString("库位:" + "CMA110GV", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 12, 44); e.Graphics.DrawString("6", new Font(new FontFamily("宋体"), 28, FontStyle.Bold), System.Drawing.Brushes.Black, 160, 12); e.Graphics.DrawString("数量:" + textBox1.Text, new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 196, 8); e.Graphics.DrawString("保质期:" + "12" + "月", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 196, 50); //画边框 gh.DrawRectangle(new Pen(new SolidBrush(Color.Black)), 306, 6, 90, 56); e.Graphics.DrawString("CML", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 340, 8); e.Graphics.DrawString("简单检查合格", new Font(new FontFamily("宋体"), 10), System.Drawing.Brushes.Black, 310, 28); e.Graphics.DrawString("IQC01", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 330, 44); e.Graphics.DrawString(dataToEncode.Text, new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, (panel1.Width - dataToEncode.Text.Length * 8) / 2, 92); e.Graphics.DrawString("描述:" + "LAMINATIONJIS C2552-50A800", new Font(new FontFamily("宋体"), 12), System.Drawing.Brushes.Black, 12, 110); Brush br = new SolidBrush(Color.Black); Pen p = new Pen(br, barcode.width); Brush br1 = new SolidBrush(Color.White); Pen p1 = new Pen(br1, barcode.width); inputString = inputString.Trim(); float x = 200;//这里是距离left for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { //这里的2是距离top,30是条码高 gh.DrawLine(p, x, 26, x, 46); x = x + barcode.width; } else { gh.DrawLine(p1, x, 26, x, 46); x = x + barcode.width; } } } gh.Dispose(); } } //预览 private void button3_Click(object sender, EventArgs e) { //保存为图片 Bitmap bmp = new Bitmap(panel1.Width, panel1.Height); panel1.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height)); bmp.Save(AppDomain.CurrentDomain.BaseDirectory + "1.png", System.Drawing.Imaging.ImageFormat.Jpeg); //预览 printPreviewDialog1.Document = printDocument1; printPreviewDialog1.WindowState = FormWindowState.Maximized; this.printPreviewDialog1.ShowDialog(); } private void button1_Click(object sender, EventArgs e) { PaintEventArgs pe = new PaintEventArgs(panel1.CreateGraphics(), panel1.ClientRectangle); DrawLine(pe); } private void panel1_Paint(object sender, PaintEventArgs e) { DrawLine(e); /* //其他什么地方都不写,就写这里也可以 //画边框 Rectangle rc = e.ClipRectangle; rc.Width = rc.Width - 1; rc.Height = rc.Height - 1; e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Red)), rc); label11.Text = "数量:" + textBox1.Text; barcode.width = Convert.ToSingle(Mwidth.Text); Graphics gh = e.Graphics; if (dataToEncode.Text != "") { inputString = barcode.getCodeB(dataToEncode.Text); //drawCodePic(); //把之前显示的用白色覆盖掉 //gh.DrawRectangle(new Pen(Color.Black), new Rectangle(new Point(0, 0), new Size(413, 40))); gh.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(1, 70), new Size(411, 38))); Brush br = new SolidBrush(Color.Black); Pen p = new Pen(br, barcode.width); Brush br1 = new SolidBrush(Color.White); Pen p1 = new Pen(br1, barcode.width); inputString = inputString.Trim(); float x = 10;//这里是距离left //这里想把条码置中,已经画好了,怎么移动位置呢? //先计算条码的width float w = 0; for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { w = w + barcode.width; } else { w = w + barcode.width; } } } x = (panel1.Width - (int)w) / 2; for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { //这里的2是距离top,30是条码高 gh.DrawLine(p, x, 70, x, 90); x = x + barcode.width; } else { gh.DrawLine(p1, x, 70, x, 90); x = x + barcode.width; } } } } if (textBox1.Text != "") { inputString = barcode.getCodeB(textBox1.Text); //drawCodePic2(); //把之前显示的用白色覆盖掉 //gh.DrawRectangle(new Pen(Color.Black), new Rectangle(new Point(0, 0), new Size(413, 40))); gh.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(1, 26), new Size(411, 38))); Brush br = new SolidBrush(Color.Black); Pen p = new Pen(br, barcode.width); Brush br1 = new SolidBrush(Color.White); Pen p1 = new Pen(br1, barcode.width); inputString = inputString.Trim(); float x = 214;//这里是距离left for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { //这里的2是距离top,30是条码高 gh.DrawLine(p, x, 26, x, 46); x = x + barcode.width; } else { gh.DrawLine(p1, x, 26, x, 46); x = x + barcode.width; } } } gh.Dispose(); } */ } public void drawCodePic2() { //把之前显示的用白色覆盖掉 Graphics gh = panel1.CreateGraphics();//这种写法条码预览或打印都出不来,NND //gh.DrawRectangle(new Pen(Color.Black), new Rectangle(new Point(0, 0), new Size(413, 40))); gh.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(1, 26), new Size(411, 38))); Brush br = new SolidBrush(Color.Black); Pen p = new Pen(br, barcode.width); Brush br1 = new SolidBrush(Color.White); Pen p1 = new Pen(br1, barcode.width); Graphics graphics = panel1.CreateGraphics();//这种写法条码预览或打印都出不来,NND inputString = inputString.Trim(); float x = 214;//这里是距离left for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { //这里的2是距离top,30是条码高 graphics.DrawLine(p, x, 26, x, 46); x = x + barcode.width; } else { graphics.DrawLine(p1, x, 26, x, 46); x = x + barcode.width; } } } graphics.Dispose(); } public void drawCodePic() { //把之前显示的用白色覆盖掉 Graphics gh = panel1.CreateGraphics();//这种写法条码预览或打印都出不来,NND //gh.DrawRectangle(new Pen(Color.Black), new Rectangle(new Point(0, 0), new Size(413, 40))); gh.FillRectangle(new SolidBrush(Color.White), new Rectangle(new Point(1, 70), new Size(411, 38))); Brush br = new SolidBrush(Color.Black); Pen p = new Pen(br, barcode.width); Brush br1 = new SolidBrush(Color.White); Pen p1 = new Pen(br1, barcode.width); Graphics graphics = panel1.CreateGraphics(); inputString = inputString.Trim(); float x = 10;//这里是距离left //这里想把条码置中,已经画好了,怎么移动位置呢? //先计算条码的width float w = 0; for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { w = w + barcode.width; } else { w = w + barcode.width; } } } x = (panel1.Width - (int)w) / 2; for (int i = 0; i < inputString.Length; i++) { for (int j = 0; j < Convert.ToInt32(inputString[i].ToString()); j++) { if (i % 2 == 0) { //这里的2是距离top,30是条码高 graphics.DrawLine(p, x, 70, x, 90); x = x + barcode.width; } else { graphics.DrawLine(p1, x, 70, x, 90); x = x + barcode.width; } } } graphics.Dispose(); } private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //打印内容 为panel1 Bitmap _NewBitmap = new Bitmap(panel1.Width, panel1.Height); panel1.DrawToBitmap(_NewBitmap, new Rectangle(0, 0, _NewBitmap.Width, _NewBitmap.Height)); e.Graphics.DrawImage(_NewBitmap, 0, 0, _NewBitmap.Width, _NewBitmap.Height); } private void button2_Click(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; //打印次数 printDocument1.PrinterSettings.Copies = 1;// Convert.ToInt16(txt_print.Text.Trim()); this.printDocument1.Print(); /* //换成多线程方式 if (thre == null) { thre = new Thread(this.printDocument1.Print); thre.Start(); } if (thre.ThreadState == ThreadState.Stopped) { thre.Abort(); GC.Collect(); thre = new Thread(this.printDocument1.Print); thre.Start(); } */ } private void button4_Click(object sender, EventArgs e) { this.pageSetupDialog1.ShowDialog(); } } }
DEMO3 相关类库
请参考类库 ZXing.Net , 该类库也能实现二维码的生成,使用起来较为方便,而且开源。
jQuery二维条形码插件 My QR Code
jQuery条形码插件 Barcode
jQuery条形码插件 jQuery Barcode
jQuery生成二维条形码 jquery.qrcode.js
Java条形码解决方案 Barbecue
Java二维条形码开发包 QR Code Library
条形码生成和识别库 Aspose.BarCode
.NET条形码开发包 NetBarcodeWriter
C语言二维条形码解析库 libqrencode
条形码扫描软件 Zebra barcode reader
参考文章
百度百科
纯C#代码生成条码
共有43款 条形码/二维码开源软件