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 + -
显示快捷键?