C# 使用 GDI+ 实现 Code39 条形码绘制
在需要独立于外部字体或第三方 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# 图像处理及条形码生成的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









