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

 //完成了头文件的定义后,我们将开始在pdf417lib.cpp文件中对相关的定义进行功能编码:

 

#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <Graphics.hpp>
#undef __INCLUDE_PDF417LIBIMP_H__
#include "pdf417lib.h"
#ifndef NULL
#ifdef  __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

 

/******************************************************************************
 * 初始化线性表
******************************************************************************/
void TPDF417::listInit(pArrayList list)
{
    list->capacity = 20;
    list->size = 0;
    list->array = (pListElement)malloc(list->capacity * sizeof(listElement));
}

/******************************************************************************
 * 释放线性表
******************************************************************************/
void TPDF417::listFree(pArrayList list)
{
    free(list->array);
    list->array = NULL;
}

/******************************************************************************
 * 给线性表增加一个元素
******************************************************************************/
void TPDF417::listAdd(pArrayList list, char type, int start, int end)
{
    if (list->size == list->capacity)
 {
        pListElement temp;
        list->capacity *= 2;
        temp = (pListElement)malloc(list->capacity * sizeof(listElement));
        memcpy(temp, list->array, list->size * sizeof(listElement));
        free(list->array);
        list->array = temp;
    }
    list->array[list->size].type = type;
    list->array[list->size].start = start;
    list->array[list->size].end = end;
    ++list->size;
}

/******************************************************************************
 * 获得线性表某个位置的元素
******************************************************************************/
pListElement TPDF417::listGet(pArrayList list, int idx)
{
    if (idx >= list->size || idx < 0)
        return NULL;
    return list->array + idx;
}

/******************************************************************************
 * 删除线性表中某个元素
******************************************************************************/
void TPDF417::listRemove(pArrayList list, int idx)
{
    if (idx >= list->size || idx < 0)
        return;
    --list->size;
    memmove(list->array + idx, list->array + (idx + 1),
  (list->size - idx) * sizeof(listElement));
}

/******************************************************************************
 * 检查线性表元素类型
******************************************************************************/
int TPDF417::checkElementType(pListElement p, char type)
{
    if (!p)
        return 0;
    return (p->type == type);
}

/******************************************************************************
 * 求取线性表元素长度
******************************************************************************/
int TPDF417::getElementLength(pListElement p)
{
    if (!p)
        return 0;
    return p->end - p->start;
}

/******************************************************************************
 * 初始化二维条形码结构
******************************************************************************/
void TPDF417::pdf417init(pPdf417param param)
{
    param->options = 0;
    param->outBits = NULL;
    param->lenBits = 0;
    param->error = 0;
    param->lenText = -1;
    param->text = "";
    param->yHeight = 3;
    param->aspectRatio = 0.5;
}

/******************************************************************************
 * 释放二维挑衅伽马结果
******************************************************************************/
void TPDF417::pdf417free(pPdf417param param)
{
    if (param->outBits != NULL)
 {
        free(param->outBits);
        param->outBits = NULL;
    }
}

/******************************************************************************
 * 输出宽度位17的码字
******************************************************************************/
void TPDF417::outCodeword17(pPdf417class p, int codeword)
{
    int bytePtr = p->bitPtr / 8;
    int bit = p->bitPtr - bytePtr * 8;
    p->param->outBits[bytePtr++] |= codeword >> (9 + bit);
    p->param->outBits[bytePtr++] |= codeword >> (1 + bit);
    codeword <<= 8;
    p->param->outBits[bytePtr] |= codeword >> (1 + bit);
    p->bitPtr += 17;
}

/******************************************************************************
 * 输出宽度为18的码字
******************************************************************************/
void TPDF417::outCodeword18(pPdf417class p, int codeword)
{
    int bytePtr = p->bitPtr / 8;
    int bit = p->bitPtr - bytePtr * 8;
    p->param->outBits[bytePtr++] |= codeword >> (10 + bit);
    p->param->outBits[bytePtr++] |= codeword >> (2 + bit);
    codeword <<= 8;
    p->param->outBits[bytePtr] |= codeword >> (2 + bit);
    if (bit == 7)
        p->param->outBits[++bytePtr] |= 0x80;
    p->bitPtr += 18;
}

/******************************************************************************
 * 输出数据码字
******************************************************************************/
void TPDF417::outCodeword(pPdf417class p, int codeword)
{
    outCodeword17(p, codeword);
}

/******************************************************************************
 * 输出结束模式
******************************************************************************/
void TPDF417::outStopPattern(pPdf417class p)
{
    outCodeword18(p, STOP_PATTERN);
}

/******************************************************************************
 * 输出起始模式
******************************************************************************/
void TPDF417::outStartPattern(pPdf417class p)
{
    outCodeword17(p, START_PATTERN);
}

/******************************************************************************
 * 输出码字
******************************************************************************/
void TPDF417::outPaintCode(pPdf417class p)
{
    int codePtr = 0;
    int row;
    int rowMod;
    int *cluster;
    int edge;
    int column;
   
 p->param->bitColumns = START_CODE_SIZE * (p->param->codeColumns + 3) + STOP_SIZE;
    p->param->lenBits = ((p->param->bitColumns - 1) / 8 + 1) * p->param->codeRows;
    p->param->outBits = (char*)malloc(p->param->lenBits);
    memset(p->param->outBits, 0, p->param->lenBits);
   
 for (row = 0; row < p->param->codeRows; ++row)
 {
        p->bitPtr = ((p->param->bitColumns - 1) / 8 + 1) * 8 * row;
        rowMod = row % 3;
        cluster = CLUSTERS[rowMod];
        outStartPattern(p);
        edge = 0;
       
  switch (rowMod)
  {
        case 0:
            edge = 30 * (row / 3) + ((p->param->codeRows - 1) / 3);
            break;
        case 1:
            edge = 30 * (row / 3) + p->param->errorLevel * 3 + ((p->param->codeRows - 1) % 3);
            break;
        default:
            edge = 30 * (row / 3) + p->param->codeColumns - 1;
            break;
        }
       
  outCodeword(p, cluster[edge]);

        for (column = 0; column < p->param->codeColumns; ++column)
  {
            outCodeword(p, cluster[p->param->codewords[codePtr++]]);
        }
       
        switch (rowMod)
  {
        case 0:
            edge = 30 * (row / 3) + p->param->codeColumns - 1;
            break;
        case 1:
            edge = 30 * (row / 3) + ((p->param->codeRows - 1) / 3);
            break;
        default:
            edge = 30 * (row / 3) + p->param->errorLevel * 3 + ((p->param->codeRows - 1) % 3);
            break;
        }
       
  outCodeword(p, cluster[edge]);
        outStopPattern(p);
    }
   
 if (p->param->options & PDF417_INVERT_BITMAP)
 {
        char* pm = p->param->outBits;
        char* end = pm + p->param->lenBits;
        while (pm < end)
            *(pm++) ^= 0xff;
    }
}

/******************************************************************************
 * 计算错误纠正码
******************************************************************************/
void TPDF417::calculateErrorCorrection(pPdf417class p, int dest)
{
    int t1 = 0;
    int t2 = 0;
    int t3 = 0;
    int *A;
    int Alength;
    int *E;
    int lastE;
    int k, e, j;
   
 if (p->param->errorLevel < 0 || p->param->errorLevel > 8)
        p->param->errorLevel = 0;
   
 A = ERROR_LEVEL[p->param->errorLevel];
    Alength = 2 << p->param->errorLevel;
    E = p->param->codewords + dest;
    memset(E, 0, Alength * sizeof(int));
    lastE = Alength - 1;
   
 for (k = 0; k < p->param->lenCodewords; ++k)
 {
        t1 = p->param->codewords[k] + E[0];
        for (e = 0; e <= lastE; ++e)
  {
            t2 = (t1 * A[lastE - e]) % MOD;
            t3 = MOD - t2;
            E[e] = ((e == lastE ? 0 : E[e + 1]) + t3) % MOD;
        }
    }
   
 for (j = 0; j < Alength; ++j)
        E[j] = (MOD - E[j]) % MOD;
}

/******************************************************************************
 * 获得文本类型和数值
******************************************************************************/
int TPDF417::getTextTypeAndValue(char* text, int size, int idx)
{
    int c;
    char *ms, *ps;
   
 if (idx >= size)
        return 0;
    c = text[idx];
    if (c >= 'A' && c <= 'Z')
        return (ALPHA + c - 'A');
    if (c >= 'a' && c <= 'z')
        return (LOWER + c - 'a');
    if (c == ' ')
        return (ALPHA + LOWER + MIXED + SPACE);
   
 ms = strchr(MIXED_SET, c);
    ps = strchr(PUNCTUATION_SET, c);
   
 if (!ms && !ps)
        return (ISBYTE + (c & 0xff));
    if (ms - MIXED_SET == ps - PUNCTUATION_SET)
        return (MIXED + PUNCTUATION + (ms - MIXED_SET));
    if (ms != NULL)
        return (MIXED + (ms - MIXED_SET));
   
 return (PUNCTUATION + (ps - PUNCTUATION_SET));
}

/******************************************************************************
 * 文本压缩
******************************************************************************/
void TPDF417::textCompaction(pPdf417class p, int start, int length)
{
    int dest[ABSOLUTE_MAX_TEXT_SIZE * 2];
    char* text = p->param->text;
    int mode = ALPHA;
    int ptr = 0;
    int fullBytes = 0;
    int v = 0;
    int k;
    int size;
    memset(dest, 0, sizeof(dest));
    length += start;
   
 for (k = start; k < length; ++k)
 {
        v = getTextTypeAndValue(text, length, k);
       
  if ((v & mode) != 0)
  {
            dest[ptr++] = v & 0xff;
            continue;
        }
       
  if ((v & ISBYTE) != 0)
  {
            if ((ptr & 1) != 0)
   {
                dest[ptr++] = (mode & PUNCTUATION) != 0 ? PAL : PS;
                mode = (mode & PUNCTUATION) != 0 ? ALPHA : mode;
            }
           
   dest[ptr++] = BYTESHIFT;
            dest[ptr++] = v & 0xff;
            fullBytes += 2;
            continue;
        }
       
  switch (mode)
  {
        case ALPHA:
            if ((v & LOWER) != 0)
   {
                dest[ptr++] = LL;
                dest[ptr++] = v & 0xff;
                mode = LOWER;
            }
            else if ((v & MIXED) != 0)
   {
                dest[ptr++] = ML;
                dest[ptr++] = v & 0xff;
                mode = MIXED;
            }
            else if ((getTextTypeAndValue(text, length, k + 1)
    & getTextTypeAndValue(text, length, k + 2) & PUNCTUATION) != 0)
   {
                dest[ptr++] = ML;
                dest[ptr++] = PL;
                dest[ptr++] = v & 0xff;
                mode = PUNCTUATION;
            }
            else
   {
                dest[ptr++] = PS;
                dest[ptr++] = v & 0xff;
            }
            break;
        case LOWER:
            if ((v & ALPHA) != 0)
   {
                if ((getTextTypeAndValue(text, length, k + 1)
     & getTextTypeAndValue(text, length, k + 2) & ALPHA) != 0)
    {
                    dest[ptr++] = ML;
                    dest[ptr++] = AL;
                    mode = ALPHA;
                }
                else
    {
                    dest[ptr++] = AS;
                }
                dest[ptr++] = v & 0xff;
            }
            else if ((v & MIXED) != 0)
   {
                dest[ptr++] = ML;
                dest[ptr++] = v & 0xff;
                mode = MIXED;
            }
            else if ((getTextTypeAndValue(text, length, k + 1)
    & getTextTypeAndValue(text, length, k + 2) & PUNCTUATION) != 0)
   {
                dest[ptr++] = ML;
                dest[ptr++] = PL;
                dest[ptr++] = v & 0xff;
                mode = PUNCTUATION;
            }
            else
   {
                dest[ptr++] = PS;
                dest[ptr++] = v & 0xff;
            }
            break;
        case MIXED:
            if ((v & LOWER) != 0)
   {
                dest[ptr++] = LL;
                dest[ptr++] = v & 0xff;
                mode = LOWER;
            }
            else if ((v & ALPHA) != 0)
   {
                dest[ptr++] = AL;
                dest[ptr++] = v & 0xff;
                mode = ALPHA;
            }
            else if ((getTextTypeAndValue(text, length, k + 1)
    & getTextTypeAndValue(text, length, k + 2) & PUNCTUATION) != 0)
   {
                dest[ptr++] = PL;
                dest[ptr++] = v & 0xff;
                mode = PUNCTUATION;
            }
            else
   {
                dest[ptr++] = PS;
                dest[ptr++] = v & 0xff;
            }
            break;
        case PUNCTUATION:
            dest[ptr++] = PAL;
            mode = ALPHA;
            --k;
            break;
        }
    }
   
 if ((ptr & 1) != 0)
        dest[ptr++] = PS;
    size = (ptr + fullBytes) / 2;
    if (size + p->cwPtr > MAX_DATA_CODEWORDS)
 {
        p->param->error = PDF417_ERROR_TEXT_TOO_BIG;
        return;
    }
   
 length = ptr;
    ptr = 0;
    while (ptr < length)
 {
        v = dest[ptr++];
        if (v >= 30)
  {
            p->param->codewords[p->cwPtr++] = v;
            p->param->codewords[p->cwPtr++] = dest[ptr++];
        }
        else
            p->param->codewords[p->cwPtr++] = v * 30 + dest[ptr++];
    }
}

/******************************************************************************
 * 基本数字的压缩
******************************************************************************/
void TPDF417::basicNumberCompaction(pPdf417class p, int start, int length)
{
    char* text = p->param->text;
    int* ret = p->param->codewords + p->cwPtr;
    int retLast = length / 3;
    int ni, k;
    p->cwPtr += retLast + 1;
    memset(ret, 0, (retLast + 1) * sizeof(int));
    ret[retLast] = 1;
    length += start;
   
 for (ni = start; ni < length; ++ni)
 {
        // 乘以10
        for (k = retLast; k >= 0; --k)
            ret[k] *= 10;
        // 加上该数字
        ret[retLast] += text[ni] - '0';
        // 传播
        for (k = retLast; k > 0; --k) {
            ret[k - 1] += ret[k] / 900;
            ret[k] %= 900;
        }
    }
}

/******************************************************************************
 * 数字压缩
******************************************************************************/
void TPDF417::numberCompaction(pPdf417class p, int start, int length)
{
    int full = (length / 44) * 15;
    int size = length % 44;
    int k;
    if (size == 0)
        size = full;
    else
        size = full + size / 3 + 1;
   
 if (size + p->cwPtr > MAX_DATA_CODEWORDS)
 {
        p->param->error = PDF417_ERROR_TEXT_TOO_BIG;
        return;
    }
   
 length += start;
    for (k = start; k < length; k += 44)
 {
        size = length - k < 44 ? length - k : 44;
        basicNumberCompaction(p, k, size);
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值