7e1c33ebed50da80f01c748b30c441bcde2cdf83
Build and test / Desktop (Linux) (push) Successful in 19m42s
Build and test / Layer separation (push) Successful in 27s
Traceability / Requirement traces (push) Successful in 34s
🐳 Android image / Build and push (push) Successful in 4s
Build and test / android-image (push) Successful in 4s
Build and test / Android (aarch64) (push) Failing after 33m12s
"Find subjects" would recognise a person on a portrait frame and then paint the outline into the hillside behind them. The detection was right and the mask was right; what was wrong was the picture drawn to show them. Instance masks live in sensor space, and correctly so — the generated shader samples them at `uv_src`, after the framing map, which is what keeps a mask on its subject through a zoom, a pan and a crop. The overlay is the one consumer that is *not* sampled by that shader. It is a flat image handed to the compositor to lay over a photograph that has already been through the framing map, so it has to arrive in the same space that photograph is in, and it did not. On a frame from a camera held sideways the outlines were drawn a quarter turn away from the subjects they described. `overlay_clip` had the same fault one layer down, and it is the more insidious of the two because it looks right. The crop and the viewport are fractions of the photograph as the user sees it — the prologue maps an output pixel through `crop_rect` *before* it unturns the frame — and they were being measured against the sensor's width and height. Two numbers, correct type, wrong axis. Both now go through `Orientation::into_shown`, so the overlay and its clip are in the photograph's space and the turn is the same one the render and the thumbnails make. Neither was noticeable until this week, and the reason is worth writing down: before the detector was given an upright frame it found almost nothing on a portrait photograph, so there was rarely an outline to be in the wrong place. Fixing the detector is what made this visible. Landscape frames were never affected, which is most of them, and is why an overlay that ignored orientation entirely survived this long. Verified on `_MG_9080.CR2`, a portrait frame of two people and a dog: the overlay was a 1599x1066 image drawn onto a 1066x1599 canvas, with the colour sitting in the mountainside above the subjects. It is now 1066x1599, and each outline is on the thing it names. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
DarkRoom
A cross-platform, non-destructive RAW photo editor for Linux and Android.
Status: early. v0.1 is a remote library viewer — see docs/milestone-v0.1.md.
Documentation
| Document | Contents |
|---|---|
| requirements.md | What the software must do — 122 numbered requirements |
| architecture.md | How it is built — crates, GPU pipeline, data model, sync |
| milestone-v0.1.md | The first buildable milestone |
Building
Desktop:
cargo run -p darkroom-desktop
Android (containerised toolchain, see docker/android):
./docker/android/build.sh cargo ndk -t arm64-v8a build --release
Current state
Working: workspace, GPU context and compute pass, adaptive Slint shell, Android cross-compilation of the core crates.
Not yet working: the zero-copy display path. The build currently uploads frames through the CPU, which is exactly what ARCH §6.1 forbids — measured at 96% of frame time at 4K. Replacing it is spike S1, the project's highest priority.
cargo run -p dr-gpu --example bench --features readback
reproduces that measurement.
Licence
GPL-3.0-or-later.
Releases
20
DarkRoom 0.24.0
Latest
Languages
Rust
86.1%
Slint
10.3%
Python
1.1%
Shell
1%
WGSL
0.9%
Other
0.6%