C# 使用 GDI+ 实现 Code39 条形码绘制

Elena
Elena
发布时间:2026-10-14| 6人浏览过
原创

在需要独立于外部字体或第三方 DLL 的场景下,可以使用 C# 内置的 System.Drawing 命名空间结合 GDI+ 技术手动绘制条形码。本文以 widely used 的 Code39 编码为例,展示如何通过代码逻辑将字符转换为特定的粗细条纹序列,并渲染为 Bitmap 对象。

原理与准备条件

Code39 是一种支持数字、大写英文字母及部分符号的自校验条码标准。其核心原理是将每个字符映射为一组“九元素”二进制串(如 000110100),其中 1 代表粗条(Bar),0 代表窄间隔(Space)。绘制时需遵循以下规范:

  • 字符集:包含 0-9, A-Z, -, ., space, $, /, +, % 共 43 个字符。
  • 起始/终止符:Code39 的起始和终止字符均为星号 (*),对应的编码固定且相同。
  • 分隔符:相邻字符间需有一个窄间隔(0)进行区分。
  • 环境要求:项目需引用 System.Drawing.dll,适用于 Windows Forms 或控制台程序中的图像处理模块。

第 1 步:定义编码映射与初始化参数

首先,建立 ASCII 字符到二进制字符串的查找表,并设置绘制时的几何参数(如条宽、高度、边距)。

具体动作:构建 Code39 映射字典

目的:建立输入字符与底层二进制流的对应关系,确保扫码枪能正确解析。
入口:创建一个静态数组或字典。
动作:按顺序填入 Code39 标准编码。注意索引 0 对应字符 '0',以此类推。同时需在外部处理时自动添加前后缀 * 以及中间的间隔 0。

string AlphaBet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
string[] Code39 = 
{
    /* 0 */ "000110100", /* 1 */ "100100001",
    /* 2 */ "001100001", /* 3 */ "101100000",
    /* ... 省略中间部分,保留关键结构 ... */
    /* * */ "010010100" // 起始/终止符
};

第 2 步:预处理输入与画布创建

接收原始字符串后,需进行合法性校验并计算最终位图的尺寸。

具体动作:校验字符并分配 Bitmap 内存

目的:防止非法字符导致乱码,并根据内容长度动态调整图片大小。
参数:
- thickLength: 粗条宽度(默认 2px)
- narrowLength: 窄条/间隔宽度(默认 1px)
- barCodeHeight: 条形码主体高度

动作:遍历输入字符串,若发现不在 AlphaBet 集合中的字符或非 * 的通配符,应返回错误提示图像。确认合法后,根据公式计算总宽度:
(单个字符宽度的总和) * 字符数 + 左右边距。

Bitmap objBitmap = new Bitmap(Width, Height);
Graphics objGraphics = Graphics.FromImage(objBitmap);
// 清空背景为白色
objGraphics.FillRectangle(Brushes.White, 0, 0, objBitmap.Width, objBitmap.Height);

第 3 步:串联编码流

将离散的字符编码组合成连续的绘制指令流。

具体动作:拼接 Start-Data-Space-Data...-End 序列

目的:形成符合物理扫描要求的连续波形。
入口:遍历用户输入的 sourceCode。
动作: 1. 初始化 strEncode 为起始符编码 "010010100"。 2. 循环每个字符,从 Code39 表中提取对应编码追加到 strEncode。 3. 每两个字符之间手动插入一个 "0" 作为间隔。 4. 循环结束后,追加结束符编码 "0010010100"(注意结束符结构与起始符略有不同,通常前缀为分离带)。

第 4 步:执行绘制与排版

基于生成的二进制流,使用 Graphics 对象在内存中作画。

具体动作:遍历二进制串绘制矩形

目的:将抽象数据转化为可见图形。
重要参数:
- i % 2 == 0: 偶数位绘制黑色条码(Bar) - i % 2 != 0: 奇数位留白或绘制白色(Space),但在 GDI+ 中通常直接跳过填充或填白以保持清晰。 动作:使用循环遍历 strEncode。如果是 1 且位置为偶数,调用 FillRectangle 绘制黑色矩形;如果是 0 且位置为奇数,则不做填充(因为背景已置白)或显式涂白以清除旧内容。每次绘制后,水平坐标 x 累加对应的条宽(粗或窄)。

具体动作:绘制底部明码 (Human Readable)

目的:方便肉眼识别辅助核对。
入口:获取原字符串 sourceCode。
动作:计算文字居中坐标。通常位于条形码最下方,使用 DrawString 方法,颜色设为黑色,字体大小适中(如 5pt-8pt)。

// 计算居中 X 坐标
SizeF sizeF = objGraphics.MeasureString(sourceCode, font);
float x = (objBitmap.Width - sizeF.Width) / 2;
float y = objBitmap.Height - sizeF.Height; // 顶部留空区域后的位置

// 先涂白底色以防遮挡
objGraphics.FillRectangle(Brushes.White, x, y, sizeF.Width, sizeF.Height);
// 写入文字
objGraphics.DrawString(sourceCode, font, Brushes.Black, x, y);

完成判断与注意事项

完成状态: 函数返回有效的 Bitmap 对象。在 WinForm 应用中,可通过 PictureBox.Image = GeneratedBitmap 直接显示验证结果。

常见排错:

  • 字体缺失:虽然本方案不依赖条形码字体文件,但如果用于 UI 显示的明码字体(如 Segoe UI)缺失,可能导致显示异常。建议指定通用字体或使用系统默认字体。
  • DPI 适配:生成的位图是像素级的。如果在高分屏或打印时需要更清晰的条码,需增大 thickLength 和 narrowLength 的基准值(例如放大 2-3 倍)。
  • 性能优化:对于批量生成场景,建议使用 double buffering 避免闪烁,并确保 Graphics 对象在使用后调用 Dispose() 释放资源。

以上就是基于 C# GDI+ 实现 Code39 条形码绘制的详细内容,更多关于 C# 图像处理及条形码生成的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。