Skip to content

Add PagedDecoder trait for multi-page formats (TIFF, PDF, DICOM) #1

@lilith

Description

@lilith

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions