Skip to content

Detect the auto crop once, and export the crop that was on screen - #873

Open
seanharding wants to merge 1 commit into
marcinz606:mainfrom
seanharding:fix/autocrop-resolved-rect
Open

Detect the auto crop once, and export the crop that was on screen#873
seanharding wants to merge 1 commit into
marcinz606:mainfrom
seanharding:fix/autocrop-resolved-rect

Conversation

@seanharding

@seanharding seanharding commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Auto Crop re-ran border detection inside every render, so the frame it found depended on the buffer that render happened to hold. A 1600 px preview and a full-resolution export are not the same pixels, and on a borderless frame the edge walk can stop somewhere else: one 35mm night scan exported 2.7% of its width further right than the preview showed, cutting a letter off the sign.

Auto and manual crops now converge on one field. GeometryConfig carries a single crop_rect plus crop_from_auto, which records where the rect came from and doubles as Auto's armed state: set with no rect yet, the next render resolves one and the controller freezes it into the edit. Neither engine detects anything any more — both slice the stored rect — and detection is reached from exactly one place, ImageProcessor, ahead of the engine split.

Re-arming is a comparison rather than something every control has to remember to do. A resolved rect stores the detection key it was found under (ratio, mode, rebate trim, orientation); when that key stops matching, the next render re-detects. Crop Offset is absent from the key and from the stored rect, since it is re-applied to whatever crop is set on every render.

Falling out of the merge: the crop tool opens on an auto crop, so it can be nudged instead of redrawn, and dragging it takes ownership. Copy-settings keeps its per-frame behaviour, because copying the armed flag without a rect still makes each target detect its own frame.

Fixes #871

Auto Crop re-ran border detection inside every render, so the frame it found
depended on the buffer that render happened to hold. A 1600 px preview and a
full-resolution export are not the same pixels, and on a borderless frame the
edge walk can stop somewhere else: one 35mm night scan exported 2.7% of its
width further right than the preview showed, cutting a letter off the sign.

Auto and manual crops now converge on one field. GeometryConfig carries a
single crop_rect plus crop_from_auto, which records where the rect came from
and doubles as Auto's armed state: set with no rect yet, the next render
resolves one and the controller freezes it into the edit. Neither engine
detects anything any more — both slice the stored rect — and detection is
reached from exactly one place, ImageProcessor, ahead of the engine split.

Re-arming is a comparison rather than something every control has to remember
to do. A resolved rect stores the detection key it was found under (ratio,
mode, rebate trim, orientation); when that key stops matching, the next render
re-detects. Crop Offset is absent from the key and from the stored rect, since
it is re-applied to whatever crop is set on every render.

Falling out of the merge: the crop tool opens on an auto crop, so it can be
nudged instead of redrawn, and dragging it takes ownership. Copy-settings keeps
its per-frame behaviour, because copying the armed flag without a rect still
makes each target detect its own frame.

The over-trim itself is untouched and still worth a look: on that frame the
deep edge walk eats 5% of the left side of a full-bleed night scan.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Export can end up cropping differently than preview

1 participant