在 Zint 中,BARCODE_C25STANDARD、BARCODE_C25INTER、BARCODE_C25IATA、BARCODE_C25LOGIC 和 BARCODE_C25IND 是 Code 2 of 5(Code 25)条形码的不同变体。这些变体在编码规则、字符集和应用场景上有所不同。Code 2 of 5(Code 25)是一种基于宽条和窄条的条形码,每个字符由 5 个条组成,其中 2 个是宽条,3 个是窄条。
BARCODE_C25STANDARD码:
- 标准 Code 2 of 5 条形码。
- 仅支持数字 0-9。
- 通用场景,适合简单的数字编码。
在使用时可指定是否添加校验码,文档中描述为:
No check digit is added by default. To add a check digit, set --vers=1 (API option_2 = 1). To add a check digit but not show it in the Human Readable Text, set --vers=2 (API option_2 = 2).
默认情况下不添加校验位,如要设置校验位则将option_2设置为1即可;如果要添加校验位但不可见则将option_2设置为2即可。
校验码计算规则: - 从右到左(从最后一位字符开始),为每个字符分配一个权重,权重交替为 3 和 1。
- 将每个字符的值乘以其权重,然后求和。
- 将加权和除以 10,取余数,然后用 10 减去余数。如果结果为 10,则校验码为 0。
BARCODE_C25STANDARD、BARCODE_C25INTER、BARCODE_C25IATA、BARCODE_C25LOGIC 和 BARCODE_C25IND码的校验码计算方法都一样。
BARCODE_C25INTER码:
- Interleaved 2 of 5(交错 2 of 5)条形码。
- 仅支持数字 0-9。如果非偶数位则在前边补0
- 每两个数字编码为一个字符。第一个数字用条表示,第二个数字用空表示。
- 广泛应用于物流、零售和仓库管理。
支持可选的校验位(通常使用 Modulo 10 校验)。
默认情况下不添加校验位,如要设置校验位则将option_2设置为1即可;如果要添加校验位但不可见则将option_2设置为2即可。
BARCODE_C25IATA码:
- IATA 2 of 5 条形码。
- 仅支持数字 0-9。
- 与标准 Code 2 of 5 类似,但专为国际航空运输协会(IATA)设计。
- 一般用于航空运输和行李标签。
支持可选的校验位。
默认情况下不添加校验位,如要设置校验位则将option_2设置为1即可;如果要添加校验位但不可见则将option_2设置为2即可。
BARCODE_C25LOGIC码:
- Logic 2 of 5 条形码。
- 仅支持数字 0-9。
- 每个字符由 3 个窄条和 2 个宽条组成。字符之间用窄空分隔。
- 一般用于电子设备和工业自动化。
支持可选的校验位。
默认情况下不添加校验位,如要设置校验位则将option_2设置为1即可;如果要添加校验位但不可见则将option_2设置为2即可。
BARCODE_C25IND码:
- Industrial 2 of 5 条形码。
- 仅支持数字 0-9。
- 每个字符由 3 个窄条和 2 个宽条组成。字符之间用窄空分隔。
- 一般用于工业标识和仓库管理。
支持可选的校验位。
默认情况下不添加校验位,如要设置校验位则将option_2设置为1即可;如果要添加校验位但不可见则将option_2设置为2即可。
以下即为生成代码:
cpp
struct zint_symbol* symbol;
symbol = ZBarcode_Create();
symbol->symbology = BARCODE_C25STANDARD; //码制
symbol->input_mode = DATA_MODE; //数据编码格式
symbol->option_2 = 1; //默认不校验、1 校验
std::string strContent = "123456";
CRect rcCode(0,0,200,50);
int nRet = ZBarcode_Encode_and_Buffer_Vector(symbol, (unsigned char*)strContent.c_str(), strContent.size(), 0);
if (nRet == 0)
{
//success
ZBarcode_Print(symbol, 0);
std::vector<CRect> vecBlackRect;
if (symbol->vector)
{
struct zint_vector_rect* rect = symbol->vector->rectangles;
while (rect)
{
CRect rcTmp;
rcTmp.left = rect->x;
rcTmp.top = rect->y;
rcTmp.right = rcTmp.left + rect->width;
rcTmp.bottom = rcTmp.top + rect->height;
vecBlackRect.push_back(rcTmp);
rect = rect->next;
}
}
double nDrawUint = (double)rcCode.Width() / symbol->width;
double nUint = (double)symbol->bitmap_width / symbol->width;
std::vector<CRect> vecDrawBlack; //绘制条码条的真实区域
for (int i = 0; i < vecBlackRect.size(); i++)
{
CRect rcTmp(vecBlackRect[i]);
rcTmp.left = rcTmp.left / nUint * nDrawUint;
rcTmp.right = rcTmp.right / nUint * nDrawUint;
rcTmp.bottom = rcTmp.top + rcCode.Height();
vecDrawBlack.push_back(rcTmp);
}
//绘制条码
//可选择是否绘制条码背景色
{
COLORREF clrBkgnd = GETCOLOR(L"RGB(255,255,255)");
CAutoRefPtr<IBrush> brush, oldbrush;
pRT->CreateSolidColorBrush(clrBkgnd, &brush);
pRT->SelectObject(brush, (IRenderObj**)&oldbrush);
pRT->FillRectangle(&rcCode);
pRT->SelectObject(oldbrush, NULL);
}
CAutoRefPtr<IPath> path;
GETRENDERFACTORY->CreatePath(&path);
for (int i = 0; i < vecDrawBlack.size(); i++)
{
CRect rcBlack;
rcBlack.left += vecDrawBlack[i].left + rcCode.left;
rcBlack.top += vecDrawBlack[i].top + rcCode.top;
rcBlack.right = rcBlack.left + vecDrawBlack[i].Width();
rcBlack.bottom = rcBlack.top + vecDrawBlack[i].Height();
path->addRect(rcBlack);
}
COLORREF clrFrgnd = GETCOLOR(L"RGB(0,0,0)"); //可自定义条码前景色
CAutoRefPtr<IBrush> brush, oldbrush;
pRT->CreateSolidColorBrush(clrFrgnd, &brush);
pRT->SelectObject(brush, (IRenderObj**)&oldbrush);
pRT->FillPath(path);
pRT->SelectObject(oldbrush, NULL);
//绘制文本(文本绘制可以选择绘制在底部还是顶部,自行计算文本位置然后进行绘制)
SIZE szContent;
pRT->MeasureText(m_sstrContent, m_sstrContent.GetLength(), &szContent); //文本整体的长度
CRect rcText(rcCode);
rcText.top = rcCode.bottom;
rcText.bottom = rcText.top + szContent.cy;
pRT->DrawText(m_sstrContent, -1, (LPRECT)rcText, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
}
else
{
//failed
//可查看errtxt值查看失败描述
}
ZBarcode_Delete(symbol);