decodeMacroBlock static method

int decodeMacroBlock(
  1. List<int> codewords,
  2. int codeIndex,
  3. PDF417ResultMetadata resultMetadata
)

Implementation

static int decodeMacroBlock(
  List<int> codewords,
  int codeIndex,
  PDF417ResultMetadata resultMetadata,
) {
  if (codeIndex + _NUMBER_OF_SEQUENCE_CODEWORDS > codewords[0]) {
    // we must have at least two bytes left for the segment index
    throw FormatsException.instance;
  }
  final segmentIndexArray = List.generate(
    _NUMBER_OF_SEQUENCE_CODEWORDS,
    (_) => codewords[codeIndex++],
  );
  //List<int> segmentIndexArray = List.filled(_NUMBER_OF_SEQUENCE_CODEWORDS, 0);
  //for (int i = 0; i < _NUMBER_OF_SEQUENCE_CODEWORDS; i++, codeIndex++) {
  //  segmentIndexArray[i] = codewords[codeIndex];
  //}

  final segmentIndexString = _decodeBase900toBase10(
    segmentIndexArray,
    _NUMBER_OF_SEQUENCE_CODEWORDS,
  );
  if (segmentIndexString.isEmpty) {
    resultMetadata.segmentIndex = 0;
  } else {
    try {
      resultMetadata.segmentIndex = int.parse(segmentIndexString);
    } on FormatException catch (_) {
      throw FormatsException.instance;
    }
  }

  // Decoding the fileId codewords as 0-899 numbers, each 0-filled to width 3. This follows the spec
  // (See ISO/IEC 15438:2015 Annex H.6) and preserves all info, but some generators (e.g. TEC-IT) write
  // the fileId using text compaction, so in those cases the fileId will appear mangled.
  final fileId = StringBuffer();
  while (codeIndex < codewords[0] &&
      codeIndex < codewords.length &&
      codewords[codeIndex] != _MACRO_PDF417_TERMINATOR &&
      codewords[codeIndex] != _BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {
    fileId.write(codewords[codeIndex].toString().padLeft(3, '0'));
    codeIndex++;
  }
  if (fileId.isEmpty) {
    // at least one fileId codeword is required (Annex H.2)
    throw FormatsException.instance;
  }
  resultMetadata.fileId = fileId.toString();

  int optionalFieldsStart = -1;
  if (codewords[codeIndex] == _BEGIN_MACRO_PDF417_OPTIONAL_FIELD) {
    optionalFieldsStart = codeIndex + 1;
  }

  while (codeIndex < codewords[0]) {
    switch (codewords[codeIndex]) {
      case _BEGIN_MACRO_PDF417_OPTIONAL_FIELD:
        codeIndex++;
        switch (codewords[codeIndex]) {
          case _MACRO_PDF417_OPTIONAL_FIELD_FILE_NAME:
            final fileName = ECIStringBuilder();
            codeIndex = _textCompaction(codewords, codeIndex + 1, fileName);
            resultMetadata.fileName = fileName.toString();
            break;
          case _MACRO_PDF417_OPTIONAL_FIELD_SENDER:
            final sender = ECIStringBuilder();
            codeIndex = _textCompaction(codewords, codeIndex + 1, sender);
            resultMetadata.sender = sender.toString();
            break;
          case _MACRO_PDF417_OPTIONAL_FIELD_ADDRESSEE:
            final addressee = ECIStringBuilder();
            codeIndex = _textCompaction(codewords, codeIndex + 1, addressee);
            resultMetadata.addressee = addressee.toString();
            break;
          case _MACRO_PDF417_OPTIONAL_FIELD_SEGMENT_COUNT:
            final segmentCount = ECIStringBuilder();
            codeIndex =
                _numericCompaction(codewords, codeIndex + 1, segmentCount);
            try {
              resultMetadata.segmentCount =
                  int.parse(segmentCount.toString());
            } on FormatException catch (_) {
              throw FormatsException.instance;
            }
            break;
          case _MACRO_PDF417_OPTIONAL_FIELD_TIME_STAMP:
            final timestamp = ECIStringBuilder();
            codeIndex =
                _numericCompaction(codewords, codeIndex + 1, timestamp);
            try {
              resultMetadata.timestamp = int.parse(timestamp.toString());
            } on FormatException catch (_) {
              throw FormatsException.instance;
            }
            break;
          case _MACRO_PDF417_OPTIONAL_FIELD_CHECKSUM:
            final checksum = ECIStringBuilder();
            codeIndex =
                _numericCompaction(codewords, codeIndex + 1, checksum);
            try {
              resultMetadata.checksum = int.parse(checksum.toString());
            } on FormatException catch (_) {
              throw FormatsException.instance;
            }
            break;
          case _MACRO_PDF417_OPTIONAL_FIELD_FILE_SIZE:
            final fileSize = ECIStringBuilder();
            codeIndex =
                _numericCompaction(codewords, codeIndex + 1, fileSize);
            try {
              resultMetadata.fileSize = int.parse(fileSize.toString());
            } on FormatException catch (_) {
              throw FormatsException.instance;
            }
            break;
          default:
            throw FormatsException.instance;
        }
        break;
      case _MACRO_PDF417_TERMINATOR:
        codeIndex++;
        resultMetadata.isLastSegment = true;
        break;
      default:
        throw FormatsException.instance;
    }
  }

  // copy optional fields to additional options
  if (optionalFieldsStart != -1) {
    int optionalFieldsLength = codeIndex - optionalFieldsStart;
    if (resultMetadata.isLastSegment) {
      // do not include terminator
      optionalFieldsLength--;
    }

    if (optionalFieldsLength > 0) {
      // ignore: deprecated_consistency, deprecated_member_use_from_same_package
      resultMetadata.optionalData = codewords.sublist(
        optionalFieldsStart,
        optionalFieldsStart + optionalFieldsLength,
      );
    }
  }

  return codeIndex;
}