FilmNeg tool: used a single luminance reference when sampling white balance spot several times in sequence, to avoid luminance drift.

Fixes #6257
This commit is contained in:
rom9
2021-06-03 19:57:28 +02:00
parent 6189a0e816
commit 726f1c1f26
2 changed files with 52 additions and 2 deletions

View File

@@ -194,6 +194,7 @@ FilmNegative::FilmNegative() :
evFilmNegativeColorSpace(ProcEventMapper::getInstance()->newEvent(ALLNORAW, "HISTORY_MSG_FILMNEGATIVE_COLORSPACE")),
refInputValues({0.f, 0.f, 0.f}),
paramsUpgraded(false),
refLuminance({{0.f, 0.f, 0.f}, 0.f}),
fnp(nullptr),
colorSpace(Gtk::manage(new MyComboBoxText())),
greenExp(createExponentAdjuster(this, M("TP_FILMNEGATIVE_GREEN"), 0.3, 4, 0.01, 1.5)), // master exponent (green channel)
@@ -343,6 +344,9 @@ void FilmNegative::read(const rtengine::procparams::ProcParams* pp, const Params
setEnabled(pp->filmNegative.enabled);
// Reset luminance reference each time params are read
refLuminance.lum = 0.f;
colorSpace->set_active(CLAMP((int)pp->filmNegative.colorSpace, 0, 1));
redRatio->setValue(pp->filmNegative.redRatio);
greenExp->setValue(pp->filmNegative.greenExp);
@@ -471,6 +475,9 @@ void FilmNegative::adjusterChanged(Adjuster* a, double newval)
);
} else if (a == outputLevel || a == greenBalance || a == blueBalance) {
// Reset luminance reference when output level/color sliders are changed
refLuminance.lum = 0.f;
listener->panelChanged(
evFilmNegativeBalance,
Glib::ustring::compose(
@@ -606,12 +613,44 @@ bool FilmNegative::button1Pressed(int modifierKey)
} else if (refSpotButton->get_active()) {
disableListener();
// If the luminance reference is not set, copy the current reference input
// values, and the corresponding output luminance
if(refLuminance.lum <= 0.f) {
RGB out;
readOutputSliders(out);
refLuminance.input = refInputValues;
refLuminance.lum = rtengine::Color::rgbLuminance(out.r, out.g, out.b);
}
RGB refOut;
fnp->getFilmNegativeSpot(provider->posImage, 32, refInputValues, refOut);
disableListener();
// Output luminance of the sampled spot
float spotLum = rtengine::Color::rgbLuminance(refOut.r, refOut.g, refOut.b);
float rexp = -(greenExp->getValue() * redRatio->getValue());
float gexp = -greenExp->getValue();
float bexp = -(greenExp->getValue() * blueRatio->getValue());
RGB mult = {
spotLum / pow_F(rtengine::max(refInputValues.r, 1.f), rexp),
spotLum / pow_F(rtengine::max(refInputValues.g, 1.f), gexp),
spotLum / pow_F(rtengine::max(refInputValues.b, 1.f), bexp)
};
// Calculate the new luminance of the initial luminance reference spot, by
// applying current multipliers
float newRefLum = rtengine::Color::rgbLuminance(
mult.r * pow_F(rtengine::max(refLuminance.input.r, 1.f), rexp),
mult.g * pow_F(rtengine::max(refLuminance.input.g, 1.f), gexp),
mult.b * pow_F(rtengine::max(refLuminance.input.b, 1.f), bexp));
// Choose a suitable gray value for the sampled spot, so that luminance
// of the initial reference spot is preserved.
float gray = spotLum * (refLuminance.lum / newRefLum);
float gray = rtengine::Color::rgbLuminance(refOut.r, refOut.g, refOut.b);
writeOutputSliders({gray, gray, gray});
refInputLabel->set_text(

View File

@@ -99,6 +99,17 @@ private:
RGB refInputValues;
bool paramsUpgraded;
/**
* Luminance reference: these input RGB values must produce this output luminance.
* This allows keeping constant luminance when picking several white balance spot
* samples in sequence; values are set on the initial white balance spot sampling,
* and reset every time params are read, or the output sliders are changed.
*/
struct {
RGB input;
float lum;
} refLuminance;
FilmNegProvider* fnp;
MyComboBoxText* const colorSpace;