decodeStream method

Future<UPdfDecodedStream> decodeStream(
  1. UPdfStream stream, {
  2. bool decrypt = true,
})

Implementation

Future<UPdfDecodedStream> decodeStream(UPdfStream stream, {bool decrypt = true}) async {
  final Uint8List? memo = stream.decoded;
  if (memo != null) return UPdfDecodedStream(bytes: memo);
  Uint8List data = stream.rawBytes ?? await source.read(stream.rawOffset, stream.rawLength);
  final UPdfEncryption? handler = encryption;
  final Object? type = stream.dict["Type"];
  final bool isMetadata = type is UPdfName && type.value == "Metadata";
  if (decrypt && handler != null && stream.rawBytes == null && !(isMetadata && !handler.encryptMetadata)) {
    data = handler.decrypt(data, stream.objectNumber, stream.generation, isString: false);
  }
  final List<String> filters = <String>[];
  final Object? filterObject = await resolve(stream.dict["Filter"]);
  if (filterObject is UPdfName) filters.add(filterObject.value);
  if (filterObject is List<Object?>) {
    for (final Object? entry in filterObject) {
      final Object? resolved = await resolve(entry);
      if (resolved is UPdfName) filters.add(resolved.value);
    }
  }
  final List<UPdfDict?> parms = <UPdfDict?>[];
  final Object? parmsObject = await resolve(stream.dict["DecodeParms"] ?? stream.dict["DP"]);
  if (parmsObject is UPdfDict) parms.add(parmsObject);
  if (parmsObject is List<Object?>) {
    for (final Object? entry in parmsObject) {
      final Object? resolved = await resolve(entry);
      parms.add(resolved is UPdfDict ? resolved : null);
    }
  }
  for (int i = 0; i < filters.length; i++) {
    final String filter = filters[i];
    final UPdfDict? parm = i < parms.length ? parms[i] : null;
    switch (filter) {
      case "FlateDecode":
      case "Fl":
        data = UPdfCodecs.inflate(data);
        data = await _applyPredictor(data, parm);
        break;
      case "LZWDecode":
      case "LZW":
        data = UPdfCodecs.lzw(data, earlyChange: (await resolve(parm?["EarlyChange"]) as num?)?.toInt() ?? 1);
        data = await _applyPredictor(data, parm);
        break;
      case "ASCII85Decode":
      case "A85":
        data = UPdfCodecs.ascii85(data);
        break;
      case "ASCIIHexDecode":
      case "AHx":
        data = UPdfCodecs.asciiHex(data);
        break;
      case "RunLengthDecode":
      case "RL":
        data = UPdfCodecs.runLength(data);
        break;
      case "Crypt":
        break;
      case "DCTDecode":
      case "DCT":
      case "JPXDecode":
      case "JBIG2Decode":
      case "CCITTFaxDecode":
      case "CCF":
        return UPdfDecodedStream(bytes: data, imageFilter: filter, imageParms: parm);
      default:
        break;
    }
  }
  if (data.length < 4 * 1024 * 1024) stream.decoded = data;
  return UPdfDecodedStream(bytes: data);
}