imazen / imazen/zencodec

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

Open
#1 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.