decodeStream function

Uint8List decodeStream(
  1. CosStream stream, {
  2. CosResolver? resolve,
  3. String? stopBeforeFilter,
})

Decodes a stream's payload by applying its /Filter chain in order.

resolve is used to chase indirect references inside /Filter, /DecodeParms, and /Length entries.

stopBeforeFilter stops the chain just before the named filter and returns the partially decoded bytes - used to undo e.g. FlateDecode wrapped around a JPEG while leaving the JPEG for a platform codec.

Implementation

Uint8List decodeStream(CosStream stream,
    {CosResolver? resolve, String? stopBeforeFilter}) {
  CosObject deref(CosObject? object) {
    var value = object ?? CosNull.instance;
    while (value is CosReference && resolve != null) {
      value = resolve(value);
    }
    return value;
  }

  final filterObject = deref(stream.dictionary['Filter']);
  final paramsObject =
      deref(stream.dictionary['DecodeParms'] ?? stream.dictionary['DP']);

  final names = <String>[];
  if (filterObject is CosName) names.add(filterObject.value);
  if (filterObject is CosArray) {
    for (final f in filterObject.items) {
      final r = deref(f);
      if (r is CosName) names.add(r.value);
    }
  }

  final params = <CosDictionary?>[];
  if (paramsObject is CosDictionary) params.add(paramsObject);
  if (paramsObject is CosArray) {
    for (final p in paramsObject.items) {
      final r = deref(p);
      params.add(r is CosDictionary ? r : null);
    }
  }

  var data = stream.rawBytes;
  for (var i = 0; i < names.length; i++) {
    if (names[i] == stopBeforeFilter) break;
    final filter = _filters[names[i]];
    if (filter == null) throw UnsupportedFilterException(names[i]);
    final t0 = PdfPerf.begin();
    data = filter.decode(data, i < params.length ? params[i] : null);
    if (PdfPerf.enabled) _recordFilterDecode(names[i], t0, data.length);
  }
  if (names.isNotEmpty) PdfPerf.add(PdfPerfCount.streamsDecoded);
  return data;
}