//完成了头文件的定义后,我们将开始在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);
}
}