/******************************************************************************
* 文件名:pdf417lib.c
* 功能 :条形码操作函数库
* modified by PRTsinghua@hotmail.com
******************************************************************************/
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#define __INCLUDE_PDF417LIBIMP_H__
#include "pdf417libimp.h"
#undef __INCLUDE_PDF417LIBIMP_H__
#include "pdf417lib.h"
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
char* MIXED_SET = "0123456789&\r\t,:#-.$/+%*=^";
char* PUNCTUATION_SET = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'";
// 线性表元素结构定义
typedef struct _listElement
{
char type;
int start;
int end;
} listElement, *pListElement;
// 线性表结果定义
typedef struct _arrayList {
pListElement array;
int size;
int capacity;
} arrayList, *pArrayList;
typedef struct _pdf417class {
int bitPtr;
int cwPtr;
pdf417param *param;
} pdf417class, *pPdf417class;
/******************************************************************************
* 初始化线性表
******************************************************************************/
void listInit(pArrayList list)
{
list->capacity = 20;
list->size = 0;
list->array = (pListElement)malloc(list->capacity * sizeof(listElement));
}
/******************************************************************************
* 释放线性表
******************************************************************************/
void listFree(pArrayList list)
{
free(list->array);
list->array = NULL;
}
/******************************************************************************
* 给线性表增加一个元素
******************************************************************************/
void 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 listGet(pArrayList list, int idx)
{
if (idx >= list->size || idx < 0)
return NULL;
return list->array + idx;
}
/******************************************************************************
* 删除线性表中某个元素
******************************************************************************/
void 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 checkElementType(pListElement p, char type)
{
if (!p)
return 0;
return (p->type == type);
}
/******************************************************************************
* 求取线性表元素长度
******************************************************************************/
int getElementLength(pListElement p)
{
if (!p)
return 0;
return p->end - p->start;
}
/******************************************************************************
* 初始化二维条形码结构
******************************************************************************/
void 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 pdf417free(pPdf417param param)
{
if (param->outBits != NULL)
{
free(param->outBits);
param->outBits = NULL;
}
}
/******************************************************************************
* 输出宽度位17的码字
******************************************************************************/
void 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 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 outCodeword(pPdf417class p, int codeword)
{
outCodeword17(p, codeword);
}
/******************************************************************************
* 输出结束模式
******************************************************************************/
void outStopPattern(pPdf417class p)
{
outCodeword18(p, STOP_PATTERN);
}
/******************************************************************************
* 输出起始模式
******************************************************************************/
void outStartPattern(pPdf417class p)
{
outCodeword17(p, START_PATTERN);
}
/******************************************************************************
* 输出码字
******************************************************************************/
void 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 * (ro