Visual-review checkpoint — survey-derived L2 looks + skin primitives¶
Companion to v1.10's photographer-workflows survey work (RFC-031/032/033 + scope-expansion). This is the darktable-session validation pass for entries that ship without lab-grade automated coverage — the natural-skin-vs-painted-skin / dramatic-vs-cartoonish / restrained-vs-flat boundaries are visual judgments, not assertions. When · Run before closing RFC-033 into ADR or before any production photographer session that depends on these entries.
What needs visual sign-off¶
Skin primitives (RFC-033 + cheap-#4 scope expansion):
skin_uniformity— Path B color-band uniformity via colorequal sat_orange shift, masked to mask_skin_regionskin_smooth_painterly— Frequency-separation approximation via masked clarity reduction
Survey L2 looks (14 new):
- 5 portrait:
look_portrait_natural_skin,look_portrait_editorial,look_portrait_skin_warm_lift,look_portrait_background_dim,look_portrait_split_tone_moody - 9 landscape:
look_landscape_grand_vista,look_landscape_intimate_quiet,look_landscape_golden_hour,look_landscape_blue_hour_cool,look_landscape_atmospheric_haze,look_landscape_dramatic_moody,look_landscape_autumn_pop,look_landscape_sky_enhance,look_landscape_water_silk
Required raws¶
- 3-5 portraits with varied skin tones (caucasian-through-deep), varied lighting (window light, studio strobe, golden-hour, mixed), and varied makeup load (natural through full editorial). At least one with visibly uneven skin (red patches on forehead, yellow undertones on cheeks).
- 5-7 landscapes covering: grand-vista wilderness, intimate small-scene (forest interior, abstract detail), golden-hour scene, blue-hour / twilight, hazy / misty / fog, dramatic stormy weather, autumn foliage, water surface (long-exposure or glassy lake).
Per-entry checklist¶
For each entry, render (render_preview or darktable-cli with the bundled baseline XMP) and visually verify the intent matches the result. Score one of:
- ✅ Matches — the rendered image reads as the entry's stated intent
- ⚠️ Approximate — generally right but parameters need tuning (note suggested adjustment)
- ❌ Wrong — fails the intent (note what's wrong; consider re-design or fall-back path)
Skin primitives¶
skin_uniformity at strengths 0.0 / -0.3 / -0.6¶
| Test image | Strength | Expected | Pass? |
|---|---|---|---|
| Portrait with red forehead patches | -0.3 | Patches noticeably reduced; natural skin still | |
| Portrait with red forehead patches | -0.6 | Strong uniformity; check it doesn't read as "painted" | |
| Portrait with deep skin tones | -0.3 | Uniformity works without lifting tone reading as flat / muddy | |
| Portrait with full lipstick/makeup | -0.5 | Lip color preserved (mask_skin_region's color_h fallback should exclude lips); if lipstick desaturates badly, that's a mask-leakage finding | |
| Studio-strobe portrait | -0.5 | Skin reads natural under hard light (the failure mode here is "plastic skin") |
Fail criteria: if skin_uniformity produces "plastic skin" at strength -0.5 on representative portraits, the visual quality bar fails. Fall back to RFC-033 Path A (full Path C decoder of colorequal — substantially heavier work) or document the strength ceiling.
skin_smooth_painterly at strengths -0.3 / -0.5 / -0.7¶
| Test image | Strength | Expected | Pass? |
|---|---|---|---|
| Close-up portrait with visible pores | -0.3 | Subtle smoothing; pores still visible | |
| Close-up portrait with visible pores | -0.5 | Noticeable smoothing without crossing into "plastic" | |
| Close-up portrait with visible pores | -0.7 | Strong smoothing; check this is the upper acceptable bound | |
| Editorial / fashion portrait | -0.5 | Composes with skin_uniformity for a complete skin pass |
Fail criteria: if -0.5 already produces over-smoothed / waxy skin, narrow the recommended range to -0.3..-0.5 and update the description's "typical -0.3 to -0.7" guidance.
Portrait L2 looks¶
look_portrait_natural_skin¶
- Skin tones unchanged in the warm direction (subtle, not orange)
- Contrast feels gentle — not flat, not punchy
- Saturation pulls back without the image looking dull
- Composes naturally with skin_uniformity / skin_smooth_painterly
look_portrait_editorial¶
- Stronger contrast than natural_skin; visibly punchier
- Split-tone reads (cool shadows + warm highlights) without skin tones turning unnatural
- Saturation pull-back doesn't make image look washed out
look_portrait_skin_warm_lift (masked)¶
- mask_skin_region binding scopes the lift to skin only
- Background / clothing exposure unchanged
- Skin reads warmer + brighter without the boundary being visible (mask edge feathering OK)
- If the mask leaks onto orange backgrounds / lipstick, document and consider override-mask recipe
look_portrait_background_dim¶
- Caller-supplied subject mask shape works (no pre-baked mask)
- Background dims by ~0.4 EV; saturation reduction visible but not aggressive
- Subject preserved by the inverse mask
look_portrait_split_tone_moody¶
- Stronger split than editorial — cool blue shadows + warm orange highlights
- Skin tones survive the strong split (the failure mode: skin turns into the highlight color)
- If skin breaks at the default values, document strength override recipe
Landscape L2 looks¶
look_landscape_grand_vista¶
- Sky and foreground both readable; no extreme tone compression
- Mild clarity bite gives definition without crunch
- Warm shadows shift visible without being over-warm
look_landscape_intimate_quiet¶
- Reads as less processed than the baseline — the explicit Marino-restraint signal
- Soft clarity (negative bilat) gives painterly feel
- If image looks just "blurry," not "painterly," recipe needs sharper tuning
look_landscape_golden_hour¶
- Warm shift visible but credible (not orange-sunset cartoon)
- Highlights amber; shadows warm; image reads as "this captured the warmth I felt"
- Already-warm scenes don't blow out into pure orange
look_landscape_blue_hour_cool¶
- Cool shift visible but credible
- Mood reads as twilight / pre-dawn
- If already-cool scenes go too cyan, consider tempering
temperatureshift
look_landscape_atmospheric_haze¶
- Hazeremoval lifts visibility WITHOUT killing the moody fog
- Strength 0.5 in the dtstyle is right (not 1.0 or 1.5 — those defeat the intent)
- Composes with golden_hour for warm-hazy scenes
look_landscape_dramatic_moody¶
- Strong contrast (1.7) reads as dramatic, not crunchy
- Cool shadows + warm highlights split adds depth without skin-tone-style cartoon
- Stormy / weather images: mood emerges; calm scenes: image reads over-processed (which is the right failure mode — this look isn't for calm scenes)
look_landscape_autumn_pop¶
- Orange / red foliage visibly lifted without the "Lightroom autumn preset" cartoon look
- Sky stays natural (the sat_blue compensation working)
- Non-foliage scenes: applies regardless but reads weird (which is the right failure mode — this look isn't for non-foliage)
look_landscape_sky_enhance (masked)¶
- mask_sky binding scopes the enhancement to sky only
- Foreground / land unchanged
- On complex skies (sunsets, partial clouds, trees in sky), parametric fallback may leak — escalate via Pattern 7 of llm-vision-for-masks.md and re-test
- Composes on top of grand_vista / dramatic_moody for sky-emphasis
look_landscape_water_silk (masked)¶
- mask_water_blue_cyan binding scopes the smoothing to water only
- Smoothing actually reads as silky water (not "blur applied to a region")
- Rocks / shore unchanged
- Cyan-tinted backgrounds may leak — note as a finding
How to run a render¶
# For each test image, ensure a workspace is bootstrapped:
chemigram ingest /path/to/test/raw.NEF --image-id test_portrait_caucasian_window
# Apply the entry under test:
chemigram apply-primitive test_portrait_caucasian_window \
--entry skin_uniformity \
--param sat_orange=-0.5 \
-p expressive-baseline
# Render the preview:
chemigram render-preview test_portrait_caucasian_window
# → outputs JPEG path; open in your viewer of choice
# Visually compare against:
# - the unprocessed baseline render
# - your reference editor (Lightroom / Capture One) doing the equivalent move
For the masked entries, also test:
- The pre-baked named mask path (default — apply with no override)
- An LLM-vision-constructed mask via Pattern 7 of llm-vision-for-masks.md
What to record¶
Per entry, capture:
- Pass/fail/approximate rating
- Test images used (anonymized identifiers)
- Specific failure modes observed (e.g., "lipstick desaturates at strength -0.7 on portrait_caucasian_makeup")
- Recommended adjustments (parameter range narrowing, mask refinement, default value changes)
Outputs¶
After the review session:
- Failures → file follow-up issues, mark the entry's manifest description with caveats (or remove and re-author)
- Strength-range tuning → update the manifest's range / default fields, regenerate via
scripts/generate-l2-looks-survey.py - Mask-leakage findings → either tighten the maskdef's parametric fallback (RFC-032), document the override-mask recipe in
vocabulary-patterns.md, or escalate to LLM-vision construction (llm-vision-for-masks.mdPattern 7) - Successes → close the visual-review checkpoint and ship the closing ADR for RFC-033 (currently blocked on this checkpoint)
See also¶
docs/photographer-workflows-survey.md— the source survey that informed all 14 looks + 2 skin primitivesdocs/rfc/RFC-033-skin-tone-uniformity.md— recommends this checkpoint before ADR closuredocs/guides/llm-vision-for-masks.md— Pattern 7 for content-aware mask escalationdocs/guides/vocabulary-patterns.md— composition recipes referencing these entriesdocs/guides/visual-proofs.md— automated visual-proof sweep (different scope: lab-grade vs visual-review)