• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

Jeet

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

玩儿条形码之条码生成

最近接到一项目,其中带了些条码的应用,本来想找专门做条码的伙伴来做,没想到找来的Partner报的价都N高,同时还不同意提供源代码。没法之下,只能自己做,项目用的是CASIO IT-500数据采集器、ZEBRA 888-TT桌面标签打印机,因为客户的硬件是在另外的供应商处采购,软件开发的时候还不能交货,以前没做过相关的应用,导致走了不少弯路。Jeet也曾经在CSDN上发过一些贴子,没想到条码的圈子里还是比较封闭,没有什么人愿意把一些相关的技术公开来。刚好今天把事情弄完来,顺便把这段时间的工作做个记录,也把一些找到的源码公布出来,同时也希望能对象我一样条形码外行的朋友有帮助。
 
 关于条码的生成方法,Jeet知道的有三种方法:
一、是使用现成的控件,网上可以找到相关的厂商,价格从1K到3K不等,可以支持Winform和Webform的应用,Web上基本都是生成对应的图形输出;

二、是使用条码字体,把要显示的条形码用条码字体显示出来,具体可以参考Codeproject上这个示例(C# Barcode Generator WebService),这个示例是WebService,要在Webform上使用只需要把结果输出成图形就可以,不过用Code3 free of 9打印出来的条码我的数据采集器并不能很好的读取,所以最后也放弃了这种做法。

三、自己编程输出条码,其实条码只是按不同的符号粗细画出来,只要知道规律就可以把不同编码规则的条码画出来。在Web上应用可以重写HttpHandler,把结果输入到图形上,加上相应的参数,就可以按自己的要求动态生成条码了。在网上也有生成Code39编码的资源,ASP.NET下生成的条形码,经过试验扫描枪可以很好的读到条码上的信息。
      但如果要使用例如Code128就没有办法了,还是得自己解决了。
  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4
  5using System.Data;
  6using System.Drawing;
  7using System.Drawing.Drawing2D;
  8
  9namespace LabelKit
 10{
 11    class BarcodeGenerator
 12    {
 13        public BarcodeGenerator()
 14        {
 15            width = 300;
 16            height = 60;
 17            humanReadable = true;
 18            fontSize = 12;
 19            fontName = "Courier New";
 20            centered = false;
 21        }

 22        
 23        
 24        private int height;
 25        private bool humanReadable;
 26        private int width;
 27        private string fontName;
 28        private int fontSize;
 29        private bool centered;
 30
 31        private static string[] left_UPCA = new string[] {"0001101", "0011001", "0010011", "0111101", "0100011", 
 32                                        "0110001", "0101111", "0111011" , "0110111", "0001011"}
;
 33        private static string[] right_UPCA = new string[] {"1110010", "1100110", "1101100", "1000010", "1011100",
 34                                        "1001110", "1010000", "1000100", "1001000", "1110100"}
; //1s compliment of left odd
 35
 36        private static string[] both_2of5 = new string[] { "NNWWN", "WNNNW", "NWNNW", "WWNNN", "NNWNW", "WNWNN",
 37                                        "NWWNN", "NNNWW", "WNNWN", "NWNWN" }
;
 38
 39        private static char[] Code128ComboAB = new char[] { 
 40            ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*',
 41            '+', ',', '-', '.', '/', '0',  '1', '2', '3', '4', '5',
 42            '6', '7', '8', '9', ':', ';',  '<', '=', '>', '?', '@',
 43            'A', 'B', 'C', 'D', 'E', 'F',  'G', 'H', 'I', 'J', 'K',
 44            'L', 'M', 'N', 'O', 'P', 'Q',  'R', 'S', 'T', 'U', 'V',
 45            'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_'
 46        }
;
 47
 48        private static char[] Code128B = new char[] { 
 49            '`', 'a', 'b',  'c', 'd', 'e', 'f',  'g', 'h', 'i', 'j',
 50            'k', 'l', 'm',  'n', 'o', 'p', 'q',  'r', 's', 't', 'u',
 51            'v', 'w', 'x',  'y', 'z', '{', '|',  '}', '~'
 52        }
;
 53
 54        private static string[] Code128Encoding = new string[] {
 55            "11011001100", "11001101100", "11001100110", "10010011000", "10010001100", "10001001100", "10011001000", 
 56            "10011000100", "10001100100", "11001001000", "11001000100", "11000100100", "10110011100", "10011011100",
 57            "10011001110", "10111001100", "10011101100", "10011100110", "11001110010", "11001011100", "11001001110",
 58            "11011100100", "11001110100", "11101101110", "11101001100", "11100101100", "11100100110", "11101100100",
 59            "11100110100", "11100110010", "11011011000", "11011000110", "11000110110", "10100011000", "10001011000",
 60            "10001000110", "10110001000", "10001101000", "10001100010", "11010001000", "11000101000", "11000100010",
 61            "10110111000", "10110001110", "10001101110", "10111011000", "10111000110", "10001110110", "11101110110",
 62            "11010001110", "11000101110", "11011101000", "11011100010", "11011101110", "11101011000", "11101000110",
 63            "11100010110", "11101101000", "11101100010", "11100011010", "11101111010", "11001000010", "11110001010",
 64            "10100110000", "10100001100", "10010110000", "10010000110", "10000101100", "10000100110", "10110010000",
 65            "10110000100", "10011010000", "10011000010", "10000110100", "10000110010", "11000010010", "11001010000",
 66            "11110111010", "11000010100", "10001111010", "10100111100", "10010111100", "10010011110", "10111100100",
 67            "10011110100", "10011110010", "11110100100", "11110010100", "11110010010", "11011011110", "11011110110",
 68            "11110110110", "10101111000", "10100011110", "10001011110", "10111101000", "10111100010", "11110101000",
 69            "11110100010", "10111011110", "10111101110", "11101011110", "11110101110", "11010000100", "11010010000",
 70            "11010011100"
 71        }
;
 72        
 73        private static string Code128Stop   = "11000111010";
 74        private enum Code128ChangeModes { CodeA = 101, CodeB = 100, CodeC = 99 };
 75        private enum Code128StartModes { CodeUnset = 0, CodeA = 103, CodeB = 104, CodeC = 105};
 76        private enum Code128Modes { CodeUnset = 0, CodeA = 1, CodeB = 2, CodeC = 3 };
 77
 78        Public Properties#region Public Properties
 79        public bool Centered
 80        {
 81            get { return centered; }
 82            set { centered = value; }
 83        }

 84
 85        public string FontName
 86        {
 87            get { return fontName; }
 88            set { fontName = value; }
 89        }

 90
 91        public int Width
 92        {
 93            get { return width; }
 94            set { width = value; }
 95        }

 96        public int Height
 97        {
 98            get { return height; }
 99            set { height = value; }
100        }

101        public bool HumanReadable
102        {
103            get { return humanReadable; }
104            set { humanReadable = value; }
105        }

106        public int FontSize
107        {
108            get { return fontSize; }
109            set { fontSize = value; }
110        }

111        #endregion

112
113        public string DrawUPCA(Graphics g, string code, int x, int y)
114        {
115            code = code.Trim();
116            try
117            {
118                Int64.Parse(code); // this ensures that the string is a number
119            }

120            catch
121            {
122                return "Code is not valid for a UPCA barcode: " + code;
123            }

124            while(code.Length < 11) // 11 is the length for upc-a barcodes;
125                code = "0" + code;
126            code = code.Substring(0, 11);
127            code = code.Trim() + CheckDigitUPCA(code);
128
129            string barbit = "101"; //START
130            for(int i = 0; i < 6; i++) // first 6 Digits
131            {
132                int digit = Int32.Parse(code.Substring(i, 1));
133                barbit += left_UPCA[digit]; 
134            }

135            barbit += "01010"; //CENTER
136            for(int i = 6; i < 12; i++) // last 5 Digits + Check Digit
137            {
138                int digit = Int32.Parse(code.Substring(i, 1));
139                barbit += right_UPCA[digit];
140            }

141            barbit += "101"; //END
142
143            Font font = new Font(fontName, fontSize, FontStyle.Bold);
144            SizeF size = g.MeasureString(code.Substring(0, 1), font);
145
146            int padding = 0;
147            if(humanReadable)
148                padding = (int)size.Width + 2;
149
150            int barwidth = (int) Math.Floor((double) (width - 2 * padding) / barbit.Length);
151            if(barwidth <= 0)
152                barwidth = 1;
153            if(centered)
154            {
155                x = (int)x - (((barwidth * 95) + 2 * padding) / 2);
156            }

157            int start = x + padding;
158            for(int i = 1; i <= barbit.Length; i++)
159            {
160                string bit = barbit.Substring(i-1, 1);
161                if (bit == "0")
162                {
163                    g.FillRectangle(Brushes.White, start, y, barwidth, height);                  
164                }

165                else // bit == "1"
166                {
167                    g.FillRectangle(Brushes.Black, start, y, barwidth, height);
168                }

169                start += barwidth;
170            }

171            g.FillRectangle(Brushes.White, x, y + height - 8, width, 8);
172            if(humanReadable)
173            {
174                g.FillRectangle(Brushes.White, x + padding + ((barwidth) * 10), y + height - 20, barwidth * 36, 20);
175                g.FillRectangle(Brushes.White, x + padding + ((barwidth) * 49), y + height - 20, barwidth * 36, 20);
176
177                g.DrawString(code.Substring(0, 1), font, Brushes.Black, x + 2, y + height - font.Height);
178                int spacing = (int)((barwidth * 36) / 5);
179                
180                for(int i = 1; i < 6; i++)
181                {
182                    g.DrawString(code.Substring(i, 1), font, Brushes.Black, x + (barwidth * 10) + padding + (spacing * (i - 1)), y + height - font.Height);
183                }

184                for(int i = 6; i < 11; i++)
185                {
186                    g.DrawString(code.Substring(i, 1), font, Brushes.Black, x + (barwidth * 49) + padding + (spacing * (i - 6)), y + height - font.Height);
187                }

188                g.DrawString(code.Substring(11, 1), font, Brushes.Black, x + ((barwidth) * 95) + padding, y + height - font.Height);
189            }

190            return "";
191        }

192
193        private string CheckDigitUPCA(string code)
194        {
195            int odd = 0;
196            int even = 0;
197            
198            for(int i = 0; i < code.Length; i += 2)
199                odd += Int32.Parse(code.Substring(i, 1));
200
201            for(int i = 1; i < code.Length; i += 2)
202                even += Int32.Parse(code.Substring(i, 1));
203
204            int check = (10 - ((odd * 3) + even) % 10) % 10;
205            return check.ToString().Trim();
206        }

207
208        public string DrawInterleaved2of5(Graphics g, string code, int x, int y)
209        {
210            return DrawInterleaved2of5(g, code, x, y, false);
211        }

212
213        public string DrawInterleaved2of5(Graphics g, string code, int x, int y, bool checksum)
214        {
215            code = code.Trim();
216            try
217            {
218                Int64.Parse(code); // this ensures that the string is a number
219            }

220            catch
221            {
222                return "Code is not valid for an Interleaved 2 of 5 barcode: " + code;
223            }

224
225            if((checksum && IsEven(code.Length)) || (!checksum && IsOdd(code.Length))) // check to make sure that the number of digits is even
226                code = "0" + code;
227
228            if(checksum)
229                code = code + CheckDigitInterleaved(code);
230
231            string barbit = "1010"; //START
232
233            for(int i = 0; i < code.Length; i++) 
234            {
235                int digitb = Int32.Parse(code.Substring(i, 1));
236                string black = both_2of5[digitb];
237                i++;
238                int digitw = Int32.Parse(code.Substring(i, 1));
239                string white = both_2of5[digitw];
240                for(int j = 0; j < 5; j++) // 5 is the width of all interleaved symbologies
241                {
242                    if(black[j] == 'W')
243                        barbit += "11";
244                    else
245                        barbit += "1";
246                    if(white[j] == 'W')
247                        barbit += "00";
248                    else
249                        barbit += "0";
250                }

251            }
           
252            barbit += "1101"; //END
253
254            Font font = new Font(fontName, fontSize, FontStyle.Bold);
255            SizeF size = g.MeasureString(code.Substring(0, 1), font);
256
257            int padding = 0;
258            if(humanReadable)
259                padding = (int)size.Width + 2;
260
261            int barwidth = (int)Math.Floor((double)(width - 2 * padding) / barbit.Length);
262            if(barwidth <= 0)
263                barwidth = 1;
264            if(centered)
265            {
266                x = (int)x - (((barwidth * barbit.Length) + 2 * padding) / 2);
267            }

268            int start = x + padding;
269            for(int i = 1; i <= barbit.Length; i++)
270            {
271                string bit = barbit.Substring(i - 1, 1);
272                if(bit == "0")
273                {
274                    g.FillRectangle(Brushes.White, start, y, barwidth, height);
275                }

276                else // bit == "1"
277                {
278                    g.FillRectangle(Brushes.Black, start, y, barwidth, height);
279                }

280                start += barwidth;
281            }

282
283            if(humanReadable)
284            {
285                int spacing = (int)((barwidth * 36) / 5);
286                for(int i = 0; i < code.Length; i++)
287                {
288                    g.DrawString(code.Substring(i, 1), font, Brushes.Black, x + (barwidth * 10) + padding + (spacing * (i - 1)), y + height + 4);
289                }

290            }

291            return "";
292        }

293
294        private string CheckDigitInterleaved(string code)
295        {
296            int odd = 0;
297            int even = 0;
298
299            for(int i = 0; i < code.Length; i += 2)
300                even += Int32.Parse(code.Substring(i, 1));
301
302            for(int i = 1; i < code.Length; i += 2)
303                odd += Int32.Parse(code.Substring(i, 1));
304
305            int check = (10 - ((odd * 3) + even) % 10) % 10;
306            return check.ToString().Trim();
307        }

308
309        public string DrawCode128(Graphics g, string code, int x, int y)
310        {
311            if(code.Length == 0)
312                return "Invalid code for Code128 barcode";
313
314            List<int> encoded = new List<int>();
315            Code128Modes currentMode = Code128Modes.CodeUnset;
316            
317            for(int i = 0; i < code.Length; i++)
318            {
319                if(IsNumber(code[i]) && i + 1 < code.Length && IsNumber(code[i + 1]))
320                {
321                    if(currentMode != Code128Modes.CodeC)
322                    {
323                        if(currentMode == Code128Modes.CodeUnset)
324                            encoded.Add((int) Code128StartModes.CodeC);
325                        else
326                            encoded.Add((int) Code128ChangeModes.CodeC);
327                        currentMode = Code128Modes.CodeC;
328                    }

329                    encoded.Add(Int32.Parse(code.Substring(i, 2)));
330                    i++;
331                }

332                else
333                {
334                    if(currentMode != Code128Modes.CodeB)
335                    {
336                        if(currentMode == Code128Modes.CodeUnset)
337                            encoded.Add((int) Code128StartModes.CodeB);
338                        else
339                            encoded.Add((int) Code128ChangeModes.CodeB);
340                        currentMode = Code128Modes.CodeB;
341                    }

342                    encoded.Add(EncodeCodeB(code[i]));
343                }

344            }

345            encoded.Add(CheckDigitCode128(encoded));
346
347            string barbit = "";
348            for(int i = 0; i < encoded.Count; i++)
349            {
350                barbit += Code128Encoding[encoded[i]];
351            }

352            barbit += Code128Stop;
353            barbit += "11"; // end code
354
355            
356
357            int barwidth = (int)Math.Floor((double)(width - 2) / (barbit.Length + 20)); // add 20 for padding
358            if(barwidth <= 0)
359                barwidth = 1;
360
361            int padding = barwidth * 10;
362            if(centered)
363            {
364                x = (int)x - (((barwidth * barbit.Length) + (padding * 2)) / 2);
365            }

366
367            int start = x + padding;
368            for(int i = 1; i <= barbit.Length; i++)
369            {
370                string bit = barbit.Substring(i - 1, 1);
371                if(bit == "0")
372                {
373                    g.FillRectangle(Brushes.White, start, y, barwidth, height);
374                }

375                else // bit == "1"
376                {
377                    g.FillRectangle(Brushes.Black, start, y, barwidth, height);
378                }

379                start += barwidth;
380            }

381
382            if(humanReadable)
383            {
384                Font font = new Font(fontName, fontSize, FontStyle.Bold);
385                SizeF size = g.MeasureString(code, font);
386                x = x + (int)((barwidth * barbit.Length) + (padding * 2)) / 2;
387                x -= (int) size.Width / 2;
388                g.DrawString(code, font, Brushes.Black, x, y + height + 4);
389               
390            }

391            return "";
392        }

393
394        private int CheckDigitCode128(List<int> codes)
395        {
396            int check = codes[0];
397            for(int i = 1; i < codes.Count; i++)
398            {
399                check = check + (codes[i] * i);
400            }

401            return check % 103;
402        }

403
404
405        private bool IsNumber(char value)
406        {
407            return '0' == value || '1' == value || '2' == value || '3' == value ||
408                   '4' == value || '5' == value || '6' == value || '7' == value ||
409                   '8' == value || '9' == value;              
410        }

411
412        private bool IsEven(int value)
413        {
414            return ((value & 1) == 0);
415        }

416
417        private bool IsOdd(int value)
418        {
419            return ((value & 1) == 1);
420        }

421
422        private int EncodeCodeB(char value)
423        {
424            for(int i = 0; i < Code128ComboAB.Length; i++)
425            {
426                if(Code128ComboAB[i] == value)
427                    return i;
428            }

429            for(int i = 0; i < Code128B.Length; i++)
430            {
431                if(Code128B[i] == value)
432                    return i + Code128ComboAB.Length;
433            }

434            throw new Exception("Invalid Character");
435        }

436    }

437}

438


posted on 2007-07-11 01:15  Jeet  阅读(2839)  评论(7)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3