概念
一維條碼即指條碼條和空的排列規則,常用的一維碼的碼制包括: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的實現

/// <summary> /// 生成條碼 Bitmap,自定義條碼高度,自定義文字對齊樣式 /// </summary> /// <param name="sourceCode"></param> /// <param name="barCodeHeight"></param> /// <param name="sf"></param> /// <returns></returns> 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生成二維條形碼 jquery.qrcode.js