Skip to content

Commit 2ae557c

Browse files
committed
docs: handoff with only proven facts, no theories
1 parent b8b59a0 commit 2ae557c

File tree

1 file changed

+105
-95
lines changed

1 file changed

+105
-95
lines changed

CONTEXT-HANDOFF.md

Lines changed: 105 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,121 @@
11
# Imageflow3 Context Handoff
22

3-
## Current State (2026-03-26)
3+
## State: 141/188 tests passing (47 failures, 4 skipped)
44

5-
**Branch**: `imageflow3`, **139/188 passing** (49 divergences between v2 and zen backends).
5+
Branch `imageflow3`. Both v2 and zen backends run against shared checksums.
66

7-
## Test Architecture
8-
9-
Tests run **both backends** (v2 + zen) against **one shared checksum set**.
10-
V2 runs first and sets the baseline. Zen must match within the test's tolerance.
11-
Divergences are bugs to fix, not baselines to fork.
7+
## Test commands
128

139
```bash
14-
# Run all tests (both backends)
15-
just test
10+
just test # both backends, shared checksums
11+
just test-filter NAME # filter by test name
12+
ZENPIPE_TRACE=1 just test-filter NAME # with pipeline trace
13+
```
1614

17-
# With auto-accept for new baselines
18-
just test-update
15+
justfile passes `--features "zen-default,c-codecs"`.
1916

20-
# justfile passes --features "zen-default,c-codecs"
21-
```
17+
## Proven facts (with tests)
2218

23-
`Context.force_backend` controls which engine runs. `Backend::V2` or `Backend::Zen`.
24-
`backends_to_test()` in test infrastructure returns both when `zen-pipeline` feature is on.
19+
### JPEG decoder parity (test: `jpeg_decoder_parity.rs`)
20+
- sRGB JPEG (Canon 5D): **delta=0** between mozjpeg and zenjpeg. Pixel-identical.
21+
- Rec.2020 PQ JPEG: **delta=122**, 100% pixels differ. Not IDCT — color matrix.
22+
- Cause unverified. Needs investigation in zenjpeg's YCbCr→RGB path for wide-gamut.
2523

26-
## Tracing
24+
### CMS transform parity (test: `moxcms/tests/rgb_vs_rgba_layout.rs`)
25+
- Layout::Rgb vs Layout::Rgba: **identical** output from moxcms.
26+
- Direct `new_srgb()` vs ICC-roundtripped sRGB destination: **identical**.
27+
- CICP vs no-CICP on destination: **identical**.
28+
- Same ICC bytes (hash verified) go to both v2 and zen CMS paths.
2729

28-
```bash
29-
ZENPIPE_TRACE=1 just test-filter test_name # text trace to stderr
30-
ZENPIPE_TRACE=svg just test-filter test_name # also write /tmp/zenpipe_trace.svg
31-
```
30+
### ICC profile extraction (zenjpeg `tests/icc_extraction.rs`)
31+
- `extract_icc_profile()` works correctly on all test images.
32+
- `or_else` fallback fix (commit `0355bf1d`) resolved extras/parser priority.
33+
34+
### Linear matte compositing (zenpixels-convert)
35+
- `matte_composite()` now blends in linear light using LUT-based sRGB↔linear.
36+
- All 3 matte compositing tests pass (hardcoded pixel checks match v2).
37+
38+
## 47 failures by category
39+
40+
### Wide-gamut JPEG decoder difference (15 tests)
41+
Rec.2020, P3, AdobeRGB, ProPhoto JPEGs. Delta=122 before CMS.
42+
sRGB JPEGs have delta=0 — decoders agree on sRGB, disagree on wide-gamut.
3243

33-
## 49 Remaining Divergences (by category)
44+
Tests: `icc_rec2020_decode_{1,2}`, `icc_display_p3_decode_{1,2,3}`,
45+
`icc_adobe_rgb_decode_{1,2}`, `icc_prophoto_decode`, `icc_gray_gamma22_decode`,
46+
`icc_repro_{imagemagick,libvips,pillow,sharp}_icc`, `jpeg_icc2_color_profile`
3447

35-
### ICC color management (18 tests)
36-
All `format=png` no-resize tests. Zen skips the identity resize (correct behavior)
37-
but v2 runs it, causing sRGB→linear→sRGB roundtrip that slightly alters pixels.
38-
The zen output is MORE correct. These need the v2 baselines updated to match zen,
39-
or the tolerance adjusted to accept the roundtrip difference.
48+
### sRGB JPEG + CMS path difference (4 tests)
49+
sRGB JPEG decoder output is identical (delta=0), but something in the
50+
CMS skip/apply path differs. Delta=49-56 in final output.
4051

41-
Tests: test_icc_srgb_canon_5d, test_icc_srgb_sony_a7rv, test_icc_display_p3_decode_{1,2,3},
42-
test_icc_adobe_rgb_decode_{1,2}, test_icc_rec2020_decode_{1,2}, test_icc_prophoto_decode,
43-
test_icc_gray_gamma22_decode, test_icc_repro_{imagemagick,libvips,pillow,sharp}_icc,
44-
test_icc_display_p3_resize_filter, test_icc_p3_crop_and_resize, test_icc_p3_to_jpeg_roundtrip,
45-
test_icc_p3_to_webp
52+
Tests: `icc_srgb_canon_5d`, `icc_srgb_sony_a7rv`,
53+
`icc_display_p3_resize_filter`, `icc_p3_crop_and_resize`
4654

4755
### Round corners (9 tests)
48-
Anti-aliasing model differs: v2 uses volumetric_offset=0.56419 with quadrant-based
49-
rendering including circle mode centering. Zen implementation matches the v2 algorithm
50-
for standard corners (similarity 85+) but circle mode on non-square canvases needs
51-
the v2's quadrant offset logic.
52-
53-
Tests: test_round_corners_{small,large,custom_pixels,custom_percent,excessive_radius,
54-
circle_wide_canvas,circle_tall_canvas,command_string}, test_round_image_corners_transparent
55-
56-
### Transparent PNG/WebP format handling (7 tests)
57-
Alpha channel handling differences between zen and v2 codec paths.
58-
59-
Tests: test_transparent_png_to_{png,jpeg,png_rounded_corners,jpeg_constrain},
60-
test_transparent_webp_to_webp, test_webp_to_webp_quality, test_problematic_png_lossy
61-
62-
### WebP scaling with alpha (3 tests)
63-
Alpha channel initialization differs for WebP decode → resize path.
64-
65-
Tests: webp_{lossless,lossy}_alpha_decode_and_scale, webp_lossy_noalpha_decode_and_scale
66-
67-
### CMYK JPEG decode (2 tests)
68-
Different CMYK→RGB conversion path.
69-
70-
Tests: decode_cmyk_jpeg, decode_rgb_with_cmyk_profile_jpeg
71-
72-
### Matte compositing (2 tests)
73-
Hardcoded pixel value checks — zen alpha compositing math differs from v2.
74-
75-
Tests: test_matte_compositing_{no_double_division,mixed_alpha}
76-
77-
### Pngquant (2 tests)
78-
Zen encoder doesn't support pngquant-style quantized PNG yet.
79-
80-
Tests: test_encode_pngquant_{command,fallback_command}
81-
82-
### Other (6 tests)
83-
- test_jpeg_crop: JPEG IDCT difference
84-
- test_branching_crop_whitespace: DAG mode crop
85-
- test_png_cicp_bt709_transfer_causes_transform: CICP color
86-
- smoke_test_corrupt_jpeg: zen decoder more tolerant
87-
- test_trim_whitespace: whitespace detection threshold
88-
89-
## Architecture (zen bridge)
90-
91-
### What lives where
92-
| Crate | Owns |
93-
|-------|------|
94-
| zenresize | resize (forced w×h), constrain (layout-aware) |
95-
| zenlayout | crop, orient, flip, rotate, expand_canvas, constrain, region, smart_crop |
96-
| zenfilters | color filters (saturation, contrast, brightness, etc.) |
97-
| zenblend | RoundedRectMask, blend modes, mask primitives |
98-
| zenpipe | crop_whitespace, fill_rect, remove_alpha, round_corners, pipeline tracing |
99-
| zencodecs | format selection, encode/decode dispatch, mozjpeg preset config |
100-
| zennode | NodeInstance/NodeDef traits, KvPairs, registry |
101-
102-
### Imageflow zen bridge files
103-
| File | Lines | Purpose |
104-
|------|-------|---------|
105-
| execute.rs | ~1500 | Pipeline orchestration, decode, encode, RIAPI expansion |
106-
| translate.rs | ~580 | v2 Node → zennode NodeInstance (uses zen registry, no custom wrappers) |
107-
| converter.rs | ~216 | NodeConverter for zenfilters, expand_canvas, region |
108-
| preset_map.rs | ~332 | v2 EncoderPreset → zencodecs CodecIntent |
109-
| riapi.rs | ~162 | Dual RIAPI parser (legacy Ir4Expand + zen-native) |
110-
| context_bridge.rs | ~166 | v2 JSON API bridge |
111-
| captured.rs | ~24 | Bitmap capture data |
56+
V2 uses volumetric_offset=0.56419 + quadrant-based rendering.
57+
Zen matches standard corners (sim 85+) but circle mode on non-square
58+
canvases needs v2's quadrant offset logic. Per-corner radii unsupported.
59+
60+
Tests: `round_corners_{small,large,custom_pixels,custom_percent,
61+
excessive_radius,circle_wide_canvas,circle_tall_canvas,command_string}`,
62+
`round_image_corners_transparent`
63+
64+
### PNG/WebP encode defaults (6 tests)
65+
`with_generic_quality()` overrides `with_lossless()` in zenpng.
66+
WebP lossless hint propagation fixed (preset_map order).
67+
JPEG matte compositing added to `stream_encode`.
68+
69+
Tests: `transparent_png_to_png_rounded_corners`, `transparent_png_to_jpeg`,
70+
`transparent_png_to_jpeg_constrain`, `transparent_webp_to_webp` (sim 98.9),
71+
`matte_transparent_png`, `webp_to_webp_quality`
72+
73+
### WebP alpha / ExpandCanvas (3 tests)
74+
ExpandCanvas fills with transparent [0,0,0,0] on opaque source.
75+
76+
Tests: `webp_{lossless,lossy}_alpha_decode_and_scale`,
77+
`webp_lossy_noalpha_decode_and_scale`
78+
79+
### Other (10 tests)
80+
- `decode_cmyk_jpeg`, `decode_rgb_with_cmyk_profile_jpeg` — CMYK path
81+
- `jpeg_crop`, `crop_with_preshrink` — JPEG crop/IDCT
82+
- `problematic_png_lossy` — pngquant palette
83+
- `pngquant_command`, `pngquant_fallback_command` — pngquant hints
84+
- `png_cicp_bt709_transfer` — CICP assertion
85+
- `branching_crop_whitespace` — DAG mode
86+
- `smoke_test_corrupt_jpeg` — zen decoder more tolerant
87+
- `icc_p3_to_{jpeg_roundtrip,webp}` — re-encode quality
88+
- `trim_whitespace` — border detection
89+
- `rot_90_*`, `jpeg_simple_rot_90` — rotation
90+
91+
## Architecture
92+
93+
### CmsMode (on ExecutionSecurity)
94+
- `Imageflow2Compat` (default): skip sRGB-like ICC on decode (desc heuristic)
95+
- `SceneReferred`: strict sRGB detection, preserve wide gamut
96+
97+
### Backend (on Context)
98+
- `Context.force_backend = Some(Backend::V2 | Backend::Zen)` for runtime selection
99+
- Tests iterate both backends via `backends_to_test()`
100+
101+
### Zen bridge (imageflow_core/src/zen/)
102+
- `translate.rs` (580 lines) — v2 Node → zennode via registry (no custom wrappers)
103+
- `converter.rs` (216 lines) — ZenFilters, ExpandCanvas, Region converters
104+
- `execute.rs` (~1500 lines) — orchestration, CMS, encode
105+
- `preset_map.rs` (~340 lines) — v2 presets → CodecIntent
106+
107+
### Zen node ownership
108+
- zenresize: resize, constrain
109+
- zenpipe: crop_whitespace, fill_rect, remove_alpha, round_corners
110+
- zenblend: RoundedRectMask (used by round_corners)
111+
- zenlayout: crop, orient, flip, rotate, expand_canvas, region
112+
113+
### Patches (Cargo.toml [patch.crates-io])
114+
- zenpixels, zenpixels-convert (local)
115+
- zencodec (local — has SourceColor::is_srgb, icc_profile_is_srgb)
116+
- zenjpeg (local — has ICC extraction fallback fix)
117+
- moxcms (local — has PR #152 #153 fixes)
118+
119+
### Pipeline tracing
120+
`ZENPIPE_TRACE=1|full|svg` — 4-layer trace (RIAPI, Bridge, Graph, Execution).
121+
Tracer facade: zero-alloc when inactive.

0 commit comments

Comments
 (0)