diff --git a/rtdata/languages/default b/rtdata/languages/default
index 10d0a89c3..9fe9975d9 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -1528,6 +1528,7 @@ HISTORY_MSG_WAVSTREND;Strength soft
HISTORY_MSG_WAVTHRDEN;Threshold local contrast
HISTORY_MSG_WAVTHREND;Threshold local contrast
HISTORY_MSG_WAVUSHAMET;Clarity method
+HISTORY_MSG_WBALANCE_OBSERVER10;Observer 10°
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -1831,6 +1832,7 @@ PREFERENCES_CHUNKSIZE_RAW_XT;Xtrans demosaic
PREFERENCES_CHUNKSIZE_RGB;RGB processing
PREFERENCES_CIE;Ciecam
PREFERENCES_CIEARTIF;Avoid artifacts
+PREFERENCES_WBA;White Balance
PREFERENCES_CLIPPINGIND;Clipping Indication
PREFERENCES_CLUTSCACHE;HaldCLUT Cache
PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs
@@ -4079,6 +4081,10 @@ TP_WBALANCE_LED_CRS;CRS SP12 WWMR16
TP_WBALANCE_LED_HEADER;LED
TP_WBALANCE_LED_LSI;LSI Lumelex 2040
TP_WBALANCE_METHOD;Method
+TP_WBALANCE_MULLABEL;Multipliers: r=%1 g=%2 b=%3
+TP_WBALANCE_MULLABEL_TOOLTIP;Values given for information purposes. You cannot change them.
+TP_WBALANCE_OBSERVER10;Observer 10° instead of Observer 2°
+TP_WBALANCE_OBSERVER10_TOOLTIP;The color management in Rawtherapee (White balance, channel multipliers, highlight recovery,...) uses the spectral data of the illuminants and colors. Observer is an important parameter of this management which takes into account the angle of perception of the eye. In 1931 it was fixed at 2° (privileges the use of the cones). In 1964 it was fixed at 10° (privileges the use of the cones, but partially takes into account the rods).\nTo avoid a (rare) drift of the colors due to the choice Observer 10° - probably due to the conversion matrix - Observer 2° must be selected.\nIn a majority of cases Observer 10° (default) will be a more relevant choice.
TP_WBALANCE_PICKER;Pick
TP_WBALANCE_SHADE;Shade
TP_WBALANCE_SIZE;Size:
diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc
index f6e980f2a..756fdf906 100644
--- a/rtengine/colortemp.cc
+++ b/rtengine/colortemp.cc
@@ -171,7 +171,7 @@ static const color_match_type cie_colour_match_jd = {//350nm to 830nm 5 nm J.D
-ColorTemp::ColorTemp (double t, double g, double e, const std::string &m) : temp(t), green(g), equal(e), method(m)
+ColorTemp::ColorTemp (double t, double g, double e, const std::string &m, StandardObserver o) : temp(t), green(g), equal(e), method(m), observer(o)
{
clip (temp, green, equal);
}
@@ -189,12 +189,24 @@ void ColorTemp::clip (double &temp, double &green, double &equal)
equal = rtengine::LIM(equal, MINEQUAL, MAXEQUAL);
}
-ColorTemp::ColorTemp (double mulr, double mulg, double mulb, double e) : equal(e), method("Custom")
+ColorTemp::ColorTemp (double mulr, double mulg, double mulb, double e, StandardObserver observer) : equal(e), method("Custom"), observer(observer)
{
- mul2temp (mulr, mulg, mulb, equal, temp, green);
+ mul2temp (mulr, mulg, mulb, equal, observer, temp, green);
}
-void ColorTemp::mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green) const
+ColorTemp ColorTemp::convertObserver(StandardObserver observer) const
+{
+ if (observer == this->observer) {
+ return *this;
+ }
+ double r;
+ double g;
+ double b;
+ getMultipliers(r, g, b);
+ return ColorTemp(r, g, b, equal, observer);
+}
+
+void ColorTemp::mul2temp (const double rmul, const double gmul, const double bmul, const double equal, StandardObserver observer, double& temp, double& green) const
{
double maxtemp = MAXTEMP, mintemp = MINTEMP;
@@ -202,7 +214,7 @@ void ColorTemp::mul2temp (const double rmul, const double gmul, const double bmu
temp = (maxtemp + mintemp) / 2;
while (maxtemp - mintemp > 1) {
- temp2mul (temp, 1.0, equal, tmpr, tmpg, tmpb);
+ temp2mul (temp, 1.0, equal, observer, tmpr, tmpg, tmpb);
if (tmpb / tmpr > bmul / rmul) {
maxtemp = temp;
@@ -2957,14 +2969,19 @@ void ColorTemp::icieCAT02float(float Xw, float Yw, float Zw, float &iCAM02BB00,
}
-void ColorTemp::temp2mulxyz (double temp, const std::string &method, double &Xxyz, double &Zxyz)
+void ColorTemp::temp2mulxyz (double temp, const std::string &method, StandardObserver observer, double &Xxyz, double &Zxyz)
{
double x, y, z;
// We first test for specially handled methods
const auto iterator = spectMap.find(method);
- const auto &color_match = (settings->observer10 == true) ? cie_colour_match_jd : cie_colour_match_jd2;
-
+ const auto &color_match = (observer == StandardObserver::TEN_DEGREES) ? cie_colour_match_jd : cie_colour_match_jd2;
+/* if(observer == StandardObserver::TEN_DEGREES){
+ printf("General Observer 10°\n");
+ } else {
+ printf("General Observer 2°\n");
+ }
+*/
if (iterator != spectMap.end()) {
spectrum_to_xyz_preset(iterator->second, x, y, z, color_match);
} else {
@@ -2999,11 +3016,11 @@ void ColorTemp::temp2mulxyz (double temp, const std::string &method, double &Xxy
Zxyz = (1.0 - x - y) / y;
}
-void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, double& gmul, double& bmul) const
+void ColorTemp::temp2mul (double temp, double green, double equal, StandardObserver observer, double& rmul, double& gmul, double& bmul) const
{
clip(temp, green, equal);
double Xwb, Zwb;
- temp2mulxyz(temp, method, Xwb, Zwb);
+ temp2mulxyz(temp, method, observer, Xwb, Zwb);
double adj = 1.0;
@@ -3170,7 +3187,13 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul,
float CRI_RT = 0.0, CRI[50];
float CRI_RTs = 0.0, CRIs[8];
- const auto &color_match = (settings->observer10 == true) ? cie_colour_match_jd : cie_colour_match_jd2;
+ const auto &color_match = (observer == StandardObserver::TEN_DEGREES) ? cie_colour_match_jd : cie_colour_match_jd2;
+ //exceptional must be used by advice people
+ if(observer == StandardObserver::TEN_DEGREES){
+ printf("CRI Observer 10°\n");
+ } else {
+ printf("CRI Observer 2°\n");
+ }
for(int i = 0; i < N_c; i++) {
spectrum_to_color_xyz_preset(spec_color[i], spect_illum[illum + 3], XchkLamp[i], YchkLamp[i], ZchkLamp[i], color_match);
@@ -3764,17 +3787,9 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
Refxyz[i].Zref = 0.f;
}
-/* if (settings->verbose) {
+ const color_match_type &color_match = (wbpar.observer == StandardObserver::TEN_DEGREES) ? cie_colour_match_jd : cie_colour_match_jd2;
- if (settings->itcwb_stdobserver10 == false) {//I will try to change settings by main
- printf("Use standard observer 2°\n");
- } else {
- printf("Use standard observer 10°\n");
- }
- }
-*/
- const color_match_type &color_match = (settings->observer10 == true) ? cie_colour_match_jd : cie_colour_match_jd2;
- // const color_match_type &color_match = (settings->itcwb_stdobserver10 == true) ? cie_colour_match_jd : cie_colour_match_jd2;
+ // const color_match_type &color_match = (wbpar.observer == StandardObserver::TEN_DEGREES) ? cie_colour_match_jd : cie_colour_match_jd2;
if (separated) {
const double tempw = Txyz[repref].Tem;
diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h
index 78091f51d..0fe56b7cd 100644
--- a/rtengine/colortemp.h
+++ b/rtengine/colortemp.h
@@ -36,6 +36,10 @@ constexpr double MINEQUAL = 0.8;
constexpr double MAXEQUAL = 1.5;
constexpr double INITIALBLACKBODY = 4000.0;
+enum class StandardObserver {
+ TWO_DEGREES,
+ TEN_DEGREES,
+};
class ColorTemp
{
@@ -45,32 +49,36 @@ private:
double green;
double equal;
std::string method;
+ StandardObserver observer{StandardObserver::TEN_DEGREES};
static void clip (double &temp, double &green);
static void clip (double &temp, double &green, double &equal);
int XYZtoCorColorTemp(double x0, double y0 , double z0, double &temp) const;
- void temp2mul (double temp, double green, double equal, double& rmul, double& gmul, double& bmul) const;
+ void temp2mul (double temp, double green, double equal, StandardObserver observer, double& rmul, double& gmul, double& bmul) const;
const static std::map spectMap;
public:
+ static constexpr StandardObserver DEFAULT_OBSERVER = StandardObserver::TEN_DEGREES;
ColorTemp () : temp(-1.), green(-1.), equal (1.), method("Custom") {}
explicit ColorTemp (double e) : temp(-1.), green(-1.), equal (e), method("Custom") {}
- ColorTemp (double t, double g, double e, const std::string &m);
- ColorTemp (double mulr, double mulg, double mulb, double e);
+ ColorTemp (double t, double g, double e, const std::string &m, StandardObserver o);
+ ColorTemp (double mulr, double mulg, double mulb, double e, StandardObserver observer);
static void tempxy(bool separated, int repref, float **Tx, float **Ty, float **Tz, float **Ta, float **Tb, float **TL, double *TX, double *TY, double *TZ, const procparams::WBParams & wbpar);
- void update (const double rmul, const double gmul, const double bmul, const double equal, const double tempBias=0.0)
+ void update (const double rmul, const double gmul, const double bmul, const double equal, StandardObserver observer, const double tempBias=0.0)
{
this->equal = equal;
- mul2temp (rmul, gmul, bmul, this->equal, temp, green);
+ this->observer = observer;
+ mul2temp (rmul, gmul, bmul, this->equal, observer, temp, green);
if (tempBias != 0.0 && tempBias >= -1.0 && tempBias <= 1.0) {
temp += temp * tempBias;
}
}
- void useDefaults (const double equal)
+ void useDefaults (const double equal, StandardObserver observer)
{
temp = 6504; // Values copied from procparams.cc
green = 1.0;
this->equal = equal;
+ this->observer = observer;
}
inline std::string getMethod() const
@@ -89,14 +97,20 @@ public:
{
return equal;
}
+ inline StandardObserver getObserver() const
+ {
+ return observer;
+ }
+
+ ColorTemp convertObserver(StandardObserver observer) const;
void getMultipliers (double &mulr, double &mulg, double &mulb) const
{
- temp2mul (temp, green, equal, mulr, mulg, mulb);
+ temp2mul (temp, green, equal, observer, mulr, mulg, mulb);
}
- void mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green) const;
- static void temp2mulxyz (double tem, const std::string &method, double &Xxyz, double &Zxyz);
+ void mul2temp (const double rmul, const double gmul, const double bmul, const double equal, StandardObserver observer, double& temp, double& green) const;
+ static void temp2mulxyz (double tem, const std::string &method, StandardObserver observer, double &Xxyz, double &Zxyz);
static void cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00, double &CAM02BB01, double &CAM02BB02, double &CAM02BB10, double &CAM02BB11, double &CAM02BB12, double &CAM02BB20, double &CAM02BB21, double &CAM02BB22, double adap );
static void cieCAT02float(float Xw, float Yw, float Zw, float &CAM02BB00, float &CAM02BB01, float &CAM02BB02, float &CAM02BB10, float &CAM02BB11, float &CAM02BB12, float &CAM02BB20, float &CAM02BB21, float &CAM02BB22, float adap);
@@ -104,7 +118,7 @@ public:
bool operator== (const ColorTemp& other) const
{
- return fabs(temp - other.temp) < 1e-10 && fabs(green - other.green) < 1e-10;
+ return fabs(temp - other.temp) < 1e-10 && fabs(green - other.green) < 1e-10 && observer != other.observer;
}
bool operator!= (const ColorTemp& other) const
{
diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc
index c33dc4a9a..eb029d77a 100644
--- a/rtengine/filmnegativeproc.cc
+++ b/rtengine/filmnegativeproc.cc
@@ -340,7 +340,7 @@ bool rtengine::ImProcFunctions::filmNegativeProcess(
imgsrc->getWBMults(currWB, params->raw, scale_mul, autoGainComp, rm, gm, bm);
float rm2, gm2, bm2;
- imgsrc->getWBMults(rtengine::ColorTemp(3500., 1., 1., "Custom"), params->raw, scale_mul, autoGainComp, rm2, gm2, bm2);
+ imgsrc->getWBMults(rtengine::ColorTemp(3500., 1., 1., "Custom", currWB.getObserver()), params->raw, scale_mul, autoGainComp, rm2, gm2, bm2);
float mg = rtengine::max(rm2, gm2, bm2);
rm2 /= mg;
gm2 /= mg;
@@ -611,7 +611,7 @@ void rtengine::Thumbnail::processFilmNegativeV2(
// as in the main image processing.
double r, g, b;
- ColorTemp(3500., 1., 1., "Custom").getMultipliers(r, g, b);
+ ColorTemp(3500., 1., 1., "Custom", params.wb.observer).getMultipliers(r, g, b);
//iColorMatrix is cam_rgb
const double rm = camwbRed / (iColorMatrix[0][0] * r + iColorMatrix[0][1] * g + iColorMatrix[0][2] * b);
const double gm = camwbGreen / (iColorMatrix[1][0] * r + iColorMatrix[1][1] * g + iColorMatrix[1][2] * b);
diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc
index d3c5d0190..350dbbfab 100644
--- a/rtengine/histmatching.cc
+++ b/rtengine/histmatching.cc
@@ -229,7 +229,7 @@ void mappingToCurve(const std::vector &mapping, std::vector &curve)
} // namespace
-void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, std::vector &outCurve)
+void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, StandardObserver observer, std::vector &outCurve)
{
BENCHFUN
@@ -313,7 +313,7 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st
eSensorType sensor_type;
double scale;
int w = fw / skip, h = fh / skip;
- std::unique_ptr thumb(Thumbnail::loadFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, false, true));
+ std::unique_ptr thumb(Thumbnail::loadFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, observer, false, true));
if (!thumb) {
if (settings->verbose) {
std::cout << "histogram matching: raw decoding failed, generating a neutral curve" << std::endl;
diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h
index d6d22c269..1f4c2179a 100644
--- a/rtengine/imagesource.h
+++ b/rtengine/imagesource.h
@@ -119,9 +119,9 @@ public:
virtual void getAutoWBMultipliers (double &rm, double &gm, double &bm) = 0;
virtual void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double & greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) = 0;
virtual ColorTemp getWB () const = 0;
- virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) = 0;
+ virtual ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal, StandardObserver observer) = 0;
virtual void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) = 0;
- virtual void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) = 0;
+ virtual void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, const procparams::WBParams & wbpar) = 0;
virtual double getDefGain () const
{
@@ -167,7 +167,7 @@ public:
}
// for RAW files, compute a tone curve using histogram matching on the embedded thumbnail
- virtual void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, std::vector &outCurve)
+ virtual void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, StandardObserver observer, std::vector &outCurve)
{
outCurve = { 0.0 };
}
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 9437f1a75..664029a5e 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -489,7 +489,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if (todo & (M_INIT | M_LINDENOISE | M_HDR)) {
if (params->wb.method == "autitcgreen") {
- imgsrc->getrgbloc(0, 0, fh, fw, 0, 0, fh, fw);
+ imgsrc->getrgbloc(0, 0, fh, fw, 0, 0, fh, fw, params->wb);
}
}
@@ -522,7 +522,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
printf("Applying white balance, color correction & sRBG conversion...\n");
}
- currWB = ColorTemp(params->wb.temperature, params->wb.green, params->wb.equal, params->wb.method);
+ currWB = ColorTemp(params->wb.temperature, params->wb.green, params->wb.equal, params->wb.method, params->wb.observer);
float studgood = 1000.f;
if (!params->wb.enabled) {
@@ -531,7 +531,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
currWB = imgsrc->getWB();
lastAwbauto = ""; //reinitialize auto
} else if (autowb) {
- if (params->wb.method == "autitcgreen" || lastAwbEqual != params->wb.equal || lastAwbTempBias != params->wb.tempBias || lastAwbauto != params->wb.method) {
+ if (params->wb.method == "autitcgreen" || lastAwbEqual != params->wb.equal || lastAwbObserver != params->wb.observer || lastAwbTempBias != params->wb.tempBias || lastAwbauto != params->wb.method) {
double rm, gm, bm;
double tempitc = 5000.f;
double greenitc = 1.;
@@ -547,7 +547,9 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if (params->wb.method == "autitcgreen") {
params->wb.temperature = tempitc;
params->wb.green = greenitc;
- currWB = ColorTemp(params->wb.temperature, params->wb.green, 1., params->wb.method);
+ currWB = ColorTemp(params->wb.temperature, params->wb.green, 1., params->wb.method, params->wb.observer);
+ //printf("tempitc=%f greitc=%f\n", tempitc, greenitc);
+
currWB.getMultipliers(rm, gm, bm);
}
@@ -558,15 +560,17 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
bias = 0.;
}
- autoWB.update(rm, gm, bm, params->wb.equal, bias);
+ autoWB.update(rm, gm, bm, params->wb.equal, params->wb.observer, bias);
lastAwbEqual = params->wb.equal;
+ lastAwbObserver = params->wb.observer;
lastAwbTempBias = params->wb.tempBias;
lastAwbauto = params->wb.method;
} else {
lastAwbEqual = -1.;
+ lastAwbObserver = ColorTemp::DEFAULT_OBSERVER;
lastAwbTempBias = 0.0;
lastAwbauto = "";
- autoWB.useDefaults(params->wb.equal);
+ autoWB.useDefaults(params->wb.equal, params->wb.observer);
}
@@ -574,17 +578,24 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
currWB = autoWB;
}
+ double rw = 1.;
+ double gw = 1.;
+ double bw = 1.;
if (params->wb.enabled) {
- params->wb.temperature = currWB.getTemp();
+ currWB = currWB.convertObserver(params->wb.observer);
+ params->wb.temperature = static_cast(currWB.getTemp());
params->wb.green = currWB.getGreen();
+ currWB.getMultipliers(rw, gw, bw);
+ imgsrc->wbMul2Camera(rw, gw, bw);
+ // printf("ra=%f ga=%f ba=%f\n", rw, gw, bw);
}
- if (autowb && awbListener) {
+ if (awbListener) {
if (params->wb.method == "autitcgreen") {
- awbListener->WBChanged(params->wb.temperature, params->wb.green, studgood);
- } else if (params->wb.method == "autold") {
- awbListener->WBChanged(params->wb.temperature, params->wb.green, -1.f);
+ awbListener->WBChanged(params->wb.temperature, params->wb.green, rw, gw, bw, studgood);
+ } else {
+ awbListener->WBChanged(params->wb.temperature, params->wb.green, rw, gw, bw, -1.f);
}
}
@@ -621,7 +632,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
PreviewProps pp(0, 0, fw, fh, scale);
// Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications
ipf.setScale(scale);
- int inpaintopposed = 1;//force getimage to use inpaint-opposed if enable, only once
+ int inpaintopposed = 1;//force getimage to use inpaint-opposed if enable, only once
imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw, inpaintopposed);
if ((todo & M_SPOT) && params->spot.enabled && !params->spot.entries.empty()) {
@@ -782,7 +793,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if (params->toneCurve.histmatching) {
if (!params->toneCurve.fromHistMatching) {
- imgsrc->getAutoMatchedToneCurve(params->icm, params->toneCurve.curve);
+ imgsrc->getAutoMatchedToneCurve(params->icm, params->wb.observer, params->toneCurve.curve);
}
if (params->toneCurve.autoexp) {
@@ -2452,11 +2463,11 @@ bool ImProcCoordinator::updateWaveforms()
return true;
}
-bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, double tempBias)
+bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, StandardObserver observer, double tempBias)
{
if (imgsrc) {
- if (lastAwbEqual != equal || lastAwbTempBias != tempBias || lastAwbauto != params->wb.method) {
+ if (lastAwbEqual != equal || lastAwbObserver != observer || lastAwbTempBias != tempBias || lastAwbauto != params->wb.method) {
// Issue 2500 MyMutex::MyLock lock(minit); // Also used in crop window
double rm, gm, bm;
params->wb.method = "autold";//same result as before multiple Auto WB
@@ -2469,13 +2480,15 @@ bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, dou
imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw, params->toneCurve);
if (rm != -1) {
- autoWB.update(rm, gm, bm, equal, tempBias);
+ autoWB.update(rm, gm, bm, equal, observer, tempBias);
lastAwbEqual = equal;
+ lastAwbObserver = observer;
lastAwbTempBias = tempBias;
lastAwbauto = params->wb.method;
} else {
lastAwbEqual = -1.;
- autoWB.useDefaults(equal);
+ lastAwbObserver = ColorTemp::DEFAULT_OBSERVER;
+ autoWB.useDefaults(equal, observer);
lastAwbauto = "";
lastAwbTempBias = 0.0;
}
@@ -2492,12 +2505,13 @@ bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, dou
}
}
-void ImProcCoordinator::getCamWB(double& temp, double& green)
+void ImProcCoordinator::getCamWB(double& temp, double& green, StandardObserver observer)
{
if (imgsrc) {
- temp = imgsrc->getWB().getTemp();
- green = imgsrc->getWB().getGreen();
+ const ColorTemp color_temp = imgsrc->getWB().convertObserver(observer);
+ temp = color_temp.getTemp();
+ green = color_temp.getGreen();
}
}
@@ -2519,8 +2533,8 @@ void ImProcCoordinator::getSpotWB(int x, int y, int rect, double& temp, double&
int tr = getCoarseBitMask(params->coarse);
- ret = imgsrc->getSpotWB(red, green, blue, tr, params->wb.equal);
- currWB = ColorTemp(params->wb.temperature, params->wb.green, params->wb.equal, params->wb.method);
+ ret = imgsrc->getSpotWB(red, green, blue, tr, params->wb.equal, params->wb.observer);
+ currWB = ColorTemp(params->wb.temperature, params->wb.green, params->wb.equal, params->wb.method, params->wb.observer);
//double rr,gg,bb;
//currWB.getMultipliers(rr,gg,bb);
@@ -2626,23 +2640,25 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
imgsrc->preprocess(ppar.raw, ppar.lensProf, ppar.coarse);
double dummy = 0.0;
imgsrc->demosaic(ppar.raw, false, dummy);
- ColorTemp currWB = ColorTemp(validParams->wb.temperature, validParams->wb.green, validParams->wb.equal, validParams->wb.method);
+ ColorTemp currWB = ColorTemp(validParams->wb.temperature, validParams->wb.green, validParams->wb.equal, validParams->wb.method, validParams->wb.observer);
if (validParams->wb.method == "Camera") {
currWB = imgsrc->getWB();
} else if (validParams->wb.method == "autold") {
- if (lastAwbEqual != validParams->wb.equal || lastAwbTempBias != validParams->wb.tempBias) {
+ if (lastAwbEqual != validParams->wb.equal || lastAwbObserver != validParams->wb.observer || lastAwbTempBias != validParams->wb.tempBias) {
double rm, gm, bm;
imgsrc->getAutoWBMultipliers(rm, gm, bm);
if (rm != -1.) {
- autoWB.update(rm, gm, bm, validParams->wb.equal, validParams->wb.tempBias);
+ autoWB.update(rm, gm, bm, validParams->wb.equal, validParams->wb.observer, validParams->wb.tempBias);
lastAwbEqual = validParams->wb.equal;
+ lastAwbObserver = validParams->wb.observer;
lastAwbTempBias = validParams->wb.tempBias;
} else {
lastAwbEqual = -1.;
+ lastAwbObserver = ColorTemp::DEFAULT_OBSERVER;
lastAwbTempBias = 0.0;
- autoWB.useDefaults(validParams->wb.equal);
+ autoWB.useDefaults(validParams->wb.equal, validParams->wb.observer);
}
}
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index 85f28004a..92cdd91c7 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -80,6 +80,7 @@ protected:
ColorTemp currWBitc;
double lastAwbEqual;
+ StandardObserver lastAwbObserver{ColorTemp::DEFAULT_OBSERVER};
double lastAwbTempBias;
Glib::ustring lastAwbauto;
@@ -433,8 +434,8 @@ public:
void setTweakOperator (TweakOperator *tOperator) override;
void unsetTweakOperator (TweakOperator *tOperator) override;
- bool getAutoWB (double& temp, double& green, double equal, double tempBias) override;
- void getCamWB (double& temp, double& green) override;
+ bool getAutoWB (double& temp, double& green, double equal, StandardObserver observer, double tempBias) override;
+ void getCamWB (double& temp, double& green, StandardObserver observer) override;
void getSpotWB (int x, int y, int rectSize, double& temp, double& green) override;
bool getFilmNegativeSpot(int x, int y, int spotSize, FilmNegativeParams::RGB &refInput, FilmNegativeParams::RGB &refOutput) override;
void getAutoCrop (double ratio, int &x, int &y, int &w, int &h) override;
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 0e08a28eb..c3e11c076 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -552,9 +552,9 @@ void ImProcFunctions::ciecam_02float(CieImage* ncie, float adap, int pW, int pwb
|| (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab)
|| (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab));
- ColorTemp::temp2mulxyz(params->wb.temperature, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB
- ColorTemp::temp2mulxyz(params->colorappearance.tempout, "Custom", Xwout, Zwout);
- ColorTemp::temp2mulxyz(params->colorappearance.tempsc, "Custom", Xwsc, Zwsc);
+ ColorTemp::temp2mulxyz(params->wb.temperature, params->wb.method, params->wb.observer, Xw, Zw); //compute white Xw Yw Zw : white current WB
+ ColorTemp::temp2mulxyz(params->colorappearance.tempout, "Custom", params->wb.observer, Xwout, Zwout);
+ ColorTemp::temp2mulxyz(params->colorappearance.tempsc, "Custom", params->wb.observer, Xwsc, Zwsc);
//viewing condition for surrsrc
if (params->colorappearance.surrsrc == "Average") {
@@ -5589,7 +5589,7 @@ double ImProcFunctions::getAutoDistor(const Glib::ustring &fname, int thumb_size
return 0.0;
}
- Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, ri, sensorType, w_raw, h_raw, 1, 1.0, FALSE);
+ Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, ri, sensorType, w_raw, h_raw, 1, 1.0, ColorTemp::DEFAULT_OBSERVER, FALSE);
if (!raw) {
delete thumb;
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
index 243f3595d..b9e82cc5d 100644
--- a/rtengine/iplocallab.cc
+++ b/rtengine/iplocallab.cc
@@ -2804,9 +2804,9 @@ void ImProcFunctions::ciecamloc_02float(const struct local_params& lp, int sp, L
}
}
- ColorTemp::temp2mulxyz(params->wb.temperature, params->wb.method, Xw, Zw); //compute white Xw Yw Zw : white current WB
- ColorTemp::temp2mulxyz(tempo, "Custom", Xwout, Zwout);
- ColorTemp::temp2mulxyz(5000, "Custom", Xwsc, Zwsc);
+ ColorTemp::temp2mulxyz(params->wb.temperature, params->wb.method, params->wb.observer, Xw, Zw); //compute white Xw Yw Zw : white current WB
+ ColorTemp::temp2mulxyz(tempo, "Custom", params->wb.observer, Xwout, Zwout);
+ ColorTemp::temp2mulxyz(5000, "Custom", params->wb.observer, Xwsc, Zwsc);
//viewing condition for surrsrc
f = 1.00f;
diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc
index 1afe72c92..afaf0cbca 100644
--- a/rtengine/previewimage.cc
+++ b/rtengine/previewimage.cc
@@ -42,20 +42,20 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext
if (ext.lowercase() == "jpg" || ext.lowercase() == "jpeg") {
// int deg = infoFromImage (fname);
- tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., ColorTemp::DEFAULT_OBSERVER, true);
if (tpp) {
data = tpp->getImage8Data();
}
} else if (ext.lowercase() == "png") {
- tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., ColorTemp::DEFAULT_OBSERVER, true);
if (tpp) {
data = tpp->getImage8Data();
}
} else if (ext.lowercase() == "tif" || ext.lowercase() == "tiff") {
// int deg = infoFromImage (fname);
- tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., true);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, width, height, 1, 1., ColorTemp::DEFAULT_OBSERVER, true);
if (tpp) {
data = tpp->getImage8Data();
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 9323bd9e7..c47723662 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -27,6 +27,7 @@
#include
#include "color.h"
+#include "colortemp.h"
#include "curves.h"
#include "procparams.h"
#include "utils.h"
@@ -1331,7 +1332,19 @@ WBParams::WBParams() :
temperature(6504),
green(1.0),
equal(1.0),
- tempBias(0.0)
+ tempBias(0.0),
+ observer(ColorTemp::DEFAULT_OBSERVER),
+ itcwb_thres(34),
+ itcwb_precis(3),
+ itcwb_size(3),
+ itcwb_delta(2),
+ itcwb_fgreen(5),
+ itcwb_rgreen(1),
+ itcwb_nopurple(true),
+ itcwb_sorted(false),
+ itcwb_forceextra(false),
+ itcwb_sampling(false)
+
{
}
@@ -1351,6 +1364,7 @@ bool WBParams::isPanningRelatedChange(const WBParams& other) const
&& green == other.green
&& equal == other.equal
&& tempBias == other.tempBias
+ && observer == other.observer
)
)
);
@@ -1364,7 +1378,19 @@ bool WBParams::operator ==(const WBParams& other) const
&& temperature == other.temperature
&& green == other.green
&& equal == other.equal
- && tempBias == other.tempBias;
+ && tempBias == other.tempBias
+ && observer == other.observer
+ && itcwb_thres == other.itcwb_thres
+ && itcwb_precis == other.itcwb_precis
+ && itcwb_size == other.itcwb_size
+ && itcwb_delta == other.itcwb_delta
+ && itcwb_fgreen == other.itcwb_fgreen
+ && itcwb_rgreen == other.itcwb_rgreen
+ && itcwb_nopurple == other.itcwb_nopurple
+ && itcwb_sorted == other.itcwb_sorted
+ && itcwb_forceextra == other.itcwb_forceextra
+ && itcwb_sampling == other.itcwb_sampling;
+
}
bool WBParams::operator !=(const WBParams& other) const
@@ -6108,6 +6134,17 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->wb.green, "White Balance", "Green", wb.green, keyFile);
saveToKeyfile(!pedited || pedited->wb.equal, "White Balance", "Equal", wb.equal, keyFile);
saveToKeyfile(!pedited || pedited->wb.tempBias, "White Balance", "TemperatureBias", wb.tempBias, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.observer, "White Balance", "StandardObserver", Glib::ustring(wb.observer == StandardObserver::TWO_DEGREES ? "TWO_DEGREES" : "TEN_DEGREES"), keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_thres, "White Balance", "Itcwb_thres", wb.itcwb_thres, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_precis, "White Balance", "Itcwb_precis", wb.itcwb_precis, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_size, "White Balance", "Itcwb_size", wb.itcwb_size, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_delta, "White Balance", "Itcwb_delta", wb.itcwb_delta, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_fgreen, "White Balance", "Itcwb_findgreen", wb.itcwb_fgreen, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_rgreen, "White Balance", "Itcwb_rangegreen", wb.itcwb_rgreen, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_nopurple, "White Balance", "Itcwb_nopurple", wb.itcwb_nopurple, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_sorted, "White Balance", "Itcwb_sorted", wb.itcwb_sorted, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_forceextra, "White Balance", "Itcwb_forceextra", wb.itcwb_forceextra, keyFile);
+ saveToKeyfile(!pedited || pedited->wb.itcwb_sampling, "White Balance", "Itcwb_sampling", wb.itcwb_sampling, keyFile);
// Colorappearance
saveToKeyfile(!pedited || pedited->colorappearance.enabled, "Color appearance", "Enabled", colorappearance.enabled, keyFile);
@@ -8039,6 +8076,17 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "Vibrance", "PastSatTog", pedited, vibrance.pastsattog, pedited->vibrance.pastsattog);
assignFromKeyfile(keyFile, "Vibrance", "SkinTonesCurve", pedited, vibrance.skintonescurve, pedited->vibrance.skintonescurve);
}
+ if (ppVersion <= 346) { // 5.8 and earlier.
+ wb.observer = StandardObserver::TWO_DEGREES;
+ if (pedited) {
+ pedited->wb.observer = true;
+ }
+ } else if (ppVersion <= 349) { // 5.9
+ wb.observer = StandardObserver::TEN_DEGREES;
+ if (pedited) {
+ pedited->wb.observer = true;
+ }
+ }
if (keyFile.has_group("White Balance")) {
assignFromKeyfile(keyFile, "White Balance", "Enabled", pedited, wb.enabled, pedited->wb.enabled);
assignFromKeyfile(keyFile, "White Balance", "Setting", pedited, wb.method, pedited->wb.method);
@@ -8049,6 +8097,29 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "White Balance", "Green", pedited, wb.green, pedited->wb.green);
assignFromKeyfile(keyFile, "White Balance", "Equal", pedited, wb.equal, pedited->wb.equal);
assignFromKeyfile(keyFile, "White Balance", "TemperatureBias", pedited, wb.tempBias, pedited->wb.tempBias);
+ Glib::ustring standard_observer;
+ assignFromKeyfile(keyFile, "White Balance", "StandardObserver", pedited, standard_observer, pedited->wb.observer);
+ if (standard_observer == "TEN_DEGREES") {
+ wb.observer = StandardObserver::TEN_DEGREES;
+ } else if (standard_observer == "TWO_DEGREES") {
+ wb.observer = StandardObserver::TWO_DEGREES;
+ }
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_thres", pedited, wb.itcwb_thres, pedited->wb.itcwb_thres);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_precis", pedited, wb.itcwb_precis, pedited->wb.itcwb_precis);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_size", pedited, wb.itcwb_size, pedited->wb.itcwb_size);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_delta", pedited, wb.itcwb_delta, pedited->wb.itcwb_delta);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_findgreen", pedited, wb.itcwb_fgreen, pedited->wb.itcwb_fgreen);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_rangegreen", pedited, wb.itcwb_rgreen, pedited->wb.itcwb_rgreen);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_nopurple", pedited, wb.itcwb_nopurple, pedited->wb.itcwb_nopurple);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_sorted", pedited, wb.itcwb_sorted, pedited->wb.itcwb_sorted);
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_forceextra", pedited, wb.itcwb_forceextra, pedited->wb.itcwb_forceextra);
+ if (ppVersion <= 349) { // 5.9 and earlier.
+ wb.itcwb_sampling = true;
+ if (pedited) {
+ pedited->wb.itcwb_sampling = true;
+ }
+ }
+ assignFromKeyfile(keyFile, "White Balance", "Itcwb_sampling", pedited, wb.itcwb_sampling, pedited->wb.itcwb_sampling);
}
if (keyFile.has_group("Defringing")) {
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index 33d95a619..48b68f598 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -59,6 +59,8 @@ class LocLLmaskexpCurve;
class LocCCmaskexpCurve;
class LocHHmaskexpCurve;
+enum class StandardObserver;
+
enum RenderingIntent : int {
RI_PERCEPTUAL = INTENT_PERCEPTUAL,
RI_RELATIVE = INTENT_RELATIVE_COLORIMETRIC,
@@ -634,11 +636,22 @@ struct WBEntry {
struct WBParams {
bool enabled;
- Glib::ustring method;
- int temperature;
- double green;
- double equal;
- double tempBias;
+ Glib::ustring method;
+ int temperature;
+ double green;
+ double equal;
+ double tempBias;
+ StandardObserver observer;
+ int itcwb_thres;
+ int itcwb_precis;
+ int itcwb_size;
+ int itcwb_delta;
+ int itcwb_fgreen;
+ int itcwb_rgreen;
+ bool itcwb_nopurple;
+ bool itcwb_sorted;
+ bool itcwb_forceextra;
+ bool itcwb_sampling;
WBParams();
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 75757d325..06aa701e8 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -843,28 +843,27 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima
int maxx = this->W, maxy = this->H, skip = pp.getSkip();
- bool iscolor = (hrp.method == "Color" || hrp.method == "Coloropp");
- const bool doClip = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]) && !hrp.hrenabled && hrp.clampOOG;
+ bool iscolor = (hrp.method == "Color" || hrp.method == "Coloropp");
+ const bool doClip = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]) && !hrp.hrenabled && hrp.clampOOG;
bool doHr = (hrp.hrenabled && !iscolor);
- if (hrp.hrenabled && iscolor) {
-
- if(hrp.method == "Coloropp" && opposed == 1) {//force Inpaint opposed if WB change, and opposed limited tne number to 1
- rgbSourceModified = false;
- }
+ if (hrp.hrenabled && iscolor) {
+ if(hrp.method == "Coloropp" && opposed == 1) {//force Inpaint opposed if WB change, and opposed limited tne number to 1
+ rgbSourceModified = false;
+ }
if (!rgbSourceModified) {
- if(hrp.method == "Color") {
- if (settings->verbose) {
- printf ("Applying Highlight Recovery: Color propagation.\n");
- }
- HLRecovery_inpaint (red, green, blue, hrp.hlbl);
- } else if(hrp.method == "Coloropp" && ctemp.getTemp() >= 0) {
- float s[3] = { rm, gm, bm };
- highlight_recovery_opposed(s, ctemp, hrp.hlth);
- }
+ if(hrp.method == "Color") {
+ if (settings->verbose) {
+ printf ("Applying Highlight Recovery: Color propagation.\n");
+ }
+ HLRecovery_inpaint (red, green, blue, hrp.hlbl);
+ } else if(hrp.method == "Coloropp" && ctemp.getTemp() >= 0) {
+ float s[3] = { rm, gm, bm };
+ highlight_recovery_opposed(s, ctemp, hrp.hlth);
+ }
rgbSourceModified = true;
}
}
-
+
// now apply the wb coefficients
if (ctemp.getTemp() >= 0) {
double r, g, b;
@@ -1297,7 +1296,7 @@ int RawImageSource::load (const Glib::ustring &fname, bool firstFrameOnly)
double cam_r = imatrices.rgb_cam[0][0] * camwb_red + imatrices.rgb_cam[0][1] * camwb_green + imatrices.rgb_cam[0][2] * camwb_blue;
double cam_g = imatrices.rgb_cam[1][0] * camwb_red + imatrices.rgb_cam[1][1] * camwb_green + imatrices.rgb_cam[1][2] * camwb_blue;
double cam_b = imatrices.rgb_cam[2][0] * camwb_red + imatrices.rgb_cam[2][1] * camwb_green + imatrices.rgb_cam[2][2] * camwb_blue;
- camera_wb = ColorTemp (cam_r, cam_g, cam_b, 1.); // as shot WB
+ camera_wb = ColorTemp (cam_r, cam_g, cam_b, 1., ColorTemp::DEFAULT_OBSERVER); // as shot WB
if (settings->verbose) {
printf("Raw As Shot White balance: temp %f, tint %f\n", camera_wb.getTemp(), camera_wb.getGreen());
@@ -1384,7 +1383,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
const double ref_r = imatrices.rgb_cam[0][0] * refwb_red + imatrices.rgb_cam[0][1] * refwb_green + imatrices.rgb_cam[0][2] * refwb_blue;
const double ref_g = imatrices.rgb_cam[1][0] * refwb_red + imatrices.rgb_cam[1][1] * refwb_green + imatrices.rgb_cam[1][2] * refwb_blue;
const double ref_b = imatrices.rgb_cam[2][0] * refwb_red + imatrices.rgb_cam[2][1] * refwb_green + imatrices.rgb_cam[2][2] * refwb_blue;
- const ColorTemp ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1.);
+ const ColorTemp ReferenceWB = ColorTemp (ref_r, ref_g, ref_b, 1., ColorTemp::DEFAULT_OBSERVER);
if (settings->verbose) {
printf("Raw Reference white balance: temp %f, tint %f, multipliers [%f %f %f | %f %f %f]\n", ReferenceWB.getTemp(), ReferenceWB.getGreen(), ref_r, ref_g, ref_b, refwb_red, refwb_blue, refwb_green);
@@ -4037,6 +4036,475 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end)
}
}
+
+static void histoxyY_low(int bfhitc, int bfwitc, const array2D & xc, const array2D & yc, const array2D & Yc, LUTf &xxx, LUTf &yyy, LUTf &YYY, LUTu &histxy)
+{
+ //calculate histogram x y in a range of 190 colors
+ //this "choice" are guided by generally colors who are in nature skin, sky, etc. in those cases "steps" are small
+ // of course we can change to be more precise
+#ifdef _OPENMP
+ #pragma omp parallel
+#endif
+ {
+ LUTu histxythr(histxy.getSize());
+ histxythr.clear();
+ LUTf xxxthr(xxx.getSize());
+ xxxthr.clear();
+ LUTf yyythr(yyy.getSize());
+ yyythr.clear();
+ LUTf YYYthr(YYY.getSize());
+ YYYthr.clear();
+#ifdef _OPENMP
+ #pragma omp for schedule(dynamic, 4) nowait
+#endif
+ for (int y = 0; y < bfhitc ; y++) {
+ for (int x = 0; x < bfwitc ; x++) {
+ int nh = -1;
+ if (xc[y][x] < 0.12f && xc[y][x] > 0.03f && yc[y][x] > 0.1f) { // near Prophoto
+ if (yc[y][x] < 0.2f) {
+ nh = 0;
+ //blue hard
+ } else if (yc[y][x] < 0.3f) {
+ nh = 1;
+ //blue
+ } else if (yc[y][x] < 0.4f) {
+ nh = 2;
+
+ } else if (yc[y][x] < 0.5f) {
+ //blue green
+ nh = 3;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 4;
+ } else if (yc[y][x] < 0.82f) {
+ //green
+ nh = 5;
+ }
+ } else if (xc[y][x] < 0.24f && yc[y][x] > 0.05f) {
+ if (yc[y][x] < 0.2f) {
+ nh = 6;
+ } else if (yc[y][x] < 0.3f) {
+ nh = 7;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 8;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 9;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 10;
+ } else if (yc[y][x] < 0.75f) {
+ nh = 11;
+ }
+ } else if (xc[y][x] < 0.28f && yc[y][x] > 0.1f) {//blue sky and other
+ if (yc[y][x] < 0.2f) {
+ nh = 12;
+ } else if (yc[y][x] < 0.25f) {
+ nh = 13;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 14;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 15;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 16;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 17;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 18;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 19;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 20;
+ } else if (yc[y][x] < 0.75f) {
+ nh = 21;
+ }
+ } else if (xc[y][x] < 0.31f && yc[y][x] > 0.1f) {//near neutral others
+ if (yc[y][x] < 0.2f) {
+ nh = 22;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 23;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 24;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 25;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 26;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 27;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 28;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 29;
+ }
+ } else if (xc[y][x] < 0.325f && yc[y][x] > 0.1f) {//neutral 34
+ if (yc[y][x] < 0.2f) {
+ nh = 30;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 31;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 32;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 33;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 34;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 35;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 36;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 37;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 38;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 39;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 40;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 41;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 42;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 43;
+ }
+ } else if (xc[y][x] < 0.335f && yc[y][x] > 0.1f) {//neutral
+ if (yc[y][x] < 0.2f) {
+ nh = 44;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 45;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 46;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 47;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 48;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 49;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 50;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 51;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 52;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 53;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 54;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 55;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 56;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 57;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 58;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 59;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 60;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 61;
+ }
+ } else if (xc[y][x] < 0.340f && yc[y][x] > 0.1f) {//neutral
+ if (yc[y][x] < 0.2f) {
+ nh = 62;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 63;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 64;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 65;
+ } else if (yc[y][x] < 0.325f) {
+ nh = 66;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 67;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 68;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 69;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 70;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 71;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 72;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 73;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 74;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 75;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 76;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 77;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 78;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 79;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 80;
+ }
+ } else if (xc[y][x] < 0.345f && yc[y][x] > 0.1f) {//neutral 37
+ if (yc[y][x] < 0.2f) {
+ nh = 81;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 82;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 83;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 84;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 85;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 86;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 87;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 88;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 89;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 90;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 91;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 92;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 93;
+ } else if (yc[y][x] < 0.39f) {
+ nh = 94;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 95;
+ } else if (yc[y][x] < 0.42f) {
+ nh = 96;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 97;
+ } else if (yc[y][x] < 0.48f) {
+ nh = 98;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 99;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 100;
+ } else if (yc[y][x] < 0.65f) {
+ nh = 101;
+ }
+ } else if (xc[y][x] < 0.355f && yc[y][x] > 0.1f) {//neutral 37
+ if (yc[y][x] < 0.2f) {
+ nh = 102;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 103;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 104;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 105;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 106;
+ } else if (yc[y][x] < 0.335f) {
+ nh = 107;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 108;
+ } else if (yc[y][x] < 0.345f) {
+ nh = 109;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 110;
+ } else if (yc[y][x] < 0.355f) {
+ nh = 111;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 112;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 113;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 114;
+ } else if (yc[y][x] < 0.39f) {
+ nh = 115;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 116;
+ } else if (yc[y][x] < 0.42f) {
+ nh = 117;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 118;
+ } else if (yc[y][x] < 0.48f) {
+ nh = 119;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 120;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 121;
+ } else if (yc[y][x] < 0.65f) {
+ nh = 122;
+ }
+ } else if (xc[y][x] < 0.365f && yc[y][x] > 0.15f) { //0.4
+ if (yc[y][x] < 0.2f) {
+ nh = 123;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 124;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 125;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 126;
+ } else if (yc[y][x] < 0.33f) {
+ nh = 127;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 128;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 129;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 130;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 131;
+ } else if (yc[y][x] < 0.38f) {
+ nh = 132;
+ } else if (yc[y][x] < 0.39f) {
+ nh = 133;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 134;
+ } else if (yc[y][x] < 0.42f) {
+ nh = 135;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 136;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 137;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 138;
+ } else if (yc[y][x] < 0.63f) {
+ nh = 139;
+ }
+ } else if (xc[y][x] < 0.405f && yc[y][x] > 0.15f) {//45
+ if (yc[y][x] < 0.2f) {
+ nh = 140;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 141;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 142;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 143;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 144;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 145;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 146;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 147;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 148;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 149;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 150;
+ }
+ } else if (xc[y][x] < 0.445f && yc[y][x] > 0.15f) {//45
+ if (yc[y][x] < 0.2f) {
+ nh = 151;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 152;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 153;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 154;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 155;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 156;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 157;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 158;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 159;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 160;
+ } else if (yc[y][x] < 0.58f) {
+ nh = 161;
+ }
+ } else if (xc[y][x] < 0.495f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.2f) {
+ nh = 162;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 163;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 164;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 165;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 166;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 167;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 168;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 169;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 170;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 171;
+ }
+ } else if (xc[y][x] < 0.545f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.2f) {
+ nh = 172;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 173;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 174;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 175;
+ } else if (yc[y][x] < 0.34f) {
+ nh = 176;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 177;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 178;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 179;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 180;
+ }
+ } else if (xc[y][x] < 0.595f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.22f) {
+ nh = 181;
+ } else if (yc[y][x] < 0.25f) {
+ nh = 182;
+ } else if (yc[y][x] < 0.3f) {
+ nh = 183;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 184;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 185;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 186;
+ }
+ } else if (xc[y][x] < 0.65f && yc[y][x] > 0.12f) {
+ if (yc[y][x] < 0.25f) {
+ nh = 187;
+ } else if (yc[y][x] < 0.3f) {
+ nh = 188;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 189;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 190;
+ }
+ } else if (xc[y][x] < 0.75f && yc[y][x] > 0.1f) {
+ nh = 191;
+ }
+ if (nh >= 0) {
+ histxythr[nh]++;
+ xxxthr[nh] += xc[y][x];
+ yyythr[nh] += yc[y][x];
+ YYYthr[nh] += Yc[y][x];
+ }
+ }
+ }
+#ifdef _OPENMP
+ #pragma omp critical
+#endif
+ {
+ histxy += histxythr;
+ xxx += xxxthr;
+ yyy += yyythr;
+ YYY += YYYthr;
+ }
+ }
+}
+
+
+
+
static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const array2D & yc, const array2D & Yc, LUTf &xxx, LUTf &yyy, LUTf &YYY, LUTu &histxy, bool purp)
{
// calculate histogram x y in a range of 236 colors
@@ -4654,7 +5122,7 @@ float static studentXY(const array2D & YYcurr, const array2D & ref
void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, const ColorManagementParams &cmp, const RAWParams &raw, const WBParams & wbpar, const ToneCurveParams &hrp)
{
/*
- Copyright (c) Jacques Desmis 6 - 2018 jdesmis@gmail.com, update 1 - 2023
+ Copyright (c) Jacques Desmis 6 - 2018 jdesmis@gmail.com, update 2 - 2023
Copyright (c) Ingo Weyrich 3 - 2020 (heckflosse67@gmx.de)
This algorithm try to find temperature correlation between 20 to 80 colors between 201 spectral color and about 20 to 55 color found in the image between 236, I just found the idea in the web "correlate with chroma" instead of RGB grey point,but I don't use any algo found on the web.
@@ -4693,7 +5161,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
22) we re-adjust references color for these xyY from 20)
23) then find all Student correlation for each couple green / temp
24) sort these Student values, and choose the minimum
- 25) then for the 3 better couple "temp / green" choose the one where green is nearest from 1.
+ 25) then for the 5 better couple "temp / green" choose the one where green is nearest from 1.
Some variables or function are not used, keep in case of
I have test with cat02 but result are not stable enough ! why ??, therefore cat02 neutralized
@@ -4704,28 +5172,37 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
You can used it in images :flowers, landscape, portrait, skin, where illuminants are "normal" (daylight, blackbody)
You must avoid when illuminant is non standard (fluorescent, LED...) and also, when the subject is lost in the image (some target to generate profiles).
- You can change parameters in option.cc
+ You can change parameters in White Balance - Frame adapted to Itcwb
Itcwb_thres : 34 by default ==> number of color used in final algorithm - between 10 and max 55
Itcwb_sorted : true by default, can improve algorithm if true, ==> sort value in something near chroma order, instead of histogram number
Itcwb_greenrange : 0 amplitude of green variation - between 0 to 2
- Itcwb_greendeltatemp : 1 - delta temp in green iterate loop for "extra" - between 0 to 4
- Itcwb_forceextra : true by default - if true force algorithm "extra" ("extra" is used when camera wbsettings are wrong) to all images
- Itcwb_sizereference : 3 by default, can be set to 5 ==> size of reference color compare to size of histogram real color
+ Itcwb_greendelta : 1 - delta temp in green iterate loop for "extra" - between 0 to 4
+ Itcwb_forceextra : false by default - Use all Ciexy diagram instead of sRGB
+ //Itcwb_sizereference : repalce by int maxnb 3 by default, can be set to 5 ==> size of reference color compare to size of histogram real color
itcwb_delta : 1 by default can be set between 0 to 5 ==> delta temp to build histogram xy - if camera temp is not probably good
- itcwb_stdobserver10 : true by default - use standard observer 10°, false = standard observer 2°
- itcwb_precis : 3 by default - can be set to 3 or 9 - 3 best sampling but more time...9 "old" settings - but low differences in times with 3 instead of 9 about twice time 160ms instead of 80ms for a big raw file
+ //itcwb_precis : replace by int precision = 3 by default - can be set to 3 or 9 - 3 best sampling but more time...9 "old" settings - but low differences in times with 3 instead of 9 about twice time 160ms instead of 80ms for a big raw file
itcwb_nopurple : true default - allow to bypass highlight recovery and inpait opposed when need flowers and not purple due to highlights...
+ itcwb_fgreen : 5 by default - between 3 to 6 - find the compromise student / green to reach green near of 1
+
+ In file options.
+ use standard observer 10°, false = standard observer 2°
*/
// BENCHFUN
- TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix("sRGB");
+ Glib::ustring profuse;
+ profuse = "sRGB";//or "Adobe RGB"
+ if( wbpar.itcwb_forceextra && wbpar.itcwb_sampling == false) {//Adobe RGB
+ profuse = "ACESp0";//cover all CIE xy diagram
+ }
+
+ TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(profuse); //ACESp0 or sRGB
const float wp[3][3] = {
{static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])},
{static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])},
{static_cast(wprof[2][0]), static_cast(wprof[2][1]), static_cast(wprof[2][2])}
};
- TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix("sRGB");
+ TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix(profuse);//ACESp0 or sRGB
//inverse matrix user select
const float wip[3][3] = {
{static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])},
@@ -4766,7 +5243,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{0.680, 1.f},
{0.690, 1.f},
{0.700, 1.f},
- {0.714, 1.f},//usual range
+ {0.714, 1.f},//usual 2 range
{0.727, 1.f},
{0.741, 1.f},
{0.755, 1.f},
@@ -4775,7 +5252,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{0.800, 1.f},
{0.806, 1.f},
{0.813, 1.f},
- {0.820, 1.f},
+ {0.820, 1.f},//usual range
{0.826, 1.f},
{0.833, 1.f},
{0.840, 1.f},
@@ -4822,13 +5299,13 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{1.220, 1.f},
{1.230, 1.f},
{1.240, 1.f},
- {1.250, 1.f},
+ {1.250, 1.f},// usual range
{1.275, 1.f},
{1.300, 1.f},
{1.325, 1.f},
{1.350, 1.f},
{1.375, 1.f},
- {1.400, 1.f},//usual range
+ {1.400, 1.f},//usual 2 range
{1.425, 1.f},
{1.450, 1.f},
{1.475, 1.f},
@@ -4884,20 +5361,25 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
int end;
} RangeGreen;
- constexpr RangeGreen Rangestandard = {24, 86};//usual green range
+ constexpr RangeGreen Rangestandard = {33, 80};//usual green range
+ constexpr RangeGreen Rangestandard2 = {24, 86};//usual 2 green range
constexpr RangeGreen Rangeextended = {15, 93};
const RangeGreen Rangemax = {0, N_g};
RangeGreen Rangegreenused;
- if (settings->itcwb_greenrange == 0) {
+ if (wbpar.itcwb_rgreen == 0) {
Rangegreenused = Rangestandard;
- } else if (settings->itcwb_greenrange == 1) {
+ } else if (wbpar.itcwb_rgreen == 1) {
+ Rangegreenused = Rangestandard2;
+ } else if (wbpar.itcwb_rgreen == 2) {
Rangegreenused = Rangeextended;
} else {
Rangegreenused = Rangemax;
}
-
+ if(wbpar.itcwb_sampling == true) {
+ Rangegreenused = Rangestandard2;
+ }
typedef struct WbTxyz {
double Tem;
double XX;
@@ -5044,8 +5526,10 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
float gmm[N_t];
float bmm[N_t];
- constexpr int siza = 237; //192 untill 01/2023 size of histogram
-
+ int siza = 237; //192 untill 01/2023 size of histogram
+ if(wbpar.itcwb_sampling == true) {
+ siza = 192;//old sampling 5.9 and before...
+ }
// tempref and greenref are camera wb values.
// I used them by default to select good spectral values !! but they are changed after
tempref = rtengine::min(tempref, 12000.0);
@@ -5062,12 +5546,12 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
//calculate R G B multiplier in function illuminant and temperature
const bool isMono = (ri->getSensorType() == ST_FUJI_XTRANS && raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::MONO))
|| (ri->getSensorType() == ST_BAYER && raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::MONO));
-
for (int tt = 0; tt < N_t; ++tt) {
double r, g, b;
float rm, gm, bm;
- ColorTemp WBiter = ColorTemp(Txyz[tt].Tem, greenitc, 1.f, "Custom");
+ ColorTemp WBiter = ColorTemp(Txyz[tt].Tem, greenitc, 1.f, "Custom", wbpar.observer);
WBiter.getMultipliers(r, g, b);
+
rm = imatrices.cam_rgb[0][0] * r + imatrices.cam_rgb[0][1] * g + imatrices.cam_rgb[0][2] * b;
gm = imatrices.cam_rgb[1][0] * r + imatrices.cam_rgb[1][1] * g + imatrices.cam_rgb[1][2] * b;
bm = imatrices.cam_rgb[2][0] * r + imatrices.cam_rgb[2][1] * g + imatrices.cam_rgb[2][2] * b;
@@ -5151,7 +5635,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
array2D yc(bfwitc, bfhitc);
array2D Yc(bfwitc, bfhitc);
- const int deltarepref = settings->itcwb_delta;
+ const int deltarepref = 1; //settings->itcwb_delta;
for (int nn = 0, drep = -deltarepref; nn <= 2; ++nn, drep += deltarepref) {
//three loop to refine color if temp camera is probably not very good
@@ -5167,7 +5651,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
const float RR = rmm[rep] * redloc[y][x];
const float GG = gmm[rep] * greenloc[y][x];
const float BB = bmm[rep] * blueloc[y][x];
- Color::rgbxyY(RR, GG, BB, xc[y][x], yc[y][x], Yc[y][x], wp);
+ Color::rgbxyY(RR, GG, BB, xc[y][x], yc[y][x], Yc[y][x], wp);//use sRGB or ACESp0
}
}
@@ -5182,12 +5666,18 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
bool purp = true;//if inpaint-opposed or something else enable purp
- if (hrp.hrenabled && hrp.method == "Coloropp" && settings->itcwb_nopurple == true) {//we disabled (user) with settings if image are naturally with purple (flowers...)
+ // if (hrp.hrenabled && hrp.method == "Coloropp" && settings->itcwb_nopurple == true) {//we disabled (user) with settings if image are naturally with purple (flowers...)
+ if (hrp.hrenabled && hrp.method == "Coloropp" && wbpar.itcwb_nopurple == true) {//we disabled (user) with settings if image are naturally with purple (flowers...)
purp = false;
}
-
- histoxyY(bfhitc, bfwitc, xc, yc, Yc, xxx, yyy, YYY, histxy, purp);//purp enable, enable purple color in WB
- //return histogram x and y for each temp and in a range of 235 colors (siza)
+ if(wbpar.itcwb_sampling == false) {
+ //printf("Use high smapling\n");
+ histoxyY(bfhitc, bfwitc, xc, yc, Yc, xxx, yyy, YYY, histxy, purp);//purp enable, enable purple color in WB
+ //return histogram x and y for each temp and in a range of 235 colors (siza)
+ } else {
+ //printf("Use low smapling - 5.9\n");
+ histoxyY_low(bfhitc, bfwitc, xc, yc, Yc, xxx, yyy, YYY, histxy);//low scaling
+ }
}
// free some memory
@@ -5255,7 +5745,11 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
int sizcurr2ref = sizcurrref - ntr;
const int sizcu30 = sizcurrref - n30;
- const int sizcu4 = rtengine::min(sizcu30, 55);//
+ int nbm = 77;//number max of color used = 1.4 * 55 in case all CIExy diagram
+ if(profuse == "sRGB" || wbpar.itcwb_sampling == true) {
+ nbm = 55;
+ }
+ const int sizcu4 = rtengine::min(sizcu30, nbm);//size of chroma values
if (settings->verbose) {
printf("ntr=%i sizcurr2ref=%i sizcu30=%i sizcu4=%i\n", ntr, sizcurr2ref, sizcu30, sizcu4);
@@ -5292,12 +5786,21 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
if (settings->verbose) {
printf("estimchrom=%f\n", estimchrom);
}
+ bool issorted = wbpar.itcwb_sorted;
- if (settings->itcwb_sorted) { //sort in ascending with chroma values
+ if(wbpar.itcwb_sampling == true) {
+ issorted = false;
+ }
+
+
+ if (issorted) { //sort in ascending with chroma values
std::sort(wbchro, wbchro + sizcu4, wbchro[0]);
}
- const int maxval = rtengine::LIM(settings->itcwb_thres, 10, 55);//max values of color to find correlation
+ int maxval = rtengine::LIM(wbpar.itcwb_thres, 10, 55);//max values of color to find correlation
+ if(wbpar.itcwb_sampling == true) {
+ maxval = 34;
+ }
sizcurr2ref = rtengine::min(sizcurr2ref, maxval); //keep about the biggest values,
@@ -5312,10 +5815,13 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
//calculate deltaE xx to find best values of spectrals data - limited to chroma values
- int maxnb = rtengine::LIM(settings->itcwb_sizereference, 1, 5);
+ // int maxnb = rtengine::LIM(settings->itcwb_sizereference, 1, 5);
+ // int maxnb = rtengine::LIM(wbpar.itcwb_size, 1, 5);
+ int maxnb = 3;
+ //wbpar.itcwb_size to verify if this setting is usefull...diificulties with High gamut and limited patch spectral colors.
- if (settings->itcwb_thres > 55) {
- maxnb = 201 / settings->itcwb_thres;
+ if (wbpar.itcwb_thres > 55) {//normally never used
+ maxnb = 201 / wbpar.itcwb_thres;
}
for (int nb = 1; nb <= maxnb; ++nb) { //max 5 iterations for Itcwb_thres=33, after trial 3 is good in most cases but in some cases 5
@@ -5423,10 +5929,12 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
Tgstud[i].student = 1000.f;//max value to initialize
Tgstud[i].tempref = 57;//5002K position in the list
Tgstud[i].greenref = 55;// 1.f position in the list
-
}
- const int dgoodref = rtengine::min(settings->itcwb_greendeltatemp, 4);
+ int dgoodref = rtengine::LIM(wbpar.itcwb_delta,1, 4);
+ if(wbpar.itcwb_sampling == true) {
+ dgoodref = 2;
+ }
const int scantempbeg = rtengine::max(goodref - (dgoodref + 1), 1);
const int scantempend = rtengine::min(goodref + dgoodref, N_t - 1);
@@ -5436,7 +5944,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
for (int tt = scantempbeg; tt < scantempend; ++tt) {
double r, g, b;
- ColorTemp WBiter(Txyz[tt].Tem, gree[gr].green, 1.f, "Custom");
+ ColorTemp WBiter(Txyz[tt].Tem, gree[gr].green, 1.f, "Custom", wbpar.observer);
WBiter.getMultipliers(r, g, b);
float rm = imatrices.cam_rgb[0][0] * r + imatrices.cam_rgb[0][1] * g + imatrices.cam_rgb[0][2] * b;
float gm = imatrices.cam_rgb[1][0] * r + imatrices.cam_rgb[1][1] * g + imatrices.cam_rgb[1][2] * b;
@@ -5508,7 +6016,12 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
// perhaps we can used a Snedecor test ? but why...at least we have confidence interval > 90%
int greengood = 55;
- int maxkgood = 5;//we can change ...to test 3, 4, 5. High values perhaps less good student, but it is a compromise...
+ int maxkgood = wbpar.itcwb_fgreen;//we can change ...to test 3, 4, 5. High values perhaps less good student, but it is a compromise...
+ maxkgood = rtengine::LIM(maxkgood, 3, 6);
+ if(wbpar.itcwb_sampling == true) {
+ maxkgood = 3; // force to 3 with old low sampling
+ }
+
int mingood = std::min(std::fabs(Tgstud[0].greenref - 55), std::fabs(Tgstud[1].greenref - 55));
for (int k = 2; k < maxkgood; ++k) {
@@ -5558,14 +6071,11 @@ void RawImageSource::WBauto(double & tempref, double & greenref, array2D
//put green (tint) in reasonable limits for an Daylight illuminant
// avoid too bi or too low values
if (wbpar.method == "autitcgreen") {
- bool extra = false;
+ bool extra = true;
if (greenref > 0.5 && greenref < 1.3) {// 0.5 and 1.3 arbitraties values
greenitc = greenref;
- if (settings->itcwb_forceextra) {
- extra = true;
- }
} else {
greenitc = 1.;
extra = true;
@@ -5576,22 +6086,16 @@ void RawImageSource::WBauto(double & tempref, double & greenref, array2D
}
}
-void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w)
+void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, const WBParams & wbpar)
{
// BENCHFUN
//used by auto WB local to calculate red, green, blue in local region
- int precision = 5;
-
- if (settings->itcwb_precis == 5) {
+ int precision = 3;//must be 3 5 or 9
+ if(wbpar.itcwb_sampling == true) {
precision = 5;
- } else if (settings->itcwb_precis < 5) {
- precision = 3;
- } else if (settings->itcwb_precis > 5) {
- precision = 9;
}
-
const int bfw = W / precision + ((W % precision) > 0 ? 1 : 0);// 5 arbitrary value can be change to 3 or 9 ;
const int bfh = H / precision + ((H % precision) > 0 ? 1 : 0);
@@ -5851,14 +6355,9 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
if (wbpar.method == "autitcgreen") {
bool twotimes = false;
- int precision = 5;
-
- if (settings->itcwb_precis == 5) {
+ int precision = 3;//must be 3 5 or 9
+ if(wbpar.itcwb_sampling == true) {
precision = 5;
- } else if (settings->itcwb_precis < 5) {
- precision = 3;
- } else if (settings->itcwb_precis > 5) {
- precision = 9;
}
const int bfw = W / precision + ((W % precision) > 0 ? 1 : 0);// 5 arbitrary value can be change to 3 or 9 ;
@@ -6106,7 +6605,7 @@ void RawImageSource::getAutoWBMultipliers(double &rm, double &gm, double &bm)
blueAWBMul = bm = imatrices.rgb_cam[2][0] * reds + imatrices.rgb_cam[2][1] * greens + imatrices.rgb_cam[2][2] * blues;
}
-ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal)
+ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal, StandardObserver observer)
{
int x;
@@ -6314,7 +6813,7 @@ ColorTemp RawImageSource::getSpotWB (std::vector &red, std::vector &rawData); // raw for cblack
void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override;
void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override;
- void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) override;
+ void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, const procparams::WBParams & wbpar) override;
void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const override;
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override;
@@ -154,7 +154,7 @@ public:
return camera_wb;
}
void getAutoWBMultipliers (double &rm, double &gm, double &bm) override;
- ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) override;
+ ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal, StandardObserver observer) override;
bool isWBProviderReady () override
{
return rawData;
@@ -186,7 +186,7 @@ public:
}
void getAutoExpHistogram (LUTu & histogram, int& histcompr) override;
void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) override;
- void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, std::vector &outCurve) override;
+ void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, StandardObserver observer, std::vector &outCurve) override;
DCPProfile *getDCP(const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as) override;
void convertColorSpace(Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) override;
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index 989ca3354..f86950457 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -472,7 +472,7 @@ class AutoWBListener
{
public:
virtual ~AutoWBListener() = default;
- virtual void WBChanged(double temp, double green, float studgood) = 0;
+ virtual void WBChanged(double temp, double green, double rw, double gw, double bw, float studgood) = 0;
};
class FrameCountListener
@@ -619,8 +619,8 @@ public:
* @return a pointer to the Crop object that handles the image data trough its own pipeline */
virtual DetailedCrop* createCrop (::EditDataProvider *editDataProvider, bool isDetailWindow) = 0;
- virtual bool getAutoWB (double& temp, double& green, double equal, double tempBias) = 0;
- virtual void getCamWB (double& temp, double& green) = 0;
+ virtual bool getAutoWB (double& temp, double& green, double equal, StandardObserver observer, double tempBias) = 0;
+ virtual void getCamWB (double& temp, double& green, StandardObserver observer) = 0;
virtual void getSpotWB (int x, int y, int rectSize, double& temp, double& green) = 0;
virtual bool getFilmNegativeSpot(int x, int y, int spotSize, procparams::FilmNegativeParams::RGB &refInput, procparams::FilmNegativeParams::RGB &refOutput) = 0;
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 84c33a734..11dae8018 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -194,7 +194,7 @@ namespace rtengine
using namespace procparams;
-Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode)
+Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool inspectorMode)
{
StdImageSource imgSrc;
@@ -310,8 +310,9 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
tpp->blueAWBMul = avg_b / double (n);
tpp->wbEqual = wbEq;
tpp->wbTempBias = 0.0;
+ tpp->wbObserver = wbObserver;
- cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen);
+ cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->wbObserver, tpp->autoWBTemp, tpp->autoWBGreen);
}
tpp->init ();
@@ -543,7 +544,7 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname)
return rml;
}
-Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, bool forHistogramMatching)
+Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching)
{
RawImage *ri = new RawImage (fname);
unsigned int tempImageNum = 0;
@@ -982,9 +983,10 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati
tpp->blueAWBMul = ri->get_rgb_cam (2, 0) * reds + ri->get_rgb_cam (2, 1) * greens + ri->get_rgb_cam (2, 2) * blues;
tpp->wbEqual = wbEq;
tpp->wbTempBias = 0.0;
+ tpp->wbObserver = wbObserver;
ColorTemp cTemp;
- cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->autoWBTemp, tpp->autoWBGreen);
+ cTemp.mul2temp (tpp->redAWBMul, tpp->greenAWBMul, tpp->blueAWBMul, tpp->wbEqual, tpp->wbObserver, tpp->autoWBTemp, tpp->autoWBGreen);
}
if (rotate && ri->get_rotateDegree() > 0) {
@@ -1121,18 +1123,19 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
float iso = metadata->getISOSpeed(imgNum);
float fcomp = metadata->getExpComp(imgNum);
- // check if the WB's equalizer value has changed
- if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4)) {
+ // check if the WB's equalizer, temperature bias, or observer value has changed
+ if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4) || wbObserver != params.wb.observer) {
wbEqual = params.wb.equal;
wbTempBias = params.wb.tempBias;
+ wbObserver = params.wb.observer;
// recompute the autoWB
ColorTemp cTemp;
- cTemp.mul2temp (redAWBMul, greenAWBMul, blueAWBMul, wbEqual, autoWBTemp, autoWBGreen);
+ cTemp.mul2temp (redAWBMul, greenAWBMul, blueAWBMul, wbEqual, wbObserver, autoWBTemp, autoWBGreen);
autoWBTemp += autoWBTemp * wbTempBias;
}
// compute WB multipliers
- ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
+ ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method, params.wb.observer);
if (!params.wb.enabled) {
currWB = ColorTemp();
@@ -1141,9 +1144,9 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
double cam_r = colorMatrix[0][0] * camwbRed + colorMatrix[0][1] * camwbGreen + colorMatrix[0][2] * camwbBlue;
double cam_g = colorMatrix[1][0] * camwbRed + colorMatrix[1][1] * camwbGreen + colorMatrix[1][2] * camwbBlue;
double cam_b = colorMatrix[2][0] * camwbRed + colorMatrix[2][1] * camwbGreen + colorMatrix[2][2] * camwbBlue;
- currWB = ColorTemp (cam_r, cam_g, cam_b, params.wb.equal);
+ currWB = ColorTemp (cam_r, cam_g, cam_b, params.wb.equal, params.wb.observer);
} else if (params.wb.method == "autold") {
- currWB = ColorTemp (autoWBTemp, autoWBGreen, wbEqual, "Custom");
+ currWB = ColorTemp (autoWBTemp, autoWBGreen, wbEqual, "Custom", wbObserver);
}
double rm, gm, bm;
@@ -1588,27 +1591,28 @@ void Thumbnail::getDimensions (int& w, int& h, double& scaleFac)
}
}
-void Thumbnail::getCamWB (double& temp, double& green)
+void Thumbnail::getCamWB (double& temp, double& green, StandardObserver observer)
{
double cam_r = colorMatrix[0][0] * camwbRed + colorMatrix[0][1] * camwbGreen + colorMatrix[0][2] * camwbBlue;
double cam_g = colorMatrix[1][0] * camwbRed + colorMatrix[1][1] * camwbGreen + colorMatrix[1][2] * camwbBlue;
double cam_b = colorMatrix[2][0] * camwbRed + colorMatrix[2][1] * camwbGreen + colorMatrix[2][2] * camwbBlue;
- ColorTemp currWB = ColorTemp (cam_r, cam_g, cam_b, 1.0); // we do not take the equalizer into account here, because we want camera's WB
+ ColorTemp currWB = ColorTemp (cam_r, cam_g, cam_b, 1.0, observer); // we do not take the equalizer into account here, because we want camera's WB
temp = currWB.getTemp ();
green = currWB.getGreen ();
}
-void Thumbnail::getAutoWB (double& temp, double& green, double equal, double tempBias)
+void Thumbnail::getAutoWB (double& temp, double& green, double equal, double tempBias, StandardObserver observer)
{
- if (equal != wbEqual || tempBias != wbTempBias) {
+ if (equal != wbEqual || tempBias != wbTempBias || observer != wbObserver) {
// compute the values depending on equal
ColorTemp cTemp;
wbEqual = equal;
wbTempBias = tempBias;
+ wbObserver = observer;
// compute autoWBTemp and autoWBGreen
- cTemp.mul2temp (redAWBMul, greenAWBMul, blueAWBMul, wbEqual, autoWBTemp, autoWBGreen);
+ cTemp.mul2temp (redAWBMul, greenAWBMul, blueAWBMul, wbEqual, wbObserver, autoWBTemp, autoWBGreen);
autoWBTemp += autoWBTemp * tempBias;
}
@@ -1665,7 +1669,7 @@ void Thumbnail::getSpotWB (const procparams::ProcParams& params, int xp, int yp,
double gm = colorMatrix[1][0] * reds + colorMatrix[1][1] * greens + colorMatrix[1][2] * blues;
double bm = colorMatrix[2][0] * reds + colorMatrix[2][1] * greens + colorMatrix[2][2] * blues;
- ColorTemp ct (rm, gm, bm, params.wb.equal);
+ ColorTemp ct (rm, gm, bm, params.wb.equal, params.wb.observer);
rtemp = ct.getTemp ();
rgreen = ct.getGreen ();
}
diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h
index 6ec1dfb34..535613ca2 100644
--- a/rtengine/rtthumbnail.h
+++ b/rtengine/rtthumbnail.h
@@ -38,6 +38,8 @@ class ustring;
namespace rtengine
{
+enum class StandardObserver;
+
class Thumbnail
{
@@ -55,6 +57,7 @@ class Thumbnail
double camwbBlue;
double redAWBMul, greenAWBMul, blueAWBMul; // multipliers for auto WB
double autoWBTemp, autoWBGreen, wbEqual, wbTempBias; // autoWBTemp and autoWBGreen are updated each time autoWB is requested and if wbEqual has been modified
+ StandardObserver wbObserver;
LUTu aeHistogram;
int aeHistCompression;
bool aeValid;
@@ -95,12 +98,12 @@ public:
void getDimensions (int& w, int& h, double& scaleFac);
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false, bool forHistogramMatching = false);
- static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, bool forHistogramMatching = false);
- static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false);
+ static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching = false);
+ static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool inspectorMode = false);
static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname);
- void getCamWB (double& temp, double& green);
- void getAutoWB (double& temp, double& green, double equal, double tempBias);
+ void getCamWB (double& temp, double& green, StandardObserver observer);
+ void getAutoWB (double& temp, double& green, double equal, double tempBias, StandardObserver observer);
void getAutoWBMultipliers (double& rm, double& gm, double& bm);
void getSpotWB (const procparams::ProcParams& params, int x, int y, int rect, double& temp, double& green);
void applyAutoExp (procparams::ProcParams& pparams);
diff --git a/rtengine/settings.h b/rtengine/settings.h
index 6e787a112..e831fa1a4 100644
--- a/rtengine/settings.h
+++ b/rtengine/settings.h
@@ -44,7 +44,6 @@ public:
bool monitorBPC; ///< Black Point Compensation for the Labimage->Monitor transform (directly, i.e. not soft-proofing and no WCS in between)
bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile
bool autocielab;
- bool observer10;
bool rgbcurveslumamode_gamut;// controls gamut enforcement for RGB curves in lumamode
bool verbose;
Glib::ustring darkFramesPath; ///< The default directory for dark frames
@@ -93,17 +92,7 @@ public:
int previewselection;
double cbdlsensi;
// bool showtooltip;
-
- int itcwb_thres;
- bool itcwb_sorted;
- int itcwb_greenrange;
- int itcwb_greendeltatemp;
- bool itcwb_forceextra;
- int itcwb_sizereference;
- int itcwb_delta;
- bool itcwb_stdobserver10;
- int itcwb_precis;
- bool itcwb_nopurple;
+ bool itcwb_enable;
//wavelet levels
double edghi;
double edglo;
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 5de3b08b0..78dd84042 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -269,7 +269,7 @@ private:
}
// set the color temperature
- currWB = ColorTemp(params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
+ currWB = ColorTemp(params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method, params.wb.observer);
if (!params.wb.enabled) {
currWB = ColorTemp();
@@ -278,7 +278,7 @@ private:
} else if (params.wb.method == "autold") {
double rm, gm, bm;
imgsrc->getAutoWBMultipliers(rm, gm, bm);
- currWB.update(rm, gm, bm, params.wb.equal, params.wb.tempBias);
+ currWB.update(rm, gm, bm, params.wb.equal, params.wb.observer, params.wb.tempBias);
}
calclum = nullptr ;
@@ -781,7 +781,7 @@ private:
if (params.toneCurve.histmatching) {
if (!params.toneCurve.fromHistMatching) {
- imgsrc->getAutoMatchedToneCurve(params.icm, params.toneCurve.curve);
+ imgsrc->getAutoMatchedToneCurve(params.icm, params.wb.observer, params.toneCurve.curve);
}
if (params.toneCurve.autoexp) {
diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc
index a3f2502f0..411b1de32 100644
--- a/rtengine/stdimagesource.cc
+++ b/rtengine/stdimagesource.cc
@@ -187,7 +187,7 @@ int StdImageSource::load (const Glib::ustring &fname)
plistener->setProgress (1.0);
}
- wb = ColorTemp (1.0, 1.0, 1.0, 1.0);
+ wb = ColorTemp (1.0, 1.0, 1.0, 1.0, ColorTemp::DEFAULT_OBSERVER);
//this is probably a mistake if embedded profile is not D65
return 0;
@@ -348,7 +348,7 @@ void StdImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
blueAWBMul = bm;
}
-ColorTemp StdImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector& blue, int tran, double equal)
+ColorTemp StdImageSource::getSpotWB (std::vector &red, std::vector &green, std::vector& blue, int tran, double equal, StandardObserver observer)
{
int rn, gn, bn;
double reds, greens, blues;
@@ -360,7 +360,7 @@ ColorTemp StdImageSource::getSpotWB (std::vector &red, std::vector& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const override {};
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override;
- void getrgbloc (int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) override {};
+ void getrgbloc (int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, const procparams::WBParams & wbpar) override {};
ColorTemp getWB () const override
{
return wb;
}
void getAutoWBMultipliers (double &rm, double &gm, double &bm) override;
- ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal) override;
+ ColorTemp getSpotWB (std::vector &red, std::vector &green, std::vector &blue, int tran, double equal, StandardObserver observer) override;
void WBauto(double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &studgood, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override;
void getAutoWBMultipliersitc(double &tempref, double &greenref, double &tempitc, double &greenitc, float &studgood, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override;
diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc
index 9e74ddb90..58532f68a 100644
--- a/rtgui/batchtoolpanelcoord.cc
+++ b/rtgui/batchtoolpanelcoord.cc
@@ -586,19 +586,19 @@ void BatchToolPanelCoordinator::unsetTweakOperator (rtengine::TweakOperator *tOp
{
}
-void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal, double tempBias)
+void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green, double equal, rtengine::StandardObserver observer, double tempBias)
{
if (!selected.empty()) {
- selected[0]->getAutoWB (temp, green, equal, tempBias);
+ selected[0]->getAutoWB (temp, green, equal, observer, tempBias);
}
}
-void BatchToolPanelCoordinator::getCamWB (double& temp, double& green)
+void BatchToolPanelCoordinator::getCamWB (double& temp, double& green, rtengine::StandardObserver observer)
{
if (!selected.empty()) {
- selected[0]->getCamWB (temp, green);
+ selected[0]->getCamWB (temp, green, observer);
}
}
diff --git a/rtgui/batchtoolpanelcoord.h b/rtgui/batchtoolpanelcoord.h
index 0009724e8..f421793ac 100644
--- a/rtgui/batchtoolpanelcoord.h
+++ b/rtgui/batchtoolpanelcoord.h
@@ -69,8 +69,8 @@ public:
) override;
// wbprovider interface
- void getAutoWB (double& temp, double& green, double equal, double tempBias) override;
- void getCamWB (double& temp, double& green) override;
+ void getAutoWB (double& temp, double& green, double equal, rtengine::StandardObserver observer, double tempBias) override;
+ void getCamWB (double& temp, double& green, rtengine::StandardObserver observer) override;
// thumbnaillistener interface
void procParamsChanged (Thumbnail* thm, int whoChangedIt) override;
diff --git a/rtgui/checkbox.cc b/rtgui/checkbox.cc
index e05ba061a..265123b23 100644
--- a/rtgui/checkbox.cc
+++ b/rtgui/checkbox.cc
@@ -80,7 +80,7 @@ void CheckBox::setValue (CheckValue newValue)
break;
case CheckValue::off:
set_inconsistent (false);
- set_active(true);
+ set_active(false);
lastActive = false;
break;
case CheckValue::unchanged:
diff --git a/rtgui/filmnegative.cc b/rtgui/filmnegative.cc
index 292fa98ae..4f1ae9311 100644
--- a/rtgui/filmnegative.cc
+++ b/rtgui/filmnegative.cc
@@ -33,6 +33,12 @@ const Glib::ustring FilmNegative::TOOL_NAME = "filmnegative";
namespace
{
+/**
+ * Observer to use for displaying the temperature and tint equivalent of the
+ * multipliers.
+ */
+constexpr rtengine::StandardObserver standard_observer = rtengine::ColorTemp::DEFAULT_OBSERVER;
+
double toAdjuster(double v)
{
return CLAMP(std::log2(v), 6, 16) - 6;
@@ -154,7 +160,7 @@ RGB getFilmNegativeExponents(const RGB &ref1, const RGB &ref2) // , const RGB &c
void temp2rgb(double outLev, double temp, double green, RGB &refOut)
{
- rtengine::ColorTemp ct = rtengine::ColorTemp(temp, green, 1., "Custom");
+ rtengine::ColorTemp ct = rtengine::ColorTemp(temp, green, 1., "Custom", standard_observer);
double rm, gm, bm;
ct.getMultipliers(rm, gm, bm);
@@ -175,7 +181,8 @@ void rgb2temp(const RGB &refOut, double &outLev, double &temp, double &green)
refOut.r / maxVal,
refOut.g / maxVal,
refOut.b / maxVal,
- 1.);
+ 1.,
+ standard_observer);
outLev = maxVal;
temp = ct.getTemp();
@@ -188,7 +195,7 @@ void rgb2temp(const RGB &refOut, double &outLev, double &temp, double &green)
FilmNegative::FilmNegative() :
FoldableToolPanel(this, TOOL_NAME, M("TP_FILMNEGATIVE_LABEL"), false, true),
EditSubscriber(ET_OBJECTS),
- NEUTRAL_TEMP(rtengine::ColorTemp(1., 1., 1., 1.)),
+ NEUTRAL_TEMP(rtengine::ColorTemp(1., 1., 1., 1., rtengine::ColorTemp::DEFAULT_OBSERVER)),
evFilmNegativeExponents(ProcEventMapper::getInstance()->newEvent(ALLNORAW, "HISTORY_MSG_FILMNEGATIVE_VALUES")),
evFilmNegativeEnabled(ProcEventMapper::getInstance()->newEvent(ALLNORAW, "HISTORY_MSG_FILMNEGATIVE_ENABLED")),
evFilmNegativeRefSpot(ProcEventMapper::getInstance()->newEvent(ALLNORAW, "HISTORY_MSG_FILMNEGATIVE_REF_SPOT")),
diff --git a/rtgui/options.cc b/rtgui/options.cc
index e230dcf8a..7d823eda4 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -595,7 +595,6 @@ void Options::setDefaults()
rtSettings.monitorIntent = rtengine::RI_RELATIVE;
rtSettings.monitorBPC = true;
rtSettings.autocielab = false;
- rtSettings.observer10 = false;
rtSettings.autoMonitorProfile = false;
rtSettings.adobe = "RTv2_Medium"; // put the name of yours profiles (here windows)
rtSettings.prophoto = "RTv2_Large"; // these names appear in the menu "output profile"
@@ -623,18 +622,8 @@ void Options::setDefaults()
rtSettings.previewselection = 5;//between 1 to 40
rtSettings.cbdlsensi = 1.0;//between 0.001 to 1
rtSettings.fftwsigma = true; //choice between sigma^2 or empirical formula
-
- rtSettings.itcwb_thres = 34;//between 10 to 55
- rtSettings.itcwb_sorted = true;
- rtSettings.itcwb_greenrange = 0;//between 0 to 2
- rtSettings.itcwb_greendeltatemp = 2;//between 0 and 4
- rtSettings.itcwb_forceextra = true;
- rtSettings.itcwb_sizereference = 3;//between 1 and 5
- rtSettings.itcwb_delta = 1;//between 0 and 5
- rtSettings.itcwb_stdobserver10 = true;
- rtSettings.itcwb_precis = 3;//3 or 5 or 9
- rtSettings.itcwb_nopurple = true;
// end locallab
+ rtSettings.itcwb_enable = true;
//wavelet
rtSettings.edghi = 3.0;//1.1 and 5.
@@ -1767,10 +1756,6 @@ void Options::readFromFile(Glib::ustring fname)
rtSettings.autocielab = keyFile.get_boolean("Color Management", "Autocielab");
}
- if (keyFile.has_key("Color Management", "Observer10")) {
- rtSettings.observer10 = keyFile.get_boolean("Color Management", "Observer10");
- }
-
if (keyFile.has_key("Color Management", "CRI")) {
rtSettings.CRI_color = keyFile.get_integer("Color Management", "CRI");
}
@@ -1802,45 +1787,10 @@ void Options::readFromFile(Glib::ustring fname)
rtSettings.level123_cbdl = keyFile.get_double("Color Management", "CBDLlevel123");
}
- if (keyFile.has_key("Color Management", "Itcwb_thres")) {
- rtSettings.itcwb_thres = keyFile.get_integer("Color Management", "Itcwb_thres");
+ if (keyFile.has_key("Color Management", "Itcwb_enable")) {
+ rtSettings.itcwb_enable = keyFile.get_boolean("Color Management", "Itcwb_enable");
}
- if (keyFile.has_key("Color Management", "Itcwb_sorted")) {
- rtSettings.itcwb_sorted = keyFile.get_boolean("Color Management", "Itcwb_sorted");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_forceextra")) {
- rtSettings.itcwb_forceextra = keyFile.get_boolean("Color Management", "Itcwb_forceextra");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_nopurple")) {
- rtSettings.itcwb_nopurple = keyFile.get_boolean("Color Management", "Itcwb_nopurple");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_stdobserver10")) {
- rtSettings.itcwb_stdobserver10 = keyFile.get_boolean("Color Management", "Itcwb_stdobserver10");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_greenrange")) {
- rtSettings.itcwb_greenrange = keyFile.get_integer("Color Management", "Itcwb_greenrange");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_greendeltatemp")) {
- rtSettings.itcwb_greendeltatemp = keyFile.get_integer("Color Management", "Itcwb_greendeltatemp");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_sizereference")) {
- rtSettings.itcwb_sizereference = keyFile.get_integer("Color Management", "Itcwb_sizereference");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_delta")) {
- rtSettings.itcwb_delta = keyFile.get_integer("Color Management", "Itcwb_delta");
- }
-
- if (keyFile.has_key("Color Management", "Itcwb_precis")) {
- rtSettings.itcwb_precis = keyFile.get_integer("Color Management", "Itcwb_precis");
- }
//if (keyFile.has_key ("Color Management", "Colortoningab")) rtSettings.colortoningab = keyFile.get_double("Color Management", "Colortoningab");
//if (keyFile.has_key ("Color Management", "Decaction")) rtSettings.decaction = keyFile.get_double("Color Management", "Decaction");
@@ -2579,7 +2529,6 @@ void Options::saveToFile(Glib::ustring fname)
keyFile.set_string("Color Management", "MonitorProfile", rtSettings.monitorProfile);
keyFile.set_boolean("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile);
keyFile.set_boolean("Color Management", "Autocielab", rtSettings.autocielab);
- keyFile.set_boolean("Color Management", "Observer10", rtSettings.observer10);
keyFile.set_boolean("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut);
keyFile.set_integer("Color Management", "Intent", rtSettings.monitorIntent);
keyFile.set_boolean("Color Management", "MonitorBPC", rtSettings.monitorBPC);
@@ -2612,16 +2561,7 @@ void Options::saveToFile(Glib::ustring fname)
//keyFile.set_boolean ("Color Management", "Ciebadpixgauss", rtSettings.ciebadpixgauss);
keyFile.set_double("Color Management", "CBDLlevel0", rtSettings.level0_cbdl);
keyFile.set_double("Color Management", "CBDLlevel123", rtSettings.level123_cbdl);
- keyFile.set_integer("Color Management", "Itcwb_thres", rtSettings.itcwb_thres);
- keyFile.set_boolean("Color Management", "Itcwb_sorted", rtSettings.itcwb_sorted);
- keyFile.set_integer("Color Management", "Itcwb_greenrange", rtSettings.itcwb_greenrange);
- keyFile.set_integer("Color Management", "Itcwb_greendeltatemp", rtSettings.itcwb_greendeltatemp);
- keyFile.set_boolean("Color Management", "Itcwb_forceextra", rtSettings.itcwb_forceextra);
- keyFile.set_boolean("Color Management", "Itcwb_nopurple", rtSettings.itcwb_nopurple);
- keyFile.set_integer("Color Management", "Itcwb_sizereference", rtSettings.itcwb_sizereference);
- keyFile.set_integer("Color Management", "Itcwb_delta", rtSettings.itcwb_delta);
- keyFile.set_boolean("Color Management", "Itcwb_stdobserver10", rtSettings.itcwb_stdobserver10);
- keyFile.set_integer("Color Management", "Itcwb_precis", rtSettings.itcwb_precis);
+ keyFile.set_boolean("Color Management", "Itcwb_enable", rtSettings.itcwb_enable);
//keyFile.set_double ("Color Management", "Colortoningab", rtSettings.colortoningab);
//keyFile.set_double ("Color Management", "Decaction", rtSettings.decaction);
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index abd4e8608..c3638cc5f 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -266,6 +266,17 @@ void ParamsEdited::set(bool v)
wb.temperature = v;
wb.equal = v;
wb.tempBias = v;
+ wb.observer = v;
+ wb.itcwb_thres = v;
+ wb.itcwb_precis = v;
+ wb.itcwb_size = v;
+ wb.itcwb_delta = v;
+ wb.itcwb_fgreen = v;
+ wb.itcwb_rgreen = v;
+ wb.itcwb_nopurple = v;
+ wb.itcwb_sorted = v;
+ wb.itcwb_forceextra = v;
+ wb.itcwb_sampling = v;
//colorShift.a = v;
//colorShift.b = v;
//lumaDenoise.enabled = v;
@@ -967,6 +978,17 @@ void ParamsEdited::initFrom(const std::vector&
wb.equal = wb.equal && p.wb.equal == other.wb.equal;
wb.temperature = wb.temperature && p.wb.temperature == other.wb.temperature;
wb.tempBias = wb.tempBias && p.wb.tempBias == other.wb.tempBias;
+ wb.observer = wb.observer && p.wb.observer == other.wb.observer;
+ wb.itcwb_thres = wb.itcwb_thres && p.wb.itcwb_thres == other.wb.itcwb_thres;
+ wb.itcwb_precis = wb.itcwb_precis && p.wb.itcwb_precis == other.wb.itcwb_precis;
+ wb.itcwb_size = wb.itcwb_size && p.wb.itcwb_size == other.wb.itcwb_size;
+ wb.itcwb_delta = wb.itcwb_delta && p.wb.itcwb_delta == other.wb.itcwb_delta;
+ wb.itcwb_fgreen = wb.itcwb_fgreen && p.wb.itcwb_fgreen == other.wb.itcwb_fgreen;
+ wb.itcwb_rgreen = wb.itcwb_rgreen && p.wb.itcwb_rgreen == other.wb.itcwb_rgreen;
+ wb.itcwb_nopurple = wb.itcwb_nopurple && p.wb.itcwb_nopurple == other.wb.itcwb_nopurple;
+ wb.itcwb_sorted = wb.itcwb_sorted && p.wb.itcwb_sorted == other.wb.itcwb_sorted;
+ wb.itcwb_forceextra = wb.itcwb_forceextra && p.wb.itcwb_forceextra == other.wb.itcwb_forceextra;
+ wb.itcwb_sampling = wb.itcwb_sampling && p.wb.itcwb_sampling == other.wb.itcwb_sampling;
//colorShift.a = colorShift.a && p.colorShift.a == other.colorShift.a;
//colorShift.b = colorShift.b && p.colorShift.b == other.colorShift.b;
//lumaDenoise.enabled = lumaDenoise.enabled && p.lumaDenoise.enabled == other.lumaDenoise.enabled;
@@ -2829,6 +2851,50 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.wb.tempBias = dontforceSet && options.baBehav[ADDSET_WB_TEMPBIAS] ? toEdit.wb.tempBias + mods.wb.tempBias : mods.wb.tempBias;
}
+ if (wb.observer) {
+ toEdit.wb.observer = mods.wb.observer;
+ }
+
+ if (wb.itcwb_thres) {
+ toEdit.wb.itcwb_thres = mods.wb.itcwb_thres;
+ }
+
+ if (wb.itcwb_precis) {
+ toEdit.wb.itcwb_precis = mods.wb.itcwb_precis;
+ }
+
+ if (wb.itcwb_size) {
+ toEdit.wb.itcwb_size = mods.wb.itcwb_size;
+ }
+
+ if (wb.itcwb_delta) {
+ toEdit.wb.itcwb_delta = mods.wb.itcwb_delta;
+ }
+
+ if (wb.itcwb_fgreen) {
+ toEdit.wb.itcwb_fgreen = mods.wb.itcwb_fgreen;
+ }
+
+ if (wb.itcwb_rgreen) {
+ toEdit.wb.itcwb_rgreen = mods.wb.itcwb_rgreen;
+ }
+
+ if (wb.itcwb_nopurple) {
+ toEdit.wb.itcwb_nopurple = mods.wb.itcwb_nopurple;
+ }
+
+ if (wb.itcwb_sorted) {
+ toEdit.wb.itcwb_sorted = mods.wb.itcwb_sorted;
+ }
+
+ if (wb.itcwb_forceextra) {
+ toEdit.wb.itcwb_forceextra = mods.wb.itcwb_forceextra;
+ }
+
+ if (wb.itcwb_sampling) {
+ toEdit.wb.itcwb_sampling = mods.wb.itcwb_sampling;
+ }
+
if (wb.green) {
toEdit.wb.green = dontforceSet && options.baBehav[ADDSET_WB_GREEN] ? toEdit.wb.green + mods.wb.green : mods.wb.green;
}
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 66db8346f..d85bec701 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -246,7 +246,19 @@ struct WBParamsEdited {
bool temperature;
bool green;
bool equal;
+ bool observer;
bool tempBias;
+ bool itcwb_thres;
+ bool itcwb_precis;
+ bool itcwb_size;
+ bool itcwb_delta;
+ bool itcwb_fgreen;
+ bool itcwb_rgreen;
+ bool itcwb_nopurple;
+ bool itcwb_sorted;
+ bool itcwb_forceextra;
+ bool itcwb_sampling;
+
};
struct DefringeParamsEdited {
diff --git a/rtgui/ppversion.h b/rtgui/ppversion.h
index 162e63f9e..f2455699c 100644
--- a/rtgui/ppversion.h
+++ b/rtgui/ppversion.h
@@ -1,11 +1,13 @@
#pragma once
// This number has to be incremented whenever the PP3 file format is modified or the behaviour of a tool changes
-#define PPVERSION 349
+#define PPVERSION 350
#define PPVERSION_AEXP 301 //value of PPVERSION when auto exposure algorithm was modified
/*
Log of version changes
+ 350 2023-03-05
+ introduced white balance standard observer
349 2020-10-29
replaced Haze removal Luminance checkbox with an adjuster to blend between luminance and normal mode
348 2018-09-25
diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc
index b04bee237..8c3290e5c 100644
--- a/rtgui/preferences.cc
+++ b/rtgui/preferences.cc
@@ -928,6 +928,10 @@ Gtk::Widget* Preferences::getColorManPanel ()
fcie->add(*gcie);
vbColorMan->pack_start (*fcie, Gtk::PACK_SHRINK);
+
+
+ //-------------
+
swColorMan->add(*vbColorMan);
return swColorMan;
}
@@ -1954,6 +1958,7 @@ void Preferences::fillPreferences()
monBPC->set_active(moptions.rtSettings.monitorBPC);
mcie->set_active(moptions.rtSettings.autocielab);
+
cbAutoMonProfile->set_active(moptions.rtSettings.autoMonitorProfile);
#endif
diff --git a/rtgui/preferences.h b/rtgui/preferences.h
index 90ea20da7..039c4d58a 100644
--- a/rtgui/preferences.h
+++ b/rtgui/preferences.h
@@ -135,6 +135,15 @@ class Preferences final :
Gtk::CheckButton* cbdaubech;
Gtk::SpinButton* hlThresh;
Gtk::SpinButton* shThresh;
+// Gtk::CheckButton* mwbacorr;
+ // Gtk::CheckButton* mwbaforc;
+ // Gtk::CheckButton* mwbanopurp;
+
+// Gtk::CheckButton* mwbasort;
+// Gtk::SpinButton* wbacorrnb;
+// Gtk::SpinButton* wbaprecis;
+// Gtk::SpinButton* wbasizeref;
+// Gtk::SpinButton* wbagreendelta;
Gtk::SpinButton* panFactor;
Gtk::CheckButton* rememberZoomPanCheckbutton;
@@ -240,7 +249,7 @@ class Preferences final :
Options moptions;
sigc::connection tconn, sconn, fconn, cpfconn, addc, setc, dfconn, ffconn, bpconn, rpconn, ipconn;
- sigc::connection autoMonProfileConn, sndEnableConn, langAutoDetectConn, autocielabConn;
+ sigc::connection autoMonProfileConn, sndEnableConn, langAutoDetectConn, autocielabConn, observer10Conn;
Glib::ustring initialTheme;
Glib::ustring initialFontFamily;
int initialFontSize;
@@ -305,6 +314,7 @@ public:
void sndEnableToggled ();
void langAutoDetectToggled ();
void autocielabToggled ();
+ void observer10Toggled ();
void selectStartupDir ();
void addExtPressed ();
diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc
index 30766ebc9..dd7995feb 100644
--- a/rtgui/thumbnail.cc
+++ b/rtgui/thumbnail.cc
@@ -139,20 +139,20 @@ void Thumbnail::_generateThumbnailImage ()
if (ext == "jpg" || ext == "jpeg") {
infoFromImage (fname);
- tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer);
if (tpp) {
cfs.format = FT_Jpeg;
}
} else if (ext == "png") {
- tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer);
if (tpp) {
cfs.format = FT_Png;
}
} else if (ext == "tif" || ext == "tiff") {
infoFromImage (fname);
- tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal);
+ tpp = rtengine::Thumbnail::loadFromImage (fname, tw, th, -1, pparams->wb.equal, pparams->wb.observer);
if (tpp) {
cfs.format = FT_Tiff;
@@ -173,7 +173,7 @@ void Thumbnail::_generateThumbnailImage ()
if ( tpp == nullptr ) {
quick = false;
- tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, tw, th, 1, pparams->wb.equal, TRUE);
+ tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE);
}
cfs.sensortype = sensorType;
@@ -216,11 +216,11 @@ const ProcParams& Thumbnail::getProcParamsU ()
if (pparams->wb.method == "Camera") {
double ct;
- getCamWB (ct, pparams->wb.green);
+ getCamWB (ct, pparams->wb.green, pparams->wb.observer);
pparams->wb.temperature = ct;
} else if (pparams->wb.method == "autold") {
double ct;
- getAutoWB (ct, pparams->wb.green, pparams->wb.equal, pparams->wb.tempBias);
+ getAutoWB (ct, pparams->wb.green, pparams->wb.equal, pparams->wb.observer, pparams->wb.tempBias);
pparams->wb.temperature = ct;
}
}
@@ -785,10 +785,10 @@ const Glib::DateTime& Thumbnail::getDateTime () const
return dateTime;
}
-void Thumbnail::getAutoWB (double& temp, double& green, double equal, double tempBias)
+void Thumbnail::getAutoWB (double& temp, double& green, double equal, rtengine::StandardObserver observer, double tempBias)
{
if (cfs.redAWBMul != -1.0) {
- rtengine::ColorTemp ct(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul, equal);
+ rtengine::ColorTemp ct(cfs.redAWBMul, cfs.greenAWBMul, cfs.blueAWBMul, equal, observer);
temp = ct.getTemp();
green = ct.getGreen();
} else {
@@ -1155,10 +1155,10 @@ bool Thumbnail::imageLoad(bool loading)
return false;
}
-void Thumbnail::getCamWB(double& temp, double& green) const
+void Thumbnail::getCamWB(double& temp, double& green, rtengine::StandardObserver observer) const
{
if (tpp) {
- tpp->getCamWB (temp, green);
+ tpp->getCamWB (temp, green, observer);
} else {
temp = green = -1.0;
}
diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h
index 491151028..4d0355747 100644
--- a/rtgui/thumbnail.h
+++ b/rtgui/thumbnail.h
@@ -127,8 +127,8 @@ public:
const Glib::ustring& getExifString () const;
const Glib::ustring& getDateTimeString () const;
const Glib::DateTime& getDateTime () const;
- void getCamWB (double& temp, double& green) const;
- void getAutoWB (double& temp, double& green, double equal, double tempBias);
+ void getCamWB (double& temp, double& green, rtengine::StandardObserver observer) const;
+ void getAutoWB (double& temp, double& green, double equal, rtengine::StandardObserver observer, double tempBias);
void getSpotWB (int x, int y, int rect, double& temp, double& green);
void applyAutoExp (rtengine::procparams::ProcParams& pparams);
diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h
index 276d9654e..7542343eb 100644
--- a/rtgui/toolpanelcoord.h
+++ b/rtgui/toolpanelcoord.h
@@ -398,16 +398,16 @@ public:
void updateShowtooltipVisibility (bool showtooltip);
// wbprovider interface
- void getAutoWB (double& temp, double& green, double equal, double tempBias) override
+ void getAutoWB (double& temp, double& green, double equal, rtengine::StandardObserver observer, double tempBias) override
{
if (ipc) {
- ipc->getAutoWB(temp, green, equal, tempBias);
+ ipc->getAutoWB(temp, green, equal, observer, tempBias);
}
}
- void getCamWB (double& temp, double& green) override
+ void getCamWB (double& temp, double& green, rtengine::StandardObserver observer) override
{
if (ipc) {
- ipc->getCamWB(temp, green);
+ ipc->getCamWB(temp, green, observer);
}
}
diff --git a/rtgui/wbprovider.h b/rtgui/wbprovider.h
index a56d93cd3..514a71300 100644
--- a/rtgui/wbprovider.h
+++ b/rtgui/wbprovider.h
@@ -18,12 +18,19 @@
*/
#pragma once
+namespace rtengine
+{
+
+enum class StandardObserver;
+
+}
+
class WBProvider
{
public:
virtual ~WBProvider() {}
- virtual void getAutoWB (double& temp, double& green, double equal, double tempBias) {}
- virtual void getCamWB (double& temp, double& green) {}
+ virtual void getAutoWB (double& temp, double& green, double equal, rtengine::StandardObserver observer, double tempBias) {}
+ virtual void getCamWB (double& temp, double& green, rtengine::StandardObserver observer) {}
virtual void spotWBRequested (int size) {}
};
diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc
index f6a26e335..761f2402a 100644
--- a/rtgui/whitebalance.cc
+++ b/rtgui/whitebalance.cc
@@ -22,6 +22,9 @@
#include "rtimage.h"
#include "options.h"
+#include "eventmapper.h"
+
+#include "../rtengine/colortemp.h"
#define MINTEMP 1500 //1200
#define MAXTEMP 60000 //12000
@@ -242,6 +245,10 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, TOOL_NAME, M("TP_WBALANC
custom_equal = 1.0;
}
+ auto m = ProcEventMapper::getInstance();
+ EvWBObserver10 = m->newEvent(ALLNORAW, "HISTORY_MSG_WBALANCE_OBSERVER10");
+
+
//Add the model columns to the Combo (which is a kind of view),
//rendering them in the default way:
method->pack_start(methodColumns.colIcon, false);
@@ -336,26 +343,35 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, TOOL_NAME, M("TP_WBALANC
StudLabel = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER));
StudLabel->set_tooltip_text(M("TP_WBALANCE_STUDLABEL_TOOLTIP"));
+ mulLabel = Gtk::manage(new Gtk::Label("---", Gtk::ALIGN_CENTER));
+ mulLabel->set_tooltip_text(M("TP_WBALANCE_MULLABEL_TOOLTIP"));
+ mulLabel->show();
+
temp = Gtk::manage (new Adjuster (M("TP_WBALANCE_TEMPERATURE"), MINTEMP, MAXTEMP, 5, CENTERTEMP, itempL, itempR, &wbSlider2Temp, &wbTemp2Slider));
green = Gtk::manage (new Adjuster (M("TP_WBALANCE_GREEN"), MINGREEN, MAXGREEN, 0.001, 1.0, igreenL, igreenR));
equal = Gtk::manage (new Adjuster (M("TP_WBALANCE_EQBLUERED"), MINEQUAL, MAXEQUAL, 0.001, 1.0, iblueredL, iblueredR));
tempBias = Gtk::manage (new Adjuster(M("TP_WBALANCE_TEMPBIAS"), -0.5, 0.5, 0.01, 0.0, itempbiasL, itempbiasR));
+ observer10 = Gtk::manage(new CheckBox(M("TP_WBALANCE_OBSERVER10"), multiImage));
+
cache_customTemp (0);
cache_customGreen (0);
cache_customEqual (0);
equal->set_tooltip_markup (M("TP_WBALANCE_EQBLUERED_TOOLTIP"));
tempBias->set_tooltip_markup (M("TP_WBALANCE_TEMPBIAS_TOOLTIP"));
+ observer10->set_tooltip_text(M("TP_WBALANCE_OBSERVER10_TOOLTIP"));
temp->show ();
green->show ();
equal->show ();
tempBias->show ();
-
+ observer10->show();
+
/* Gtk::Box* boxgreen = Gtk::manage (new Gtk::Box ());
boxgreen->show ();
boxgreen->pack_start(*igreenL);
boxgreen->pack_start(*green);
boxgreen->pack_start(*igreenR);*/
+ pack_start(*mulLabel);
pack_start(*StudLabel);
pack_start (*temp);
@@ -363,11 +379,14 @@ WhiteBalance::WhiteBalance () : FoldableToolPanel(this, TOOL_NAME, M("TP_WBALANC
pack_start (*green);
pack_start (*equal);
pack_start (*tempBias);
+ pack_start(*observer10);
+
temp->setAdjusterListener (this);
green->setAdjusterListener (this);
equal->setAdjusterListener (this);
tempBias->setAdjusterListener (this);
+ observer10->setCheckBoxListener(this);
spotbutton->signal_pressed().connect( sigc::mem_fun(*this, &WhiteBalance::spotPressed) );
methconn = method->signal_changed().connect( sigc::mem_fun(*this, &WhiteBalance::optChanged) );
@@ -394,6 +413,8 @@ void WhiteBalance::enabledChanged()
}
+
+
void WhiteBalance::adjusterChanged(Adjuster* a, double newval)
{
int tVal = (int)temp->getValue();
@@ -456,6 +477,36 @@ void WhiteBalance::adjusterChanged(Adjuster* a, double newval)
}
}
+void WhiteBalance::checkBoxToggled(CheckBox* c, CheckValue newval)
+{
+ if (!(getEnabled() && listener)) {
+ return;
+ }
+
+ if (c == observer10) {
+ // If camera WB, update the temperature and tint according to observer.
+ const Gtk::TreeModel::Row row = getActiveMethod();
+ unsigned int methodId = findWBEntryId(row[methodColumns.colLabel], WBLT_GUI);
+ const WBEntry &currMethod = WBParams::getWbEntries()[methodId];
+ if (row[methodColumns.colLabel] != M("GENERAL_UNCHANGED") && currMethod.type == WBEntry::Type::CAMERA && wbp) {
+ double ctemp, cgreen;
+ wbp->getCamWB(ctemp, cgreen,
+ observer10->getValue() == CheckValue::off
+ ? rtengine::StandardObserver::TWO_DEGREES
+ : rtengine::StandardObserver::TEN_DEGREES);
+ temp->setValue(temp->getAddMode() ? 0.0 : static_cast(ctemp));
+ green->setValue(green->getAddMode() ? 0.0 : cgreen);
+ }
+
+ listener->panelChanged(
+ EvWBObserver10,
+ c->getValue() == CheckValue::on ? M("GENERAL_ENABLED")
+ : c->getValue() == CheckValue::off
+ ? M("GENERAL_DISABLED")
+ : M("GENERAL_UNCHANGED"));
+ }
+}
+
void WhiteBalance::optChanged ()
{
Gtk::TreeModel::Row row = getActiveMethod();
@@ -472,6 +523,7 @@ void WhiteBalance::optChanged ()
return;
}
StudLabel->hide();
+ mulLabel->show();
if (opt != row[methodColumns.colId]) {
@@ -482,6 +534,7 @@ void WhiteBalance::optChanged ()
green->setEditedState (UnEdited);
equal->setEditedState (UnEdited);
tempBias->setEditedState (UnEdited);
+ observer10->setEdited(false);
} else {
unsigned int methodId = findWBEntryId (row[methodColumns.colLabel], WBLT_GUI);
const WBEntry& currMethod = WBParams::getWbEntries()[methodId];
@@ -498,7 +551,10 @@ void WhiteBalance::optChanged ()
case WBEntry::Type::CAMERA:
if (wbp) {
double ctemp, cgreen;
- wbp->getCamWB (ctemp, cgreen);
+ wbp->getCamWB(ctemp, cgreen,
+ observer10->getValue() == CheckValue::off
+ ? rtengine::StandardObserver::TWO_DEGREES
+ : rtengine::StandardObserver::TEN_DEGREES);
temp->setValue (temp->getAddMode() ? 0.0 : (int)ctemp);
green->setValue (green->getAddMode() ? 0.0 : cgreen);
equal->setValue (equal->getAddMode() ? 0.0 : 1.0);
@@ -507,6 +563,7 @@ void WhiteBalance::optChanged ()
temp->setEditedState (UnEdited);
green->setEditedState (UnEdited);
equal->setEditedState (UnEdited);
+ observer10->setEdited(false);
}
}
@@ -517,7 +574,7 @@ void WhiteBalance::optChanged ()
if (batchMode) {
temp->setEditedState (UnEdited);
green->setEditedState (UnEdited);
- // equal remain as is
+ // equal and observer remain as is
}
// Recomputing AutoWB will happen in improccoordinator.cc
@@ -540,6 +597,7 @@ void WhiteBalance::optChanged ()
temp->setEditedState (Edited);
green->setEditedState (Edited);
equal->setEditedState (Edited);
+ observer10->setEdited(true);
}
break;
@@ -563,6 +621,7 @@ void WhiteBalance::optChanged ()
temp->setEditedState (Edited);
green->setEditedState (Edited);
equal->setEditedState (Edited);
+ observer10->setEdited(true);
}
break;
@@ -578,6 +637,7 @@ void WhiteBalance::optChanged ()
void WhiteBalance::spotPressed ()
{
StudLabel->hide();
+ mulLabel->show();
if (wblistener) {
wblistener->spotWBRequested (getSize());
@@ -599,6 +659,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited)
methconn.block (true);
equal->setValue (pp->wb.equal);
+ observer10->setValue(rtengine::StandardObserver::TEN_DEGREES == pp->wb.observer);
tempBias->setValue (pp->wb.tempBias);
tempBias->set_sensitive(true);
@@ -608,6 +669,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited)
green->setEditedState (UnEdited);
equal->setEditedState (pedited->wb.equal ? Edited : UnEdited);
tempBias->setEditedState (pedited->wb.tempBias ? Edited : UnEdited);
+ observer10->setEdited(pedited->wb.observer);
}
if (pedited && !pedited->wb.method) {
@@ -648,7 +710,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited)
if (wbp) {
double ctemp = -1.0;
double cgreen = -1.0;
- wbp->getCamWB (ctemp, cgreen);
+ wbp->getCamWB (ctemp, cgreen, pp->wb.observer);
if (ctemp != -1.0) {
// Set the camera's temperature value, or 0.0 if in ADD mode
@@ -720,6 +782,7 @@ void WhiteBalance::read (const ProcParams* pp, const ParamsEdited* pedited)
StudLabel->show();
} else {
StudLabel->hide();
+ mulLabel->show();
}
}
@@ -744,6 +807,7 @@ void WhiteBalance::write (ProcParams* pp, ParamsEdited* pedited)
pedited->wb.green = green->getEditedState ();
pedited->wb.equal = equal->getEditedState ();
pedited->wb.tempBias = tempBias->getEditedState ();
+ pedited->wb.observer = observer10->getEdited();
pedited->wb.method = row[methodColumns.colLabel] != M("GENERAL_UNCHANGED");
pedited->wb.enabled = !get_inconsistent();
}
@@ -759,6 +823,12 @@ void WhiteBalance::write (ProcParams* pp, ParamsEdited* pedited)
pp->wb.temperature = temp->getIntValue ();
pp->wb.green = green->getValue ();
pp->wb.equal = equal->getValue ();
+ pp->wb.observer =
+ observer10->getValue() == CheckValue::on
+ ? rtengine::StandardObserver::TEN_DEGREES
+ : observer10->getValue() == CheckValue::off
+ ? rtengine::StandardObserver::TWO_DEGREES
+ : pp->wb.observer;
pp->wb.tempBias = tempBias->getValue ();
}
@@ -771,7 +841,7 @@ void WhiteBalance::setDefaults (const ProcParams* defParams, const ParamsEdited*
if (wbp && defParams->wb.method == "Camera") {
double ctemp;
double cgreen;
- wbp->getCamWB (ctemp, cgreen);
+ wbp->getCamWB (ctemp, cgreen, defParams->wb.observer);
// FIXME: Seems to be always -1.0, called too early? Broken!
if (ctemp != -1.0) {
@@ -945,14 +1015,20 @@ inline Gtk::TreeRow WhiteBalance::getActiveMethod ()
return *(method->get_active());
}
-void WhiteBalance::WBChanged(double temperature, double greenVal, float studgood)
+void WhiteBalance::WBChanged(double temperature, double greenVal, double rw, double gw, double bw, float studgood)
{
idle_register.add(
- [this, temperature, greenVal, studgood]() -> bool
+ [this, temperature, greenVal, rw, gw, bw, studgood]() -> bool
{
disableListener();
temp->setValue(temperature);
green->setValue(greenVal);
+ mulLabel->set_text(
+ Glib::ustring::compose(M("TP_WBALANCE_MULLABEL"),
+ Glib::ustring::format(std::fixed, std::setprecision(4), rw),
+ Glib::ustring::format(std::fixed, std::setprecision(2), gw),
+ Glib::ustring::format(std::fixed, std::setprecision(4), bw))
+ );
StudLabel->set_text(
Glib::ustring::compose(M("TP_WBALANCE_STUDLABEL"),
Glib::ustring::format(std::fixed, std::setprecision(4), studgood))
diff --git a/rtgui/whitebalance.h b/rtgui/whitebalance.h
index f172590c8..56d8b646c 100644
--- a/rtgui/whitebalance.h
+++ b/rtgui/whitebalance.h
@@ -21,6 +21,7 @@
#include
#include "adjuster.h"
+#include "checkbox.h"
#include "guiutils.h"
#include "toolpanel.h"
#include "wbprovider.h"
@@ -35,7 +36,7 @@ public:
virtual void spotWBRequested(int size) = 0;
};
-class WhiteBalance final : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoWBListener
+class WhiteBalance final : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, public FoldableToolPanel, public rtengine::AutoWBListener
{
enum WB_LabelType {
@@ -45,6 +46,7 @@ class WhiteBalance final : public ToolParamBlock, public AdjusterListener, publi
private:
Gtk::Label* StudLabel;
+ Gtk::Label* mulLabel;
protected:
class MethodColumns : public Gtk::TreeModel::ColumnRecord
@@ -60,6 +62,8 @@ protected:
add(colId);
}
};
+
+ rtengine::ProcEvent EvWBObserver10;
static Glib::RefPtr wbPixbufs[rtengine::toUnderlying(rtengine::procparams::WBEntry::Type::CUSTOM) + 1];
Glib::RefPtr refTreeModel;
@@ -71,6 +75,7 @@ protected:
Adjuster* green;
Adjuster* equal;
Adjuster* tempBias;
+ CheckBox* observer10;
Gtk::Button* spotbutton;
int opt;
@@ -114,6 +119,7 @@ public:
void spotPressed ();
void spotSizeChanged ();
void adjusterChanged(Adjuster* a, double newval) override;
+ void checkBoxToggled(CheckBox* c, CheckValue newval) override;
int getSize ();
void setWBProvider (WBProvider* p)
{
@@ -125,7 +131,7 @@ public:
}
void setWB (int temp, double green);
void resetWB ();
- void WBChanged (double temp, double green, float studgood) override;
+ void WBChanged (double temp, double green, double rw, double gw, double bw, float studgood) override;
void setAdjusterBehavior (bool tempadd, bool greenadd, bool equaladd, bool tempbiasadd);
void trimValues (rtengine::procparams::ProcParams* pp) override;