• 玩儿条形码之条码生成


    最近接到一项目,其中带了些条码的应用,本来想找专门做条码的伙伴来做,没想到找来的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


  • 相关阅读:
    Components controls 区别
    lazarus 2016 2月18 4:22:35 支持android开发了, 既ios,linux,macosx,window,web 后 囊括一切啦。 哈哈
    Delphi MlSkin V1.1 发布啦! 它能让你的程序拥有像QQ一样多彩炫丽的外观!
    Tclientdataset的CloneCursor问题 clientdataset 复制 赋值 的问题
    字符串 映射 函数
    字符串 映射相应的 函数 字符串驱动技术—— MethodAddress , MethodName , ObjectInvoke
    一分钟了解nohup和&的功效
    Linux shell标准输入,标准输出,错误输出
    (一)shell编程之执行脚本的三种方式
    Shell:执行脚本文件方法
  • 原文地址:https://www.cnblogs.com/jeet/p/813373.html
Copyright © 2020-2023  润新知