📄 qrinput.c
字号:
/* * qrencode - QR Code encoder * * Input data chunk class * Copyright (C) 2006, 2007, 2008 Kentaro Fukuchi <fukuchi@megaui.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include "qrencode.h"#include "qrspec.h"#include "bitstream.h"#include "qrinput.h"/****************************************************************************** * Entry of input data *****************************************************************************/static QRinput_List *QRinput_List_newEntry(QRencodeMode mode, int size, const unsigned char *data){ QRinput_List *entry; if(QRinput_check(mode, size, data)) { errno = EINVAL; return NULL; } entry = (QRinput_List *)malloc(sizeof(QRinput_List)); if(entry == NULL) return NULL; entry->mode = mode; entry->size = size; entry->data = (unsigned char *)malloc(size); if(entry->data == NULL) { free(entry); return NULL; } memcpy(entry->data, data, size); entry->bstream = NULL; entry->next = NULL; return entry;}static QRinput_List *QRinput_List_freeEntry(QRinput_List *entry){ QRinput_List *next; next = entry->next; free(entry->data); if(entry->bstream) { BitStream_free(entry->bstream); } free(entry); return next;}static QRinput_List *QRinput_List_dup(QRinput_List *entry){ QRinput_List *n; n = (QRinput_List *)malloc(sizeof(QRinput_List)); if(n == NULL) return NULL; n->mode = entry->mode; n->size = entry->size; n->data = (unsigned char *)malloc(n->size); if(n->data == NULL) { free(n); return NULL; } memcpy(n->data, entry->data, entry->size); n->bstream = NULL; n->next = NULL; return n;}/****************************************************************************** * Input Data *****************************************************************************/QRinput *QRinput_new(void){ return QRinput_new2(0, QR_ECLEVEL_L);}QRinput *QRinput_new2(int version, QRecLevel level){ QRinput *input; if(version < 0 || version > QRSPEC_VERSION_MAX || level < QR_ECLEVEL_L || level > QR_ECLEVEL_H) { errno = EINVAL; return NULL; } input = (QRinput *)malloc(sizeof(QRinput)); if(input == NULL) return NULL; input->head = NULL; input->tail = NULL; input->version = version; input->level = level; return input;}int QRinput_getVersion(QRinput *input){ return input->version;}int QRinput_setVersion(QRinput *input, int version){ if(version < 0 || version > QRSPEC_VERSION_MAX) { errno = EINVAL; return -1; } input->version = version; return 0;}QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input){ return input->level;}int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level){ if(level < QR_ECLEVEL_L || level > QR_ECLEVEL_H) { errno = EINVAL; return -1; } input->level = level; return 0;}static void QRinput_appendEntry(QRinput *input, QRinput_List *entry){ if(input->tail == NULL) { input->head = entry; input->tail = entry; } else { input->tail->next = entry; input->tail = entry; } entry->next = NULL;}int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data){ QRinput_List *entry; entry = QRinput_List_newEntry(mode, size, data); if(entry == NULL) { return -1; } QRinput_appendEntry(input, entry); return 0;}int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity){ QRinput_List *entry; unsigned char buf[3]; if(size > MAX_STRUCTURED_SYMBOLS) { errno = EINVAL; return -1; } if(index <= 0 || index > MAX_STRUCTURED_SYMBOLS) { errno = EINVAL; return -1; } buf[0] = (unsigned char)size; buf[1] = (unsigned char)index; buf[2] = parity; entry = QRinput_List_newEntry(QR_MODE_STRUCTURE, 3, buf); if(entry == NULL) { return -1; } entry->next = input->head; input->head = entry; return 0;}void QRinput_free(QRinput *input){ QRinput_List *list; list = input->head; while(list != NULL) { list = QRinput_List_freeEntry(list); } free(input);}static unsigned char QRinput_calcParity(QRinput *input){ unsigned char parity = 0; QRinput_List *list; int i; list = input->head; while(list != NULL) { if(list->mode != QR_MODE_STRUCTURE) { for(i=list->size-1; i>=0; i--) { parity ^= list->data[i]; } } list = list->next; } return parity;}QRinput *QRinput_dup(QRinput *input){ QRinput *n; QRinput_List *list, *e; n = QRinput_new2(input->version, input->level); if(n == NULL) return NULL; list = input->head; while(list != NULL) { e = QRinput_List_dup(list); QRinput_appendEntry(n, e); list = list->next; } return n;}/****************************************************************************** * Numeric data *****************************************************************************//** * Check the input data. * @param size * @param data * @return result */static int QRinput_checkModeNum(int size, const char *data){ int i; for(i=0; i<size; i++) { if(data[i] < '0' || data[i] > '9') return -1; } return 0;}/** * Estimates the length of the encoded bit stream of numeric data. * @param size * @return number of bits */int QRinput_estimateBitsModeNum(int size){ int w; int bits; w = size / 3; bits = w * 10; switch(size - w * 3) { case 1: bits += 4; break; case 2: bits += 7; break; default: break; } return bits;}/** * Convert the number data to a bit stream. * @param entry */static void QRinput_encodeModeNum(QRinput_List *entry, int version){ int words; int i; unsigned int val; words = entry->size / 3; entry->bstream = BitStream_new(); val = 0x1; BitStream_appendNum(entry->bstream, 4, val); val = entry->size; BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_NUM, version), val); for(i=0; i<words; i++) { val = (entry->data[i*3 ] - '0') * 100; val += (entry->data[i*3+1] - '0') * 10; val += (entry->data[i*3+2] - '0'); BitStream_appendNum(entry->bstream, 10, val); } if(entry->size - words * 3 == 1) { val = entry->data[words*3] - '0'; BitStream_appendNum(entry->bstream, 4, val); } else if(entry->size - words * 3 == 2) { val = (entry->data[words*3 ] - '0') * 10; val += (entry->data[words*3+1] - '0'); BitStream_appendNum(entry->bstream, 7, val); }}/****************************************************************************** * Alphabet-numeric data *****************************************************************************/const signed char QRinput_anTable[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};/** * Check the input data. * @param size * @param data * @return result */static int QRinput_checkModeAn(int size, const char *data){ int i; for(i=0; i<size; i++) { if(QRinput_lookAnTable(data[i]) < 0) return -1; } return 0;}/** * Estimates the length of the encoded bit stream of alphabet-numeric data. * @param size * @return number of bits */int QRinput_estimateBitsModeAn(int size){ int w; int bits; w = size / 2; bits = w * 11; if(size & 1) { bits += 6; } return bits;}/** * Convert the alphabet-numeric data to a bit stream. * @param entry */static void QRinput_encodeModeAn(QRinput_List *entry, int version){ int words; int i; unsigned int val; words = entry->size / 2; entry->bstream = BitStream_new(); val = 0x2; BitStream_appendNum(entry->bstream, 4, val); val = entry->size; BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_AN, version), val); for(i=0; i<words; i++) { val = (unsigned int)QRinput_lookAnTable(entry->data[i*2 ]) * 45; val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]); BitStream_appendNum(entry->bstream, 11, val); } if(entry->size & 1) { val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]); BitStream_appendNum(entry->bstream, 6, val); }}/****************************************************************************** * 8 bit data *****************************************************************************//** * Estimates the length of the encoded bit stream of 8 bit data. * @param size * @return number of bits */int QRinput_estimateBitsMode8(int size){ return size * 8;}/** * Convert the 8bits data to a bit stream. * @param entry */static void QRinput_encodeMode8(QRinput_List *entry, int version){ int i; unsigned int val; entry->bstream = BitStream_new(); val = 0x4; BitStream_appendNum(entry->bstream, 4, val); val = entry->size; BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_8, version), val); for(i=0; i<entry->size; i++) { BitStream_appendNum(entry->bstream, 8, entry->data[i]); }}/****************************************************************************** * Kanji data *****************************************************************************//** * Estimates the length of the encoded bit stream of kanji data. * @param size * @return number of bits */int QRinput_estimateBitsModeKanji(int size){ return (size / 2) * 13;}/** * Check the input data. * @param size * @param data * @return result */static int QRinput_checkModeKanji(int size, const unsigned char *data){ int i; unsigned int val; if(size & 1) return -1; for(i=0; i<size; i+=2) { val = ((unsigned int)data[i] << 8) | data[i+1]; if(val < 0x8140 || (val > 0x9ffc && val < 0xe040) || val > 0xebbf) { return -1; } } return 0;}/** * Convert the kanji data to a bit stream. * @param entry */static void QRinput_encodeModeKanji(QRinput_List *entry, int version){ int i; unsigned int val, h; entry->bstream = BitStream_new(); val = 0x8; BitStream_appendNum(entry->bstream, 4, val); val = entry->size / 2; BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_KANJI, version), val); for(i=0; i<entry->size; i+=2) { val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1]; if(val <= 0x9ffc) { val -= 0x8140; } else { val -= 0xc140; } h = (val >> 8) * 0xc0; val = (val & 0xff) + h; BitStream_appendNum(entry->bstream, 13, val); }}/****************************************************************************** * Structured Symbol *****************************************************************************//** * Convert a structure symbol code to a bit stream. * @param entry */static void QRinput_encodeModeStructure(QRinput_List *entry, int version){ entry->bstream = BitStream_new(); BitStream_appendNum(entry->bstream, 4, 0x03); BitStream_appendNum(entry->bstream, 4, entry->data[1] - 1); BitStream_appendNum(entry->bstream, 4, entry->data[0] - 1); BitStream_appendNum(entry->bstream, 8, entry->data[2]);}/****************************************************************************** * Validation *****************************************************************************/int QRinput_check(QRencodeMode mode, int size, const unsigned char *data){ if(size <= 0) return -1; switch(mode) { case QR_MODE_NUM: return QRinput_checkModeNum(size, (const char *)data); break; case QR_MODE_AN: return QRinput_checkModeAn(size, (const char *)data); break; case QR_MODE_KANJI: return QRinput_checkModeKanji(size, data); break; case QR_MODE_8: return 0; break; case QR_MODE_STRUCTURE: return 0; break; default: break; } return -1;}/****************************************************************************** * Estimation of the bit length *****************************************************************************//**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -