public ReedSolomon(GenericGF galoisField, int correctionBytes) { _messageLength = galoisField.Size - 1; _correctionLength = correctionBytes; _informationLength = _messageLength - _correctionLength; _reedSolomonEncoder = new ReedSolomonEncoder(galoisField); _reedSolomonDecoder = new ReedSolomonDecoder(galoisField); _simpleRsDecoder = new SimpleRSDecoder(); }
public ReedSolomon(int correctionBytes) { var galoisField = GenericGF.DATA_MATRIX_FIELD_256; _messageLength = galoisField.Size - 1; _correctionLength = correctionBytes; _informationLength = _messageLength - _correctionLength; _reedSolomonEncoder = new ReedSolomonEncoder(galoisField); _reedSolomonDecoder = new ReedSolomonDecoder(galoisField); _simpleRsDecoder = new SimpleRSDecoder(); }
private static void testDecoder(GenericGF field, int[] dataWords, int[] ecWords) { ReedSolomonDecoder decoder = new ReedSolomonDecoder(field); int[] message = new int[dataWords.Length + ecWords.Length]; int maxErrors = ecWords.Length / 2; Random random = getPseudoRandom(); int iterations = field.Size > 256 ? 1 : DECODER_TEST_ITERATIONS; for (int j = 0; j < iterations; j++) { for (int i = 0; i < ecWords.Length; i++) { if (i > 10 && i < ecWords.Length / 2 - 10) { // performance improvement - skip intermediate cases in long-running tests i += ecWords.Length / 10; } Array.Copy(dataWords, 0, message, 0, dataWords.Length); Array.Copy(ecWords, 0, message, dataWords.Length, ecWords.Length); corrupt(message, i, random, field.Size); if (!decoder.decode(message, ecWords.Length)) { // fail only if maxErrors exceeded Assert.IsTrue(i > maxErrors, "Decode in " + field + " (" + dataWords.Length + ',' + ecWords.Length + ") failed at " + i); // else stop break; } if (i < maxErrors) { assertDataEquals("Decode in " + field + " (" + dataWords.Length + ',' + ecWords.Length + ") failed at " + i + " errors", dataWords, message); } } } }
/// <summary> /// Initializes a new instance of the <see cref="Decoder"/> class. /// </summary> public Decoder() { rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256); }
/// <summary> /// Corrects the parameter bits using Reed-Solomon algorithm /// </summary> /// <param name="parameterData">paremeter bits</param> /// <param name="compact">compact true if this is a compact Aztec code</param> /// <returns></returns> private static bool correctParameterData(bool[] parameterData, bool compact) { int numCodewords; int numDataCodewords; if (compact) { numCodewords = 7; numDataCodewords = 2; } else { numCodewords = 10; numDataCodewords = 4; } int numECCodewords = numCodewords - numDataCodewords; int[] parameterWords = new int[numCodewords]; const int codewordSize = 4; for (int i = 0; i < numCodewords; i++) { int flag = 1; for (int j = 1; j <= codewordSize; j++) { if (parameterData[codewordSize * i + codewordSize - j]) { parameterWords[i] += flag; } flag <<= 1; } } var rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM); if (!rsDecoder.decode(parameterWords, numECCodewords)) return false; for (int i = 0; i < numDataCodewords; i++) { int flag = 1; for (int j = 1; j <= codewordSize; j++) { parameterData[i * codewordSize + codewordSize - j] = (parameterWords[i] & flag) == flag; flag <<= 1; } } return true; }
/// <summary> /// Initializes a new instance of the <see cref="Decoder"/> class. /// </summary> public Decoder() { rsDecoder = new ReedSolomonDecoder(GenericGF.QR_CODE_FIELD_256); }
/// <summary> ///Performs RS error correction on an array of bits. /// </summary> /// <param name="rawbits">The rawbits.</param> /// <returns>the corrected array</returns> private bool[] correctBits(bool[] rawbits) { GenericGF gf; int codewordSize; if (ddata.NbLayers <= 2) { codewordSize = 6; gf = GenericGF.AZTEC_DATA_6; } else if (ddata.NbLayers <= 8) { codewordSize = 8; gf = GenericGF.AZTEC_DATA_8; } else if (ddata.NbLayers <= 22) { codewordSize = 10; gf = GenericGF.AZTEC_DATA_10; } else { codewordSize = 12; gf = GenericGF.AZTEC_DATA_12; } int numDataCodewords = ddata.NbDatablocks; int numCodewords = rawbits.Length/codewordSize; if (numCodewords < numDataCodewords) return null; int offset = rawbits.Length%codewordSize; int numECCodewords = numCodewords - numDataCodewords; int[] dataWords = new int[numCodewords]; for (int i = 0; i < numCodewords; i++, offset += codewordSize) { dataWords[i] = readCode(rawbits, offset, codewordSize); } var rsDecoder = new ReedSolomonDecoder(gf); if (!rsDecoder.decode(dataWords, numECCodewords)) return null; // Now perform the unstuffing operation. // First, count how many bits are going to be thrown out as stuffing int mask = (1 << codewordSize) - 1; int stuffedBits = 0; for (int i = 0; i < numDataCodewords; i++) { int dataWord = dataWords[i]; if (dataWord == 0 || dataWord == mask) { return null; } else if (dataWord == 1 || dataWord == mask - 1) { stuffedBits++; } } // Now, actually unpack the bits and remove the stuffing bool[] correctedBits = new bool[numDataCodewords*codewordSize - stuffedBits]; int index = 0; for (int i = 0; i < numDataCodewords; i++) { int dataWord = dataWords[i]; if (dataWord == 1 || dataWord == mask - 1) { // next codewordSize-1 bits are all zeros or all ones SupportClass.Fill(correctedBits, index, index + codewordSize - 1, dataWord > 1); index += codewordSize - 1; } else { for (int bit = codewordSize - 1; bit >= 0; --bit) { correctedBits[index++] = (dataWord & (1 << bit)) != 0; } } } if (index != correctedBits.Length) return null; return correctedBits; }
/// <summary> /// Corrects the parameter bits using Reed-Solomon algorithm /// </summary> /// <param name="parameterData">paremeter bits</param> /// <param name="compact">compact true if this is a compact Aztec code</param> /// <returns></returns> private static int getCorrectedParameterData(long parameterData, bool compact) { int numCodewords; int numDataCodewords; if (compact) { numCodewords = 7; numDataCodewords = 2; } else { numCodewords = 10; numDataCodewords = 4; } int numECCodewords = numCodewords - numDataCodewords; int[] parameterWords = new int[numCodewords]; for (int i = numCodewords - 1; i >= 0; --i) { parameterWords[i] = (int)parameterData & 0xF; parameterData >>= 4; } var rsDecoder = new ReedSolomonDecoder(GenericGF.AZTEC_PARAM); if (!rsDecoder.decode(parameterWords, numECCodewords)) return -1; // Toss the error correction. Just return the data as an integer int result = 0; for (int i = 0; i < numDataCodewords; i++) { result = (result << 4) + parameterWords[i]; } return result; }
/// <summary> /// Decoder() constructor /// </summary> public Decoder() { rsDecoder = new ReedSolomonDecoder(GenericGF.MAXICODE_FIELD_64); }
/// <summary> /// performs RS error correction on an array of bits /// </summary> /// <param name="rawbits">The rawbits.</param> /// <returns>the corrected array</returns> /// <exception cref="FormatException">if the input contains too many errors</exception> private bool[] correctBits(bool[] rawbits) { GenericGF gf; if (ddata.NbLayers <= 2) { codewordSize = 6; gf = GenericGF.AZTEC_DATA_6; } else if (ddata.NbLayers <= 8) { codewordSize = 8; gf = GenericGF.AZTEC_DATA_8; } else if (ddata.NbLayers <= 22) { codewordSize = 10; gf = GenericGF.AZTEC_DATA_10; } else { codewordSize = 12; gf = GenericGF.AZTEC_DATA_12; } int numDataCodewords = ddata.NbDatablocks; int numECCodewords; int offset; if (ddata.Compact) { offset = NB_BITS_COMPACT[ddata.NbLayers] - numCodewords * codewordSize; numECCodewords = NB_DATABLOCK_COMPACT[ddata.NbLayers] - numDataCodewords; } else { offset = NB_BITS[ddata.NbLayers] - numCodewords * codewordSize; numECCodewords = NB_DATABLOCK[ddata.NbLayers] - numDataCodewords; } int[] dataWords = new int[numCodewords]; for (int i = 0; i < numCodewords; i++) { int flag = 1; for (int j = 1; j <= codewordSize; j++) { if (rawbits[codewordSize * i + codewordSize - j + offset]) { dataWords[i] += flag; } flag <<= 1; } //if (dataWords[i] >= flag) { // flag++; //} } var rsDecoder = new ReedSolomonDecoder(gf); if (!rsDecoder.decode(dataWords, numECCodewords)) return null; offset = 0; invertedBitCount = 0; bool[] correctedBits = new bool[numDataCodewords * codewordSize]; for (int i = 0; i < numDataCodewords; i++) { bool seriesColor = false; int seriesCount = 0; int flag = 1 << (codewordSize - 1); for (int j = 0; j < codewordSize; j++) { bool color = (dataWords[i] & flag) == flag; if (seriesCount == codewordSize - 1) { if (color == seriesColor) { //bit must be inverted return null; } seriesColor = false; seriesCount = 0; offset++; invertedBitCount++; } else { if (seriesColor == color) { seriesCount++; } else { seriesCount = 1; seriesColor = color; } correctedBits[i * codewordSize + j - offset] = color; } flag = (int)((uint)flag >> 1); // flag >>>= 1; } } return correctedBits; }