LR-META-XMP: keep saved Upright in the photo's frame, put sidecar crops there too (#205)
Review fixes for the saved Upright import. - The saved matrix is placed when the sidecar is merged, in the frame the file's orientation and then the photo's own Rotate Left / Right give (Orientation::then). Read Metadata after a rotation no longer keeps it in the old frame (up to 21 px off on DSC_1457). Rotate Left / Right turns a stored Upright correction with the photo (upright::turned), LightCraft's own as well. - Sidecar crops go through the Lightroom catalog import's conversion (catalog_crop, moved to crs::crop_in_frame unchanged) whenever the file's orientation is known. A portrait raw's crop used to cut the wrong side (DSC_1486 rendered 2548 x 4812 for Lightroom's 3200 x 3808; now 0.12 px mean from Lightroom's export after the NEF frame inset), and straightened crops from a real catalog's settings came out 8459 x 3827 for Lightroom's 7725 x 5150. A straightened crop on top of a saved Upright isn't measured: the mode is solved again, with the warning. - Lightroom catalogs don't read the saved Upright until a real catalog verifies its encoding and frame: the mode is solved again and the import reports it. - Guided Upright guides are reported whether or not automatic matrices are present. The new regressions fail on the previous commit and pass here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
aaf3094c8d
commit
7bb11f4604
15 files changed
+428
-130
No files matched your search
@@ -42,8 +42,10 @@ WITHOUT ROWID or virtual table produces an explicit error, handled as a warning
|
||||
Develop settings reuse the existing XMP/preset mapper. Supported sliders, curves and supported
|
||||
mask structures remain editable, but this is approximate rendering: camera profiles, Adobe AI
|
||||
models, some masking/retouch fields and process-version algorithms are not reproduced. Unmapped
|
||||
fields are reported. Lightroom's saved Upright correction is kept in the stored image's frame, like the crop (see
|
||||
[xmp-interop.md](xmp-interop.md), *Saved Upright geometry*). Lightroom's `ProcessVersion` is not mapped: newly imported photos are on
|
||||
fields are reported. Lightroom's saved Upright correction isn't read from catalogs yet: how a catalog stores it, and
|
||||
whether the catalog's orientation agrees with the decoded file, haven't been checked on a real catalog, so the mode
|
||||
is solved again and the import reports `Upright` (XMP sidecars keep it: [xmp-interop.md](xmp-interop.md), *Saved
|
||||
Upright geometry*). Lightroom's `ProcessVersion` is not mapped: newly imported photos are on
|
||||
LightCraft's latest rendering process, and photos already in the library keep theirs
|
||||
([process-versions.md](process-versions.md)). When a recovery archive is saved, it retains source settings/history/snapshots
|
||||
and original smart-collection rules. Smart collections become regular albums with current
|
||||
|
||||
@@ -167,7 +167,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
|
||||
| LR-META-COPYRIGHT-DEFAULT | Default copyright on import | P1 | ✅ | `cmd:library.preferences` (`import.copyright`, `import.creator`), `crates/ui-egui/src/panels/settings.rs` | Settings → Import → Metadata; fills only photos without their own |
|
||||
| LR-META-LOCATION | Location editing | P2 | 🟡 | `cmd:photo.setMeta` (`location`, `city`, `state`, `country`, `gps`), `cmd:metadata.reverseGeocode` | place fields and GPS (decimal or degrees / minutes / seconds) edited in Info, read/written as IPTC Core / Photoshop / EXIF XMP; Show on Map opens OpenStreetMap; Fill Location fills empty City / State / Country from GPS offline (GeoNames, downloaded on request: `cmd:metadata.downloadPlaceNames`); no embedded map |
|
||||
| LR-META-COPYPASTE | Copy / paste metadata | P2 | ✅ | `cmd:photo.copyMetadata`, `cmd:photo.pasteMetadata` | title, caption, alt text, extended description, copyright (notice, status, usage terms, info URL), creator, place fields, keywords; `fields` picks a subset |
|
||||
| LR-META-XMP | XMP read/write | P0 | ✅ | `cmd:photo.saveMetadataToFile`, `cmd:photo.readMetadataFromFile`, `cmd:library.xmpPreferences`, `crates/engine/src/sidecar.rs`, `docs/xmp-interop.md` | sidecar wins for metadata; a sidecar capture time (`exif:DateTimeOriginal` / `photoshop:DateCreated` / `xmp:CreateDate`) fills in only when the file has none; saving merges into an existing sidecar (`crates/meta/src/xmp_merge.rs`): another app's `crs:`, `xmpMM:History` and unknown namespaces are kept byte for byte, an unreadable sidecar is backed up first; with stem naming, files sharing a stem (raw + JPEG) get separate sidecars (`<file>.xmp` for all but the raw); a `crs:` custom white balance on a relative-WB raw is shifted from `crs:AsShotTemperature` rather than read as Kelvin, or kept As Shot and reported when the packet has no as-shot white (issue #510); heal and clone spots (`crs:RetouchAreas`, legacy `crs:RetouchInfo`) are read into our spots (`crates/engine/src/crs_masks.rs`, see `docs/xmp-interop.md` → Spot removal); Lightroom's saved Upright correction for the selected mode (`crs:UprightTransform_*`) is kept instead of being solved again, matching three Lightroom Upright Auto exports to under 1 px (issue #205, `crates/engine/src/tests_upright.rs`, see `docs/xmp-interop.md` → Saved Upright geometry), and `crs:PerspectiveUpright` 2, 3, 4 read as Full, Level, Vertical |
|
||||
| LR-META-XMP | XMP read/write | P0 | ✅ | `cmd:photo.saveMetadataToFile`, `cmd:photo.readMetadataFromFile`, `cmd:library.xmpPreferences`, `crates/engine/src/sidecar.rs`, `docs/xmp-interop.md` | sidecar wins for metadata; a sidecar capture time (`exif:DateTimeOriginal` / `photoshop:DateCreated` / `xmp:CreateDate`) fills in only when the file has none; saving merges into an existing sidecar (`crates/meta/src/xmp_merge.rs`): another app's `crs:`, `xmpMM:History` and unknown namespaces are kept byte for byte, an unreadable sidecar is backed up first; with stem naming, files sharing a stem (raw + JPEG) get separate sidecars (`<file>.xmp` for all but the raw); a `crs:` custom white balance on a relative-WB raw is shifted from `crs:AsShotTemperature` rather than read as Kelvin, or kept As Shot and reported when the packet has no as-shot white (issue #510); heal and clone spots (`crs:RetouchAreas`, legacy `crs:RetouchInfo`) are read into our spots (`crates/engine/src/crs_masks.rs`, see `docs/xmp-interop.md` → Spot removal); Lightroom's saved Upright correction for the selected mode (`crs:UprightTransform_*`) is kept from XMP instead of being solved again, matching three Lightroom Upright Auto exports to under 1 px (issue #205, `crates/engine/src/tests_upright.rs`, see `docs/xmp-interop.md` → Saved Upright geometry; not yet from Lightroom catalogs), `crs:PerspectiveUpright` 2, 3, 4 read as Full, Level, Vertical, and sidecar crops go through the file's orientation like catalog crops (portrait raws were cut on the wrong side) |
|
||||
| LR-META-EXIF-FULL | Full EXIF/IPTC [Classic] | P1 | ✅ | `cmd:photo.allMetadata`, `cmd:dialog.allMetadata`, `crates/meta/src/tags.rs`, `crates/meta/src/exif.rs`, `crates/meta/src/iptc.rs` | read and written on export; Info ▸ All Metadata…: every TIFF / EXIF / GPS / interop tag (named, common values spelled out) and the XMP fields, searchable; metadata presets |
|
||||
|
||||
## F. Edit panel — global adjustments (EDIT)
|
||||
@@ -215,7 +215,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts).
|
||||
)
|
||||
| LR-EDIT-OPTICS-DEFRINGE | Defringe | P1 | ✅ | `ctl:optics.defringe*` | no fringe eyedropper |
|
||||
| LR-EDIT-OPTICS-MANUAL | Manual distortion / vignetting | P1 | ✅ | `ctl:optics.distortion`, `ctl:optics.vignetting`, `ctl:optics.vignettingMidpoint` | |
|
||||
| LR-EDIT-GEOM-UPRIGHT | Upright | P1 | ✅ | `cmd:geometry.upright`, `cmd:geometry.guides` | LightCraft's own solver; Lightroom's saved Upright from XMP and catalogs is kept as it is (LR-META-XMP) |
|
||||
| LR-EDIT-GEOM-UPRIGHT | Upright | P1 | ✅ | `cmd:geometry.upright`, `cmd:geometry.guides` | LightCraft's own solver; Lightroom's saved Upright from XMP is kept as it is (LR-META-XMP); Rotate Left / Right turns a stored correction with the photo |
|
||||
| LR-EDIT-GEOM-MANUAL | Manual transform | P1 | ✅ | `ctl:geometry.*` | |
|
||||
| LR-EDIT-GEOM-CONSTRAIN | Constrain crop | P1 | ✅ | `crates/ui-egui/src/panels/right.rs` (checkbox → `cmd:develop.merge`) | |
|
||||
| LR-EDIT-GEOM-GRID | Grid while transforming | P2 | ✅ | `crates/ui-egui/src/panels/detail.rs` | a fine grid over the photo while a geometry slider is dragged |
|
||||
@@ -787,7 +787,7 @@ Latin stays upright. Advanced Japanese composition remains open. Regression cove
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-12 | minor | LR-META-XMP: Lightroom's saved Upright correction for the selected mode is kept from XMP and catalogs instead of being solved again (issue #205); `PerspectiveUpright` 2, 3, 4 read as Full, Level, Vertical; statuses unchanged |
|
||||
| 2026-10-12 | minor | LR-META-XMP: Lightroom's saved Upright correction for the selected mode is kept from XMP instead of being solved again (issue #205; catalogs fall back and report it); `PerspectiveUpright` 2, 3, 4 read as Full, Level, Vertical; sidecar crops follow the file's orientation; LR-EDIT-GEOM-UPRIGHT: Rotate turns a stored correction; statuses unchanged |
|
||||
| 2026-10-11 | minor | KEY-SLIDER-TYPE: honor immediate Return/Escape and keep typed keys in the value editor; add regression references |
|
||||
| 2026-10-11 | minor | LR-PROF-CAMERACOLOR: raws with a black-and-white camera JPEG take its tone curve (issue #577) |
|
||||
| 2026-10-11 | minor | LR-VIEW-ZOOM and LR-VIEW-COMPARE: Compare and Reference are sharp at 1:1 (zoom windows per pane, two originals kept decoded while they are open); statuses unchanged |
|
||||
|
||||
@@ -157,7 +157,7 @@ essentials replaces its guessed 45% raw look with 84% × 0.75 (+1 point).
|
||||
|---|---:|---:|---|
|
||||
| Interaction fidelity / UI clarity | ×0.95 | ×0.95 | brush live preview gaps and feathering (#517, #518); crop artefacts and limits (#731, #742, #770, #771); Compare white-balance selector (#743–#745); low-res slider previews (#330); dialogs taller than the window (#781); mouse-wheel scroll (#714); 100% zoom capped (gap 4) |
|
||||
| Stability on real machines | ×0.92 | ×0.92 | launch and quit crashes or silent startup failures (#250 macOS 12 Intel, #315 Windows Intel GPU, #431 Intel Mac, #260, #462, #783 Linux / Nouveau, #790 Windows installer); tests run in CI on FreeBSD only (gap 9) |
|
||||
| File exchange with Lightroom users (mainstream) / opening files people send (essentials) | ×0.92 | ×0.95 | Adobe XMP sidecars change colours (#290), XMP CameraProfile ignored (#204), Guided Upright from XMP not carried over (#205), catalog import fails (#599), same Light values render differently (#523, #209), no write-back to `.lrcat`; for casual users: CR3 beyond verified bodies, compressed ORF, HE NEF open as previews (#473, #485, #556), HEIC trouble (#693) |
|
||||
| File exchange with Lightroom users (mainstream) / opening files people send (essentials) | ×0.92 | ×0.95 | Adobe XMP sidecars change colours (#290), XMP CameraProfile ignored (#204), Guided Upright and catalog Upright not carried over (#205), catalog import fails (#599), same Light values render differently (#523, #209), no write-back to `.lrcat`; for casual users: CR3 beyond verified bodies, compressed ORF, HE NEF open as previews (#473, #485, #556), HEIC trouble (#693) |
|
||||
| **Product** | **×0.804** | **×0.830** | |
|
||||
|
||||
### Mainstream practitioner: ~49%
|
||||
@@ -297,7 +297,7 @@ P2 items 12–25 h; look tuning, performance, packaging, hardening 25–45 h.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-12 | patch | File-exchange evidence: Lightroom's saved Upright correction is kept from XMP and catalogs (#205); only Guided Upright isn't carried over; the ×0.92 / ×0.95 discount and all numbers are unchanged |
|
||||
| 2026-10-12 | patch | File-exchange evidence: Lightroom's saved Upright correction is kept from XMP sidecars (#205); Guided Upright and catalogs aren't carried over yet; the ×0.92 / ×0.95 discount and all numbers are unchanged |
|
||||
| 2026-10-11 | minor | EOS R5 Mark II CR3 verified (raw-parity.md): use-weighted share whose camera decodes 84% → 85%, RAW decoding 76% → 77%; full 60.6% → 60.7%, mainstream depth 71.8% → 72.1%, essentials depth 77.4% → 77.5%; the rounded numbers (~61%, ~49%, ~64%) are unchanged |
|
||||
| 2026-10-10 | minor | RAW measured model by model (raw-parity.md): RAW decoding (76%) and colour (35%) are explicit rows of the full sum (59% → 61%); mainstream uses the use-weighted 84% plus a ×0.85 colour discount (51% → 49%); essentials uses 84% × colour 0.75 (63% → 64%); beta ~14 points |
|
||||
| 2026-10-10 | minor | Full number restored to an additive weighted sum over the dimensions (~59%; method aligned with the standard, no new evidence); hours to ~95% for each of the three audiences; beta distance ~16 points |
|
||||
|
||||
+6
-2
@@ -5,8 +5,12 @@
|
||||
### Lightroom Upright comes across
|
||||
- Photos edited in Lightroom with Upright Auto, Full, Level or Vertical now open framed as they are in Lightroom
|
||||
(issue #205). LightCraft keeps the correction Lightroom saved with the edit instead of analysing the photo again.
|
||||
This works for XMP sidecars, DNG files with the edit inside and Lightroom Classic catalogs. Photos imported
|
||||
earlier get it with Photo ▸ Read Metadata from File.
|
||||
This works for XMP sidecars and DNG files with the edit inside; photos imported earlier get it with Photo ▸ Read
|
||||
Metadata from File. Lightroom Classic catalogs still have it worked out again for now, and the import says so.
|
||||
- Rotate Left and Rotate Right turn an Upright correction with the photo. It used to stay as it was, so the photo
|
||||
came out skewed after a turn.
|
||||
- A crop read from an XMP sidecar now lands where Lightroom put it on photos shown on their side (portrait raws),
|
||||
and straightened crops keep Lightroom's frame. A portrait crop used to cut the wrong side of the photo.
|
||||
- Lightroom's Upright values 2, 3 and 4 now read as Full, Level and Vertical. They used to come in as Level,
|
||||
Vertical and Full.
|
||||
- Guided Upright doesn't come across yet (Lightroom's guides aren't read), and the import report says so. The
|
||||
|
||||
+9
-7
@@ -141,7 +141,7 @@ application's renderer and is ignored: the photo keeps LightCraft's own process,
|
||||
| `ShadowTint`, `RedHue/Saturation`, `GreenHue/Saturation`, `BlueHue/Saturation` | `calibration.shadows_tint`, `calibration.red_hue/red_sat`, … | Calibration panel, 1:1 |
|
||||
| `PerspectiveVertical/Horizontal/Rotate/Scale/Aspect/X/Y` | `geometry.vertical/horizontal/rotate/scale/aspect/offset_x/offset_y` | |
|
||||
| `PerspectiveUpright` | `geometry.upright`, `geometry.upright_transform` | 0 off, 1 auto, 2 full, 3 level, 4 vertical, 5 guided; Lightroom's saved correction for the selected mode is kept as it is when it can be (see *Saved Upright geometry*), otherwise LightCraft works the mode out itself (Guided needs guides drawn in LightCraft: Lightroom's aren't read) and photo import says so |
|
||||
| `HasCrop`, `CropLeft/Top/Right/Bottom`, `CropAngle` | `crop.geometry` | normalized edges → rect; angle in degrees; `HasCrop="False"` → no crop |
|
||||
| `HasCrop`, `CropLeft/Top/Right/Bottom`, `CropAngle` | `crop.geometry` | Lightroom's edges are on the stored image (before its orientation) and its straighten angle turns the other way: both go into the frame the photo is shown in (through the file's orientation and the photo's Rotate Left / Right), as the Lightroom catalog import does; when the file's orientation isn't known (Synchronize Folder, a raw shown from its preview) the edges are taken as written; `HasCrop="False"` → no crop |
|
||||
|
||||
Values pass through our control specs, so anything outside our slider ranges gets clamped.
|
||||
|
||||
@@ -158,23 +158,25 @@ photo is framed as in Lightroom instead of being analysed again, when
|
||||
- `UprightVersion` is `151388160` (the only version seen so far; any other is solved again);
|
||||
- `UprightTransformCount` includes the mode's matrix, and the matrix is nine finite numbers that make a sensible
|
||||
correction (no part of the photo at or beyond the horizon, no mirror, no collapse);
|
||||
- the file's orientation is known: on import, Read Metadata from File and Lightroom catalog import (Synchronize
|
||||
Folder solves the mode again).
|
||||
- the file's orientation is known: on import and Read Metadata from File (Synchronize Folder solves the mode again,
|
||||
and Lightroom catalog import doesn't read saved Upright yet: see [lightroom-catalog-import.md](lightroom-catalog-import.md));
|
||||
- the crop has no straighten angle (a straightened crop on top of a saved Upright isn't measured yet).
|
||||
|
||||
The matrix's convention was measured on Lightroom's exports, not assumed (issue #205): a forward homography (photo
|
||||
before correction to photo after it, column vectors) in coordinates normalised to the stored image (x / width,
|
||||
y / height, origin top left, y down, before the EXIF orientation), applied before the crop, with Lightroom's scale
|
||||
to fill the frame already in it. LightCraft turns it with the file's orientation into its own frame
|
||||
(`geometry.upright_transform`, centred coordinates of the oriented image) and applies the crop on top, as
|
||||
Lightroom does. On three public NEF raws exported by Lightroom Classic 12 with Upright Auto (one shown in portrait,
|
||||
(`geometry.upright_transform`, centred coordinates of the oriented image, the photo's own Rotate Left / Right
|
||||
included) and applies the crop on top, as Lightroom does. Rotate Left / Right later turns the kept correction with
|
||||
the photo, as it does LightCraft's own Upright. On three public NEF raws exported by Lightroom Classic 12 with Upright Auto (one shown in portrait,
|
||||
one cropped with Constrain Crop on), LightCraft's geometry with the kept matrix matches the exports to about half a
|
||||
pixel on average and under a pixel at worst, at full size; without it, the frames differ by 22 to 36 px on average.
|
||||
|
||||
Not measured yet: the Transform sliders (Vertical, Horizontal, Rotate, Aspect, Scale, X / Y Offset) together with a
|
||||
saved Upright (LightCraft applies its own slider mapping on top, as with its own Upright), Level, Vertical and Full
|
||||
exports (their matrices have those modes' shapes, but no export of them with its raw was available), photos with
|
||||
Lightroom lens profile corrections, and an angled crop on top of Upright. Guided Upright's guides
|
||||
(`UprightFourSegments_*`) aren't read.
|
||||
Lightroom lens profile corrections, and a straightened crop on top of Upright (solved again, with the warning). Guided
|
||||
Upright's guides (`UprightFourSegments_*`) aren't read: import says so whenever a packet has them.
|
||||
|
||||
**Not mapped:** camera profiles and looks (`CameraProfile`, `Look`; we have our own profile set), red eye, lens blur,
|
||||
process-version 2010 field names, and AI features. Local adjustments and spot removal are read as described below.
|
||||
|
||||
Reference in new issue
Block a user