专业编程基础技术教程

网站首页 > 基础教程 正文

手撸一个C#代码生成Code128码

ccvgpt 2024-08-11 14:58:58 基础教程 11 ℃

以前做工厂项目,用到条码工具,从网上找了个开源的,后来发现兼容性并不好,于是自己网上搜搜文章,就开始动手自己干。关于128码的原理介绍可以看看这个:

CODE 128和GS1-128|条码基本知识|学习条码规格和读取技术的站点“条码讲座”|基恩士

手撸一个C#代码生成Code128码

其实条形码的生成,都是差不多的思路,每个字符都是由几个不同宽窄的条形符号代表的,多个字符从而有更多的条形符号组合在一起形成1个条形码。字符串越长,生成的条形码就越长。

代码思路也很简单:

1、构建code128,字符(字母、数字、特殊符号)对应的条码描述,初始化条码生成的一些自定义设置

2、输入字符,根据每给字符根据字典映射对应的条码描述符,根据描述符依次绘制条形码。

3、输出图片,就结束了。

废话不多说,上代码:


## 辅助代码

    public class BarCode128Settings
    {
        public float NarrowWidth { get; set; } = 2f;
        public Color BackColor { get; set; } = Color.White;
        public Color BarColor { get; set; } = Color.Black;
        public float Height { get; set; } = 60f;

        /// <summary>
        /// 上据顶部的边距/条码与文本中之间的边距/文本或条码据下部的边距
        /// </summary>
        public float Gutter { get; set; } = 5f;

        public int Width { get; set; }
        public bool DisplayText { get; set; } = true;
        public Font TextFont { get; set; } = new Font("宋体", 12);
    }


    public interface IBarCodeEntity
    {

    }
    public abstract class AbsBarCodeEntity
    {
        public byte Id { get; set; }
        public string BandCode { get; set; }
    }


    public class BarCode128Entity: AbsBarCodeEntity
    {
        public BarCode128Entity()
        {

        }
        public BarCode128Entity(byte id, string codeA, string codeB, string codeC, string bandCode)
        {
            Id = id;
            CodeA = codeA;
            CodeB = codeB;
            CodeC = codeC;
            BandCode = bandCode;
        }
         
        public string CodeA { get; set; }
        public string CodeB { get; set; }
        public string CodeC { get; set; } 
    }


## 代码主题

  /// <summary>
    ///  code128条码生成器
    /// </summary>
    public class BarCodeCreator
    {
        public const byte Code128StartA = 103;
        public const byte Code128StartB = 104;
        public const byte Code128StartC = 105;
        public const string EndBandCode = "2331112";
        /// <summary>
        /// CodeA、CodeB转CodeC
        /// </summary>
        public const byte CodeC = 99;
        /// <summary>
        /// CodeA、CodeC转CodeB
        /// </summary>
        public const byte CodeB = 100;
        /// <summary>
        /// CodeB、CodeC转CodeA
        /// </summary>
        public const byte CodeA = 101;

        private List<BarCode128Entity> _code128Tables = new List<BarCode128Entity>(107);
        private BarCode128Settings _settings;


        private void AddBarCode128Entity(byte id, string codeA, string codeB, string codeC, string bandCode)
        {
            _code128Tables.Add(new BarCode128Entity(id, codeA, codeB, codeC, bandCode));
        }

        public BarCodeCreator(BarCode128Settings settings)
        {
            _settings = settings;

            if (_settings.NarrowWidth < 1) throw new FormatException(#34;{nameof(_settings.NarrowWidth)}值不能小于1");


            #region 构建数据表
            AddBarCode128Entity(0, " ", " ", "00", "212222");
            AddBarCode128Entity(1, "!", "!", "01", "222122");
            AddBarCode128Entity(2, "\"", "\"", "02", "222221");
            AddBarCode128Entity(3, "#", "#", "03", "121223");
            AddBarCode128Entity(4, "#34;, "#34;, "04", "121322");
            AddBarCode128Entity(5, "%", "%", "05", "131222");
            AddBarCode128Entity(6, "&", "&", "06", "122213");
            AddBarCode128Entity(7, "'", "'", "07", "122312");
            AddBarCode128Entity(8, "(", "(", "08", "132212");
            AddBarCode128Entity(9, ")", ")", "09", "221213");
            AddBarCode128Entity(10, "*", "*", "10", "221312");
            AddBarCode128Entity(11, "+", "+", "11", "231212");
            AddBarCode128Entity(12, ",", ",", "12", "112232");
            AddBarCode128Entity(13, "-", "-", "13", "122132");
            AddBarCode128Entity(14, ".", ".", "14", "122231");
            AddBarCode128Entity(15, "/", "/", "15", "113222");
            AddBarCode128Entity(16, "0", "0", "16", "123122");
            AddBarCode128Entity(17, "1", "1", "17", "123221");
            AddBarCode128Entity(18, "2", "2", "18", "223211");
            AddBarCode128Entity(19, "3", "3", "19", "221132");
            AddBarCode128Entity(20, "4", "4", "20", "221231");
            AddBarCode128Entity(21, "5", "5", "21", "213212");
            AddBarCode128Entity(22, "6", "6", "22", "223112");
            AddBarCode128Entity(23, "7", "7", "23", "312131");
            AddBarCode128Entity(24, "8", "8", "24", "311222");
            AddBarCode128Entity(25, "9", "9", "25", "321122");
            AddBarCode128Entity(26, ":", ":", "26", "321221");
            AddBarCode128Entity(27, ";", ";", "27", "312212");
            AddBarCode128Entity(28, "<", "<", "28", "322112");
            AddBarCode128Entity(29, "=", "=", "29", "322211");
            AddBarCode128Entity(30, ">", ">", "30", "212123");
            AddBarCode128Entity(31, "?", "?", "31", "212321");
            AddBarCode128Entity(32, "@", "@", "32", "232121");
            AddBarCode128Entity(33, "A", "A", "33", "111323");
            AddBarCode128Entity(34, "B", "B", "34", "131123");
            AddBarCode128Entity(35, "C", "C", "35", "131321");
            AddBarCode128Entity(36, "D", "D", "36", "112313");
            AddBarCode128Entity(37, "E", "E", "37", "132113");
            AddBarCode128Entity(38, "F", "F", "38", "132311");
            AddBarCode128Entity(39, "G", "G", "39", "211313");
            AddBarCode128Entity(40, "H", "H", "40", "231113");
            AddBarCode128Entity(41, "I", "I", "41", "231311");
            AddBarCode128Entity(42, "J", "J", "42", "112133");
            AddBarCode128Entity(43, "K", "K", "43", "112331");
            AddBarCode128Entity(44, "L", "L", "44", "132131");
            AddBarCode128Entity(45, "M", "M", "45", "113123");
            AddBarCode128Entity(46, "N", "N", "46", "113321");
            AddBarCode128Entity(47, "O", "O", "47", "133121");
            AddBarCode128Entity(48, "P", "P", "48", "313121");
            AddBarCode128Entity(49, "Q", "Q", "49", "211331");
            AddBarCode128Entity(50, "R", "R", "50", "231131");
            AddBarCode128Entity(51, "S", "S", "51", "213113");
            AddBarCode128Entity(52, "T", "T", "52", "213311");
            AddBarCode128Entity(53, "U", "U", "53", "213131");
            AddBarCode128Entity(54, "V", "V", "54", "311123");
            AddBarCode128Entity(55, "W", "W", "55", "311321");
            AddBarCode128Entity(56, "X", "X", "56", "331121");
            AddBarCode128Entity(57, "Y", "Y", "57", "312113");
            AddBarCode128Entity(58, "Z", "Z", "58", "312311");
            AddBarCode128Entity(59, "[", "[", "59", "332111");
            AddBarCode128Entity(60, "\\", "\\", "60", "314111");
            AddBarCode128Entity(61, "]", "]", "61", "221411");
            AddBarCode128Entity(62, "^", "^", "62", "431111");
            AddBarCode128Entity(63, "_", "_", "63", "111224");
            AddBarCode128Entity(64, "NUL", "`", "64", "111422");
            AddBarCode128Entity(65, "SOH", "a", "65", "121124");
            AddBarCode128Entity(66, "STX", "b", "66", "121421");
            AddBarCode128Entity(67, "ETX", "c", "67", "141122");
            AddBarCode128Entity(68, "EOT", "d", "68", "141221");
            AddBarCode128Entity(69, "ENQ", "e", "69", "112214");
            AddBarCode128Entity(70, "ACK", "f", "70", "112412");
            AddBarCode128Entity(71, "BEL", "g", "71", "122114");
            AddBarCode128Entity(72, "BS", "h", "72", "122411");
            AddBarCode128Entity(73, "HT", "i", "73", "142112");
            AddBarCode128Entity(74, "LF", "j", "74", "142211");
            AddBarCode128Entity(75, "VT", "k", "75", "241211");
            AddBarCode128Entity(76, "FF", "l", "76", "221114");
            AddBarCode128Entity(77, "CR", "m", "77", "413111");
            AddBarCode128Entity(78, "SO", "n", "78", "241112");
            AddBarCode128Entity(79, "SI", "o", "79", "134111");
            AddBarCode128Entity(80, "DLE", "p", "80", "111242");
            AddBarCode128Entity(81, "DC1", "q", "81", "121142");
            AddBarCode128Entity(82, "DC2", "r", "82", "121241");
            AddBarCode128Entity(83, "DC3", "s", "83", "114212");
            AddBarCode128Entity(84, "DC4", "t", "84", "124112");
            AddBarCode128Entity(85, "NAK", "u", "85", "124211");
            AddBarCode128Entity(86, "SYN", "v", "86", "411212");
            AddBarCode128Entity(87, "ETB", "w", "87", "421112");
            AddBarCode128Entity(88, "CAN", "x", "88", "421211");
            AddBarCode128Entity(89, "EM", "y", "89", "212141");
            AddBarCode128Entity(90, "SUB", "z", "90", "214121");
            AddBarCode128Entity(91, "ESC", "{", "91", "412121");
            AddBarCode128Entity(92, "FS", "|", "92", "111143");
            AddBarCode128Entity(93, "GS", "}", "93", "111341");
            AddBarCode128Entity(94, "RS", "~", "94", "131141");
            AddBarCode128Entity(95, "US", "DEL", "95", "114113");
            AddBarCode128Entity(96, "FNC3", "FNC3", "96", "114311");
            AddBarCode128Entity(97, "FNC2", "FNC2", "97", "411113");
            AddBarCode128Entity(98, "SHIFT", "SHIFT", "98", "411311");
            AddBarCode128Entity(99, "CODEC", "CODEC", "99", "113141");
            AddBarCode128Entity(100, "CODEB", "FNC4", "CODEB", "114131");
            AddBarCode128Entity(101, "FNC4", "CODEA", "CODEA", "311141");
            AddBarCode128Entity(102, "FNC1", "FNC1", "FNC1", "411131");
            AddBarCode128Entity(103, "StartA", "StartA", "StartA", "211412");
            AddBarCode128Entity(104, "StartB", "StartB", "StartB", "211214");
            AddBarCode128Entity(105, "StartC", "StartC", "StartC", "211232");
            AddBarCode128Entity(106, "Stop", "Stop", "Stop", "2331112");
            #endregion
        }

        /// <summary>
        /// 生成128条码
        /// </summary>
        /// <param name="barCodeText">条码文本数据</param>
        /// <param name="barCodeEncode">条码编码方式</param>      
        /// <returns>图形</returns>
        public Bitmap GeneratorCodeImage(string barCodeText, BarCodeEncode barCodeEncode)
        {
            string displayText = barCodeText + "";  //可视条码
            StringBuilder bandCode = new StringBuilder();                 //转换成bar(b)/space(s)的代码。如:212423 表示:bbsbbssssbbsss

            IList<int> displayTextIds = new List<int>();       //可视条码对应的id值集合
            int startCode = Code128StartB;                     //起始位 
            var regNum = new Regex("\\d{2}");

            switch (barCodeEncode)
            {
                case BarCodeEncode.Code128Auto:
                    {

                        var currentEncode = BarCodeEncode.Code128C; //当前编码类型
                        startCode = Code128StartC;                  //起始码值
                        if (barCodeText.Length < 2 || !regNum.IsMatch(barCodeText.Substring(0, 2)))
                        {
                            currentEncode = BarCodeEncode.Code128B;
                            startCode = Code128StartB;
                        }

                        while (barCodeText.Length != 0)
                        {
                            if (currentEncode == BarCodeEncode.Code128C)
                            {
                                if (barCodeText.Length >= 2)
                                {
                                    //还有很多,且当前2位是数字 
                                    var numbers = barCodeText.Substring(0, 2);
                                    if (regNum.IsMatch(numbers))
                                    {
                                        var entity = FindEntity(currentEncode, numbers);
                                        displayTextIds.Add(entity.Id);
                                        bandCode.Append(entity.BandCode);

                                        barCodeText = barCodeText.Remove(0, 2);
                                    }
                                    else //当前2位不是数字 转CodeB
                                    {
                                        currentEncode = BarCodeEncode.Code128B;
                                        var entity = FindEntity(CodeB);
                                        displayTextIds.Add(entity.Id);
                                        bandCode.Append(entity.BandCode);
                                    }
                                }
                                else
                                {
                                    //最后1个字符 转CodeB
                                    currentEncode = BarCodeEncode.Code128B;
                                    var entity = FindEntity(CodeB);
                                    displayTextIds.Add(entity.Id);
                                    bandCode.Append(entity.BandCode);

                                    //最后1位处理
                                    entity = FindEntityThrowNull(x => x.CodeB == barCodeText.Substring(0, 1), #34;没有找到代码({barCodeText.Substring(0, 1)})对应的实体对象");
                                    displayTextIds.Add(entity.Id);
                                    bandCode.Append(entity.BandCode);

                                    barCodeText = barCodeText.Remove(0, 1);
                                    break;
                                }
                            }
                            else if (currentEncode == BarCodeEncode.Code128B)
                            {
                                if (barCodeText.Length >= 2)
                                {
                                    //还有很多,且当前2位是数字 转CodeC
                                    if (regNum.IsMatch(barCodeText.Substring(0, 2)))
                                    {
                                        currentEncode = BarCodeEncode.Code128C;
                                        var entity = FindEntity(CodeC);
                                        displayTextIds.Add(entity.Id);
                                        bandCode.Append(entity.BandCode);
                                    }
                                    else //当前2位不是数字 获取1位
                                    {
                                        var entity = FindEntityThrowNull(x => x.CodeB == barCodeText.Substring(0, 1), #34;没有找到代码({barCodeText.Substring(0, 1)})对应的实体对象");
                                        displayTextIds.Add(entity.Id);
                                        bandCode.Append(entity.BandCode);

                                        barCodeText = barCodeText.Remove(0, 1);
                                    }
                                }
                                else
                                {
                                    //最后1个字符   
                                    var entity = FindEntityThrowNull(x => x.CodeB == barCodeText.Substring(0, 1), #34;没有找到代码({barCodeText.Substring(0, 1)})对应的实体对象");
                                    displayTextIds.Add(entity.Id);
                                    bandCode.Append(entity.BandCode);

                                    barCodeText = barCodeText.Remove(0, 1);
                                }
                            }
                        }
                    }
                    break;

                case BarCodeEncode.Code128C:
                case BarCodeEncode.EAN128:
                    {
                        startCode = Code128StartC;
                        if (barCodeText.Length % 2 == 1) throw new Exception("字符长度必须是偶数");

                        if (barCodeEncode == BarCodeEncode.EAN128)
                        {//增加Fun1 
                            displayTextIds.Add(102);
                            bandCode.Append("411131");
                        }

                        while (barCodeText.Length != 0)
                        {
                            var numbers = barCodeText.Substring(0, 2);
                            if (!regNum.IsMatch(numbers))
                            {
                                throw new Exception(#34;字符{numbers}不是数字!");
                            }

                            var entity = FindEntity(BarCodeEncode.Code128C, numbers);
                            bandCode.Append(entity.BandCode);
                            displayTextIds.Add(entity.Id);
                            barCodeText = barCodeText.Remove(0, 2);
                        }
                    }
                    break;

                //CodeA/CodeB
                case BarCodeEncode.Code128A:
                case BarCodeEncode.Code128B:
                    {
                        startCode = barCodeEncode == BarCodeEncode.Code128A
                                                            ? Code128StartA
                                                            : Code128StartB;
                        while (barCodeText.Length != 0)
                        {
                            var entity = FindEntity(barCodeEncode, barCodeText.Substring(0, 1));
                            bandCode.Append(entity.BandCode);
                            displayTextIds.Add(entity.Id);
                            barCodeText = barCodeText.Remove(0, 1);
                        }
                    }
                    break;


                default:
                    throw new NotImplementedException("不受支持的编码类型!");

            }


            if (displayTextIds.Count == 0) throw new Exception("错误的编码,无数据");

            //获得校验位
            var startEntity = FindEntity(startCode);
            var check = startEntity.Id + 0;
            for (int i = 0; i < displayTextIds.Count; i++)
            {
                check += displayTextIds[i] * (i + 1);
            }
            check = check % 103;

            bandCode.Insert(0, startEntity.BandCode);
            bandCode.Append(FindEntity(check).BandCode);     //增加 校验位 BandCode
            bandCode.Append(EndBandCode);                    //增加结束位 BandCode

            Bitmap barCodeImage = DrawImage(bandCode.ToString());
            DrawBarCodeText(barCodeImage, displayText);
            return barCodeImage;
        }



        /// <summary>
        /// 获取目标对应的数据
        /// </summary>
        /// <param name="barCodeEncode">编码类别</param>
        /// <param name="codeValue">数值 A b  30</param> 
        /// <returns>编码</returns>
        private BarCode128Entity FindEntity(BarCodeEncode barCodeEncode, string codeValue)
        {
            if (_code128Tables == null || _code128Tables.Count == 0)
            {
                throw new ArgumentNullException("code128映射表为空!");
            }

            switch (barCodeEncode)
            {
                case BarCodeEncode.Code128A:
                    {
                        foreach (var entity in _code128Tables)
                        {
                            if (entity.CodeA == codeValue)
                                return entity;
                        }
                    }
                    break;
                case BarCodeEncode.Code128B:
                    {
                        foreach (var entity in _code128Tables)
                        {
                            if (entity.CodeB == codeValue)
                                return entity;
                        }
                    }
                    break;
                case BarCodeEncode.Code128C:
                case BarCodeEncode.EAN128:
                    {
                        foreach (var entity in _code128Tables)
                        {
                            if (entity.CodeC == codeValue)
                                return entity;
                        }
                    }
                    break;
                case BarCodeEncode.Code128Auto:
                    throw new ArgumentException("字符对应的真实编码不能为Auto!");

                default:
                    break;
            }

            throw new ArgumentNullException(#34;没有找到对应到编码数值,当前文本非法({codeValue})");
        }

        /// <summary>
        /// 根据编号获得条纹
        /// </summary>
        /// <param name="codeId"></param>
        /// <returns></returns>
        private BarCode128Entity FindEntity(int codeId)
        {
            return FindEntityThrowNull(x => x.Id == codeId, #34;没有找到id({codeId})对应的实体对象");
        }

        private BarCode128Entity FindEntityThrowNull(Predicate<BarCode128Entity> predicate,
            string throwMessage = "根据条件没有找到实体对象!", bool throwable = true)
        {
            foreach (var entity in _code128Tables)
            {
                if (predicate.Invoke(entity)) return entity;
            }

            if (throwable) throw new Exception(throwMessage);

            return null;
        }


        /// <summary>
        /// 获得条码图形
        /// </summary>
        /// <param name="bandCode">编码后的文字类似于:1233412312312314123123124</param>
        /// <returns>图形</returns>
        private Bitmap DrawImage(string bandCode)
        {
            var margin = _settings.Gutter;
            var barHeight = _settings.Height - margin * 2;

            char[] everyBandCode = bandCode.ToCharArray();
            float barCodeWidth = 0;
            for (int i = 0; i < everyBandCode.Length; i++)
            {
                barCodeWidth += Int32.Parse(everyBandCode[i].ToString()) * _settings.NarrowWidth;
            }

            var marginLR = 2 * 10 * _settings.NarrowWidth;
            barCodeWidth += marginLR;//左右两边空白


            Bitmap codeImage = new Bitmap((int)barCodeWidth, (int)(_settings.Height));

            using (Graphics g = Graphics.FromImage(codeImage))
            {
                float offsetX = marginLR / 2;//沿着X轴向右平移
                g.Clear(_settings.BackColor);
                var barBrush = new SolidBrush(_settings.BarColor);
                for (int i = 0; i < everyBandCode.Length; i++)
                {
                    float width = Int32.Parse(everyBandCode[i].ToString()) * _settings.NarrowWidth;  //获取宽度
                    if (!((i & 1) == 0))//space
                    {
                        //g.FillRectangle(Brushes.White, new RectangleF(offsetX, (int)margin, width,  height));
                    }
                    else //Bar 
                    {
                        g.FillRectangle(barBrush, new RectangleF(offsetX, (int)margin, width, barHeight));
                    }

                    offsetX += width;
                }
                //g.FillRectangle(Brushes.White, new RectangleF(offsetX, (int)margin, gutter/2, height));
                g.Flush();
            }

            return codeImage;
        }

        /// <summary>
        /// 显示可见条码文字 如果小于40 不显示文字
        /// </summary>
        /// <param name="bitmap">图形</param>           
        private void DrawBarCodeText(Bitmap bitmap, string displayText)
        {
            if (_settings.TextFont == null || _settings.DisplayText == false) return;

            using (Graphics g = Graphics.FromImage(bitmap))
            {

                SizeF drawSize = g.MeasureString(displayText, _settings.TextFont);
                if (drawSize.Height > bitmap.Height - 10 || drawSize.Width > bitmap.Width)
                {
                    g.Flush();
                    g.Dispose();
                    return;
                }

                int starY = bitmap.Height - (int)drawSize.Height - (int)_settings.Gutter;
                g.FillRectangle(new SolidBrush(_settings.BackColor), new Rectangle(0, starY, bitmap.Width, (int)drawSize.Height));
                g.DrawString(displayText, _settings.TextFont, new SolidBrush(_settings.BarColor),
                    new RectangleF(0, starY + _settings.Gutter, bitmap.Width, drawSize.Height),
                    new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
                g.Flush();
                g.Dispose();
            }
        }


    }


    /// <summary>
    /// 条码编码类别
    /// </summary>
    public enum BarCodeEncode
    {
        Code128A,
        Code128B,
        Code128C,
        EAN128,
        Code128Auto
    }

Tags:

最近发表
标签列表