encodeData static method

AztecCode encodeData(
  1. Uint8List data, [
  2. int minECCPercent = defaultAztecLayers,
  3. int userSpecifiedLayers = defaultAztecLayers,
  4. Encoding? charset,
])

Encodes the given binary content as an Aztec symbol

@param data input data string @param minECCPercent minimal percentage of error check words (According to ISO/IEC 24778:2008, a minimum of 23% + 3 words is recommended) @param userSpecifiedLayers if non-zero, a user-specified value for the number of layers @param charset character set to mark using ECI; if null, no ECI code will be inserted, and the default encoding of ISO/IEC 8859-1 will be assuming by readers. @return Aztec symbol matrix with metadata

Implementation

static AztecCode encodeData(
  Uint8List data, [
  int minECCPercent = defaultAztecLayers,
  int userSpecifiedLayers = defaultAztecLayers,
  Encoding? charset,
]) {
  // High-level encode
  final BitArray bits = HighLevelEncoder(data, charset).encode();

  // stuff bits and choose symbol size
  final int eccBits = bits.size * minECCPercent ~/ 100 + 11;
  final int totalSizeBits = bits.size + eccBits;
  bool compact;
  int layers;
  int totalBitsLayer;
  int wordSize;
  BitArray? stuffedBits;
  if (userSpecifiedLayers != defaultAztecLayers) {
    compact = userSpecifiedLayers < 0;
    layers = (userSpecifiedLayers).abs();
    if (layers > (compact ? _maxNbBitsCompact : _maxNbBits)) {
      throw ArgumentError('Illegal value $userSpecifiedLayers for layers');
    }
    totalBitsLayer = _totalBitsInLayer(layers, compact);
    wordSize = _wordSize[layers];
    final int usableBitsInLayers =
        totalBitsLayer - (totalBitsLayer % wordSize);
    stuffedBits = stuffBits(bits, wordSize);
    if (stuffedBits.size + eccBits > usableBitsInLayers) {
      throw ArgumentError('Data to large for user specified layer');
    }
    if (compact && stuffedBits.size > wordSize * 64) {
      // Compact format only allows 64 data words, though C4 can hold more words than that
      throw ArgumentError('Data to large for user specified layer');
    }
  } else {
    wordSize = 0;
    stuffedBits = null;
    // We look at the possible table sizes in the order Compact1, Compact2, Compact3,
    // Compact4, Normal4,...  Normal(i) for i < 4 isn't typically used since Compact(i+1)
    // is the same size, but has more data.
    for (int i = 0;; i++) {
      if (i > _maxNbBits) {
        throw ArgumentError('Data too large for an Aztec code');
      }
      compact = i <= 3;
      layers = compact ? i + 1 : i;
      totalBitsLayer = _totalBitsInLayer(layers, compact);
      if (totalSizeBits > totalBitsLayer) {
        continue;
      }
      // [Re]stuff the bits if this is the first opportunity, or if the
      // wordSize has changed
      if (stuffedBits == null || wordSize != _wordSize[layers]) {
        wordSize = _wordSize[layers];
        stuffedBits = stuffBits(bits, wordSize);
      }
      final int usableBitsInLayers =
          totalBitsLayer - (totalBitsLayer % wordSize);
      if (compact && stuffedBits.size > wordSize * 64) {
        // Compact format only allows 64 data words, though C4 can hold more words than that
        continue;
      }
      if (stuffedBits.size + eccBits <= usableBitsInLayers) {
        break;
      }
    }
  }
  final BitArray messageBits =
      _generateCheckWords(stuffedBits, totalBitsLayer, wordSize);

  // generate mode message
  final int messageSizeInWords = stuffedBits.size ~/ wordSize;
  final BitArray modeMessage =
      generateModeMessage(compact, layers, messageSizeInWords);

  // allocate symbol
  final int baseMatrixSize =
      (compact ? 11 : 14) + layers * 4; // not including alignment lines
  final List<int> alignmentMap = List.filled(baseMatrixSize, 0);
  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);
    final int origCenter = baseMatrixSize ~/ 2;
    final int center = matrixSize ~/ 2;
    for (int i = 0; i < origCenter; i++) {
      final int newOffset = i + i ~/ 15;
      alignmentMap[origCenter - i - 1] = center - newOffset - 1;
      alignmentMap[origCenter + i] = center + newOffset + 1;
    }
  }
  final BitMatrix matrix = BitMatrix(matrixSize);

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

  // draw mode message
  _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.set(matrixSize ~/ 2 - j, k);
        matrix.set(matrixSize ~/ 2 + j, k);
        matrix.set(k, matrixSize ~/ 2 - j);
        matrix.set(k, matrixSize ~/ 2 + j);
      }
    }
  }

  return AztecCode(
    isCompact: compact,
    size: matrixSize,
    layers: layers,
    codeWords: messageSizeInWords,
    matrix: matrix,
  );
}