Skip to content

Keep HDR auto-bracket within the exposure ceiling - #278

Draft
jkytomaki wants to merge 5 commits into
jareff-g:masterfrom
jkytomaki:hdr_bracket_clamp
Draft

jkytomaki wants to merge 5 commits into
jareff-g:masterfrom
jkytomaki:hdr_bracket_clamp

Conversation

@jkytomaki

Copy link
Copy Markdown
Contributor

Follow-up hardening on top of #277 (includes its commits). Keeps the HDR auto-bracket within HDR_MAX_EXP in the corner case where the metered exposure approaches the 1000 ms ceiling (near-opaque frames):

  • Clamp hdr_best_exp and the bracket endpoints to HDR_MAX_EXP
  • When the ceiling is hit, slide the bracket interval down so HdrBracketWidth is preserved (instead of compressing it into duplicate exposures)
  • Cap the per-capture exposure after HdrBracketShift is applied, so a positive shift cannot push captures past HDR_MAX_EXP

Draft: edge-case behavior (metered exposure >= ~950 ms) has not been hardware-tested yet.

Known pre-existing issues in this area, not addressed here: the bracket minimum ratchets upward across re-meters and never comes back down; the HDR exposure list is built at init before saved config is loaded; HdrBracketShift is not persisted to the config file.

In auto-bracket mode, adjust_hdr_bracket() is called every
hdr_auto_bracket_frames (8) frames. It enables auto exposure, performs
several probe captures to read the metered exposure, then disables auto
exposure again. This leaves the sensor at the metered exposure rather
than at the exposure the previous frame ended on.

capture_hdr() only forced a dry run when the probe changed the bracket
values (recalculate_hdr_exp_list). When the metered exposure was
unchanged, perform_dry_run stayed False, so the first capture of the
frame was taken via the skip-dry-run path, which assumes the sensor is
already settled at the previous frame's last exposure. Because the probe
had moved the exposure, that first capture - the longest exposure on
reversed (even) frames, saved as the .3 bracket - was captured before
the sensor settled and came out under-exposed.

The result was a corrupt long-exposure bracket recurring on a fixed
8-frame grid, producing a once-per-second brightness dip when the
brackets are later fused.

Force a real dry run whenever the exposure probe has run, regardless of
whether the bracket values changed, so every capture on those frames
settles before being saved.
adjust_hdr_bracket() recomputed HdrMinExp and pushed HdrMinExp +
HdrBracketWidth into the max-exposure spinbox, but it never declared
HdrMaxExp global and never updated it. As a result:

- ConfigData["HdrMaxExp"] was written from the stale global, so the
  saved max disagreed with the value shown in the UI, and
- hdr_reinit() rebuilt the bracket list from the stale HdrMaxExp, so the
  longest exposure actually captured did not match the displayed max.

Declare HdrMaxExp global and set it to HdrMinExp + HdrBracketWidth, the
same way the manual min/max handlers do, so the widget, the config and
the captured bracket stay consistent after an auto re-meter.
When auto-bracket re-meters, HdrMaxExp was set to HdrMinExp +
HdrBracketWidth with no upper bound. A high metered exposure could push
it past HDR_MAX_EXP (1000 ms): the over-max value went into the exposure
list, was sent to the camera, and was persisted to config. Clamp it to
HDR_MAX_EXP so the auto-bracket stays within the same range the manual
max-exposure control enforces.
The previous change clamped only HdrMaxExp. When the metered exposure is
above HDR_MAX_EXP, hdr_best_exp and HdrMinExp could still exceed the
maximum, producing an over-max middle/low exposure and even an inverted
min>max bracket (e.g. metered 1200, width 50 -> min 1175, max 1000).

Clamp hdr_best_exp and HdrMinExp to HDR_MAX_EXP as well, so all three
bracket values stay within [.., HDR_MAX_EXP] and HdrMinExp <= HdrMaxExp
always holds. PreviousCurrentExposure still stores the raw metered value,
so auto-exposure change detection is unaffected.
Clamping HdrMaxExp to HDR_MAX_EXP without moving HdrMinExp down compressed
the bracket near the ceiling (duplicate exposures at metered >= 1000 ms).
Slide the interval down instead so HdrBracketWidth is preserved.

HdrBracketShift was applied after the clamp with only a lower bound, so a
positive shift could push captures past HDR_MAX_EXP. Cap the shifted value.
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.

1 participant