Lightroom: Correct copying of crops and local adjustments
Lightroom has long incorrectly copied crops and local adjustments between photos with different orientations. LR 10.2 tried unsuccessfully to fix that but broke copying between originals and virtual copies. This memo provides consistent principles of how copying should behave, test results of the current broken behavior, and a guide to implementing correct behavior.
Since this memo spans a number of bug reports about different symptoms, it shouldn't be merged with any one of them.
How Copying Crops and Adjustments Should Behave
Users almost always place crops and local adjustments relative to the photo's content. A Spot Removal is placed over a blemish on a face; an Adjustment Brush lightens the shadows under eyes; a crop is placed tightly around a face; a Graduated Filter darkens the sky.
So if a user copies a crop or local adjustment from a raw to a TIFF produced from that raw by Photoshop, the user expects the adjustment to appear in the exact same visual position and have the same effect. A Graduated Filter aligned with the horizon in the raw should also be aligned with the horizon in the TIFF; a Spot Removal applied to a face blemish in the raw should be located on that blemish in the TIFF.
Similarly, if a user copies a local adjustment from an original to a cropped virtual copy, the user expects the adjustment to appear in same position relative to the content of the photo, e.g. an Adjustment Brush applied under the eyes should appear under the eyes in the cropped virtual copy.
Prior to LR 10.2, when crops and local adjustments were copied between photos with different orientations (e.g. a photo rotated in-camera and a TIFF created by editing that photo in Photoshop), the crops and adjustments appear at the wrong sizes and positions.
LR 10.2 tried to fix that. Crops now copy correctly between different orientations, but Graduated Filters and Adjustment Brushes only work when the target photo has had its metadata saved to disk, and Spot Removals and Radial Filters don't work at all. And if the source or target photos have been cropped, copying local adjustments doesn't work.
Worse, 10.2 broke copying local adjustments from originals to cropped virtual copies (which necessarily have the same orientation), with the adjustments ending up in the wrong size and position. (Recently, the development team decided that new behavior of 10.2 with cropped virtual copies was "by design", not a bug. I hope this memo will persuade them differently.)
Finally, when LR 10.2 copies Spot Removals from an original to a virtual copy, the source of the clone can shift in position significantly, even when the virtual copy is uncropped.
I've done extensive testing of copying crops and local adjustments with numerous combinations of orientation, cropping, and virtual copies, and only a few combinations work correctly (see the table below).
I used four versions of a JPEG photo that was originally landscape, with EXIF Orientation = Horizontal and internal LR orientation = "AB". Visually, all three appear as portrait in LR.
- "normal" is a version of the photo rotated clockwise in LR, edited in Photoshop, and saved as a JPEG. It has EXIF Orientation = Horizontal and internal LR orientation = "AB".
- "rotated" is a version of the photo rotated clockwise in LR. It's internal LR orientation is "BC".
- "rotated saved" is "rotated" with its metadata saved with Metadata > Save Metadata To File.
- "cropped VC" is a cropped virtual copy of the source or destination photo.
Each row of the table below represents the results of copying a Crop, Spot Removal (Clone), Graduated Filter, Radial Filter, and Adjustment Brush from the source photo to the destination photo. Y indicates correct copying, N incorrect copying.
For example, here are the test results for the first two rows, copying "normal" to "rotated" and "normal to "rotated saved":
Counter-clockwise on "normal" are a Radial Filter, Graduated Filter, Adjustment Brush, and Spot Removal (clone). Only the Graduated Filter and Adjustment Brush copy correctly, to "rotated saved". (The crop test isn't shown.)
Implementing the Desired Behavior
Implementing the desired behavior is straightforward, requiring elementary coordinate transformations from the source to destination photos. I've implemented these transformations for my Any Crop and Any Filter plugins, and I've posted a shorter description a couple years ago.
Internally, LR represents a photo as an underlying image (an array of pixels) and an "orientation", which specifies how much the underlying image should be rotated (0, 90, 180, 270 degrees) and whether it should be mirrored to display it visually. Rotating or flipping an image in LR changes just the orientation. But when you edit a photo in Photoshop, it actually rotates and mirrors the pixels in the underlying image as specified by the orientation, and the saved TIFF will then have an orientation with no rotation or mirroring.
LR represents the coordinates of crops and local adjustments with values in [0..1], where (0, 0) represents the upper-left corner of the underlying image before any orientation (rotation and mirroring) has been applied. Call this coordinate system the underlying-pixels coordinates. Call the coordinate system after the orientation has been applied the visible-pixels coordinates.
Prior to LR 10.2, when LR copied crops and local adjustments, it simply copied their underlying-pixel coordinates, which produces the wrong results when the source and target have different orientations.
When copying, LR should instead translate the underlying-pixel coordinates of the adjustments in the source image to visible coordinates. Then it should translate those visible coordinates to the underlying pixel coordinates of the target photo.
LR 10.2 apparently tries to do something like this but gets it wrong in several ways:
- It doesn't transform the coordinates for Spot Removals or Radial Filters.
- It gets the target photo's orientation from its saved metadata rather than the current catalog setting.
- It appears to use visible-pixel coordinates that are relative to the photo after any crop has been applied as well as orientation. Instead, it should use visible-pixel coordinates that are relative to the orientation but not the crop. That will ensure, for example, that a Spot Removal is applied to the exact same part of the photo even if the target or source or both are cropped.