📄 pdf417lib.c
字号:
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 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);
}
}
/******************************************************************************
* 字节压缩6
******************************************************************************/
static void 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 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 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, ptrS, lastTxt, j, txt;
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 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;
}
}
/******************************************************************************
* 最大可能的纠错级别
******************************************************************************/
static int maxPossibleErrorLevel(int remain)
{
int level = 8;
int size = 512;
while (level > 0)
{
if (remain >= size)
return level;
--level;
size >>= 1;
}
return 0;
}
/******************************************************************************
* 废弃链表
******************************************************************************/
void 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);
}
}
/******************************************************************************
* 获得最大平方
******************************************************************************/
static int 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 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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -