Average a patch under the white balance picker, not one photosite
The probe's comment said a 192px render "averages a small neighbourhood into each of its pixels". It does not: the composed shader fetches the source at one position per output pixel - nearest for an unrotated frame, four photosites blended otherwise - so the probe was a point sample of a noisy sensor, and two painted-white air conditioners on the same wall answered +37 and -50. The tap is now narrowed to the patch of the canvas around the click, a couple of percent of its width and square on screen, and rendered at 64x64 with interpolation forced on, which puts a sample on every sensor pixel under it at any ordinary zoom. The samples are averaged, with the void and clipped ones left out rather than allowed to pull the mean, and fewer than half surviving is refused. compose_camera_probe takes the patch; the merge's compose_camera_linear keeps its nearest sampling. The readback shrinks from six megabytes to sixty-four kilobytes. A frame of alternating warm and cool columns, averaging neutral, moves the controls by at most two units; a point sample swung them to sixty.
This commit is contained in:
@@ -858,14 +858,36 @@ impl EditGraph {
|
||||
}
|
||||
|
||||
/// TRACES: FR-DEV-3
|
||||
/// The camera-space tap under this edit's own framing — crop, view,
|
||||
/// rotation and all — so a fraction of what is on the canvas is a
|
||||
/// fraction of what this renders. Nothing else of the edit: no
|
||||
/// operation, no mask, no repair. See
|
||||
/// [`crate::operation::compose_camera_probe`] for why the white balance
|
||||
/// picker reads from here and not from the display.
|
||||
pub fn compose_camera_probe(&self) -> ComposedShader {
|
||||
crate::operation::compose_camera_probe(&self.warps, &self.framing)
|
||||
/// The camera-space tap over one patch of what is on the canvas.
|
||||
///
|
||||
/// `patch` is in fractions of the visible region — the coordinates a
|
||||
/// click on the canvas arrives in — and is laid over this edit's own
|
||||
/// framing: crop, view, rotation and all, so a fraction of the canvas is
|
||||
/// a fraction of the probe. Nothing else of the edit: no operation, no
|
||||
/// mask, no repair. Rendering only the patch is what lets a small target
|
||||
/// cover every sensor pixel under it rather than sampling one in fifty;
|
||||
/// see [`crate::operation::compose_camera_probe`] for why the white
|
||||
/// balance picker reads from here and not from the display.
|
||||
///
|
||||
/// The patch is centred where asked and held to the view's own minimum
|
||||
/// extent: at a deep zoom a patch a fraction of the view would be
|
||||
/// smaller than a view may be, and letting `set_view` widen it from one
|
||||
/// corner would move the sample off the point that was clicked.
|
||||
pub fn compose_camera_probe(&self, patch: crate::framing::CropRect) -> ComposedShader {
|
||||
use crate::framing::CropRect;
|
||||
let mut framing = self.framing;
|
||||
let view = framing.view();
|
||||
let width = (patch.width * view.width).max(CropRect::MIN_EXTENT);
|
||||
let height = (patch.height * view.height).max(CropRect::MIN_EXTENT);
|
||||
let cx = view.x + (patch.x + patch.width * 0.5) * view.width;
|
||||
let cy = view.y + (patch.y + patch.height * 0.5) * view.height;
|
||||
framing.set_view(CropRect {
|
||||
x: (cx - width * 0.5).clamp(0.0, 1.0 - width),
|
||||
y: (cy - height * 0.5).clamp(0.0, 1.0 - height),
|
||||
width,
|
||||
height,
|
||||
});
|
||||
crate::operation::compose_camera_probe(&self.warps, &framing)
|
||||
}
|
||||
|
||||
/// TRACES: FR-DEV-19c
|
||||
|
||||
Reference in New Issue
Block a user