From 923b445ddb3c5d45ccebd9031770081f87fbd603 Mon Sep 17 00:00:00 2001 From: Joel Sutter Date: Fri, 17 Jun 2011 14:57:42 +0200 Subject: [PATCH] Fix bitcount info length calculation, Symbols with versions larger than 9 should work propperly now --- include/dataencoder.h | 19 +++---------- src/qrgen/dataencoder.c | 60 ++++++++++++++++++++++++++++++++++------- src/qrgen/symbolinfo.c | 10 ++++--- 3 files changed, 59 insertions(+), 30 deletions(-) diff --git a/include/dataencoder.h b/include/dataencoder.h index c926a1c..2b909ae 100644 --- a/include/dataencoder.h +++ b/include/dataencoder.h @@ -10,24 +10,11 @@ static const byte Terminator = 0; // 0000 static const byte Padding[] = {236, 17}; // 11101100 and 00010001 -/* - * This needs to be extended - * now only Version 1-9 are coded - * Version Numeric Alpha Byte - * 1 - 9 10 9 8 - * 10 - 26 12 11 16 - * 27 - 40 13 13 16 - */ -typedef enum { - CountByte = 8, - CountAlpha, // 9 - CountNumeric // 10 -} CharacterCountBitsCount; - struct SymbolInfo; bool encodeData(bitstream* bs, const SymbolInfo* si); -int getBitCount(int numChars, EncodeModeIndicator mode); -int getByteCount(int numChars, EncodeModeIndicator mode); +int getBitCount(int numChars, EncodeModeIndicator mode, int version); +int getByteCount(int numChars, EncodeModeIndicator mode, int version); +int getCharacterCountBitCount(EncodeModeIndicator mode, int version); #endif //DATAENCODER_H diff --git a/src/qrgen/dataencoder.c b/src/qrgen/dataencoder.c index 885b1c0..11137cc 100644 --- a/src/qrgen/dataencoder.c +++ b/src/qrgen/dataencoder.c @@ -18,19 +18,16 @@ bool encodeData(bitstream* bs, const SymbolInfo* si) bool (*encode)(bitstream* bs, const byte* data, int dataSize) = NULL; /* Mode specific encode routine */ - CharacterCountBitsCount ccbc = 0; /* Mode specific size of Character Count Information */ + int ccbc = 0; /* Mode specific size of Character Count Information */ switch(si->encodeMode) { case ModeByte: - ccbc = CountByte; encode = &encodeByte; break; case ModeAlpha: - ccbc = CountAlpha; encode = &encodeAlpha; break; case ModeNumeric: - ccbc = CountNumeric; encode = &encodeNumeric; break; default: @@ -38,6 +35,8 @@ bool encodeData(bitstream* bs, const SymbolInfo* si) return false; } + ccbc = getCharacterCountBitCount(si->encodeMode, si->version); + bs_add_b(bs, si->encodeMode, 4); /* add Mode information*/ bs_add_i(bs, si->dataCount, ccbc); /* add Character count information */ bool ret = (*encode)(bs, si->inputData, si->dataCount); /* add data, mode speicific */ @@ -63,22 +62,22 @@ bool encodeData(bitstream* bs, const SymbolInfo* si) } -int getBitCount(int numChars, EncodeModeIndicator mode) +int getBitCount(int numChars, EncodeModeIndicator mode, int version) { switch(mode) { case ModeNumeric: - return 4 + CountNumeric + 10 * (numChars / 3) + ((numChars % 3 == 0) ? 0 : ((numChars % 3 == 1) ? 4 : 7)); + return 4 + getCharacterCountBitCount(mode, version) + 10 * (numChars / 3) + ((numChars % 3 == 0) ? 0 : ((numChars % 3 == 1) ? 4 : 7)); case ModeAlpha: - return 4 + CountAlpha + 11 * (numChars / 2) + 6 *(numChars % 2); + return 4 + getCharacterCountBitCount(mode, version) + 11 * (numChars / 2) + 6 *(numChars % 2); case ModeByte: - return 4 + CountByte + 8 * numChars; + return 4 + getCharacterCountBitCount(mode, version) + 8 * numChars; } return 0; } -int getByteCount(int numChars, EncodeModeIndicator mode) +int getByteCount(int numChars, EncodeModeIndicator mode, int version) { - int tmp = getBitCount(numChars, mode); + int tmp = getBitCount(numChars, mode, version); return tmp / 8 + ((tmp % 8) ? 1 : 0); } @@ -180,5 +179,46 @@ byte alphaValue(byte alpha) error("Character not usable in alpha mode: %c", alpha); return -1; +} +int getCharacterCountBitCount(EncodeModeIndicator mode, int version) +{ +/* + * Version Numeric Alpha Byte + * 1 - 9 10 9 8 + * 10 - 26 12 11 16 + * 27 - 40 13 13 16 + */ + switch(mode) + { + case ModeNumeric: + if (version >= 1 && version <= 9) + return 10; + else if (version >= 10 && version <= 26) + return 12; + else if (version >= 27 && version <= 40) + return 13; + break; + case ModeAlpha: + if (version >= 1 && version <= 9) + return 9; + else if (version >= 10 && version <= 26) + return 11; + else if (version >= 27 && version <= 40) + return 13; + break; + case ModeByte: + if (version >= 1 && version <= 9) + return 8; + else if (version >= 10 && version <= 26) + return 16; + else if (version >= 27 && version <= 40) + return 16; + break; + default: + error("Mode %d invalid", mode); + return -1; + } + error("Version %d invalid", version); + return -1; } diff --git a/src/qrgen/symbolinfo.c b/src/qrgen/symbolinfo.c index 1996b07..797b337 100644 --- a/src/qrgen/symbolinfo.c +++ b/src/qrgen/symbolinfo.c @@ -165,7 +165,7 @@ bool si_encode(SymbolInfo* si) si->ecCodeWords = get_ec_codewords(si->version, si->ecLevel); si->dataCodeWords = get_data_codewords(si->version, si->ecLevel); si->blockInfo = get_block_info(si->version, si->ecLevel); - si->encodedDataCount = getByteCount(si->dataCount, si->encodeMode); + si->encodedDataCount = getByteCount(si->dataCount, si->encodeMode, si->version); /* 2. encode data */ bitstream* bs = bs_init(); @@ -208,11 +208,13 @@ bool si_encode(SymbolInfo* si) int get_min_version(int dataCount, int encMode, int ecLevel) { - dataCount = getByteCount(dataCount, encMode); + int byteCount; int i; if (dataCount < 0 || ecLevel < 0 || ecLevel > 3) return 0; - for (i = 0; i < 40; i++) { - if (get_data_codewords(i+1, ecLevel) >= dataCount) return i+1; + for (i = 1; i <= 40; i++) { + //at version 10 and 27 The characterCountDataLength changes, so recalculate the whole length + if (i == 1 || i == 10 || i == 27) byteCount = getByteCount(dataCount, encMode, i); + if (get_data_codewords(i, ecLevel) >= byteCount) return i; } return 0; }