Implements Reed-Solomon encoding, as the name implies.
예제 #1
0
        private static void testEncodeDecodeRandom(GenericGF field, int dataSize, int ecSize)
        {
            Assert.IsTrue(dataSize > 0 && dataSize <= field.Size - 3, "Invalid data size for " + field);
            Assert.IsTrue(ecSize > 0 && ecSize + dataSize <= field.Size, "Invalid ECC size for " + field);
            ReedSolomonEncoder encoder = new ReedSolomonEncoder(field);

            int[]  message    = new int[dataSize + ecSize];
            int[]  dataWords  = new int[dataSize];
            int[]  ecWords    = new int[ecSize];
            Random random     = getPseudoRandom();
            int    iterations = field.Size > 256 ? 1 : DECODER_RANDOM_TEST_ITERATIONS;

            for (int i = 0; i < iterations; i++)
            {
                // generate random data
                for (int k = 0; k < dataSize; k++)
                {
                    dataWords[k] = random.Next(field.Size);
                }
                // generate ECC words
                Array.Copy(dataWords, 0, message, 0, dataWords.Length);
                encoder.encode(message, ecWords.Length);
                Array.Copy(message, dataSize, ecWords, 0, ecSize);
                // check to see if Decoder can fix up to ecWords/2 random errors
                testDecoder(field, dataWords, ecWords);
            }
        }
 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();
 }
예제 #4
0
        private static void testEncoder(GenericGF field, int[] dataWords, int[] ecWords)
        {
            ReedSolomonEncoder encoder = new ReedSolomonEncoder(field);

            int[] messageExpected = new int[dataWords.Length + ecWords.Length];
            int[] message         = new int[dataWords.Length + ecWords.Length];
            Array.Copy(dataWords, 0, messageExpected, 0, dataWords.Length);
            Array.Copy(ecWords, 0, messageExpected, dataWords.Length, ecWords.Length);
            Array.Copy(dataWords, 0, message, 0, dataWords.Length);
            encoder.encode(message, ecWords.Length);
            assertDataEquals("Encode in " + field + " (" + dataWords.Length + ',' + ecWords.Length + ") failed",
                             messageExpected, message);
        }
예제 #5
0
      private static BitArray generateCheckWords(BitArray bitArray, int totalBits, int wordSize)
      {
         if (bitArray.Size % wordSize != 0)
            throw new InvalidOperationException("size of bit array is not a multiple of the word size");

         // bitArray is guaranteed to be a multiple of the wordSize, so no padding needed
         int messageSizeInWords = bitArray.Size / wordSize;

         var rs = new ReedSolomonEncoder(getGF(wordSize));
         var totalWords = totalBits / wordSize;
         var messageWords = bitsToWords(bitArray, wordSize, totalWords);
         rs.encode(messageWords, totalWords - messageSizeInWords);

         var startPad = totalBits % wordSize;
         var messageBits = new BitArray();
         messageBits.appendBits(0, startPad);
         foreach (var messageWord in messageWords)
         {
            messageBits.appendBits(messageWord, wordSize);
         }
         return messageBits;
      }
예제 #6
0
      /// <summary>
      /// Encodes the given binary content as an Aztec symbol
      /// </summary>
      /// <param name="data">input data string</param>
      /// <param name="minECCPercent">minimal percentange of error check words (According to ISO/IEC 24778:2008,
      /// a minimum of 23% + 3 words is recommended)</param>
      /// <returns>Aztec symbol matrix with metadata</returns>
      public static AztecCode encode(byte[] data, int minECCPercent)
      {
         // High-level encode
         var bits = new HighLevelEncoder(data).encode();

         // stuff bits and choose symbol size
         int eccBits = bits.Size * minECCPercent / 100 + 11;
         int totalSizeBits = bits.Size + eccBits;
         int layers;
         int wordSize = 0;
         int totalSymbolBits = 0;
         BitArray stuffedBits = null;
         for (layers = 1; layers < NB_BITS_COMPACT.Length; layers++)
         {
            if (NB_BITS_COMPACT[layers] >= totalSizeBits)
            {
               if (wordSize != WORD_SIZE[layers])
               {
                  wordSize = WORD_SIZE[layers];
                  stuffedBits = stuffBits(bits, wordSize);
               }
               totalSymbolBits = NB_BITS_COMPACT[layers];
               if (stuffedBits.Size + eccBits <= NB_BITS_COMPACT[layers])
               {
                  break;
               }
            }
         }
         bool compact = true;
         if (layers == NB_BITS_COMPACT.Length)
         {
            compact = false;
            for (layers = 1; layers < NB_BITS.Length; layers++)
            {
               if (NB_BITS[layers] >= totalSizeBits)
               {
                  if (wordSize != WORD_SIZE[layers])
                  {
                     wordSize = WORD_SIZE[layers];
                     stuffedBits = stuffBits(bits, wordSize);
                  }
                  totalSymbolBits = NB_BITS[layers];
                  if (stuffedBits.Size + eccBits <= NB_BITS[layers])
                  {
                     break;
                  }
               }
            }
         }
         if (layers == NB_BITS.Length)
         {
            throw new ArgumentException("Data too large for an Aztec code");
         }

         // pad the end
         int messageSizeInWords = (stuffedBits.Size + wordSize - 1) / wordSize;
         for (int i = messageSizeInWords * wordSize - stuffedBits.Size; i > 0; i--)
         {
            stuffedBits.appendBit(true);
         }

         // generate check words
         var rs = new ReedSolomonEncoder(getGF(wordSize));
         var totalSizeInFullWords = totalSymbolBits / wordSize;
         var messageWords = bitsToWords(stuffedBits, wordSize, totalSizeInFullWords);
         rs.encode(messageWords, totalSizeInFullWords - messageSizeInWords);

         // convert to bit array and pad in the beginning
         var startPad = totalSymbolBits % wordSize;
         var messageBits = new BitArray();
         messageBits.appendBits(0, startPad);
         foreach (var messageWord in messageWords)
         {
            messageBits.appendBits(messageWord, wordSize);
         }

         // generate mode message
         var modeMessage = generateModeMessage(compact, layers, messageSizeInWords);

         // allocate symbol
         var baseMatrixSize = compact ? 11 + layers * 4 : 14 + layers * 4; // not including alignment lines
         var alignmentMap = new int[baseMatrixSize];
         int matrixSize;
         if (compact)
         {
            // no alignment marks in compact mode, alignmentMap is a no-op
            matrixSize = baseMatrixSize;
            for (int i = 0; i < alignmentMap.Length; i++)
            {
               alignmentMap[i] = i;
            }
         }
         else
         {
            matrixSize = baseMatrixSize + 1 + 2 * ((baseMatrixSize / 2 - 1) / 15);
            int origCenter = baseMatrixSize / 2;
            int center = matrixSize / 2;
            for (int i = 0; i < origCenter; i++)
            {
               int newOffset = i + i / 15;
               alignmentMap[origCenter - i - 1] = center - newOffset - 1;
               alignmentMap[origCenter + i] = center + newOffset + 1;
            }
         }
         var matrix = new BitMatrix(matrixSize);

         // draw mode and data bits
         for (int i = 0, rowOffset = 0; i < layers; i++)
         {
            int rowSize = compact ? (layers - i) * 4 + 9 : (layers - i) * 4 + 12;
            for (int j = 0; j < rowSize; j++)
            {
               int columnOffset = j * 2;
               for (int k = 0; k < 2; k++)
               {
                  if (messageBits[rowOffset + columnOffset + k])
                  {
                     matrix[alignmentMap[i * 2 + k], alignmentMap[i * 2 + j]] = true;
                  }
                  if (messageBits[rowOffset + rowSize * 2 + columnOffset + k])
                  {
                     matrix[alignmentMap[i * 2 + j], alignmentMap[baseMatrixSize - 1 - i * 2 - k]] = true;
                  }
                  if (messageBits[rowOffset + rowSize * 4 + columnOffset + k])
                  {
                     matrix[alignmentMap[baseMatrixSize - 1 - i * 2 - k], alignmentMap[baseMatrixSize - 1 - i * 2 - j]] = true;
                  }
                  if (messageBits[rowOffset + rowSize * 6 + columnOffset + k])
                  {
                     matrix[alignmentMap[baseMatrixSize - 1 - i * 2 - j], alignmentMap[i * 2 + k]] = true;
                  }
               }
            }
            rowOffset += rowSize * 8;
         }
         drawModeMessage(matrix, compact, matrixSize, modeMessage);

         // draw alignment marks
         if (compact)
         {
            drawBullsEye(matrix, matrixSize / 2, 5);
         }
         else
         {
            drawBullsEye(matrix, matrixSize / 2, 7);
            for (int i = 0, j = 0; i < baseMatrixSize / 2 - 1; i += 15, j += 16)
            {
               for (int k = (matrixSize / 2) & 1; k < matrixSize; k += 2)
               {
                  matrix[matrixSize / 2 - j, k] = true;
                  matrix[matrixSize / 2 + j, k] = true;
                  matrix[k, matrixSize / 2 - j] = true;
                  matrix[k, matrixSize / 2 + j] = true;
               }
            }
         }

         return new AztecCode
                        {
                           isCompact = compact,
                           Size = matrixSize,
                           Layers = layers,
                           CodeWords = messageSizeInWords,
                           Matrix = matrix
                        };
      }
예제 #7
0
      private static BitArray generateCheckWords(BitArray stuffedBits, int totalSymbolBits, int wordSize)
      {
         var messageSizeInWords = (stuffedBits.Size + wordSize - 1) / wordSize;
         for (var i = messageSizeInWords * wordSize - stuffedBits.Size; i > 0; i--)
         {
            stuffedBits.appendBit(true);
         }

         var rs = new ReedSolomonEncoder(getGF(wordSize));
         var totalSizeInFullWords = totalSymbolBits / wordSize;
         var messageWords = bitsToWords(stuffedBits, wordSize, totalSizeInFullWords);
         rs.encode(messageWords, totalSizeInFullWords - messageSizeInWords);

         var startPad = totalSymbolBits % wordSize;
         var messageBits = new BitArray();
         messageBits.appendBits(0, startPad);
         foreach (var messageWord in messageWords)
         {
            messageBits.appendBits(messageWord, wordSize);
         }
         return messageBits;
      }