Skip to content

Printing Notes: the dodge/burn map and print recipe as a printer writes them - #767

Merged
marcinz606 merged 1 commit into
mainfrom
feat/printer-notes
Aug 6, 2026
Merged

Printing Notes: the dodge/burn map and print recipe as a printer writes them#767
marcinz606 merged 1 commit into
mainfrom
feat/printer-notes

Conversation

@marcinz606

Copy link
Copy Markdown
Owner

What

A darkroom printer keeps a printing record — paper, grade, exposure, then the dodge/burn instructions in stops, often sketched straight onto the work print. Every number that record needs was already in the config (PolygonMask.strength is EV stops, the recipe lives in ExposureConfig, FinishConfig.vignette_stops is an edge burn), but nothing showed it the way a printer reads it and nothing left the app with it.

The Export tab gets a Printing Notes section with two side-by-side buttons:

  • Preview (also Shift+N) — draws the marked-up work print over the frame: burns hatched, dodges left open, each mask badged with its number and value in stops, plus a card with the print recipe. Display-only.
  • Export — writes <stem>_notes.jpg into the export folder: the same map baked onto the rendered frame with the recipe in a band underneath. A separate file; a normal export is never annotated.

Conventions (borrowed, not invented)

  • Shading/hatching marks where the paper gets extra exposure, so burns are hatched and dodges are open.
  • The numbers are exposure, not brightness: a burn reads +, a dodge reads . PolygonMask.strength is the opposite sign (+ = dodge = brighter), so mask_notes inverts it in one place and a test pins that. Values snap to ⅓/½/¼ glyphs when they land close, otherwise decimals.
  • Every mask is on the map, hidden ones included — the eye toggle unclutters editing, but a record that quietly omits a burn is wrong.
  • The overlay steps aside wherever the zone grid does (test strip, flat peek, crop/analysis) and additionally over the compare baseline, which has no masks applied.

How it is built

  • services/view/printing_notes.py — pure text: stops_label, mask_notes, recipe_lines (defaults omitted). No Qt, and it takes sub-configs rather than WorkspaceConfig since domain/models imports the features.
  • desktop/view/canvas/printing_notes.py — the painting, shared by canvas and sheet; scale sizes pens/hatch/type so a full-res sheet is not hairlines.
  • The sheet is baked from the frame the canvas already rendered, so screen and file agree by construction. Resolution therefore follows the preview — HQ on gives a full-resolution sheet. Re-rendering at export resolution would mean plumbing uv_grid through the export path for no legibility gain.
  • The inverse uv_grid lookup inside CanvasOverlay._raw_to_screen moved to CoordinateMapping.map_raw_to_viewport (the mirror of the existing map_click_to_raw), so the canvas and the sheet map coordinates through one implementation.

Verification

  • make all green (3442 passed).
  • New: tests/test_printing_notes.py (labels, sign inversion, recipe contents), tests/test_printing_notes_overlay.py (when the map paints, hatch on burns only, sheet geometry), tests/test_printing_notes_panel.py (the section, both buttons, no toggle echo).
  • Headless driver on samples/DSC00448.ARW: real render → dodge + burn masks → sheet baked; masks land where the pipeline puts them, recipe reads 1 Burn +1 · 2 Dodge −½.

Docs updated in the same change: docs/USER_GUIDE.md §6.3 (overlay + conventions) and §11 (the section). No PIPELINE.md change — nothing touches pixels.

… exportable

A darkroom printer keeps a printing record: paper, grade, exposure, then the
dodge/burn instructions in stops, often sketched onto the straight print. Every
number for that record was already in the config; nothing showed it the way a
printer reads it and nothing left the app with it.

The Export tab's new Printing Notes section previews the marked-up work print on
the canvas (Shift+N) and exports it as `<stem>_notes.jpg`: burns hatched, dodges
open, each mask badged with its value in stops, and the recipe in a band below.
Display-only — a normal export is never annotated.

Stops are written in the exposure domain a printing record uses, so a burn reads
+ and a dodge reads −, inverting PolygonMask.strength in one helper.

The sheet is baked from the frame the canvas already rendered, so screen and file
agree by construction (resolution follows the preview; HQ gives a full-res sheet).
The inverse uv_grid lookup behind CanvasOverlay._raw_to_screen moves to
CoordinateMapping.map_raw_to_viewport so the canvas and the sheet share one
mapping and cannot drift.
@marcinz606
marcinz606 marked this pull request as ready for review August 6, 2026 18:18
@marcinz606
marcinz606 merged commit dbffc90 into main Aug 6, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant