예제 #1
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)
      {
         var aztec = new AztecCode();

         // High-level encode
         var bits = highLevelEncode(data);

         // 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;
               }
            }
         }

         aztec.isCompact = compact;
         aztec.Size = matrixSize;
         aztec.Layers = layers;
         aztec.CodeWords = messageSizeInWords;
         aztec.Matrix = matrix;
         return aztec;
      }
예제 #2
0
      private static BitMatrix renderResult(AztecCode code, int width, int height)
      {
         var input = code.Matrix;
         if (input == null)
         {
            throw new InvalidOperationException("No input code matrix");
         }

         int inputWidth = input.Width;
         int inputHeight = input.Height;
         int outputWidth = Math.Max(width, inputWidth);
         int outputHeight = Math.Max(height, inputHeight);

         int multiple = Math.Min(outputWidth / inputWidth, outputHeight / inputHeight);
         int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
         int topPadding = (outputHeight - (inputHeight * multiple)) / 2;

         var output = new BitMatrix(outputWidth, outputHeight);

         for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple)
         {
            // Write the contents of this row of the barcode
            for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple)
            {
               if (input[inputX, inputY])
               {
                  output.setRegion(outputX, outputY, multiple, multiple);
               }
            }
         }

         return output;
      }
예제 #3
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)
        {
            var aztec = new AztecCode();

            // High-level encode
            var bits = highLevelEncode(data);

            // 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;
                    }
                }
            }

            aztec.isCompact = compact;
            aztec.Size      = matrixSize;
            aztec.Layers    = layers;
            aztec.CodeWords = messageSizeInWords;
            aztec.Matrix    = matrix;
            return(aztec);
        }