diff --git a/ui/dr-ui/src/develop.rs b/ui/dr-ui/src/develop.rs index 9319963..2961566 100644 --- a/ui/dr-ui/src/develop.rs +++ b/ui/dr-ui/src/develop.rs @@ -1829,7 +1829,20 @@ impl DevelopSession { let Some(seg) = self.segmentation.as_ref() else { return (0, 0, 0, 0); }; - let (w, h) = seg.proxy_size(); + // **Shown pixels, matching `overlay_image`.** 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 — so measuring them against the sensor's width + // and height puts the clip on the wrong axis the moment the two + // differ. That is the same confusion as the overlay itself had, one + // layer down, and it is silent for exactly the images where it is + // wrong: a landscape frame has nothing to notice. + let (sw, sh) = seg.proxy_size(); + let (w, h) = self + .graph + .framing() + .effective_orientation() + .oriented_size(sw as u32, sh as u32); let rect = self.graph.framing().visible_rect(); // Rounded outward, so half a pixel of rounding never shows as a strip @@ -1858,6 +1871,26 @@ impl DevelopSession { return None; } let (rgba, w, h) = self.segmentation.as_ref()?.overlay_rgba(); + + // TRACES: FR-DEV-3h + // **Turned the right way up before it is drawn.** Instance masks live + // in sensor space, because the generated shader samples them after + // the framing map (`uv_src`) — but this is not sampled by that shader. + // It is a flat image handed to the compositor to lay over a + // photograph that *has* been through the framing map, so it has to + // arrive in the same space the photograph is in. + // + // Without this the outlines are drawn in the sensor's orientation over + // an upright picture: on a portrait frame the colour sits nowhere near + // the subject, which reads as the detector having failed rather than + // as the overlay being turned. Nothing announces it, and it is + // invisible on landscape frames, which is most of them. + let (rgba, w, h) = self + .graph + .framing() + .effective_orientation() + .into_shown(&rgba, w, h, 4); + let buffer = slint::SharedPixelBuffer::::clone_from_slice(&rgba, w, h); Some(slint::Image::from_rgba8(buffer)) }