Re-record the manual under the scene-referred pipeline

D19 changed how every raw photograph renders, so every picture was
stale; all forty are recorded again from this tree. Beside the ones
already in the page there is now one for Tone Mapping: an alpine frame
whose clouds sit near white, its White Point raised to bring them back
and lowered for a brighter picture, its Contrast raised, then Before.

The panorama film unticks the first frame and ticks it back, so the
Frames list and the re-solve show; it no longer films minutes of
"Reading the frames", cutting from the first seconds of the job to the
alignment. The manual's presets menu opens beside the rail, not beside
the photograph.
This commit is contained in:
2026-09-27 19:43:09 -04:00
parent e600dae3df
commit 5e863fa718
34 changed files with 117 additions and 70 deletions
+7 -4
View File
@@ -174,6 +174,8 @@ the strip at its head narrows it to one group.
Exposure, contrast, highlights, shadows, blacks, whites and a tone curve. Exposure, contrast, highlights, shadows, blacks, whites and a tone curve.
Hold `Before` to see the photograph as it was. Hold `Before` to see the photograph as it was.
![Raising exposure, pulling the highlights, lifting the shadows, then holding Before](media/develop-light.gif)
`Tone Mapping`, last in the group, is how the scene is fitted onto the `Tone Mapping`, last in the group, is how the scene is fitted onto the
screen, and it runs after every other adjustment. `White Point` says how many screen, and it runs after every other adjustment. `White Point` says how many
stops above middle grey reach white — raise it to bring a bright sky back stops above middle grey reach white — raise it to bring a bright sky back
@@ -181,9 +183,10 @@ from white, lower it for a brighter, punchier picture — and `Contrast` sets
the slope of the curve between. Every adjustment above it works on the scene the slope of the curve between. Every adjustment above it works on the scene
as the camera recorded it, highlights beyond white included, so pulling the as the camera recorded it, highlights beyond white included, so pulling the
highlights recovers what the sensor caught rather than what the screen could highlights recovers what the sensor caught rather than what the screen could
show. show. A JPEG has been fitted to a screen already, by the camera, so on a
JPEG these two do nothing.
![Raising exposure, pulling the highlights, lifting the shadows, then holding Before](media/develop-light.gif) ![Raising the white point to bring the clouds back from white, lowering it for a brighter picture, raising the contrast, then holding Before](media/develop-tonemap.gif)
### Looking closer ### Looking closer
@@ -299,7 +302,7 @@ a gradient over the sky whose `Print Exposure` burns it in.
Every change is a step; `Undo` and the History panel walk them. `Snapshot` Every change is a step; `Undo` and the History panel walk them. `Snapshot`
keeps the current state under a name. `Presets`, at the foot of the tool keeps the current state under a name. `Presets`, at the foot of the tool
rail on the left, opens a menu of presets beside the photograph, filed in rail on the left, opens a menu of presets beside the rail, over the photograph, filed in
folders that start closed: your own under `Yours`, then the ones DarkRoom folders that start closed: your own under `Yours`, then the ones DarkRoom
ships — `Essentials`, `Skies`, and `Film`, which holds `Colour`, `Cinema` ships — `Essentials`, `Skies`, and `Film`, which holds `Colour`, `Cinema`
and `Black and white`, one measured stock each. Choosing a folder opens it; and `Black and white`, one measured stock each. Choosing a folder opens it;
@@ -356,7 +359,7 @@ It opens in develop all the same, on a reduced copy that is drawn from the
full resolution wherever you zoom in, and it exports at full size. The same full resolution wherever you zoom in, and it exports at full size. The same
goes for a panorama Lightroom stitched and saved as a DNG. goes for a panorama Lightroom stitched and saved as a DNG.
![Twelve frames aligned, the projections tried, and the border filled](media/panorama.gif) ![Twelve frames aligned, the first left out and brought back, the projections tried, and the border filled](media/panorama.gif)
![The alignment on a cylinder, each frame outlined where it landed](media/panorama-aligned.png) ![The alignment on a cylinder, each frame outlined where it landed](media/panorama-aligned.png)
+6 -4
View File
@@ -263,6 +263,7 @@ the strip at its head narrows it to one group.</p>
<h3 id="light">Light</h3> <h3 id="light">Light</h3>
<p>Exposure, contrast, highlights, shadows, blacks, whites and a tone curve. <p>Exposure, contrast, highlights, shadows, blacks, whites and a tone curve.
Hold <code>Before</code> to see the photograph as it was.</p> Hold <code>Before</code> to see the photograph as it was.</p>
<figure><img loading="lazy" src="media/develop-light.gif" alt="Raising exposure, pulling the highlights, lifting the shadows, then holding Before"><figcaption>Raising exposure, pulling the highlights, lifting the shadows, then holding Before</figcaption></figure>
<p><code>Tone Mapping</code>, last in the group, is how the scene is fitted onto the <p><code>Tone Mapping</code>, last in the group, is how the scene is fitted onto the
screen, and it runs after every other adjustment. <code>White Point</code> says how many screen, and it runs after every other adjustment. <code>White Point</code> says how many
stops above middle grey reach white — raise it to bring a bright sky back stops above middle grey reach white — raise it to bring a bright sky back
@@ -270,8 +271,9 @@ from white, lower it for a brighter, punchier picture — and <code>Contrast</co
the slope of the curve between. Every adjustment above it works on the scene the slope of the curve between. Every adjustment above it works on the scene
as the camera recorded it, highlights beyond white included, so pulling the as the camera recorded it, highlights beyond white included, so pulling the
highlights recovers what the sensor caught rather than what the screen could highlights recovers what the sensor caught rather than what the screen could
show.</p> show. A JPEG has been fitted to a screen already, by the camera, so on a
<figure><img loading="lazy" src="media/develop-light.gif" alt="Raising exposure, pulling the highlights, lifting the shadows, then holding Before"><figcaption>Raising exposure, pulling the highlights, lifting the shadows, then holding Before</figcaption></figure> JPEG these two do nothing.</p>
<figure><img loading="lazy" src="media/develop-tonemap.gif" alt="Raising the white point to bring the clouds back from white, lowering it for a brighter picture, raising the contrast, then holding Before"><figcaption>Raising the white point to bring the clouds back from white, lowering it for a brighter picture, raising the contrast, then holding Before</figcaption></figure>
<h3 id="looking-closer">Looking closer</h3> <h3 id="looking-closer">Looking closer</h3>
<p>Double-click for 1:1; drag to move about; double-click again to fit. The <p>Double-click for 1:1; drag to move about; double-click again to fit. The
wheel zooms to any amount in between. Past 1:1 the file's own pixels are wheel zooms to any amount in between. Past 1:1 the file's own pixels are
@@ -353,7 +355,7 @@ a gradient over the sky whose <code>Print Exposure</code> burns it in.</p>
<h3 id="history-snapshots-presets">History, snapshots, presets</h3> <h3 id="history-snapshots-presets">History, snapshots, presets</h3>
<p>Every change is a step; <code>Undo</code> and the History panel walk them. <code>Snapshot</code> <p>Every change is a step; <code>Undo</code> and the History panel walk them. <code>Snapshot</code>
keeps the current state under a name. <code>Presets</code>, at the foot of the tool keeps the current state under a name. <code>Presets</code>, at the foot of the tool
rail on the left, opens a menu of presets beside the photograph, filed in rail on the left, opens a menu of presets beside the rail, over the photograph, filed in
folders that start closed: your own under <code>Yours</code>, then the ones DarkRoom folders that start closed: your own under <code>Yours</code>, then the ones DarkRoom
ships — <code>Essentials</code>, <code>Skies</code>, and <code>Film</code>, which holds <code>Colour</code>, <code>Cinema</code> ships — <code>Essentials</code>, <code>Skies</code>, and <code>Film</code>, which holds <code>Colour</code>, <code>Cinema</code>
and <code>Black and white</code>, one measured stock each. Choosing a folder opens it; and <code>Black and white</code>, one measured stock each. Choosing a folder opens it;
@@ -398,7 +400,7 @@ preview and in the composite.</p>
It opens in develop all the same, on a reduced copy that is drawn from the It opens in develop all the same, on a reduced copy that is drawn from the
full resolution wherever you zoom in, and it exports at full size. The same full resolution wherever you zoom in, and it exports at full size. The same
goes for a panorama Lightroom stitched and saved as a DNG.</p> goes for a panorama Lightroom stitched and saved as a DNG.</p>
<figure><img loading="lazy" src="media/panorama.gif" alt="Twelve frames aligned, the projections tried, and the border filled"><figcaption>Twelve frames aligned, the projections tried, and the border filled</figcaption></figure> <figure><img loading="lazy" src="media/panorama.gif" alt="Twelve frames aligned, the first left out and brought back, the projections tried, and the border filled"><figcaption>Twelve frames aligned, the first left out and brought back, the projections tried, and the border filled</figcaption></figure>
<figure><img loading="lazy" src="media/panorama-aligned.png" alt="The alignment on a cylinder, each frame outlined where it landed"><figcaption>The alignment on a cylinder, each frame outlined where it landed</figcaption></figure> <figure><img loading="lazy" src="media/panorama-aligned.png" alt="The alignment on a cylinder, each frame outlined where it landed"><figcaption>The alignment on a cylinder, each frame outlined where it landed</figcaption></figure>
<figure><img loading="lazy" src="media/panorama-filled.png" alt="The same, with the ragged border filled by the model rather than cropped away"><figcaption>The same, with the ragged border filled by the model rather than cropped away</figcaption></figure> <figure><img loading="lazy" src="media/panorama-filled.png" alt="The same, with the ragged border filled by the model rather than cropped away"><figcaption>The same, with the ragged border filled by the model rather than cropped away</figcaption></figure>
<h2 id="export">Export</h2> <h2 id="export">Export</h2>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+41 -2
View File
@@ -784,6 +784,34 @@ def develop_light():
undo_all() undo_all()
@scene(media=['develop-tonemap.gif'], sources=DEVELOP_SRC + PIPELINE_SRC)
def develop_tonemap():
"""Tone Mapping on an alpine frame whose clouds are nearly white: the
white point raised to bring the clouds back from white, then lowered
for a brighter, harder picture, the contrast raised, and Before held.
Its Contrast is the Light group's second, so it is taken by position."""
at_develop(ALPS_SKY)
group('Light')
in_column('White Point@Slider')
rec('develop-tonemap')
pause(0.8)
slide('White Point', TONEMAP_WHITE_UP)
pause(1.2)
slide('White Point', -TONEMAP_WHITE_DOWN)
pause(1.2)
x0, y0, x1, y1 = column()
cx, cy = handle(dr.find('Contrast@Slider#-1', within=(x0, y0, x1, y1)))
dr.drag(cx, cy, cx + TONEMAP_CONTRAST, cy, 25)
pause(1.2)
hold_before(1.6)
pause(1.0)
cut()
undo_all()
TONEMAP_WHITE_UP, TONEMAP_WHITE_DOWN, TONEMAP_CONTRAST = 80, 110, 90 # pixels along the track
@scene(media=['develop-zoom.gif'], sources=DEVELOP_SRC + ['ui/dr-ui/src/develop/render.rs']) @scene(media=['develop-zoom.gif'], sources=DEVELOP_SRC + ['ui/dr-ui/src/develop/render.rs'])
def develop_zoom(): def develop_zoom():
"""1:1 with a double-click, a pan, and then further in with the wheel. """1:1 with a double-click, a pan, and then further in with the wheel.
@@ -1289,11 +1317,22 @@ def join(name, parts):
'core/dr-pano/src/**']) 'core/dr-pano/src/**'])
def panorama(): def panorama():
select_pano() select_pano()
rec('panorama-a') rec('panorama-0')
dr.click_on('Merge to panorama@Button') dr.click_on('Merge to panorama@Button')
pause(4)
cut()
# Reading and aligning twelve frames is minutes on a busy machine; the
# film shows it start and picks up once the alignment is on the page.
dr.wait_for('Fill the border@RadioButton', 600) dr.wait_for('Fill the border@RadioButton', 600)
pause(3) pause(3)
shot('panorama-aligned') shot('panorama-aligned')
rec('panorama-a')
pause(1)
# The first frame left out and brought back: the rest are solved again
# from the pairs already matched, so each takes a moment, not a re-read.
for _ in range(2):
dr.click(*dr.centre(f'{PANO_FIRST}.CR2@CheckBox'))
pause(4)
for projection in ('Perspective', 'Spherical', 'Cylindrical'): for projection in ('Perspective', 'Spherical', 'Cylindrical'):
dr.click_on(f'{projection}@RadioButton') dr.click_on(f'{projection}@RadioButton')
pause(5) pause(5)
@@ -1312,7 +1351,7 @@ def panorama():
dr.click_on('Merge@Button') dr.click_on('Merge@Button')
pause(8) pause(8)
cut() cut()
join('panorama', ['panorama-a', 'panorama-b']) join('panorama', ['panorama-0', 'panorama-a', 'panorama-b'])
# The merge itself takes minutes too; the scene is done when the DNG is. # The merge itself takes minutes too; the scene is done when the DNG is.
wait_for_new(DEMO_LIBRARY, '.dng', started, 600) if DEMO_LIBRARY else pause(60) wait_for_new(DEMO_LIBRARY, '.dng', started, 600) if DEMO_LIBRARY else pause(60)
pause(5) pause(5)