Add PagedDecoder trait for multi-page formats (TIFF, PDF, DICOM)
- Dominant language
- Rust
- Stars
- 2
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
## 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
```rust
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, At>;
/// Decode the page at `index` to pixels.
/// Returns `None` if `index` is past the last page.
fn decode_page(&mut self, index: u32) -> Result, At>;
}
```
## 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 |
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by locating DecodeJob and the existing Decode, StreamingDecode, and FullFrameDecoder traits, then read ImageInfo, DecodeOutput, and At to understand how a parallel execution mode fits. Done means defining the PagedDecoder API with per-page metadata and pixel decoding, including None for indexes past the last page and support for independent page properties.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100