qrinput.c

来自「二维码QR的编码实现。C语言实现。希望各位一起学习。一起做条码开发」· C语言 代码 · 共 1,184 行 · 第 1/2 页

C
1,184
字号
 * Estimates the length of the encoded bit stream on the current version. * @param entry * @param version version of the symbol * @return number of bits */static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version){	int bits = 0;	int l, m;	int num;	if(version == 0) version = 1;	switch(entry->mode) {		case QR_MODE_NUM:			bits = QRinput_estimateBitsModeNum(entry->size);			break;		case QR_MODE_AN:			bits = QRinput_estimateBitsModeAn(entry->size);			break;		case QR_MODE_8:			bits = QRinput_estimateBitsMode8(entry->size);			break;		case QR_MODE_KANJI:			bits = QRinput_estimateBitsModeKanji(entry->size);			break;		case QR_MODE_STRUCTURE:			return STRUCTURE_HEADER_BITS;		default:			return 0;	}	l = QRspec_lengthIndicator(entry->mode, version);	m = 1 << l;	num = (entry->size + m - 1) / m;	bits += num * (4 + l); // mode indicator (4bits) + length indicator	return bits;}/** * Estimates the length of the encoded bit stream of the data. * @param input input data * @param version version of the symbol * @return number of bits */int QRinput_estimateBitStreamSize(QRinput *input, int version){	QRinput_List *list;	int bits = 0;	list = input->head;	while(list != NULL) {		bits += QRinput_estimateBitStreamSizeOfEntry(list, version);		list = list->next;	}	return bits;}/** * Estimates the required version number of the symbol. * @param input input data * @return required version number */static int QRinput_estimateVersion(QRinput *input){	int bits;	int version, prev;	version = 0;	do {		prev = version;		bits = QRinput_estimateBitStreamSize(input, prev);		version = QRspec_getMinimumVersion((bits + 7) / 8, input->level);		if (version < 0) {			return -1;		}	} while (version > prev);	return version;}/** * Returns required length in bytes for specified mode, version and bits. * @param mode * @param version * @param bits * @return required length of code words in bytes. */int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits){	int payload, size, chunks, remain, maxsize;	payload = bits - 4 - QRspec_lengthIndicator(mode, version);	switch(mode) {		case QR_MODE_NUM:			chunks = payload / 10;			remain = payload - chunks * 10;			size = chunks * 3;			if(remain >= 7) {				size += 2;			} else if(remain >= 4) {				size += 1;			}			break;		case QR_MODE_AN:			chunks = payload / 11;			remain = payload - chunks * 11;			size = chunks * 2;			if(remain >= 6) size++;			break;		case QR_MODE_8:			size = payload / 8;			break;		case QR_MODE_KANJI:			size = (payload / 13) * 2;			break;		case QR_MODE_STRUCTURE:			size = payload / 8;			break;		default:			size = 0;			break;	}	maxsize = QRspec_maximumWords(mode, version);	if(size < 0) size = 0;	if(size > maxsize) size = maxsize;	return size;}/****************************************************************************** * Data conversion *****************************************************************************//** * Convert the input data in the data chunk to a bit stream. * @param entry * @return number of bits */static int QRinput_encodeBitStream(QRinput_List *entry, int version){	int words;	QRinput_List *st1, *st2;	if(entry->bstream != NULL) {		BitStream_free(entry->bstream);		entry->bstream = NULL;	}	words = QRspec_maximumWords(entry->mode, version);	if(entry->size > words) {		st1 = QRinput_List_newEntry(entry->mode, words, entry->data);		st2 = QRinput_List_newEntry(entry->mode, entry->size - words, &entry->data[words]);		QRinput_encodeBitStream(st1, version);		QRinput_encodeBitStream(st2, version);		entry->bstream = BitStream_new();		BitStream_append(entry->bstream, st1->bstream);		BitStream_append(entry->bstream, st2->bstream);		QRinput_List_freeEntry(st1);		QRinput_List_freeEntry(st2);	} else {		switch(entry->mode) {			case QR_MODE_NUM:				QRinput_encodeModeNum(entry, version);				break;			case QR_MODE_AN:				QRinput_encodeModeAn(entry, version);				break;			case QR_MODE_8:				QRinput_encodeMode8(entry, version);				break;			case QR_MODE_KANJI:				QRinput_encodeModeKanji(entry, version);				break;			case QR_MODE_STRUCTURE:				QRinput_encodeModeStructure(entry, version);				break;			default:				break;		}	}	return BitStream_size(entry->bstream);}/** * Convert the input data to a bit stream. * @param input input data. * @return length of the bit stream. */static int QRinput_createBitStream(QRinput *input){	QRinput_List *list;	int bits = 0;	list = input->head;	while(list != NULL) {		bits += QRinput_encodeBitStream(list, input->version);		list = list->next;	}	return bits;}/** * Convert the input data to a bit stream. * When the version number is given and that is not sufficient, it is increased * automatically. * @param input input data. * @return -1 if the input data was too large. Otherwise 0. */static int QRinput_convertData(QRinput *input){	int bits;	int ver;	ver = QRinput_estimateVersion(input);	if(ver > QRinput_getVersion(input)) {		QRinput_setVersion(input, ver);	}	for(;;) {		bits = QRinput_createBitStream(input);		ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level);		if(ver < 0) {			return -1;		} else if(ver > QRinput_getVersion(input)) {			QRinput_setVersion(input, ver);		} else {			break;		}	}	return 0;}/** * Create padding bits for the input data. * @param input input data. * @return padding bit stream. */static BitStream *QRinput_createPaddingBit(QRinput *input){	int bits, maxbits, words, maxwords, i;	QRinput_List *list;	BitStream *bstream;	maxwords = QRspec_getDataLength(input->version, input->level);	maxbits = maxwords * 8;	list = input->head;	bits = 0;	while(list != NULL) {		bits += BitStream_size(list->bstream);		list = list->next;	}	words = (bits + 7) / 8;	if(maxbits - bits < 5) {		if(maxbits == bits) {			return NULL;		} else {			bstream = BitStream_new();			BitStream_appendNum(bstream, maxbits - bits, 0);			return bstream;		}	}	bits += 4;	words = (bits + 7) / 8;	bstream = BitStream_new();	BitStream_appendNum(bstream, words * 8 - bits + 4, 0);	for(i=0; i<maxwords - words; i++) {		BitStream_appendNum(bstream, 8, (i&1)?0x11:0xec);	}	return bstream;}/** * Merge all bit streams in the input data. * @param input input data. * @return merged bit stream */BitStream *QRinput_mergeBitStream(QRinput *input){	BitStream *bstream;	QRinput_List *list;	if(QRinput_convertData(input) < 0) {		return NULL;	}	bstream = BitStream_new();	if(bstream == NULL) return NULL;	list = input->head;	while(list != NULL) {		BitStream_append(bstream, list->bstream);		list = list->next;	}	return bstream;}/** * Merge all bit streams in the input data and append padding bits * @param input input data. * @return padded merged bit stream */BitStream *QRinput_getBitStream(QRinput *input){	BitStream *bstream;	BitStream *padding;	bstream = QRinput_mergeBitStream(input);	if(bstream == NULL) {		return NULL;	}	padding = QRinput_createPaddingBit(input);	if(padding != NULL) {		BitStream_append(bstream, padding);		BitStream_free(padding);	}	return bstream;}/** * Pack all bit streams padding bits into a byte array. * @param input input data. * @return padded merged byte stream */unsigned char *QRinput_getByteStream(QRinput *input){	BitStream *bstream;	unsigned char *array;	bstream = QRinput_getBitStream(input);	if(bstream == NULL) {		return NULL;	}	array = BitStream_toByte(bstream);	BitStream_free(bstream);	return array;}/****************************************************************************** * Structured input data *****************************************************************************/static QRinput_InputList *QRinput_InputList_newEntry(QRinput *input){	QRinput_InputList *entry;	entry = (QRinput_InputList *)malloc(sizeof(QRinput_InputList));	if(entry == NULL) return NULL;	entry->input = input;	entry->next = NULL;	return entry;}static QRinput_InputList *QRinput_InputList_freeEntry(QRinput_InputList *entry){	QRinput_InputList *next;	next = entry->next;	QRinput_free(entry->input);	free(entry);	return next;}QRinput_Struct *QRinput_Struct_new(void){	QRinput_Struct *s;	s = (QRinput_Struct *)malloc(sizeof(QRinput_Struct));	if(s == NULL) return NULL;	s->size = 0;	s->parity = -1;	s->head = NULL;	s->tail = NULL;	return s;}void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity){	s->parity = (int)parity;}int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input){	QRinput_InputList *e;	e = QRinput_InputList_newEntry(input);	if(e == NULL) return -1;	s->size++;	if(s->tail == NULL) {		s->head = e;		s->tail = e;	} else {		s->tail->next = e;		s->tail = e;	}	return s->size;}void QRinput_Struct_free(QRinput_Struct *s){	QRinput_InputList *list;		list = s->head;	while(list != NULL) {		list = QRinput_InputList_freeEntry(list);	}	free(s);}static unsigned char QRinput_Struct_calcParity(QRinput_Struct *s){	QRinput_InputList *list;	unsigned char parity = 0;	list = s->head;	while(list != NULL) {		parity ^= QRinput_calcParity(list->input);		list = list->next;	}	QRinput_Struct_setParity(s, parity);	return parity;}static int QRinput_List_shrinkEntry(QRinput_List *entry, int bytes){	unsigned char *data;	data = (unsigned char *)malloc(bytes);	if(data == NULL) return -1;	memcpy(data, entry->data, bytes);	free(entry->data);	entry->data = data;	entry->size = bytes;	return 0;}int QRinput_splitEntry(QRinput_List *entry, int bytes){	QRinput_List *e;	int ret;	e = QRinput_List_newEntry(entry->mode, entry->size - bytes, entry->data + bytes);	if(e == NULL) {		return -1;	}	ret = QRinput_List_shrinkEntry(entry, bytes);	if(ret < 0) {		QRinput_List_freeEntry(e);		return -1;	}	e->next = entry->next;	entry->next = e;	return 0;}QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input){	QRinput *p;	QRinput_Struct *s;	int bits, maxbits, nextbits, bytes;	QRinput_List *list, *next, *prev;	s = QRinput_Struct_new();	if(s == NULL) return NULL;	input = QRinput_dup(input);	if(input == NULL) {		QRinput_Struct_free(s);		return NULL;	}	QRinput_Struct_setParity(s, QRinput_calcParity(input));	maxbits = QRspec_getDataLength(input->version, input->level) * 8 - STRUCTURE_HEADER_BITS;	if(maxbits <= 0) {		QRinput_Struct_free(s);		return NULL;	}	bits = 0;	list = input->head;	prev = NULL;	while(list != NULL) {		nextbits = QRinput_estimateBitStreamSizeOfEntry(list, input->version);		if(bits + nextbits <= maxbits) {			bits += QRinput_encodeBitStream(list, input->version);			prev = list;			list = list->next;		} else {			bytes = QRinput_lengthOfCode(list->mode, input->version, maxbits - bits);			if(bytes > 0) {				/* Splits this entry into 2 entries. */				QRinput_splitEntry(list, bytes);				/* First half is the tail of the current input. */				next = list->next;				list->next = NULL;				/* Second half is the head of the next input, p.*/				p = QRinput_new2(input->version, input->level);				p->head = next;				/* Renew QRinput.tail. */				p->tail = input->tail;				input->tail = list;				/* Point to the next entry. */				prev = list;				list = next;			} else {				/* Current entry will go to the next input. */				prev->next = NULL;				p = QRinput_new2(input->version, input->level);				p->head = list;				p->tail = input->tail;				input->tail = prev;			}			QRinput_Struct_appendInput(s, input);			input = p;			bits = 0;		}	}	QRinput_Struct_appendInput(s, input);	if(s->size > MAX_STRUCTURED_SYMBOLS) {		QRinput_Struct_free(s);		errno = ERANGE;		return NULL;	}	if(QRinput_Struct_insertStructuredAppendHeaders(s) < 0) {		QRinput_Struct_free(s);		return NULL;	}	return s;}int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s){	int num, i;	QRinput_InputList *list;	if(s->parity < 0) {		QRinput_Struct_calcParity(s);	}	num = 0;	list = s->head;	while(list != NULL) {		num++;		list = list->next;	}	i = 1;	list = s->head;	while(list != NULL) {		if(QRinput_insertStructuredAppendHeader(list->input, num, i, s->parity))			return -1;		i++;		list = list->next;	}	return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?