wai-rs: jpegai_bitstream — tools-header (TON) post-filter chain parser #18

Merged
dcharlot merged 1 commit from feat/jpegai-ton into main 2026-07-17 01:24:22 -04:00
Owner

Decodes the TON post-filter chain → ToolsHeader: EFE-linear (B1 means + two decode_filters groups), eICCI (per-tile use flags + signalled Y/joint-UV model indices — the last input the eICCI net needed), EFE-nonlinear (min/max symbol, masks, luma ranges, A1 weights), LEF — in filters-factory order, each gated by its recursive enable flag.

Adds the universal width rule as a primitive: BitReader::read_max(max) reads ceil(log2(max+1)) bits (reference HeaderCoder::calc_bits_count). No header field has a fixed width, and several are runtime-dependent — a just-decoded max_symbol sets the width of the weights after it (65535→16 bits, then 99→7 bits inside the same EFE-linear header).

Validated on real test256.bin, ending exactly on bit 973 (+3 pad closing the 63-byte TON), every value matching. Two independent cross-checks: EFN luma range (497/25320) + the 8 A1 weights are the luma_min_q/luma_max_q/weights_q15 of the byte-exact efn_filter; and B1/100 = 125.61/130.91 are the means efl_chroma consumes.

start_bit is the first filter enable flag, not the TON payload start — _stream_header_part defaults to tool_header, so other tools emit into TON ahead of the chain (2 such bits here).

Decodes the TON post-filter chain → `ToolsHeader`: EFE-linear (B1 means + two decode_filters groups), eICCI (per-tile use flags + signalled Y/joint-UV **model indices** — the last input the eICCI net needed), EFE-nonlinear (min/max symbol, masks, luma ranges, A1 weights), LEF — in filters-factory order, each gated by its recursive enable flag. **Adds the universal width rule as a primitive:** `BitReader::read_max(max)` reads `ceil(log2(max+1))` bits (reference `HeaderCoder::calc_bits_count`). No header field has a fixed width, and several are **runtime-dependent** — a just-decoded `max_symbol` sets the width of the weights after it (65535→16 bits, then 99→**7** bits inside the same EFE-linear header). **Validated on real test256.bin**, ending exactly on **bit 973** (+3 pad closing the 63-byte TON), every value matching. Two independent cross-checks: EFN luma range (497/25320) + the 8 A1 weights **are** the `luma_min_q`/`luma_max_q`/`weights_q15` of the byte-exact `efn_filter`; and B1/100 = 125.61/130.91 are the means `efl_chroma` consumes. `start_bit` is the first filter enable flag, not the TON payload start — `_stream_header_part` defaults to `tool_header`, so other tools emit into TON ahead of the chain (2 such bits here).
Decodes the post-filter chain of the TON substream into a ToolsHeader: EFE-linear
(B1 plane means + two decode_filters groups), eICCI (per-tile use flags, short-list
flag, and the signalled Y / joint-UV model indices), EFE-nonlinear (min/max symbol,
mask flags, per-plane luma ranges and A1 weights), and LEF (enable + reference
channel) — in filters-factory order, each gated by its recursive enable flag.

Adds the header's universal width rule as a first-class primitive:
BitReader::read_max(max) reads ceil(log2(max+1)) bits, per the reference
HeaderCoder::calc_bits_count. No header field has a fixed width, and several are
runtime-dependent: a just-decoded max_symbol sets the width of the weights that
follow it (65535 -> 16 bits, then 99 -> 7 bits within the same EFE-linear header).

Validated on real test256.bin, ending exactly on bit 973 (+3 pad closing the 63-byte
TON) with every value matching the reference. Two independent cross-checks: the EFE
nonlinear luma range (497/25320) and its 8 A1 weights are exactly the luma_min_q /
luma_max_q / weights_q15 inputs of the byte-exact efn_filter, and B1/100 = 125.61 /
130.91 are the plane means efl_chroma consumes.

start_bit is the first filter's enable flag, not the TON payload start:
_stream_header_part defaults to "tool_header", so other tools emit into TON ahead of
the chain (two such bits precede EFE-linear in the reference stream); locating that
prefix generally requires walking the whole tool tree.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!18
No description provided.