SOUI基于Zint生成Code11码

Code 11 是一种高密度的数字条形码,主要用于标识电信设备和电子元件。它的名称来源于其能够编码 11 种字符:数字 0-9 和连接符 -。Code 11 是一种双向可读的条形码,支持校验位以提高数据准确性。
在使用BARCODE_CODE11码制生成code 11码时可指定其是否校验。默认是以两位校验码的设置生成。文档中的描述为:
Two modulo-11 check digits are added by default. To add just one check digit, set --vers=1 (API option_2 = 1). To add no check digits, set --vers=2 (API option_2 = 2).
故而如果我们需要更改其校验规则只需在生成时更改option_2参数的值即可。
生成代码如下:

struct zint_symbol* symbol;
symbol = ZBarcode_Create();
symbol->symbology = BARCODE_CODE11;   //码制
symbol->input_mode = DATA_MODE; //数据编码格式
symbol->option_2 = 1;   //默认添加俩校验位、1 添加一个校验位、2 不添加校验位

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);

在绘制文本时根据如果需要将校验码绘制出来则将校验码追加在原始数据后进行绘制。

校验码计算规则:
1位校验码计算:

  • 分配权重:从右到左(从最后一位字符开始),为每个字符分配一个权重,权重从 1 开始递增。
  • 计算加权和:将每个字符的值乘以其权重,然后求和。字符 - 的值为 10。
  • 计算校验码:将加权和除以 11,取余数作为校验码。如果余数为 10,则校验码为 -。
  • 附加校验码:将校验码附加到条码数据的末尾。
    2位校验码计算:
  • 在1位校验码的基础上再计算一次校验码,计算出的结果即为第2位校验码,然后将第二位的校验码也附加到条码数据的末尾。
    计算代码示例:
//计算第一位校验码
SStringW sstrContent = L"123456";
std::vector<int> vecCheckOne;
int nLength = m_sstrContent.GetLength();
for (int i = 0; i < nLength; i++)
{
    SStringW sstrChar = m_sstrContent.GetAt(i);
    if (sstrChar == L"-")  vecCheckOne.push_back(10);
    else
    {
        int nChar = std::stoi(sstrChar.c_str());
        vecCheckOne.push_back(nChar);    
    }
}

int nTmp = 0;
for (int i = 0; i < vecCheckOne.size(); i++)
{
    nTmp += (vecCheckOne.size() - i) * vecCheckOne[i];
}
int nCheck = nTmp % 11;

SString sstrCheck;
if (nCheck == 10) sstrCheck = L"-";
else sstrCheck.Format(L"%d", nCheck);

//第二位校验码跟上边计算一样,用带第一位的校验码数据再处理一次得出的结果即为第二位校验码。
//TODO:
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值