Edit

kc3-lang/libqrencode/tests/decoder.c

Branch :

  • Show log

    Commit

  • Author : Kentaro Fukuchi
    Date : 2017-10-08 02:17:28
    Hash : 06494038
    Message : Fixed some warnings. (closing #89 and #102)

  • tests/decoder.c
  • #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <iconv.h>
    #if HAVE_CONFIG_H
    #include "../config.h"
    #endif
    #include "../qrspec.h"
    #include "../bitstream.h"
    #include "../mask.h"
    #include "../mqrspec.h"
    #include "../mmask.h"
    #include "common.h"
    #include "decoder.h"
    
    static unsigned int bitToInt(unsigned char *bits, int length)
    {
    	int i;
    	unsigned int val = 0;
    
    	for(i=0; i<length; i++) {
    		val = val << 1;
    		val |= (bits[i] & 1);
    	}
    
    	return val;
    }
    
    static int decodeLength(int *bits_length, unsigned char **bits, QRencodeMode mode, int version, int mqr)
    {
    	int i;
    	int length = 0;
    	int lbits;
    
    	if(mqr) {
    		lbits = MQRspec_lengthIndicator(mode, version);
    	} else {
    		lbits = QRspec_lengthIndicator(mode, version);
    	}
    
    	if(*bits_length < lbits) {
    		printf("Bit length is too short: %d\n", *bits_length);
    		return 0;
    	}
    
    	length = 0;
    	for(i=0; i<lbits; i++) {
    		length = length << 1;
    		length += (*bits)[i];
    	}
    
    	*bits_length -= lbits;
    	*bits += lbits;
    
    	return length;
    }
    
    static DataChunk *decodeNum(int *bits_length, unsigned char **bits, int version, int mqr)
    {
    	int i;
    	int size, sizeInBit, words, remain;
    	unsigned char *p;
    	char *buf, *q;
    	unsigned int val;
    	DataChunk *chunk;
    
    	size = decodeLength(bits_length, bits, QR_MODE_NUM, version, mqr);
    	if(size < 0) return NULL;
    
    	words = size / 3;
    	remain = size - words * 3;
    	sizeInBit = words * 10;
    	if(remain == 2) {
    		sizeInBit += 7;
    	} else if(remain == 1) {
    		sizeInBit += 4;
    	}
    	if(*bits_length < sizeInBit) {
    		printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
    		return NULL;
    	}
    
    	buf = (char *)malloc((size_t)size + 1);
    	p = *bits;
    	q = buf;
    	for(i=0; i<words; i++) {
    		val = bitToInt(p, 10);
    		sprintf(q, "%03d", val);
    		p += 10;
    		q += 3;
    	}
    	if(remain == 2) {
    		val = bitToInt(p, 7);
    		sprintf(q, "%02d", val);
    	} else if(remain == 1) {
    		val = bitToInt(p, 4);
    		sprintf(q, "%1d", val);
    	}
    	buf[size] = '\0';
    
    	chunk = DataChunk_new(QR_MODE_NUM);
    	chunk->size = size;
    	chunk->data = (unsigned char *)buf;
    	*bits_length -= sizeInBit;
    	*bits += sizeInBit;
    
    	return chunk;
    }
    
    static const char decodeAnTable[45] = {
    	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
    	'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
    	'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*',
    	'+', '-', '.', '/', ':'
    };
    
    static DataChunk *decodeAn(int *bits_length, unsigned char **bits, int version, int mqr)
    {
    	int i;
    	int size, sizeInBit, words, remain;
    	unsigned char *p;
    	char *buf, *q;
    	unsigned int val;
    	int ch, cl;
    	DataChunk *chunk;
    
    	size = decodeLength(bits_length, bits, QR_MODE_AN, version, mqr);
    	if(size < 0) return NULL;
    
    	words = size / 2;
    	remain = size - words * 2;
    	sizeInBit = words * 11 + remain * 6;
    	if(*bits_length < sizeInBit) {
    		printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
    		return NULL;
    	}
    
    	buf = (char *)malloc((size_t)size + 1);
    	p = *bits;
    	q = buf;
    	for(i=0; i<words; i++) {
    		val = bitToInt(p, 11);
    		ch = (int)(val / 45);
    		cl = (int)(val % 45);
    		sprintf(q, "%c%c", decodeAnTable[ch], decodeAnTable[cl]);
    		p += 11;
    		q += 2;
    	}
    	if(remain == 1) {
    		val = bitToInt(p, 6);
    		sprintf(q, "%c", decodeAnTable[val]);
    	}
    
    	chunk = DataChunk_new(QR_MODE_AN);
    	chunk->size = size;
    	chunk->data = (unsigned char *)buf;
    	*bits_length -= sizeInBit;
    	*bits += sizeInBit;
    
    	return chunk;
    }
    
    static DataChunk *decode8(int *bits_length, unsigned char **bits, int version, int mqr)
    {
    	int i;
    	int size, sizeInBit;
    	unsigned char *p;
    	unsigned char *buf, *q;
    	DataChunk *chunk;
    
    	size = decodeLength(bits_length, bits, QR_MODE_8, version, mqr);
    	if(size < 0) return NULL;
    
    	sizeInBit = size * 8;
    	if(*bits_length < sizeInBit) {
    		printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
    		return NULL;
    	}
    
    	buf = (unsigned char *)malloc((size_t)size);
    	p = *bits;
    	q = buf;
    	for(i=0; i<size; i++) {
    		*q = (unsigned char)bitToInt(p, 8);
    		p += 8;
    		q += 1;
    	}
    
    	chunk = DataChunk_new(QR_MODE_8);
    	chunk->size = size;
    	chunk->data = buf;
    	*bits_length -= sizeInBit;
    	*bits += sizeInBit;
    
    	return chunk;
    }
    
    static DataChunk *decodeKanji(int *bits_length, unsigned char **bits, int version, int mqr)
    {
    	int i;
    	int size, sizeInBit;
    	unsigned char *p;
    	char *buf, *q;
    	unsigned int val;
    	unsigned int ch, cl;
    	DataChunk *chunk;
    
    	size = decodeLength(bits_length, bits, QR_MODE_KANJI, version, mqr);
    	if(size < 0) return NULL;
    
    	sizeInBit = size * 13;
    	if(*bits_length < sizeInBit) {
    		printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
    		return NULL;
    	}
    
    	buf = (char *)malloc((size_t)size * 2 + 1);
    	p = *bits;
    	q = buf;
    	for(i=0; i<size; i++) {
    		val = bitToInt(p, 13);
    		ch = val / 0xc0;
    		cl = val - ch * 0xc0;
    		val = ch * 256 + cl;
    		if(val >= 0x1f00) {
    			val += 0xc140;
    		} else {
    			val += 0x8140;
    		}
    		sprintf(q, "%c%c", (val>>8) & 0xff, val & 0xff);
    		p += 13;
    		q += 2;
    	}
    
    	chunk = DataChunk_new(QR_MODE_KANJI);
    	chunk->size = size * 2;
    	chunk->data = (unsigned char *)buf;
    	*bits_length -= sizeInBit;
    	*bits += sizeInBit;
    
    	return chunk;
    }
    
    static DataChunk *decodeChunk(int *bits_length, unsigned char **bits, int version)
    {
    	unsigned int val;
    
    	if(*bits_length < 4) {
    		return NULL;
    	}
    	val = bitToInt(*bits, 4);
    	*bits_length -= 4;
    	*bits += 4;
    	switch(val) {
    		case 0:
    			return NULL;
    		case 1:
    			return decodeNum(bits_length, bits, version, 0);
    		case 2:
    			return decodeAn(bits_length, bits, version, 0);
    		case 4:
    			return decode8(bits_length, bits, version, 0);
    		case 8:
    			return decodeKanji(bits_length, bits, version, 0);
    		default:
    			break;
    	}
    
    	printf("Invalid mode in a chunk: %d\n", val);
    
    	return NULL;
    }
    
    static DataChunk *decodeChunkMQR(int *bits_length, unsigned char **bits, int version)
    {
    	int modebits, termbits;
    	unsigned int val;
    
    	modebits = version - 1;
    	termbits = version * 2 + 1;
    	if(*bits_length >= termbits) {
    		val = bitToInt(*bits, termbits);
    		if(val == 0) {
    			*bits += termbits;
    			*bits_length -= termbits;
    			return NULL;
    		}
    	} else {
    		if(*bits_length < modebits) {
    			val = bitToInt(*bits, *bits_length);
    		} else {
    			val = bitToInt(*bits, modebits);
    		}
    		if(val == 0) {
    			return NULL;
    		} else {
    			printf("Terminating bits include 1-bit.\n");
    			return NULL;
    		}
    	}
    	val = bitToInt(*bits, modebits);
    	if(version == 4 && val > 3) {
    		printf("Invalid mode number %d.\n", val);
    	}
    	*bits_length -= modebits;
    	*bits += modebits;
    	switch(val) {
    		case 0:
    			return decodeNum(bits_length, bits, version, 1);
    		case 1:
    			return decodeAn(bits_length, bits, version, 1);
    		case 2:
    			return decode8(bits_length, bits, version, 1);
    		case 3:
    			return decodeKanji(bits_length, bits, version, 1);
    		default:
    			break;
    	}
    
    	printf("Invalid mode in a chunk: %d\n", val);
    
    	return NULL;
    }
    
    static int appendChunk(QRdata *qrdata, int *bits_length, unsigned char **bits)
    {
    	DataChunk *chunk;
    
    	if(qrdata->mqr) {
    		chunk = decodeChunkMQR(bits_length, bits, qrdata->version);
    	} else {
    		chunk = decodeChunk(bits_length, bits, qrdata->version);
    	}
    	if(chunk == NULL) {
    		return 1;
    	}
    
    	if(qrdata->last == NULL) {
    		qrdata->chunks = chunk;
    	} else {
    		qrdata->last->next = chunk;
    	}
    	qrdata->last = chunk;
    
    	return 0;
    }
    
    QRdata *QRdata_new(void)
    {
    	QRdata *qrdata;
    
    	qrdata = (QRdata *)calloc(sizeof(QRdata), 1);
    	if(qrdata == NULL) return NULL;
    
    	qrdata->eccResult = 0;
    
    	return qrdata;
    }
    
    QRdata *QRdata_newMQR(void)
    {
    	QRdata *qrdata;
    
    	qrdata = QRdata_new();
    	if(qrdata == NULL) return NULL;
    
    	qrdata->mqr = 1;
    
    	return qrdata;
    }
    
    void QRdata_free(QRdata *qrdata)
    {
    	DataChunk_freeList(qrdata->chunks);
    	if(qrdata->data != NULL) {
    		free(qrdata->data);
    	}
    	free(qrdata);
    }
    
    static int QRdata_decodeBits(QRdata *qrdata, int length, unsigned char *bits)
    {
    	int ret = 0;
    
    	while(ret == 0) {
    		ret = appendChunk(qrdata, &length, &bits);
    	}
    
    	return length;
    }
    
    int QRdata_decodeBitStream(QRdata *qrdata, BitStream *bstream)
    {
    	return QRdata_decodeBits(qrdata, bstream->length, bstream->data);
    }
    
    void QRdata_dump(QRdata *data)
    {
    	DataChunk_dumpChunkList(data->chunks);
    }
    
    int QRcode_decodeVersion(QRcode *code)
    {
    	unsigned int v1, v2;
    	int x, y, width;
    	unsigned char *p;
    
    	width = code->width;
    	if(width < 45) {
    		return (width - 21)/ 4 + 1;
    	}
    
    	v1 = 0;
    	p = code->data + width * (width - 9) + 5;
    	for(x=0; x<6; x++) {
    		for(y=0; y<3; y++) {
    			v1 = v1 << 1;
    			v1 |= *(p - y * width - x) & 1;
    		}
    	}
    
    	v2 = 0;
    	p = code->data + width * 5 + width - 9;
    	for(y=0; y<6; y++) {
    		for(x=0; x<3; x++) {
    			v2 = v2 << 1;
    			v2 |= *(p - y * width - x) & 1;
    		}
    	}
    
    	if(v1 != v2) {
    		printf("Two verion patterns are different.\n");
    		return -1;
    	}
    
    	return (int)(v1 >> 12);
    }
    
    int QRcode_decodeFormat(QRcode *code, QRecLevel *level, int *mask)
    {
    	unsigned int v1, v2;
    	int i, width;
    	unsigned char *p;
    
    	width = code->width;
    
    	v1 = 0;
    	p = code->data + width * 8;
    	for(i=0; i<8; i++) {
    		v1 = v1 << 1;
    		if(i < 6) {
    			v1 |= *(p + i) & 1;
    		} else {
    			v1 |= *(p + i + 1) & 1;
    		}
    	}
    	p = code->data + width * 7 + 8;
    	for(i=0; i<7; i++) {
    		v1 = v1 << 1;
    		if(i < 1) {
    			v1 |= *(p - width * i) & 1;
    		} else {
    			v1 |= *(p - width * (i + 1)) & 1;
    		}
    	}
    
    	v2 = 0;
    	p = code->data + width * (width - 1) + 8;
    	for(i=0; i<7; i++) {
    		v2 = v2 << 1;
    		v2 |= *(p - width * i) & 1;
    	}
    	p = code->data + width * 8 + width - 8;
    	for(i=0; i<8; i++) {
    		v2 = v2 << 1;
    		v2 |= *(p + i) & 1;
    	}
    
    	if(v1 != v2) {
    		printf("Two format infos are different.\n");
    		return -1;
    	}
    	v1 = (v1 ^ 0x5412) >> 10;
    	*mask = v1 & 7;
    	switch((v1 >> 3) & 3) {
    		case 1:
    			*level = QR_ECLEVEL_L;
    			break;
    		case 0:
    			*level = QR_ECLEVEL_M;
    			break;
    		case 3:
    			*level = QR_ECLEVEL_Q;
    			break;
    		case 2:
    			*level = QR_ECLEVEL_H;
    			break;
    		default:
    			break;
    	}
    
    	return 0;
    }
    
    static unsigned char *unmask(QRcode *code, QRecLevel level, int mask)
    {
    	unsigned char *unmasked;
    
    	unmasked = Mask_makeMask(code->width, code->data, mask, level);
    
    	return unmasked;
    }
    
    unsigned char *QRcode_unmask(QRcode *code)
    {
    	int ret, version, mask;
    	QRecLevel level;
    
    	version = QRcode_decodeVersion(code);
    	if(version < 1) return NULL;
    	ret = QRcode_decodeFormat(code, &level, &mask);
    	if(ret < 0) return NULL;
    
    	return unmask(code, level, mask);
    }
    
    typedef struct {
    	int width;
    	unsigned char *frame;
    	int x, y;
    	int dir;
    	int bit;
    	int mqr;
    } FrameFiller;
    
    static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr)
    {
    	FrameFiller *filler;
    
    	filler = (FrameFiller *)malloc(sizeof(FrameFiller));
    	if(filler == NULL) return NULL;
    	filler->width = width;
    	filler->frame = frame;
    	filler->x = width - 1;
    	filler->y = width - 1;
    	filler->dir = -1;
    	filler->bit = -1;
    	filler->mqr = mqr;
    
    	return filler;
    }
    
    static unsigned char *FrameFiller_next(FrameFiller *filler)
    {
    	unsigned char *p;
    	int x, y, w;
    
    	if(filler->bit == -1) {
    		filler->bit = 0;
    		return filler->frame + filler->y * filler->width + filler->x;
    	}
    
    	x = filler->x;
    	y = filler->y;
    	p = filler->frame;
    	w = filler->width;
    
    	if(filler->bit == 0) {
    		x--;
    		filler->bit++;
    	} else {
    		x++;
    		y += filler->dir;
    		filler->bit--;
    	}
    
    	if(filler->dir < 0) {
    		if(y < 0) {
    			y = 0;
    			x -= 2;
    			filler->dir = 1;
    			if(!filler->mqr && x == 6) {
    				x--;
    				y = 9;
    			}
    		}
    	} else {
    		if(y == w) {
    			y = w - 1;
    			x -= 2;
    			filler->dir = -1;
    			if(!filler->mqr && x == 6) {
    				x--;
    				y -= 8;
    			}
    		}
    	}
    	if(x < 0 || y < 0) return NULL;
    
    	filler->x = x;
    	filler->y = y;
    
    	if(p[y * w + x] & 0x80) {
    		// This tail recursion could be optimized.
    		return FrameFiller_next(filler);
    	}
    	return &p[y * w + x];
    }
    
    static BitStream *extractBits(int width, unsigned char *frame, int spec[5])
    {
    	BitStream *bstream;
    	unsigned char *bits, *p, *q;
    	FrameFiller *filler;
    	int i, j;
    	int col, row, d1, b1, blocks, idx, words;
    
    	blocks = QRspec_rsBlockNum(spec);
    	words = QRspec_rsDataLength(spec);
    	d1 = QRspec_rsDataCodes1(spec);
    	b1 = QRspec_rsBlockNum1(spec);
    	bits = (unsigned char *)malloc((size_t)words * 8);
    	/*
    	 * 00 01 02 03 04 05 06 07 08 09
    	 * 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 36 37 38 39 40 41
    	 * 42 43 44 45 46 47 48 49 50 51 52
    	 */
    
    	row = col = 0;
    	filler = FrameFiller_new(width, frame, 0);
    	for(i=0; i<words; i++) {
    		col = i / blocks;
    		row = i % blocks + ((col >= d1)?b1:0);
    		idx = d1 * row + col + ((row > b1)?(row-b1):0);
    		q = bits + idx * 8;
    		for(j=0; j<8; j++) {
    			p = FrameFiller_next(filler);
    			q[j] = *p & 1;
    		}
    	}
    	free(filler);
    
    	bstream = BitStream_newWithBits((size_t)words * 8, bits);
    	free(bits);
    
    	return bstream;
    }
    
    BitStream *QRcode_extractBits(QRcode *code, int *dataLength, int *eccLength)
    {
    	BitStream *bstream;
    	unsigned char *unmasked;
    	int spec[5];
    	int ret, version, mask;
    	QRecLevel level;
    
    	version = QRcode_decodeVersion(code);
    	if(version < 1) return NULL;
    	ret = QRcode_decodeFormat(code, &level, &mask);
    	if(ret < 0) return NULL;
    
    	QRspec_getEccSpec(version, level, spec);
    
    	unmasked = unmask(code, level, mask);
    	if(unmasked == NULL) return NULL;
    
    	bstream = extractBits(code->width, unmasked, spec);
    	free(unmasked);
    
    	*dataLength = QRspec_rsDataLength(spec) * 8;
    	*eccLength = QRspec_rsEccLength(spec) * 8;
    
    	return bstream;
    }
    
    static int checkRemainderWords(int length, unsigned char *bits, int remainder)
    {
    	int rbits, words;
    	unsigned char *p, v;
    	int i;
    
    	words = remainder / 8;
    	rbits = remainder - words * 8;
    	bits += (length - remainder);
    	for(i=0; i<rbits; i++) {
    		if((bits[i]&1) != 0) {
    			printf("Terminating code includes 1-bit.\n");
    			printBinary(bits, remainder);
    			return -1;
    		}
    	}
    	p = bits + rbits;
    	for(i=0; i<words; i++) {
    		v = (unsigned char)bitToInt(p, 8);
    		if(v != ((i&1)?0x11:0xec)) {
    			printf("Remainder codewords wrong.\n");
    			printBinary(bits, remainder);
    			return -1;
    		}
    		p += 8;
    	}
    
    	return 0;
    }
    
    QRdata *QRcode_decodeBits(QRcode *code)
    {
    	BitStream *bstream;
    	unsigned char *unmasked;
    	int spec[5];
    	int ret, version, mask;
    	int length;
    	QRecLevel level;
    	QRdata *qrdata;
    
    	version = QRcode_decodeVersion(code);
    	if(version < 1) return NULL;
    	ret = QRcode_decodeFormat(code, &level, &mask);
    	if(ret < 0) return NULL;
    
    	QRspec_getEccSpec(version, level, spec);
    	length = QRspec_rsDataLength(spec) * 8;
    
    	unmasked = unmask(code, level, mask);
    	if(unmasked == NULL) return NULL;
    
    	bstream = extractBits(code->width, unmasked, spec);
    	free(unmasked);
    
    	qrdata = QRdata_new();
    	qrdata->version = version;
    	qrdata->level = level;
    	ret = QRdata_decodeBitStream(qrdata, bstream);
    	if(ret > 0) {
    		checkRemainderWords(length, bstream->data, ret);
    	}
    
    	BitStream_free(bstream);
    
    	return qrdata;
    }
    
    void QRdata_concatChunks(QRdata *qrdata)
    {
    	qrdata->data = DataChunk_concatChunkList(qrdata->chunks, &qrdata->size);
    }
    
    QRdata *QRcode_decode(QRcode *code)
    {
    	QRdata *qrdata;
    
    	qrdata = QRcode_decodeBits(code);
    	QRdata_concatChunks(qrdata);
    
    	return qrdata;
    }
    
    /*
     * Micro QR Code decoder
     */
    
    struct FormatInfo MQRformat[] = {
    	{1, QR_ECLEVEL_L},
    	{2, QR_ECLEVEL_L},
    	{2, QR_ECLEVEL_M},
    	{3, QR_ECLEVEL_L},
    	{3, QR_ECLEVEL_M},
    	{4, QR_ECLEVEL_L},
    	{4, QR_ECLEVEL_M},
    	{4, QR_ECLEVEL_Q}
    };
    
    int QRcode_decodeFormatMQR(QRcode *code, int *version, QRecLevel *level, int *mask)
    {
    	unsigned int v, t;
    	int i, width;
    	unsigned char *p;
    
    	width = code->width;
    
    	v = 0;
    	p = code->data + width * 8 + 1;
    	for(i=0; i<8; i++) {
    		v = v << 1;
    		v |= p[i] & 1;
    	}
    	p = code->data + width * 7 + 8;
    	for(i=0; i<7; i++) {
    		v = v << 1;
    		v |= *(p - width * i) & 1;
    	}
    	v ^= 0x4445;
    	*mask = (v >> 10) & 3;
    	t = (v >> 12) & 7;
    	*version = MQRformat[t].version;
    	*level = MQRformat[t].level;
    	if(*version * 2 + 9 != width) {
    		printf("Decoded version number does not match to the size.\n");
    		return -1;
    	}
    	return 0;
    }
    
    static unsigned char *unmaskMQR(QRcode *code, QRecLevel level, int mask)
    {
    	unsigned char *unmasked;
    
    	unmasked = MMask_makeMask(code->version, code->data, mask, level);
    
    	return unmasked;
    }
    
    unsigned char *QRcode_unmaskMQR(QRcode *code)
    {
    	int ret, version, mask;
    	QRecLevel level;
    
    	ret = QRcode_decodeFormatMQR(code, &version, &level, &mask);
    	if(ret < 0) return NULL;
    
    	return unmaskMQR(code, level, mask);
    }
    
    static BitStream *extractBitsMQR(int width, unsigned char *frame, int version, QRecLevel level)
    {
    	BitStream *bstream;
    	unsigned char *bits;
    	FrameFiller *filler;
    	int i;
    	int size;
    
    	size = MQRspec_getDataLengthBit(version, level) + MQRspec_getECCLength(version, level) * 8;
    	bits = (unsigned char *)malloc((size_t)size);
    	filler = FrameFiller_new(width, frame, 1);
    	for(i=0; i<size; i++) {
    		bits[i] = *(FrameFiller_next(filler)) & 1;
    	}
    	free(filler);
    
    	bstream = BitStream_newWithBits((size_t)size, bits);
    	free(bits);
    
    	return bstream;
    }
    
    BitStream *QRcode_extractBitsMQR(QRcode *code, int *dataLength, int *eccLength, int *version, QRecLevel *level)
    {
    	BitStream *bstream;
    	unsigned char *unmasked;
    	int ret, mask;
    
    	ret = QRcode_decodeFormatMQR(code, version, level, &mask);
    	if(ret < 0) return NULL;
    
    	unmasked = unmaskMQR(code, *level, mask);
    	if(unmasked == NULL) return NULL;
    
    	*dataLength = MQRspec_getDataLengthBit(*version, *level);
    	*eccLength = MQRspec_getECCLength(*version, *level) * 8;
    	bstream = extractBitsMQR(code->width, unmasked, *version, *level);
    	free(unmasked);
    
    	return bstream;
    }
    
    static int checkRemainderWordsMQR(int length, unsigned char *bits, int remainder, int version)
    {
    	int rbits, words, paddings;
    	unsigned char *p, v;
    	int i, decoded;
    
    	decoded = length - remainder;
    	bits += decoded;
    	words = (decoded + 7) / 8;
    	rbits = words * 8 - decoded;
    	for(i=0; i<rbits; i++) {
    		if((bits[i]&1) != 0) {
    			printf("Terminating code includes 1-bit.\n");
    			printBinary(bits, remainder);
    			return -1;
    		}
    	}
    
    	paddings = (length - words * 8) / 8;
    	p = bits + rbits;
    	for(i=0; i<paddings; i++) {
    		v = (unsigned char)bitToInt(p, 8);
    		if(v != ((i&1)?0x11:0xec)) {
    			printf("Remainder codewords wrong.\n");
    			printBinary(bits, remainder);
    			return -1;
    		}
    		p += 8;
    	}
    	rbits = length - (paddings + words)* 8;
    	if(rbits > 0) {
    		if((version == 1 || version == 3) && rbits == 4) {
    			v = (unsigned char)bitToInt(p, 4);
    			if(v != 0) {
    				printf("Last padding bits include 1-bit.\n");
    				return -1;
    			}
    		} else {
    			printf("The length of the last padding bits is %d, not %d.\n", rbits, (version == 1 || version == 3)?4:0);
    			return -1;
    		}
    	}
    
    	return 0;
    }
    
    QRdata *QRcode_decodeBitsMQR(QRcode *code)
    {
    	BitStream *bstream;
    	int ret, version, dataLength, eccLength;
    	QRecLevel level;
    	QRdata *qrdata;
    
    	bstream = QRcode_extractBitsMQR(code, &dataLength, &eccLength, &version, &level);
    	if(bstream == NULL) {
    		return NULL;
    	}
    
    	qrdata = QRdata_newMQR();
    	qrdata->version = version;
    	qrdata->level = level;
    	ret = QRdata_decodeBits(qrdata, dataLength, bstream->data);
    	if(ret > 0) {
    		ret = checkRemainderWordsMQR(dataLength, bstream->data, ret, version);
    		if(ret < 0) {
    			QRdata_free(qrdata);
    			qrdata = NULL;
    		}
    	}
    
    	BitStream_free(bstream);
    
    	return qrdata;
    }
    
    QRdata *QRcode_decodeMQR(QRcode *code)
    {
    	QRdata *qrdata;
    	qrdata = QRcode_decodeBitsMQR(code);
    	if(qrdata != NULL) {
    		QRdata_concatChunks(qrdata);
    	}
    
    	return qrdata;
    }