玩儿条形码之条码生成

最近接到一项目,其中带了些条码的应用,本来想找专门做条码的伙伴来做,没想到找来的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
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(011);
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(01), 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-11);
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 * 3620);
175                g.FillRectangle(Brushes.White, x + padding + ((barwidth) * 49), y + height - 20, barwidth * 3620);
176
177                g.DrawString(code.Substring(01), 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(111), 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(01), 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 - 11);
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 - 11);
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


原文地址:https://www.cnblogs.com/jeet/p/813373.html