Completeness row C8. The exact decoder (jpegai_decode) decoded one configuration, the reference codestream's; every other trapped. With the jpegai/v1 bundle (tools_0, the high-operation-point synthesis, one eICCI pair) it now decodes: - pictures whose sides are 128, 192 or 256, any display cropping (the post-filters run on the displayed picture; eICCI pads a side to a multiple of 4 by repetition); - beta_displacement_log from -1069 to 702, the chroma one independent or not; - LSBS off per plane; residual variance scaling and GRFS both off, or GRFS alone (one band); - each post-filter off; eICCI on any plane subset with the bundle's pair; no colour transform. Held by 29 configuration vectors (wai-rs/tests/vectors/jpegai/configs/: synthetic pictures the reference software's encoder coded at each configuration, its rate search off, and header edits of them), each pinned to its RGB8 (the same digests on Linux x86_64 and macOS arm64), decoded the direct way to the same bits at every stage, and max|d| = 1 from the reference decoder's picture on 2.5% to 6.6% of samples (tests/jpegai_configs.rs; wai-jpegai-e2e.yml). Refused with a new code, configuration_undetermined (D74): residual variance scaling without GRFS (the reference dequantises it by an integer shift or a float division as its tables sit, and raises on a CPU) and a signalled colour matrix (a library inverse, applied by its first row alone; the reference raises before either). Everything else outside scope is refused as before, each with a vector or a header test showing where. Readings fixed (D74): the scale's incomplete 8x8 blocks pad with 1411; LEF samples its scale surface at the binary32 quotient's floor; no colour transform gives the decoded components. The float ONNX path keeps the reference codestream's configuration alone (check_reference_configuration). The scale path's text (integer-operators 13.6.1) gains the picture's sizes, beta and the RVS modes; 13.6.2 states the graphs' declared sizes as maxima. Second reader: tools/wai_jpegai_header.py (standard library) reads and writes the headers and gives each codestream's scope; tools/wai_jpegai_configs.py writes the manifest, checks that reader against it and holds decodes to the reference pictures; tools/wai_jpegai_make_vectors.py makes the vectors (the edits regenerate byte for byte). Planted faults (cfg(wai_planted), never in an ordinary build), each caught by the vectors: likely-pad-index, beta-after-likely, grfs-only-floor, rvs-mode-swap, lef-nearest-round, icci-pad-index, crop-index, icci-subset-swap, lsbs-off-ignored, ct0-order. Co-Authored-By: Claude Opus 5.5 <[email protected]>
3.5 KiB
JPEG AI reference codestream and configuration vectors
test256.bin (367 bytes, SHA-256
99840e5f472423f5a1261c9ec219d12dc910e9623d752672555dfea69ea4a097) is the output
of the ISO/IEC 6048-1 reference software's encoder (BSD-3) at its default operating
point, for a 256×256 synthetic RGB test image (gradients and blocks). Segment layout:
PIH 49 bytes, TON 63, RDI 1, SORP 97, SORS 47, SOZ 83.
It is the configuration the float decode path implements, and one of those
wai::jpegai_decode implements, so the unit tests in src/jpegai_decode.rs use it to check
the decoder's scope guard: the unmodified codestream is accepted, and copies with a single
header field changed (β inside and past the encoder's range, model_id, the colour
transform, an LSBS flag, display cropping) are accepted or refused as the field asks.
Decoding it to pixels needs the sink-supplied weight bundle, which is not committed;
see tests/jpegai_e2e_full.rs.
configs/
The configuration vectors (tests/jpegai_configs.rs): synthetic pictures, made from a seed
by tools/wai_jpegai_make_vectors.py, coded by the reference software's encoder (its tree at
b0f832cde85bd873fbfa995668b7d7c8d0b0c2fe, BSD licence, Copyright (c) 2010-2022, ITU/ISO/IEC)
at one configuration each with its rate search off, and a few header edits of them, each
named as such. made.json says how each was made; manifest.json, which
tools/wai_jpegai_configs.py writes, gives each one's SHA-256, its scope from the second
header reader (tools/wai_jpegai_header.py), and what the exact decoder does with it with the
jpegai/v1 bundle: the digest and size of the RGB8 it decodes to, or the refusal. Each vector
in scope carries the reference decoder's picture (<name>.ref.png, written by the reference
decoder; for no colour transform, the picture it decodes rounded to 8 bits, because its file
writer converts that picture again, decisions D74), and the
manifest how far the exact decode is from it (apart). Vectors prefixed n- code the same
configurations with eICCI off, because the reference encoder chooses eICCI's model per
picture and the bundle carries one pair; e- vectors are header edits. x- vectors are
refusal fixtures, header edits of test256 each setting one field where the decoder stops, so
that every condition of its scope a codestream can fail is caught by a vector
(wai_jpegai_configs.py --weakened leaves each condition out of the second reader in turn: 28
of its 29 are caught; the 29th, display cropping removing the whole picture, no codestream in
scope can fail, its sides being at least 128 and the cropping at most 63).
Decode time, one host's reading
2026-11-12, 09:15 UTC: macOS arm64, a 28-core build host (one-minute load 12.6 at the start,
17.2 at the end), rustc 1.99.1, a release build, tests/jpegai_configs.rs with the bundle
loaded once and each picture decoded through the integer operator set on the host's threads,
milliseconds a picture. With eICCI on its three planes, 256 × 256: 931 to 992 (test256, the
cropped, colour-0 and eICCI-subset edits of it; on one plane, 973 to 988); with eICCI off,
256 × 256: 319 to 331 (each β, LSBS, RVS, GRFS, post-filter and colour vector), 327 with it on
no plane; 256 × 192 and 192 × 256: 239 and 248 (254 cropped); 192 × 192: 194; 128 × 256 and
256 × 128: 189 and 179; 128 × 128: 106; eICCI on one plane at 192 × 192 and 256 × 192: 541 and
717. The eICCI network, in float, is about two thirds of a 256 × 256 decode. No comparison is
made with any other decoder.