readCodewords method

Uint8List readCodewords()

Reads the bits in the [BitMatrix] representing the finder pattern in the correct order in order to reconstruct the codewords bytes contained within the QR Code.

@return bytes encoded within the QR Code @throws FormatException if the exact number of bytes expected is not read

Implementation

Uint8List readCodewords() {
  final formatInfo = readFormatInformation();
  final version = readVersion();

  // Get the data mask for the format used in this QR Code. This will exclude
  // some bits from reading as we wind through the bit matrix.
  final dataMask = DataMask.values[formatInfo.dataMask];
  final dimension = _bitMatrix.height;
  dataMask.unmaskBitMatrix(_bitMatrix, dimension);

  final functionPattern = version.buildFunctionPattern();

  bool readingUp = true;
  final result = Uint8List(version.totalCodewords);
  int resultOffset = 0;
  int currentByte = 0;
  int bitsRead = 0;
  // Read columns in pairs, from right to left
  for (int j = dimension - 1; j > 0; j -= 2) {
    if (j == 6) {
      // Skip whole column with vertical alignment pattern;
      // saves time and makes the other code proceed more cleanly
      j--;
    }
    // Read alternatingly from bottom to top then top to bottom
    for (int count = 0; count < dimension; count++) {
      final i = readingUp ? dimension - 1 - count : count;
      for (int col = 0; col < 2; col++) {
        // Ignore bits covered by the function pattern
        if (!functionPattern.get(j - col, i)) {
          // Read a bit
          bitsRead++;
          currentByte <<= 1;
          if (_bitMatrix.get(j - col, i)) {
            currentByte |= 1;
          }
          // If we've made a whole byte, save it off
          if (bitsRead == 8) {
            result[resultOffset++] = currentByte;
            bitsRead = 0;
            currentByte = 0;
          }
        }
      }
    }
    readingUp ^= true; // readingUp = !readingUp; // switch directions
  }
  if (resultOffset != version.totalCodewords) {
    throw FormatsException.instance;
  }
  return result;
}