C++Builder下利用TImage制作二维条码PDF417打印控件(五)

2023-11-07

//接上文

 /******************************************************************************
 * 字节压缩6
******************************************************************************/
void TPDF417::byteCompaction6(pPdf417class p, int start)
{
    int length = 6;
    char* text = p->param->text;
    int* ret = p->param->codewords + p->cwPtr;
    int retLast = 4;
    int ni, k;
    p->cwPtr += retLast + 1;
    memset(ret, 0, (retLast + 1) * sizeof(int));
    length += start;
   
 for (ni = start; ni < length; ++ni)
 {
        // 乘以256
        for (k = retLast; k >= 0; --k)
            ret[k] *= 256;
        // 加上该数字
        ret[retLast] += (int)text[ni] & 0xff;
        // 传播
        for (k = retLast; k > 0; --k)
  {
            ret[k - 1] += ret[k] / 900;
            ret[k] %= 900;
        }
    }
}

/******************************************************************************
 * 字节压缩
******************************************************************************/
void TPDF417::byteCompaction(pPdf417class p, int start, int length)
{
    int k, j;
    int size = (length / 6) * 5 + (length % 6);
   
 if (size + p->cwPtr > MAX_DATA_CODEWORDS)
 {
        p->param->error = PDF417_ERROR_TEXT_TOO_BIG;
        return;
    }
   
 length += start;
    for (k = start; k < length; k += 6)
 {
        size = length - k < 44 ? length - k : 6;
        if (size < 6)
  {
            for (j = 0; j < size; ++j)
                p->param->codewords[p->cwPtr++] = (int)p->param->text[k + j] & 0xff;
        }
        else
  {
            byteCompaction6(p, k);
        }
    }
}

/******************************************************************************
 * 中断文本
******************************************************************************/
void TPDF417::breakString(pPdf417class p, pArrayList list)
{
    char* text = p->param->text;
    int textLength = p->param->lenText;
    int lastP = 0;
    int startN = 0;
    int nd = 0;
    char c = 0;
    int k, lastTxt, j, txt;
    //int ptrS;
    pListElement v;
    pListElement vp;
    pListElement vn;
    list->size = 0;
   
 for (k = 0; k < textLength; ++k)
 {
        c = text[k];
       
  if (c >= '0' && c <= '9')
  {
            if (nd == 0)
                startN = k;
            ++nd;
            continue;
        }
       
  if (nd >= 13)
  {
            if (lastP != startN)
   {
                c = text[lastP];
                //ptrS = lastP;
                lastTxt = (c >= ' ' && c < 127) || c == '/r'
     || c == '/n' || c == '/t';
              
    for (j = lastP; j < startN; ++j)
    {
                    c = text[j];
                    txt = (c >= ' ' && c < 127) || c == '/r'
      || c == '/n' || c == '/t';
                   
     if (txt != lastTxt)
     {
                        listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, j);
                        lastP = j;
                        lastTxt = txt;
                    }
                }
                listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, startN);
            }
           
   listAdd(list, 'N', startN, k);
            lastP = k;
        }
        nd = 0;
    }
  
 if (nd < 13)
        startN = textLength;
   
 if (lastP != startN)
 {
        c = text[lastP];
        //ptrS = lastP;
        lastTxt = (c >= ' ' && c < 127) || c == '/r' || c == '/n' || c == '/t';
       
  for (j = lastP; j < startN; ++j)
  {
            c = text[j];
            txt = (c >= ' ' && c < 127) || c == '/r' || c == '/n' || c == '/t';
           
   if (txt != lastTxt)
   {
                listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, j);
                lastP = j;
                lastTxt = txt;
            }
        }
        listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, startN);
    }
   
 if (nd >= 13)
        listAdd(list, 'N', startN, textLength);
  
 // 优化,合并短的字节
    for (k = 0; k < list->size; ++k)
 {
        v = listGet(list, k);
        vp = listGet(list, k - 1);
        vn = listGet(list, k + 1);;
       
  if (checkElementType(v, 'B') && getElementLength(v) == 1)
  {
            if (checkElementType(vp, 'T') && checkElementType(vn, 'T')
                && getElementLength(vp) + getElementLength(vn) >= 3)
   {
                vp->end = vn->end;
                listRemove(list, k);
                listRemove(list, k);
                k = -1;
                continue;
            }
        }
    }
   
 // 合并文本区段
    for (k = 0; k < list->size; ++k)
 {
        v = listGet(list, k);
        vp = listGet(list, k - 1);
        vn = listGet(list, k + 1);;
       
  if (checkElementType(v, 'T') && getElementLength(v) >= 5)
  {
            int redo = 0;
           
   if ((checkElementType(vp, 'B') && getElementLength(vp) == 1)
    || checkElementType(vp, 'T'))
   {
                redo = 1;
                v->start = vp->start;
                listRemove(list, k - 1);
                --k;
            }
           
   if ((checkElementType(vn, 'B') && getElementLength(vn) == 1)
    || checkElementType(vn, 'T'))
   {
                redo = 1;
                v->end = vn->end;
                listRemove(list, k + 1);
            }
           
   if (redo)
   {
                k = -1;
                continue;
            }
        }
    }
   
 // 合并二值区段
    for (k = 0; k < list->size; ++k)
 {
        v = listGet(list, k);
        vp = listGet(list, k - 1);
        vn = listGet(list, k + 1);;
       
  if (checkElementType(v, 'B'))
  {
            int redo = 0;
           
   if ((checkElementType(vp, 'T') && getElementLength(vp) < 5)
    || checkElementType(vp, 'B'))
   {
                redo = 1;
                v->start = vp->start;
                listRemove(list, k - 1);
                --k;
            }
           
   if ((checkElementType(vn, 'T') && getElementLength(vn) < 5)
    || checkElementType(vn, 'B'))
   {
                redo = 1;
                v->end = vn->end;
                listRemove(list, k + 1);
            }
           
   if (redo)
   {
                k = -1;
                continue;
            }
        }
    }
   
 // 检查所有数字
    if (list->size == 1 && (v = listGet(list, 0))->type == 'T'
  && getElementLength(v) >= 8)
 {
        for (k = v->start; k < v->end; ++k)
  {
            c = text[k];
            if (c < '0' || c > '9')
                break;
        }
        if (k == v->end)
            v->type = 'N';
    }
}

/******************************************************************************
 * 汇编
******************************************************************************/
void TPDF417::assemble(pPdf417class p, pArrayList list)
{
    int k;
    if (list->size == 0)
        return;
    p->cwPtr = 1;
   
 for (k = 0; k < list->size; ++k)
 {
        pListElement v = listGet(list, k);
        switch (v->type)
  {
        case 'T':
            if (k != 0)
                p->param->codewords[p->cwPtr++] = TEXT_MODE;
            textCompaction(p, v->start, v->end - v->start);
            break;
        case 'N':
            p->param->codewords[p->cwPtr++] = NUMERIC_MODE;
            numberCompaction(p, v->start, v->end - v->start);
            break;
        case 'B':
            p->param->codewords[p->cwPtr++]
    = (v->end - v->start) % 6 ? BYTE_MODE : BYTE_MODE_6;
            byteCompaction(p, v->start, v->end - v->start);
            break;
        }
        if (p->param->error)
            return;
    }
}
 
/******************************************************************************
 * 最大可能的纠错级别
******************************************************************************/
int TPDF417::maxPossibleErrorLevel(int remain)
{
    int level = 8;
    int size = 512;
   
 while (level > 0)
 {
        if (remain >= size)
            return level;
        --level;
        size >>= 1;
    }
   
 return 0;
}

/******************************************************************************
 * 废弃链表
******************************************************************************/
void TPDF417::dumpList(pPdf417class p, pArrayList list)
{
    int k;
   
 if (list->size == 0)
        return;
   
 for (k = 0; k < list->size; ++k)
 {
        pListElement v = listGet(list, k);
        printf("%c%.*s/n", v->type, v->end - v->start, p->param->text + v->start);
    }
}
/******************************************************************************
 * 转换整数为二进制数
******************************************************************************/
AnsiString TPDF417::GetBinStr(int n)
{
          AnsiString   str;

          for(UINT   d=n;   d!=0;   d>>=1)
                  str.Insert((d&1)?'1':'0',   1);
          if(str.IsEmpty())str='0';

          while(str.Length()%8!=0)
          {
              str="0"+str;
          }
          return   str;
}
/******************************************************************************
 * 获得最大平方
******************************************************************************/
int TPDF417::getMaxSquare(pPdf417param p)
{
    if (p->codeColumns > 21)
 {
        p->codeColumns = 29;
        p->codeRows = 32;
    }
    else
 {
        p->codeColumns = 16;
        p->codeRows = 58;
    }
    return MAX_DATA_CODEWORDS + 2;
}

/******************************************************************************
 * 画出条形码
******************************************************************************/
void TPDF417::paintCode(pPdf417param p)
{
    pdf417class pp;
    arrayList list;
    int maxErr, fixedColumn, lenErr, tot, skipRowColAdjust, pad;
    pp.param = p;
    p->error = 0;
   
 if (p->options & PDF417_USE_RAW_CODEWORDS)
 {
        if (p->lenCodewords > MAX_DATA_CODEWORDS || p->lenCodewords < 1
   || p->lenCodewords != p->codewords[0])
  {
            p->error = PDF417_ERROR_INVALID_PARAMS;
            return;
        }
    }
    else
 {
        if (p->lenText < 0)
            p->lenText = strlen(p->text);
        if (p->lenText > ABSOLUTE_MAX_TEXT_SIZE)
  {
            p->error = PDF417_ERROR_TEXT_TOO_BIG;
            return;
        }
        listInit(&list);
        breakString(&pp, &list);
        dumpList(&pp, &list);
        assemble(&pp, &list);
        listFree(&list);
        if (p->error)
            return;
        p->codewords[0] = p->lenCodewords = pp.cwPtr;
    }
   
 maxErr = maxPossibleErrorLevel(MAX_DATA_CODEWORDS + 2 - p->lenCodewords);
    if (!(p->options & PDF417_USE_ERROR_LEVEL))
 {
        if (p->lenCodewords < 41)
            p->errorLevel = 2;
        else if (p->lenCodewords < 161)
            p->errorLevel = 3;
        else if (p->lenCodewords < 321)
            p->errorLevel = 4;
        else
            p->errorLevel = 5;
    }
   
 if (p->errorLevel < 0)
        p->errorLevel = 0;
    else if (p->errorLevel > maxErr)
        p->errorLevel = maxErr;
    if (p->codeColumns < 1)
        p->codeColumns = 1;
    else if (p->codeColumns > 30)
        p->codeColumns = 30;
    if (p->codeRows < 3)
        p->codeRows = 3;
    else if (p->codeRows > 90)
        p->codeRows = 90;
   
 lenErr = 2 << p->errorLevel;
    fixedColumn = !(p->options & PDF417_FIXED_ROWS);
    skipRowColAdjust = 0;
    tot = p->lenCodewords + lenErr;
   
 if (p->options & PDF417_FIXED_RECTANGLE)
 {
        tot = p->codeColumns * p->codeRows;
        if (tot > MAX_DATA_CODEWORDS + 2)
  {
            tot = getMaxSquare(p);
        }
        if (tot < p->lenCodewords + lenErr)
            tot = p->lenCodewords + lenErr;
        else
            skipRowColAdjust = 1;
    }
    else if (!(p->options & (PDF417_FIXED_COLUMNS | PDF417_FIXED_ROWS)))
 {
        double c, b;
        fixedColumn = 1;
        if (p->aspectRatio < 0.001)
            p->aspectRatio = 0.001f;
        else if (p->aspectRatio > 1000)
            p->aspectRatio = 1000;
        b = 73 * p->aspectRatio - 4;
        c = (-b + sqrt(b * b + 4 * 17 * p->aspectRatio
   * (p->lenCodewords + lenErr) * p->yHeight)) / (2 * 17 * p->aspectRatio);
        p->codeColumns = (int)(c + 0.5);
        if (p->codeColumns < 1)
            p->codeColumns = 1;
        else if (p->codeColumns > 30)
            p->codeColumns = 30;
    }
   
 if (!skipRowColAdjust)
 {
        if (fixedColumn)
  {
            p->codeRows = (tot - 1) / p->codeColumns + 1;
            if (p->codeRows < 3)
                p->codeRows = 3;
            else if (p->codeRows > 90)
   {
                p->codeRows = 90;
                p->codeColumns = (tot - 1) / 90 + 1;
            }
        }
        else
  {
            p->codeColumns = (tot - 1) / p->codeRows + 1;
            if (p->codeColumns > 30)
   {
                p->codeColumns = 30;
                p->codeRows = (tot - 1) / 30 + 1;
            }
        }
        tot = p->codeRows * p->codeColumns;
    }
   
 if (tot > MAX_DATA_CODEWORDS + 2)
 {
        tot = getMaxSquare(p);
    }
   
 p->errorLevel = maxPossibleErrorLevel(tot - p->lenCodewords);
    lenErr = 2 << p->errorLevel;
    pad = tot - lenErr - p->lenCodewords;
    pp.cwPtr = p->lenCodewords;
    while (pad--)
        p->codewords[pp.cwPtr++] = TEXT_MODE;
    p->codewords[0] = p->lenCodewords = pp.cwPtr;
    calculateErrorCorrection(&pp, pp.param->lenCodewords);
    pp.param->lenCodewords = tot;
    outPaintCode(&pp);
}

/******************************************************************************
 * 设置条形码值
******************************************************************************/
void TPDF417::setValue(AnsiString Value)
{
   if(Value.Length()>90&&Value.Length()<150)
   {
        for(int i=0;i<150-Value.Length();i++)
        {
            Value+=" ";
        }
   }

    FValue=Value;
}

void TPDF417::makeDrawCode()
{
    pdf417param  p;
    pdf417init(&p);
/*
    char *outBits;  // 输出的bit位
    int lenBits;  // 长度
    int bitColumns;
    int codeRows;  // 层数
    int codeColumns; // 列数
    int codewords[928]; // 码字
    int lenCodewords; // 码字个数
    int errorLevel;  // 纠错码级别
    char *text;   // 文本
    int lenText;  // 文本长度
    int options;  // 选项
*/
 p.text = FValue.c_str() ;
    p.options = PDF417_INVERT_BITMAP;
    paintCode(&p);

 if (p.error)
 {
        pdf417free(&p);
    }

    int cols = p.bitColumns / 8 + 1;
    int k;
    AnsiString f;
    FDrawColumns=cols;
    FDrawRows=p.codeRows;

    for (k = 0; k < p.lenBits; ++k)
    {

          f+=GetBinStr(((int)p.outBits[k] & 0xff));
    }
    FDrawCode=f;
    pdf417free(&p);
}
/******************************************************************************
 * 设置绘制像素大小单位
******************************************************************************/
void TPDF417::setDrawPix(int pix)
{
    FDrawPix=pix;
}
/******************************************************************************
 * 设置绘制像素高度单位
******************************************************************************/
void TPDF417::setDrawRowHeightPix(int pix)
{
    FDrawRowHeightPix=pix;
}
/******************************************************************************
 * 绘制PDF417条码在Canvas上
******************************************************************************/
void TPDF417::DrawCodeBar(TCanvas *c)
{
    FWidth=FDrawColumns*8*FDrawPix;
    FHeight=FDrawRows*FDrawRowHeightPix;
    TRect r;
    r.Left=0;
    r.Top=0;
    r.Right=FWidth;
    r.Bottom=FHeight;
    c->FillRect(r);
    TPen *p = new TPen();
    p->Color=clWhite;
    p->Width=FDrawPix;
    c->Pen=p;
    int x,y;
    x=0;y=FHeight;
    c->MoveTo(x,y);
    int j=1;
    for(int k=0;k<FDrawRows;k++)
    {

        for(int i=0;i<FDrawColumns*8;i++)
        {

            if(FDrawCode.SubString(j,1)=="0"&&i<FDrawColumns*8)
            {
                p->Color=clBlack;
                p->Width=FDrawPix;
                c->Pen=p;
                c->MoveTo(x,y);
                c->LineTo(x,y-FDrawRowHeightPix);
            }
            if(FDrawCode.SubString(j,1)=="1")
            {
                p->Color=clWhite;
                p->Width=FDrawPix;
                c->Pen=p;
                c->MoveTo(x,y);
                c->LineTo(x,y-FDrawRowHeightPix);
            }
            x=(i*FDrawPix);
            j++;
        }
            p->Color=clWhite;
            p->Width=FDrawPix;
            c->Pen=p;
            c->MoveTo(x,y);
            c->LineTo(x,y-FDrawRowHeightPix);
        y=FHeight-(k*FDrawRowHeightPix);
    }

}

/******************************************************************************
 * 生成PDF417条码在Canvas上
******************************************************************************/

void TPDF417::DoCodeBar(TCanvas *canvas,AnsiString Value,int DrawPix,int RowHeightPix)
{
    setValue(Value);   //设置值
    setDrawPix(DrawPix);//设置绘画像素宽度
    setDrawRowHeightPix(RowHeightPix);//设置绘画像素高度
    makeDrawCode();    //生成绘画代码
    DrawCodeBar(canvas);//绘画条码到canvas中
}
/******************************************************************************
 * 获取PDF417条码在Canvas上的范围
******************************************************************************/

TRect TPDF417::GetCanvasRect()
{
    TRect r;
    r.Left=0;
    r.Top=0;
    r.Right=FWidth;
    r.Bottom=FHeight;
    return r;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++Builder下利用TImage制作二维条码PDF417打印控件(五) 的相关文章

随机推荐

  • 通过docker搭建gitlab

    通过docker搭建gitlab 一 安装 拉取docker镜像 docker pull gitlab gitlab ce 启动容器 docker run d p 4443 443 p 8080 80 p 222 22 name gitla
  • 计算机桌面背景设置,电脑桌面背景设置图文教程

    桌面背景就是电脑屏幕所使用的各种图片 让我们的电脑看起来更好看 更漂亮 更有个性 但是很多人不知道电脑桌面背景如何设置 今天 小编就给大家介绍一下设置电脑桌面背景的操作方法 唯美的 搞笑的 文艺的高逼格桌面壁纸 还有超级好看的自拍照怎么能放
  • Postgresql语句持续更新

    分区表 partition by case when then end if else 日期 Date Timestamp text String互转 时间获取周 月等 自增序列 创建表 删除表 修改表 默认值 重命名列 修改列类型 时间序
  • python3.8.so.1.0‘: dlopen: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29‘ not found

    Linux下打包Python程序无法在别人系统上运行libpython3 6m so 1 0 dlopen lib64 libc so 6 version GLIBC 2 25 not wangziyang777的博客 CSDN博客 351
  • 安全方向就业前景

    安全方向人才招聘 文章目录 安全方向人才招聘 前言 安全人员基本技能 web安全工程师 web安全研发工程师 安全运维工程师 安全测试工程师 Windows逆向工程师 Android安全工程师 系统研发工程师 安全产品运营员 风控安全工程师
  • Linux与Windows的区别

    版权声明 本文为博主原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接和本声明 本文链接 https blog csdn net chao199512 article details 79873866 当我们每个人接
  • 什么是Xshell? 干啥用的?

    Linux的远程连接工具 要登录Linux服务器使用的工具是putty SecureCRT Xshell 1 Xshell简介 Xshell 是一个强大的安全终端模拟软件 它支持SSH1 SSH2 以及Microsoft Windows 平
  • 分析注释 sequence_input_layer.py

    video order list 存放视频名称 对应视频 video dict 字典 每一个视频下都对应dict里的一项 usr bin env python Data layer for video Change flow frames
  • KVM虚拟机网络配置方式 (Bridge方式 Nat方式)

    Summary 使用libvirt安装完qemu kvm虚拟机 但是发现虚拟机不能上网 虚拟机想要上网 有很多中方法 我们称Guest机器为虚拟机 Host机器为开机运行的真实机器 KVM虚拟机网络配置一般的两种方式 NAT 默认上网 虚拟
  • 毕业设计——基于深度学习的手势识别以及手势交互功能(TensorFlow)(YOLO)

    目录 前言 1 背景介绍 2 项目简介 3 环境配置 配置介绍 版本 4 模型实现 数据集制作 手势训练 模型评估 识别效果 5 GUI界面以及手势交互的实现 区域介绍 展示 初始页面 识别页面 多媒体控制页面 6 结语 前言 今天 向大家
  • 【iOS】跳转邮箱发送邮件,支持系统内多个邮箱的方案 swift 实现

    我们永远无法知道运行应用程序的iPhone iPad是否安装了Apple的Mail应用程序 因为用户可以删除它 一 前言 网上一般都让这么写 let email foo bar com if let url URL string mailt
  • ubuntu apt-get grade 报错11: Resource temporarily unavailable

    ubuntu更新源时报错 报错详细提示如下 E Could not get lock var lib dpkg lock frontend open 11 Resource temporarly unavailable E Unable t
  • Android中View.inflate()

    Inflate可用于将一个xml中定义的布局控件找出来 因为在一个Activity里如果直接用findViewById 的话 对应的是setConentView 的那个layout里的组件 因此如果当前Activity里需要用到别的layo
  • 图像数据流识别圆形_我的电赛作品:BP算法鸟类图像识别系统

    作者 我的果果超可爱 本文由面包板社区版主原创 未经本人允许 禁止转载 不知不觉已经12月了 经过2020这个魔幻的一年 回想当年参加电子竞赛 仿佛回到了念书的快乐时光 不知不觉已经好几年了诶 任时光匆匆流走 我们还剩下什么呢 好了言归正传
  • CUDA10.0 官方手册 章三 CUDA编程接口

    因为这章内容比较碎 不好提炼 大部分为原文翻译 人工翻译 不是机器翻译 抵制不负责任的机翻从你我做起 翻译不易 转载贴上出处 630056108 qq com 目录 3 1 用NVCC编译 3 1 1 编译工作流 3 1 2 二进制兼容性
  • IPv6表示方法与配置案例

    1 IPv6地址格式 IPv4地址长度32位 IPv6的地址长度为128位 是IPv4地址长度的4倍 采用十六进制表示 表示方式如下 冒号分隔十六进制表示法 格式为X X X X X X X X 其中每个X表示地址中的16个二进制B 十六进
  • Tkinter批量截取log

    http automap bj bcebos com mapautozip 5 3 0 20201020 repacked path for 10x adas BaiduNavi china zip usr bin python codin
  • react获取经纬度

    useEffect gt if navigator geolocation navigator geolocation getCurrentPosition position gt const latitude position coord
  • Kubernetes学习之路(一)之概念和架构解析和证书创建和分发

    1 Kubernetes的重要概念 转自 CloudMan老师公众号 每天5分钟玩转Kubernetes https item jd com 26225745440 html Cluster Cluster 是计算 存储和网络资源的集合 K
  • C++Builder下利用TImage制作二维条码PDF417打印控件(五)

    接上文 字节压缩6 void TPDF417 byteCompaction6 pPdf417class p int start int length 6 char text p gt param gt text int ret p gt p