decodeStream method
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);
}