Summary
Multi-page formats like TIFF, PDF, and DICOM contain independent images (pages) that differ in dimensions, color space, bit depth, ICC profile, resolution, and orientation. The existing FullFrameDecoder trait is animation-oriented (same canvas, temporal ordering, compositing) and doesn't fit.
Proposed API
trait PagedDecoder {
type Error;
/// Metadata for the page at `index`, without decoding pixels.
/// Returns `None` if `index` is past the last page.
fn page_info(&mut self, index: u32) -> Result<Option<ImageInfo>, At<Self::Error>>;
/// Decode the page at `index` to pixels.
/// Returns `None` if `index` is past the last page.
fn decode_page(&mut self, index: u32) -> Result<Option<DecodeOutput>, At<Self::Error>>;
}
Design decisions
- No
page_count(): TIFF stores pages as a linked list of IFDs — the count isn't in the header and requires walking the entire chain. Instead, callers discover the last page by getting None back. This avoids forcing an upfront scan.
- Reuse
ImageInfo: Each page is an independent image. ImageInfo already carries dimensions, format, alpha, orientation, source color (ICC, CICP, bit depth), and embedded metadata. Unused fields (animation, gain map) default to harmless values. No new metadata type needed.
page_info() is cheap: Reads the IFD/page header (tag parsing only, no pixel decompression). Useful for building a page list UI or selecting which pages to decode.
- Random access by index: Pages are 0-indexed in file order. The underlying
tiff crate caches IFD offsets as they're visited, so repeated access to the same page is O(1) after first visit.
- Fits existing trait hierarchy:
PagedDecoder is another execution mode from DecodeJob, parallel to Decode, StreamingDecode, and FullFrameDecoder.
Per-page metadata (TIFF)
Every TIFF tag is per-IFD. Each page can independently vary:
- Dimensions, bit depth, sample format
- Color space (PhotometricInterpretation), ICC profile
- Compression method
- Resolution/DPI, orientation
- Extra samples / alpha
- Planar vs chunky layout
Why not FullFrameDecoder?
|
Animation (GIF/APNG/WebP) |
Pages (TIFF/PDF) |
| Dimensions |
Same canvas |
Different per page |
| Temporal ordering |
Yes (duration_ms) |
No |
| Compositing/disposal |
Yes |
No |
| Random access |
Nice-to-have |
Essential |
| Per-image metadata |
Shared |
Independent |
Summary
Multi-page formats like TIFF, PDF, and DICOM contain independent images (pages) that differ in dimensions, color space, bit depth, ICC profile, resolution, and orientation. The existing
FullFrameDecodertrait is animation-oriented (same canvas, temporal ordering, compositing) and doesn't fit.Proposed API
Design decisions
page_count(): TIFF stores pages as a linked list of IFDs — the count isn't in the header and requires walking the entire chain. Instead, callers discover the last page by gettingNoneback. This avoids forcing an upfront scan.ImageInfo: Each page is an independent image.ImageInfoalready carries dimensions, format, alpha, orientation, source color (ICC, CICP, bit depth), and embedded metadata. Unused fields (animation, gain map) default to harmless values. No new metadata type needed.page_info()is cheap: Reads the IFD/page header (tag parsing only, no pixel decompression). Useful for building a page list UI or selecting which pages to decode.tiffcrate caches IFD offsets as they're visited, so repeated access to the same page is O(1) after first visit.PagedDecoderis another execution mode fromDecodeJob, parallel toDecode,StreamingDecode, andFullFrameDecoder.Per-page metadata (TIFF)
Every TIFF tag is per-IFD. Each page can independently vary:
Why not
FullFrameDecoder?