当前位置: 首页 > news >正文

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:

相关文章:

  • LabVIEW与小众设备集成
  • XSS 常用标签及绕过姿势总结
  • React 初级教程
  • RadASM环境,win32汇编入门教程之三
  • 数论补充 之 前后缀分解问题
  • Word 公式转 CSDN 插件 发布
  • 使用Node.js进行串口通信
  • 1.推荐算法基本概念
  • 基于Ceedling的嵌入式软件单元测试
  • Lineageos 22.1 aosp15 定制学习专栏介绍
  • MySQL无法连接到本地localhost的解决办法2024.11.8
  • DHCP协议概述
  • 【JS】实现一个hexo插件并发布
  • 相机姿态估计
  • SQL-leetcode—1527. 患某种疾病的患者
  • 1.【线性代数】——方程组的几何解释
  • springboot026在线文档管理系统
  • 深入剖析 Apache Shiro550 反序列化漏洞及复现
  • boss直聘登录 网易易盾 无感 滑块 分析
  • 本地DataGrip连接Linux服务器中MySQL失败处理方法
  • 制定出台民营经济促进法有何重大意义?全国人大常委会法工委回应
  • 巴西外长维埃拉:国际形势日益复杂,金砖国家必须发挥核心作用
  • 习近平在上海考察
  • 伊朗内政部长:港口爆炸由于“疏忽”和未遵守安全规定造成
  • 纪录电影《中国有戏:天幕计划》启动,有望太空播放
  • 广东一公司违规开展学科培训被罚没470万,已注销营业执照