darktable-org / darktable-org/darktable

Exposure area mapping ignores black correction

Open
#22,183 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
13.1k
Forks
1.4k
Avg merge
22h 14m
Merged PRs (30d)
198

Description

Severity: medium. Pre-existing at
d63f1023a3ca8db0c192c902e2d2151a161b6dac, still present at
11093f0767b118d8f046562026e37a29dec8aacf. Verified 2026-09-06.

The area mapping tool treats exposure as a pure gain in both measurement and
correction. Processing applies an offset and a gain depending on that offset,
so the tool can report the wrong brightness and fail to reach its requested target
even when the current black/white range is valid.

Example and source path

For a normalized neutral input profile, sample input 0.25, black 0.10 and a target
luminance of 0.50:

  • Correction passes white = 0.25 / 0.50 = 0.50 to the setter
    (src/iop/exposure.c:994), yielding +1 EV with compensations off.
  • Processing instead produces (0.25 - 0.10) / (0.50 - 0.10) = 0.375
    (exposure.c:516-517, :565-571). That is 25% below the requested target.
  • The actual required white is 0.10 + (0.25 - 0.10) / 0.50 = 0.40, corresponding
    to approximately +1.32193 EV.
  • At +1 EV, measurement also predicts 0.50 because it multiplies input XYZ by
    exp2f(exposure) (exposure.c:954-964), while processing still produces 0.375.

Black 0.10 is inside the slider's normal soft range (exposure.c:1324), and black
is below white throughout this example. This is not an inverted/invalid edit.
The default small negative black value makes the discrepancy smaller, not absent.

The correction discrepancy was executed using color_picker_apply() from both
compiled plugins, followed by module parameter commitment and CPU processing:
both returned +1 EV and output 0.375 for the above target. The measurement discrepancy
was established from its formula; the measurement GUI was not executed.

Recommendation and related work

Use the actual affine exposure transform for measurement and solve its inverse for
correction. Account for how the black offset transforms through the input profile,
and handle nonpositive/unreachable targets without invalid parameter writes.

Related: #22184
The present report covers manual mode; it does not duplicate that mode-guard issue.
#22005 has a related affine-inverse error in color-checker normalization reporting,
but uses a different consumer and needs a different fix.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/iop/exposure.c at the measurement code around lines 954-964, the correction setter around line 994, and processing around lines 516-517 and 565-571. Trace color_picker_apply() in both compiled plugins and the black-range handling around line 1324. Done means measurement and correction use the affine exposure transform, solve its inverse safely, and avoid invalid writes for nonpositive or unreachable targets.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.