decodeAsync static method

Future<TiffDocument> decodeAsync(
  1. TiffAsyncByteSource source
)

Decodes from a TiffAsyncByteSource — storage that can only be read asynchronously, such as a browser File/Blob or an HTTP server answering Range requests (see package:tiff/tiff_web.dart).

Only the header and IFDs are read here, in a few reads of at least 64 KiB each. Pixel data is then read per call — and only the strips/tiles that call needs — by the pages' async methods (TiffImage.decodeRegionAsync, TiffImage.decodeRegionRgba8Async, TiffImage.readTileJpegAsync, ...), so the file can be far larger than memory. Their synchronous counterparts throw a TiffException on these pages, since there is nothing loaded for them to read.

Implementation

static Future<TiffDocument> decodeAsync(TiffAsyncByteSource source) async {
  const readAhead = 64 * 1024;
  const carriedBytes = 1024 * 1024;
  final prefetch = PrefetchByteSource(source);
  final session = PrefetchSession();
  final header = await prefetch.run(
    [(0, 16)],
    () => TiffHeader.parse(prefetch),
    session: session,
    readAhead: readAhead,
  );
  final reader = TiffByteReader(prefetch, header.byteOrder.endian);

  final images = <TiffImage>[];
  var nextIfdOffset = header.firstIfdOffset;
  while (nextIfdOffset != 0) {
    // Consecutive IFDs are often close together, so the latest reads are
    // kept for the next page; older ones are dropped to bound memory on a
    // file with thousands of pages.
    session.keepRecent(carriedBytes);
    final offset = nextIfdOffset;
    final (image, next) = await prefetch.run(
      const [],
      () => _readPage(reader, offset, header.isBigTiff),
      session: session,
      readAhead: readAhead,
    );
    images.add(image);
    nextIfdOffset = next;
  }
  return _document(images, header, prefetch);
}