mirror of
https://github.com/storytold/lightcraft.git
synced 2026-11-10 10:29:55 -06:00
Second review round. - Paste, Paste from Previous, Sync and Auto Sync copied a stored Upright correction as it was: a virtual copy turned right got the original's matrix (15.4 px mean, 23.2 px max at 3200 x 4800), and so did a file with another EXIF orientation. They now re-express it from the source photo's frame into each target's through the stored image, as Lightroom keeps it (upright_frames). A patch that turns a photo without bringing a correction (a crop paste, a preset) turns the correction it keeps. Import records the file's orientation in the catalog (Photo::file_orientation, optional); photos imported earlier are taken as stored the way they are shown. - Synchronize Folder read sidecars without the photo's frame: a sidecar whose only change was its time undid import's crop conversion and cleared the kept Upright, silently. Its scan and its read now use the recorded frame (else the file's), and its report carries the sidecars' warnings. Without any frame an existing photo keeps its crop, and the report says so. - The Lightroom catalog import's XMP column dropped its diagnostics (Guided guides vanished); they now go into the per-image report, once alongside the develop settings' ones. - The release note says what isn't covered yet. The new regressions fail on the previous commit and pass here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
3.2 KiB
Rust
62 lines
3.2 KiB
Rust
//! Upright corrections belong to the frame of the photo they are stored with
|
|
//! (`Geometry::upright_transform`: centred coordinates of the photo as shown, after its file's
|
|
//! orientation and its own Rotate Left / Right). Settings moved between photos (Paste, Paste from
|
|
//! Previous, Sync, Auto Sync) re-express a correction in the target's frame through the stored
|
|
//! image, which is how Lightroom keeps it, and a settings patch that turns a photo turns the
|
|
//! correction it keeps (issue #205).
|
|
|
|
use lightcraft_catalog::Photo;
|
|
use lightcraft_develop::DevelopSettings;
|
|
use lightcraft_geom::{Homography, Orientation};
|
|
use serde_json::Value;
|
|
|
|
use crate::sidecar::StoredFrame;
|
|
|
|
/// A photo's frame for its Upright correction: its file's stored image, then its own rotation.
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
pub struct PhotoFrame {
|
|
pub stored: StoredFrame,
|
|
pub user: Orientation,
|
|
}
|
|
|
|
/// The frame of photo `p` with settings `s`. A photo imported before the file's orientation was
|
|
/// recorded is taken as stored the way it is shown.
|
|
pub fn frame_of(p: &Photo, s: &DevelopSettings) -> Option<PhotoFrame> {
|
|
let stored = crate::sidecar::recorded_frame(p).or_else(|| StoredFrame::of_shown(Orientation::Normal, f64::from(p.width), f64::from(p.height)))?;
|
|
Some(PhotoFrame { stored, user: s.orientation })
|
|
}
|
|
|
|
/// Correction `h`, made in frame `from`, as the same correction of the stored image in frame `to`.
|
|
pub fn reexpress(h: &Homography, from: &PhotoFrame, to: &PhotoFrame) -> Option<Homography> {
|
|
let on_stored = crate::crs::upright_on_stored(h, from.stored.orientation.then(from.user), from.stored.width, from.stored.height)?;
|
|
let saved = crate::crs::SavedUpright { mode: lightcraft_develop::Upright::Auto, matrix: on_stored };
|
|
crate::crs::upright_in_frame(&saved, to.stored.orientation.then(to.user), to.stored.width, to.stored.height)
|
|
}
|
|
|
|
/// Settings `after` of photo `p` (which had `before`) once `patch` is applied: a correction the
|
|
/// patch brought from photo frame `source` is put into `p`'s frame; a correction `p` keeps is
|
|
/// turned when the patch turned the photo. A patch from nowhere in particular (a preset) leaves a
|
|
/// correction it brings as it is.
|
|
pub fn settle(p: &Photo, before: &DevelopSettings, after: &mut DevelopSettings, patch: &Value, source: Option<&PhotoFrame>) {
|
|
let Some(target) = frame_of(p, after) else { return };
|
|
let (from, h) = if patch.pointer("/geometry/upright_transform").is_some() {
|
|
(source.copied(), after.geometry.upright_transform)
|
|
} else if after.orientation != before.orientation {
|
|
(frame_of(p, before), after.geometry.upright_transform)
|
|
} else {
|
|
return;
|
|
};
|
|
if let (Some(from), Some(h)) = (from, h) {
|
|
// a frame it can't be put in (no size) leaves it to be solved again
|
|
after.geometry.upright_transform = reexpress(&h, &from, &target);
|
|
}
|
|
}
|
|
|
|
/// `patch` applied to settings `before` of photo `p` for a transfer from photo frame `source`,
|
|
/// with the Upright correction in `p`'s frame ([`settle`]).
|
|
pub fn transferred(p: &Photo, before: &DevelopSettings, patch: &Value, source: Option<&PhotoFrame>) -> DevelopSettings {
|
|
let mut after = lightcraft_develop::apply_partial(before, patch, 1.0);
|
|
settle(p, before, &mut after, patch, source);
|
|
after
|
|
}
|