diff --git a/rtdata/languages/default b/rtdata/languages/default
index 68fda352b..84b28c955 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -1417,6 +1417,7 @@ HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values
HISTORY_MSG_GAMUTMUNSEL;Gamut-Munsell
HISTORY_MSG_HISTMATCHING;Auto-matched tone curve
HISTORY_MSG_HLBL;Color propagation - blur
+HISTORY_MSG_HLTH;Inpaint opposed - gain threshold
HISTORY_MSG_ICL_LABGRIDCIEXY;Cie xy
HISTORY_MSG_ICM_AINTENT;Abstract profile intent
HISTORY_MSG_ICM_BLUX;Primaries Blue X
@@ -2518,8 +2519,10 @@ TP_GRADIENT_STRENGTH_TOOLTIP;Filter strength in stops.
TP_HLREC_BLEND;Blend
TP_HLREC_CIELAB;CIELab Blending
TP_HLREC_COLOR;Color Propagation
+TP_HLREC_COLOROPP;Inpaint Opposed
TP_HLREC_ENA_TOOLTIP;Could be activated by Auto Levels.
TP_HLREC_HLBLUR;Blur
+TP_HLREC_HLTH;Gain threshold
TP_HLREC_LABEL;Highlight reconstruction
TP_HLREC_LUMINANCE;Luminance Recovery
TP_HLREC_METHOD;Method:
diff --git a/rtdata/profiles/Auto-Matched Curve - ISO High.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO High.pp3
index 99f0af8fe..16c9a71f5 100644
--- a/rtdata/profiles/Auto-Matched Curve - ISO High.pp3
+++ b/rtdata/profiles/Auto-Matched Curve - ISO High.pp3
@@ -4,7 +4,7 @@ HistogramMatching=true
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Directional Pyramid Denoising]
Enabled=true
diff --git a/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3
index c94077b21..e6c7fb96c 100644
--- a/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3
+++ b/rtdata/profiles/Auto-Matched Curve - ISO Low.pp3
@@ -4,7 +4,7 @@ HistogramMatching=true
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[LensProfile]
LcMode=lfauto
diff --git a/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3 b/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3
index f9196bb30..ffb5587b9 100644
--- a/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3
+++ b/rtdata/profiles/Auto-Matched Curve - ISO Medium.pp3
@@ -4,7 +4,7 @@ HistogramMatching=true
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Directional Pyramid Denoising]
Enabled=true
diff --git a/rtdata/profiles/Film Negative - Black and White.pp3 b/rtdata/profiles/Film Negative - Black and White.pp3
index ad2a38e1e..3bebe7e3c 100644
--- a/rtdata/profiles/Film Negative - Black and White.pp3
+++ b/rtdata/profiles/Film Negative - Black and White.pp3
@@ -11,7 +11,7 @@ Curve2=1;0;0;0.0397505754145333;0.020171771436200074;0.54669745433149319;0.69419
[HLRecovery]
Enabled=false
-Method=Blend
+Method=Coloropp
[Black & White]
Enabled=true
diff --git a/rtdata/profiles/Film Negative.pp3 b/rtdata/profiles/Film Negative.pp3
index 0ecac1d33..e76c61866 100644
--- a/rtdata/profiles/Film Negative.pp3
+++ b/rtdata/profiles/Film Negative.pp3
@@ -11,7 +11,7 @@ Curve2=1;0;0;0.0397505754145333;0.020171771436200074;0.54669745433149319;0.69419
[HLRecovery]
Enabled=false
-Method=Blend
+Method=Coloropp
[Crop]
FixedRatio=false
diff --git a/rtdata/profiles/Pop/Pop 1.pp3 b/rtdata/profiles/Pop/Pop 1.pp3
index 2152a268b..cbdf4ab5b 100644
--- a/rtdata/profiles/Pop/Pop 1.pp3
+++ b/rtdata/profiles/Pop/Pop 1.pp3
@@ -19,7 +19,7 @@ Curve2=0;
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Luminance Curve]
Enabled=true
diff --git a/rtdata/profiles/Pop/Pop 2 Lab.pp3 b/rtdata/profiles/Pop/Pop 2 Lab.pp3
index 796aeb5ba..f4c01fd1b 100644
--- a/rtdata/profiles/Pop/Pop 2 Lab.pp3
+++ b/rtdata/profiles/Pop/Pop 2 Lab.pp3
@@ -19,7 +19,7 @@ Curve2=0;
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Luminance Curve]
Enabled=true
diff --git a/rtdata/profiles/Pop/Pop 3 Skin.pp3 b/rtdata/profiles/Pop/Pop 3 Skin.pp3
index 650b2e189..ebce37b58 100644
--- a/rtdata/profiles/Pop/Pop 3 Skin.pp3
+++ b/rtdata/profiles/Pop/Pop 3 Skin.pp3
@@ -19,7 +19,7 @@ Curve2=0;
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Luminance Curve]
Enabled=true
diff --git a/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3 b/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3
index 9faa32a0a..1e3527ceb 100644
--- a/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3
+++ b/rtdata/profiles/Pop/Pop 4 Black-and-White.pp3
@@ -19,7 +19,7 @@ Curve2=0;
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Black & White]
Enabled=true
diff --git a/rtdata/profiles/Standard Film Curve - ISO High.pp3 b/rtdata/profiles/Standard Film Curve - ISO High.pp3
index 4dd3a9b1d..42bbed6d3 100644
--- a/rtdata/profiles/Standard Film Curve - ISO High.pp3
+++ b/rtdata/profiles/Standard Film Curve - ISO High.pp3
@@ -6,7 +6,7 @@ Curve=1;0;0;0.11;0.089999999999999997;0.32000000000000001;0.42999999999999999;0.
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Directional Pyramid Denoising]
Enabled=true
diff --git a/rtdata/profiles/Standard Film Curve - ISO Low.pp3 b/rtdata/profiles/Standard Film Curve - ISO Low.pp3
index 45fcca730..342b1c8d3 100644
--- a/rtdata/profiles/Standard Film Curve - ISO Low.pp3
+++ b/rtdata/profiles/Standard Film Curve - ISO Low.pp3
@@ -6,7 +6,7 @@ Curve=1;0;0;0.11;0.089999999999999997;0.32000000000000001;0.42999999999999999;0.
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[LensProfile]
LcMode=lfauto
diff --git a/rtdata/profiles/Standard Film Curve - ISO Medium.pp3 b/rtdata/profiles/Standard Film Curve - ISO Medium.pp3
index 4aff630f5..f3b292094 100644
--- a/rtdata/profiles/Standard Film Curve - ISO Medium.pp3
+++ b/rtdata/profiles/Standard Film Curve - ISO Medium.pp3
@@ -6,7 +6,7 @@ Curve=1;0;0;0.11;0.089999999999999997;0.32000000000000001;0.42999999999999999;0.
[HLRecovery]
Enabled=true
-Method=Blend
+Method=Coloropp
[Directional Pyramid Denoising]
Enabled=true
diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc
index e3bd9c988..4c70ad951 100644
--- a/rtengine/clutstore.cc
+++ b/rtengine/clutstore.cc
@@ -57,7 +57,7 @@ bool loadFile(
rtengine::procparams::ColorManagementParams icm;
icm.workingProfile = working_color_space;
- img_src.getImage(curr_wb, TR_NONE, img_float.get(), pp, rtengine::procparams::ToneCurveParams(), rtengine::procparams::RAWParams());
+ img_src.getImage(curr_wb, TR_NONE, img_float.get(), pp, rtengine::procparams::ToneCurveParams(), rtengine::procparams::RAWParams(), 0);
if (!working_color_space.empty()) {
img_src.convertColorSpace(img_float.get(), icm, curr_wb);
diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc
index a4dd8a4d1..4ba47b25a 100644
--- a/rtengine/colortemp.cc
+++ b/rtengine/colortemp.cc
@@ -33,7 +33,7 @@
namespace rtengine
{
-static double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer.
+static const color_match_type cie_colour_match_jd2 = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer.
{0.0000000, 0.000000, 0.000000}, {0.0000000, 0.000000, 0.000000}, {0.0001299, 0.0003917, 0.0006061},
{0.0002321, 0.000006965, 0.001086}, {0.0004149, 0.00001239, 0.001946}, {0.0007416, 0.00002202, 0.003846},
{0.001368, 0.000039, 0.006450001}, {0.002236, 0.000064, 0.01054999}, {0.004243, 0.000120, 0.02005001},
@@ -70,7 +70,7 @@ static double cie_colour_match_jd2[97][3] = {//350nm to 830nm 5 nm J.Desmis 2
};
-static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer.
+static const color_match_type cie_colour_match_jd = {//350nm to 830nm 5 nm J.Desmis 10° Standard Observer.
{0.000000000000, 0.000000000000, 0.000000000000},
{0.000000000000, 0.000000000000, 0.000000000000},
{0.000000122200, 0.000000013398, 0.000000535027},
@@ -2963,15 +2963,16 @@ void ColorTemp::temp2mulxyz (double temp, const std::string &method, double &Xxy
// 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;
if (iterator != spectMap.end()) {
- spectrum_to_xyz_preset(iterator->second, x, y, z);
+ spectrum_to_xyz_preset(iterator->second, x, y, z, color_match);
} else {
// otherwise we use the Temp+Green generic solution
if (temp <= INITIALBLACKBODY) {
// if temperature is between 2000K and 4000K we use blackbody, because there will be no Daylight reference below 4000K...
// of course, the previous version of RT used the "magical" but wrong formula of U.Fuchs (Ufraw).
- spectrum_to_xyz_blackbody(temp, x, y, z);
+ spectrum_to_xyz_blackbody(temp, x, y, z, color_match);
} else {
// from 4000K up to 25000K: using the D illuminant (daylight) which is standard
double x_D, y_D;
@@ -2990,7 +2991,7 @@ void ColorTemp::temp2mulxyz (double temp, const std::string &method, double &Xxy
double interm = 0.0241 + 0.2562 * x_D - 0.734 * y_D;
double m1 = (-1.3515 - 1.7703 * x_D + 5.9114 * y_D) / interm;
double m2 = (0.03 - 31.4424 * x_D + 30.0717 * y_D) / interm;
- spectrum_to_xyz_daylight(m1, m2, x, y, z);
+ spectrum_to_xyz_daylight(m1, m2, x, y, z, color_match);
}
}
@@ -3169,17 +3170,19 @@ 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;
+
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]);
+ spectrum_to_color_xyz_preset(spec_color[i], spect_illum[illum + 3], XchkLamp[i], YchkLamp[i], ZchkLamp[i], color_match);
}
//calculate XYZ for each color : for Blackbody and Daylight at tempw
if(tempw <= INITIALBLACKBODY) {
for(int i = 0; i < N_c; i++) {
- spectrum_to_color_xyz_blackbody(spec_color[i], tempw, Xchk[i], Ychk[i], Zchk[i]);
+ spectrum_to_color_xyz_blackbody(spec_color[i], tempw, Xchk[i], Ychk[i], Zchk[i], color_match);
}
- spectrum_to_xyz_blackbody(tempw, x, y, z);//for white point
+ spectrum_to_xyz_blackbody(tempw, x, y, z, color_match);//for white point
} else { // after 6600K (arbitrary) I use daylight...because ...but there is no lamp...
double m11, m22, x_DD, y_DD, interm2;
@@ -3197,10 +3200,10 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul,
m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2;
for(int i = 0; i < N_c; i++) {
- spectrum_to_color_xyz_daylight(spec_color[i], m11, m22, Xchk[i], Ychk[i], Zchk[i]);
+ spectrum_to_color_xyz_daylight(spec_color[i], m11, m22, Xchk[i], Ychk[i], Zchk[i], color_match);
}
- spectrum_to_xyz_daylight(m11, m22, x, y, z);
+ spectrum_to_xyz_daylight(m11, m22, x, y, z, color_match);
}
if (settings->verbose) {
@@ -3394,16 +3397,16 @@ I have increase precision used by J.Walker and pass to 350nm to 830nm
And also add 10° standard observer
*/
-void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, double &y, double &z)
+void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, double &y, double &z, const color_match_type &color_match)
{
int i;
double lambda, X = 0, Y = 0, Z = 0, XYZ;
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = daylight_spect(lambda, _m1, _m2);
- X += Me * cie_colour_match_jd2[i][0];
- Y += Me * cie_colour_match_jd2[i][1];
- Z += Me * cie_colour_match_jd2[i][2];
+ X += Me * color_match[i][0];
+ Y += Me * color_match[i][1];
+ Z += Me * color_match[i][2];
}
XYZ = (X + Y + Z);
@@ -3412,16 +3415,16 @@ void ColorTemp::spectrum_to_xyz_daylight(double _m1, double _m2, double &x, doub
z = Z / XYZ;
}
-void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, double &z)
+void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, double &z, const color_match_type &color_match)
{
int i;
double lambda, X = 0, Y = 0, Z = 0, XYZ;
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = blackbody_spect(lambda, _temp);
- X += Me * cie_colour_match_jd2[i][0];
- Y += Me * cie_colour_match_jd2[i][1];
- Z += Me * cie_colour_match_jd2[i][2];
+ X += Me * color_match[i][0];
+ Y += Me * color_match[i][1];
+ Z += Me * color_match[i][2];
}
XYZ = (X + Y + Z);
@@ -3430,7 +3433,7 @@ void ColorTemp::spectrum_to_xyz_blackbody(double _temp, double &x, double &y, do
z = Z / XYZ;
}
-void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, double &y, double &z)
+void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, double &y, double &z, const color_match_type &color_match)
{
int i;
double lambda, X = 0, Y = 0, Z = 0, XYZ;
@@ -3454,9 +3457,9 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou
*/
for (i = 0, lambda = 350.; lambda < 830.1; i++, lambda += 5.) {
double Me = get_spectral_color(lambda, spec_intens);
- X += Me * cie_colour_match_jd2[i][0];
- Y += Me * cie_colour_match_jd2[i][1];
- Z += Me * cie_colour_match_jd2[i][2];
+ X += Me * color_match[i][0];
+ Y += Me * color_match[i][1];
+ Z += Me * color_match[i][2];
}
XYZ = (X + Y + Z);
@@ -3466,7 +3469,7 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou
}
//calculate XYZ from spectrum data (color) and illuminant : J.Desmis December 2011
-void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz)
+void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz, const color_match_type &color_match)
{
int i;
double lambda, X = 0, Y = 0, Z = 0, Yo = 0;
@@ -3478,9 +3481,9 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou
Me = get_spectral_color(lambda, spec_color);
Mc = get_spectral_color(lambda, spec_intens);
- X += Mc * cie_colour_match_jd2[i][0] * Me;
- Y += Mc * cie_colour_match_jd2[i][1] * Me;
- Z += Mc * cie_colour_match_jd2[i][2] * Me;
+ X += Mc * color_match[i][0] * Me;
+ Y += Mc * color_match[i][1] * Me;
+ Z += Mc * color_match[i][2] * Me;
}
for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) {
@@ -3488,7 +3491,7 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou
double Ms;
Ms = get_spectral_color(lambda, spec_intens);
- Yo += cie_colour_match_jd2[i][1] * Ms;
+ Yo += color_match[i][1] * Ms;
}
xx = X / Yo;
@@ -3497,7 +3500,7 @@ void ColorTemp::spectrum_to_color_xyz_preset(const double* spec_color, const dou
}
//calculate XYZ from spectrum data (color) and illuminant : J.Desmis december 2011
-void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz)
+void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz, const color_match_type &color_match)
{
int i;
double lambda, X = 0, Y = 0, Z = 0;
@@ -3505,9 +3508,9 @@ void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double
for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) {
const double Me = spec_color[i];
const double Mc = daylight_spect(lambda, _m1, _m2);
- X += Mc * cie_colour_match_jd2[i][0] * Me;
- Y += Mc * cie_colour_match_jd2[i][1] * Me;
- Z += Mc * cie_colour_match_jd2[i][2] * Me;
+ X += Mc * color_match[i][0] * Me;
+ Y += Mc * color_match[i][1] * Me;
+ Z += Mc * color_match[i][2] * Me;
}
xx = X / Y;
@@ -3516,7 +3519,7 @@ void ColorTemp::spectrum_to_color_xyz_daylight(const double* spec_color, double
}
//calculate XYZ from spectrum data (color) and illuminant : J.Desmis december 2011
-void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double _temp, double &xx, double &yy, double &zz)
+void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double _temp, double &xx, double &yy, double &zz, const color_match_type &color_match)
{
int i;
double lambda, X = 0, Y = 0, Z = 0;
@@ -3524,9 +3527,9 @@ void ColorTemp::spectrum_to_color_xyz_blackbody(const double* spec_color, double
for (i = 0, lambda = 350; lambda < 830.1; i++, lambda += 5) {
const double Me = spec_color[i];
const double Mc = blackbody_spect(lambda, _temp);
- X += Mc * cie_colour_match_jd2[i][0] * Me;
- Y += Mc * cie_colour_match_jd2[i][1] * Me;
- Z += Mc * cie_colour_match_jd2[i][2] * Me;
+ X += Mc * color_match[i][0] * Me;
+ Y += Mc * color_match[i][1] * Me;
+ Z += Mc * color_match[i][2] * Me;
}
xx = X / Y;
@@ -3762,27 +3765,21 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
}
if (settings->verbose) {
- if (settings->itcwb_stdobserver10 == false) {
+ 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");
}
}
- if (settings->itcwb_stdobserver10 == true) {
- for (int i = 0; i < 97; i++) {
- cie_colour_match_jd2[i][0] = cie_colour_match_jd[i][0];
- cie_colour_match_jd2[i][1] = cie_colour_match_jd[i][1];;
- cie_colour_match_jd2[i][2] = cie_colour_match_jd[i][2];
- }
- }
+ const color_match_type &color_match = (settings->itcwb_stdobserver10 == true) ? cie_colour_match_jd : cie_colour_match_jd2;
if (separated) {
const double tempw = Txyz[repref].Tem;
if (tempw <= INITIALBLACKBODY) {
for (int i = 0; i < N_c; i++) {
- spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, TX[i], TY[i], TZ[i]);
+ spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, TX[i], TY[i], TZ[i], color_match);
}
} else {
double m11, m22, x_DD, y_DD, interm2;
@@ -3801,7 +3798,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2;
for (int i = 0; i < N_c; i++) {
- spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, TX[i], TY[i], TZ[i]);
+ spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, TX[i], TY[i], TZ[i], color_match);
}
}
} else {
@@ -3810,7 +3807,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
if (tempw <= INITIALBLACKBODY) {
for (int i = 0; i < N_c; i++) {
- spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref);
+ spectrum_to_color_xyz_blackbody(spec_colorforxcyc[i], tempw, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref, color_match);
}
} else {
double x_DD;
@@ -3829,7 +3826,7 @@ void ColorTemp::tempxy(bool separated, int repref, float **Tx, float **Ty, float
const double m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2;
for (int i = 0; i < N_c; i++) {
- spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref);
+ spectrum_to_color_xyz_daylight(spec_colorforxcyc[i], m11, m22, Refxyz[i].Xref, Refxyz[i].Yref, Refxyz[i].Zref, color_match);
}
}
diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h
index 89c324490..78091f51d 100644
--- a/rtengine/colortemp.h
+++ b/rtengine/colortemp.h
@@ -26,6 +26,8 @@
namespace rtengine
{
+using color_match_type = double [97][3];
+
constexpr double MINTEMP = 1500.0;
constexpr double MAXTEMP = 60000.0;
constexpr double MINGREEN = 0.02;
@@ -375,13 +377,13 @@ public:
static const double JDC468_greym13_325_spect[97];
static const double JDC468_greyf26_156_spect[97];
*/
- static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z);
- static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z);
- static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z);
+ static void spectrum_to_xyz_daylight (double _m1, double _m2, double &x, double &y, double &z, const color_match_type &color_match);
+ static void spectrum_to_xyz_blackbody (double _temp, double &x, double &y, double &z, const color_match_type &color_match);
+ static void spectrum_to_xyz_preset (const double* spec_intens, double &x, double &y, double &z, const color_match_type &color_match);
- static void spectrum_to_color_xyz_daylight (const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz);
- static void spectrum_to_color_xyz_blackbody (const double* spec_color, double _temp, double &xx, double &yy, double &zz);
- static void spectrum_to_color_xyz_preset (const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz);
+ static void spectrum_to_color_xyz_daylight (const double* spec_color, double _m1, double _m2, double &xx, double &yy, double &zz, const color_match_type &color_match);
+ static void spectrum_to_color_xyz_blackbody (const double* spec_color, double _temp, double &xx, double &yy, double &zz, const color_match_type &color_match);
+ static void spectrum_to_color_xyz_preset (const double* spec_color, const double* spec_intens, double &xx, double &yy, double &zz, const color_match_type &color_match);
};
}
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index f4ac49fc4..8ddaa5f75 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -228,18 +228,18 @@ void Crop::update(int todo)
if (settings->leveldnautsimpl == 1) {
if (params.dirpyrDenoise.Cmethod == "MAN" || params.dirpyrDenoise.Cmethod == "PON") {
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
- parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
+ parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
}
} else {
if (params.dirpyrDenoise.C2method == "MANU") {
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
- parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
+ parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
}
}
if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PRE") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "PREV")) {
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
- parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
+ parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
if ((!isDetailWindow) && parent->adnListener && skip == 1 && params.dirpyrDenoise.enabled) {
float lowdenoise = 1.f;
@@ -451,7 +451,7 @@ void Crop::update(int todo)
for (int wcr = 0; wcr <= 2; wcr++) {
for (int hcr = 0; hcr <= 2; hcr++) {
PreviewProps ppP(coordW[wcr], coordH[hcr], crW, crH, 1);
- parent->imgsrc->getImage(parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.raw);
+ parent->imgsrc->getImage(parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0);
// we only need image reduced to 1/4 here
for (int ii = 0; ii < crH; ii += 2) {
@@ -613,7 +613,7 @@ void Crop::update(int todo)
// if (params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
- parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
+ parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
}
if ((todo & M_SPOT) && params.spot.enabled && !params.spot.entries.empty()) {
@@ -749,7 +749,7 @@ void Crop::update(int todo)
fattalCrop.reset(f);
PreviewProps pp(0, 0, parent->fw, parent->fh, skip);
int tr = getCoarseBitMask(params.coarse);
- parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw);
+ parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw, 0);
parent->imgsrc->convertColorSpace(f, params.icm, parent->currWB);
if (params.dirpyrDenoise.enabled || params.filmNegative.enabled || params.spot.enabled) {
diff --git a/rtengine/filmnegativeproc.cc b/rtengine/filmnegativeproc.cc
index ae1813db9..c33dc4a9a 100644
--- a/rtengine/filmnegativeproc.cc
+++ b/rtengine/filmnegativeproc.cc
@@ -84,7 +84,7 @@ void getSpotAvgMax(ImageSource *imgsrc, ColorTemp currWB, const std::unique_ptr<
}
rtengine::Imagefloat spotImg(spotSize, spotSize);
- imgsrc->getImage(currWB, tr, &spotImg, pp, params->toneCurve, params->raw);
+ imgsrc->getImage(currWB, tr, &spotImg, pp, params->toneCurve, params->raw, 0);
auto avgMax = [spotSize, &spotImg](RGB & avg, RGB & max) -> void {
avg = {};
diff --git a/rtengine/hilite_recon.cc b/rtengine/hilite_recon.cc
index a45e5d345..07d1a7b7b 100644
--- a/rtengine/hilite_recon.cc
+++ b/rtengine/hilite_recon.cc
@@ -32,14 +32,15 @@
#include "opthelper.h"
#include "rawimagesource.h"
#include "rt_math.h"
-//#define BENCHMARK
-//#include "StopWatch.h"
+#define BENCHMARK
+#include "StopWatch.h"
#include "guidedfilter.h"
#include "settings.h"
#include "gauss.h"
#include "rescale.h"
#include "iccstore.h"
#include "color.h"
+#include "linalgebra.h"
namespace
{
@@ -301,7 +302,7 @@ using namespace procparams;
void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue, int blur)
{
- // BENCHFUN
+ BENCHFUN
double progress = 0.0;
if (plistener) {
@@ -1226,5 +1227,371 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
}// end of HLReconstruction
+
+//-----------------------------------------------------------------------------
+// "inpaint opposed" algorithm taken from darktable
+//
+// (Very effective, very simple, very neat)
+//
+// Kudos to the original authors (@jenshannoschwalm from dt, in collaboration
+// with @garagecoder and @Iain from gmic).
+//
+// Copyright and description of the original code follows
+//
+/*
+ Copyright (C) 2022 darktable developers.
+
+ darktable is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ darktable is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with darktable. If not, see .
+*/
+
+/* The refavg values are calculated in raw-RGB-cube3 space
+ We calculate all color channels in the 3x3 photosite area, this can be understaood as a "superpixel",
+ the "asking" location is in the centre.
+ As this works for bayer and xtrans sensors we don't have a fixed ratio but calculate the average
+ for every color channel first.
+ refavg for one of red, green or blue is defined as means of both other color channels (opposing).
+
+ The basic idea / observation for the _process_opposed algorithm is, the refavg is a good estimate
+ for any clipped color channel in the vast majority of images, working mostly fine both for small specular
+ highlighted spots and large areas.
+
+ The correction via some sort of global chrominance further helps to correct color casts.
+ The chrominace data are taken from the areas morphologically very close to clipped data.
+ Failures of the algorithm (color casts) are in most cases related to
+ a) very large differences between optimal white balance coefficients vs what we have as D65 in the darktable pipeline
+ b) complicated lightings so the gradients are not well related
+ c) a wrong whitepoint setting in the rawprepare module.
+ d) the maths might not be best
+*/
+//-----------------------------------------------------------------------------
+
+namespace {
+
+constexpr int HL_BORDER = 8;
+constexpr float HL_POWERF = 3.0f;
+
+// void border_fill_zero(int *d, int width, int height)
+// {
+// for (int i = 0; i < HL_BORDER * width; i++) {
+// d[i] = 0;
+// }
+// for (int i = (height - HL_BORDER - 1) * width; i < width*height; i++) {
+// d[i] = 0;
+// }
+// for (int row = HL_BORDER; row < height - HL_BORDER; row++) {
+// int *p1 = d + row*width;
+// int *p2 = d + (row+1)*width - HL_BORDER;
+// for(int i = 0; i < HL_BORDER; i++) {
+// p1[i] = p2[i] = 0;
+// }
+// }
+// }
+
+
+int test_dilate(const int *img, int i, int w1)
+{
+ int retval = 0;
+ retval = img[i-w1-1] | img[i-w1] | img[i-w1+1] |
+ img[i-1] | img[i] | img[i+1] |
+ img[i+w1-1] | img[i+w1] | img[i+w1+1];
+ if (retval) {
+ return retval;
+ }
+
+ const size_t w2 = 2*w1;
+ retval = img[i-w2-1] | img[i-w2] | img[i-w2+1] |
+ img[i-w1-2] | img[i-w1+2] |
+ img[i-2] | img[i+2] |
+ img[i+w1-2] | img[i+w1+2] |
+ img[i+w2-1] | img[i+w2] | img[i+w2+1];
+ if (retval) {
+ return retval;
+ }
+
+ const size_t w3 = 3*w1;
+ retval = img[i-w3-2] | img[i-w3-1] | img[i-w3] | img[i-w3+1] | img[i-w3+2] |
+ img[i-w2-3] | img[i-w2-2] | img[i-w2+2] | img[i-w2+3] |
+ img[i-w1-3] | img[i-w1+3] |
+ img[i-3] | img[i+3] |
+ img[i+w1-3] | img[i+w1+3] |
+ img[i+w2-3] | img[i+w2-2] | img[i+w2+2] | img[i+w2+3] |
+ img[i+w3-2] | img[i+w3-1] | img[i+w3] | img[i+w3+1] | img[i+w3+2];
+ return retval;
+}
+
+
+void dilating(const int *img, int *o, int w1, int height)
+{
+#ifdef _OPENMP
+# pragma omp parallel for
+#endif
+ for (int row = HL_BORDER; row < height - HL_BORDER; row++) {
+ for (int col = HL_BORDER, i = row*w1 + col; col < w1 - HL_BORDER; col++, i++) {
+ o[i] = test_dilate(img, i, w1);
+ }
+ }
+}
+
+} // namespace
+
+void RawImageSource::highlight_recovery_opposed(float scale_mul[3], const ColorTemp &wb, float gainth)
+{
+ BENCHFUN
+
+ if (settings->verbose) {
+ std::cout << "Applying Highlight Recovery: Inpaint opposed" << std::endl;
+ }
+
+ if (plistener) {
+ plistener->setProgressStr("PROGRESSBAR_HLREC");
+ plistener->setProgress(0);
+ }
+
+ double rr, gg, bb;
+ wb.getMultipliers(rr, gg, bb);
+ wbMul2Camera(rr, gg, bb);
+
+ float gain = 1.2f * gainth;
+
+ float clipval = 0.987f / gain;
+ const float scalecoeffs[3] = {
+ scale_mul[0] * float(rr) / 65535.f,
+ scale_mul[1] * float(gg) / 65535.f,
+ scale_mul[2] * float(bb) / 65535.f,
+ };
+ const float clips[3] = {
+ clipval * float(rr),
+ clipval * float(gg),
+ clipval * float(bb)
+ };
+ const float clipdark[3] = {
+ 0.03f * clips[0],
+ 0.125f * clips[1],
+ 0.03f * clips[2]
+ };
+
+ bool anyclipped = false;
+ float **chan[3] = { red, green, blue };
+
+ const float clipscale[3] = {
+ clips[0] / scalecoeffs[0],
+ clips[1] / scalecoeffs[1],
+ clips[2] / scalecoeffs[2]
+ };
+
+ int x1 = W, y1 = H, x2 = 0, y2 = 0;
+ for (int y = 0; y < H; ++y) {
+ for (int x = 0; x < W; ++x) {
+ for (int c = 0; c < 3; ++c) {
+ if (chan[c][y][x] >= clipscale[c]) {
+ anyclipped = true;
+ x1 = std::min(x, x1);
+ x2 = std::max(x, x2);
+ y1 = std::min(y, y1);
+ y2 = std::max(y, y2);
+ }
+ }
+ }
+ }
+
+ if (!anyclipped) {
+ if (plistener) {
+ plistener->setProgress(1.0);
+ }
+ return;
+ }
+
+ x1 = std::max(x1-1, 0);
+ x2 = std::min(x2+1, W-1);
+ y1 = std::max(y1-1, 0);
+ y2 = std::min(y2+1, H-1);
+
+ const int cW = x2 - x1 + 1;
+ const int cH = y2 - y1 + 1;
+
+#ifdef _OPENMP
+# pragma omp parallel for
+#endif
+ for (int y = 0; y < cH; ++y) {
+ const int yy = y + y1;
+ for (int x = 0; x < cW; ++x) {
+ const int xx = x + x1;
+ for (int c = 0; c < 3; ++c) {
+ chan[c][yy][xx] *= scalecoeffs[c];
+ }
+ }
+ }
+
+ if (plistener) {
+ plistener->setProgress(0.1);
+ }
+
+ multi_array2D tmp(cW, cH);
+
+ const int pwidth = cW + 2 * HL_BORDER;
+ const int pheight = cH + 2 * HL_BORDER;
+ const int p_size = pwidth * pheight;
+ AlignedBuffer mask_vec(4 * p_size);
+ int *mask_buffer = mask_vec.data;
+
+ const auto mask_val =
+ [&](int c, int y, int x) -> int &
+ {
+ return mask_buffer[c * p_size + (HL_BORDER + y) * pwidth + x + HL_BORDER];
+ };
+
+ const auto set_refavg =
+ [&](int y, int x) -> bool
+ {
+ const int yy = y + y1;
+ const int xx = x + x1;
+ bool found = false;
+ for (int c = 0; c < 3 && !found; ++c) {
+ if (chan[c][yy][xx] >= clips[c]) {
+ found = true;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+
+ float mean[3] = { 0.0f, 0.0f, 0.0f };
+ for (int dy = -1; dy < 2; dy++) {
+ for (int dx = -1; dx < 2; dx++) {
+ for (int c = 0; c < 3; ++c) {
+ mean[c] += std::max(0.0f, chan[c][yy+dy][xx+dx]);
+ }
+ }
+ }
+ for (int c = 0; c < 3; ++c) {
+ mean[c] = pow_F(mean[c] / 9.0f, 1.0f / HL_POWERF);
+ }
+
+ const float croot_refavg[3] = {
+ 0.5f * (mean[1] + mean[2]),
+ 0.5f * (mean[0] + mean[2]),
+ 0.5f * (mean[0] + mean[1])
+ };
+
+ for (int c = 0; c < 3; ++c) {
+ if (chan[c][yy][xx] >= clips[c]) {
+ tmp[c][y][x] = pow_F(croot_refavg[c], HL_POWERF);
+ mask_val(c, y, x) = 1;
+ }
+ }
+ return true;
+ };
+
+#ifdef _OPENMP
+# pragma omp parallel for
+#endif
+ for (int y = 0; y < cH; ++y) {
+ const int yy = y + y1;
+ for (int x = 0; x < cW; ++x) {
+ const int xx = x + x1;
+ for (int c = 0; c < 3; ++c) {
+ tmp[c][y][x] = std::max(0.f, chan[c][yy][xx]);
+ }
+
+ if ((x > 0) && (x < cW - 1) && (y > 0) && (y < cH - 1)) {
+ set_refavg(y, x);
+ }
+ }
+ }
+
+ if (plistener) {
+ plistener->setProgress(0.3);
+ }
+
+ for (size_t i = 0; i < 3; i++) {
+ int *mask = mask_buffer + i * p_size;
+ int *tmp = mask_buffer + 3 * p_size;
+ //border_fill_zero(mask, pwidth, pheight);
+ dilating(mask, tmp, pwidth, pheight);
+ memcpy(mask, tmp, p_size * sizeof(int));
+ }
+
+ float cr_sum[3] = { 0.f, 0.f, 0.f };
+ int cr_cnt[3] = { 0, 0, 0 };
+
+#ifdef _OPENMP
+# pragma omp parallel for reduction(+ : cr_sum, cr_cnt)
+#endif
+ for (int y = 1; y < cH-1; ++y) {
+ const int yy = y + y1;
+ for (int x = 1; x < cW-1; ++x) {
+ const int xx = x + x1;
+ for (int c = 0; c < 3; ++c) {
+ const float inval = std::max(0.0f, chan[c][yy][xx]);
+ if (mask_val(c, y, x) && (inval > clipdark[c]) && (inval < clips[c])) {
+ cr_sum[c] += inval - tmp[c][y][x];
+ ++cr_cnt[c];
+ }
+ }
+ }
+ }
+
+ if (plistener) {
+ plistener->setProgress(0.6);
+ }
+
+ float chrominance[3] = {
+ cr_sum[0] / std::max(1.f, float(cr_cnt[0])),
+ cr_sum[1] / std::max(1.f, float(cr_cnt[1])),
+ cr_sum[2] / std::max(1.f, float(cr_cnt[2]))
+ };
+
+#ifdef _OPENMP
+# pragma omp parallel for
+#endif
+ for (int y = 0; y < cH; ++y) {
+ const int yy = y + y1;
+ for (int x = 0; x < cW; ++x) {
+ const int xx = x + x1;
+ for (int c = 0; c < 3; ++c) {
+ const float inval = std::max(0.0f, chan[c][yy][xx]);
+ if (inval >= clips[c]) {
+ chan[c][yy][xx] = std::max(inval, tmp[c][y][x] + chrominance[c]);
+ }
+ }
+ }
+ }
+
+ if (plistener) {
+ plistener->setProgress(0.9);
+ }
+
+#ifdef _OPENMP
+# pragma omp parallel for
+#endif
+ for (int y = 0; y < cH; ++y) {
+ const int yy = y + y1;
+ for (int x = 0; x < cW; ++x) {
+ const int xx = x + x1;
+ for (int c = 0; c < 3; ++c) {
+ chan[c][yy][xx] /= scalecoeffs[c];
+ }
+ }
+ }
+
+ if (plistener) {
+ plistener->setProgress(1.0);
+ }
+}
+
+
+
+
}
diff --git a/rtengine/iimage.h b/rtengine/iimage.h
index 2c75a0d59..a544b454a 100644
--- a/rtengine/iimage.h
+++ b/rtengine/iimage.h
@@ -111,7 +111,7 @@ public:
{
rm = gm = bm = 1.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)
+ 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)
{
rm = gm = bm = 1.0;
}
diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h
index a8ea8f851..d6d22c269 100644
--- a/rtengine/imagesource.h
+++ b/rtengine/imagesource.h
@@ -109,7 +109,7 @@ public:
virtual void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const = 0;
// use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat*
- virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw) = 0;
+ virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw, int opposed) = 0;
virtual eSensorType getSensorType () const = 0;
virtual bool isMono () const = 0;
// true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource
@@ -117,10 +117,10 @@ public:
virtual void convertColorSpace (Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) = 0; // DIRTY HACK: this method is derived in rawimagesource and strimagesource, but (...,RAWParams raw) will be used ONLY for raw images
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) = 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 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) = 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 double getDefGain () const
@@ -195,6 +195,9 @@ public:
}
virtual void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) = 0;
virtual void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) = 0;
+ virtual void wbMul2Camera(double &rm, double &gm, double &bm) = 0;
+ virtual void wbCamera2Mul(double &rm, double &gm, double &bm) = 0;
+
};
}
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index ec5ffc8ef..cc2d75b3d 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -1,6 +1,6 @@
/*
* This file is part of RawTherapee.
- *
+ *
* Copyright (c) 2004-2010 Gabor Horvath
*
* RawTherapee is free software: you can redistribute it and/or modify
@@ -409,11 +409,13 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if (imageTypeListener) {
imageTypeListener->imageTypeChanged(imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS, imgsrc->isMono(), imgsrc->isGainMapSupported());
}
-
+ bool iscolor = (params->toneCurve.method == "Color");// || params->toneCurve.method == "Coloropp");
if ((todo & M_RAW)
|| (!highDetailRawComputed && highDetailNeeded)
- || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified())
- || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) {
+ // || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified())
+ // || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) {
+ || (params->toneCurve.hrenabled && !iscolor && imgsrc->isRGBSourceModified())
+ || (!params->toneCurve.hrenabled && iscolor && imgsrc->isRGBSourceModified())) {
if (settings->verbose) {
if (imgsrc->getSensorType() == ST_BAYER) {
@@ -466,8 +468,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if ((todo & M_RAW)
|| (!highDetailRawComputed && highDetailNeeded)
- || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified())
- || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) {
+ // || (params->toneCurve.hrenabled && params->toneCurve.method != "Color" && imgsrc->isRGBSourceModified())
+ // || (!params->toneCurve.hrenabled && params->toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) {
+ || (params->toneCurve.hrenabled && !iscolor && imgsrc->isRGBSourceModified())
+ || (!params->toneCurve.hrenabled && iscolor && imgsrc->isRGBSourceModified())) {
if (highDetailNeeded) {
highDetailRawComputed = true;
} else {
@@ -510,8 +514,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
if (todo & (M_INIT | M_LINDENOISE | M_HDR)) {
MyMutex::MyLock initLock(minit); // Also used in crop window
-
- imgsrc->HLRecovery_Global(params->toneCurve); // this handles Color HLRecovery
+ // imgsrc->HLRecovery_Global(params->toneCurve); // this handles Color HLRecovery
if (settings->verbose) {
@@ -538,7 +541,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
printf("tempref=%f greref=%f\n", tempref, greenref);
}
- imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw);
+ 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 (params->wb.method == "autitcgreen") {
params->wb.temperature = tempitc;
@@ -617,8 +620,8 @@ 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);
-
- imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw);
+ 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()) {
spotsDone = true;
@@ -2462,7 +2465,7 @@ bool ImProcCoordinator::getAutoWB(double& temp, double& green, double equal, dou
double greenitc = 1.;
float studgood = 1000.f;
double tempref, greenref;
- imgsrc->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc, studgood, 0, 0, fh, fw, 0, 0, fh, fw, rm, gm, bm, params->wb, params->icm, params->raw);
+ 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);
@@ -2649,7 +2652,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
currWB = ColorTemp(); // = no white balance
}
- imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw);
+ imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw, 0);
ImProcFunctions ipf(&ppar, true);
if (ipf.needsTransform(fW, fH, imgsrc->getRotateDegree(), imgsrc->getMetaData())) {
diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc
index bdc1b6db1..811e941e4 100644
--- a/rtengine/iplocallab.cc
+++ b/rtengine/iplocallab.cc
@@ -2128,7 +2128,7 @@ void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg,
Imagefloat img(int(fw / SCALE + 0.5), int(fh / SCALE + 0.5));
const ProcParams neutral;
- imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw);
+ imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw, 0);
imgsrc->convertColorSpace(&img, params->icm, imgsrc->getWB());
float minVal = RT_INFINITY;
float maxVal = -RT_INFINITY;
diff --git a/rtengine/linalgebra.h b/rtengine/linalgebra.h
new file mode 100644
index 000000000..32e44e147
--- /dev/null
+++ b/rtengine/linalgebra.h
@@ -0,0 +1,275 @@
+/* -*- C++ -*-
+ * This file is part of ART
+ *
+ * Copyright (c) 2022 Alberto Griggio
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+ */
+
+#pragma once
+#include
+
+namespace rtengine {
+
+template
+class Vec3 {
+public:
+ Vec3() { data_[0] = data_[1] = data_[2] = T(); }
+ Vec3(T a, T b, T c) { data_[0] = a; data_[1] = b; data_[2] = c; }
+
+ template
+ Vec3(T2 const a[3]) { data_[0] = a[0]; data_[1] = a[1]; data_[2] = a[2]; }
+
+ Vec3 &operator=(const Vec3 &a) = default;
+
+ template
+ Vec3 &operator=(T2 const a[3])
+ {
+ data_[0] = a[0]; data_[1] = a[1]; data_[2] = a[2];
+ return *this;
+ }
+
+ T operator[](int i) const { return data_[i]; }
+ T &operator[](int i) { return data_[i]; }
+ operator const T *() const { return data_; }
+ operator T *() { return data_; }
+
+private:
+ T data_[3];
+};
+
+typedef Vec3 Vec3f;
+
+
+template
+class Mat33 {
+public:
+ Mat33()
+ {
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ data_[i][j] = T();
+ }
+ }
+ }
+
+ Mat33(T a00, T a01, T a02,
+ T a10, T a11, T a12,
+ T a20, T a21, T a22)
+ {
+ data_[0][0] = a00; data_[0][1] = a01; data_[0][2] = a02;
+ data_[1][0] = a10; data_[1][1] = a11; data_[1][2] = a12;
+ data_[2][0] = a20; data_[2][1] = a21; data_[2][2] = a22;
+ }
+
+ template
+ Mat33(const T2 m[3][3])
+ {
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ data_[i][j] = m[i][j];
+ }
+ }
+ }
+
+ Mat33 &operator=(const Mat33 &m) = default;
+
+ template
+ Mat33 &operator=(const T2 m[3][3])
+ {
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ data_[i][j] = m[i][j];
+ }
+ }
+ return *this;
+ }
+
+ T const *operator[](int i) const { return data_[i]; }
+ T *operator[](int i) { return data_[i]; }
+ typedef const T(*Data)[3];
+ operator Data() const { return data_; }
+
+private:
+ T data_[3][3];
+};
+
+
+typedef Mat33 Mat33f;
+
+
+template
+Mat33 identity()
+{
+ return Mat33(1, 0, 0, 0, 1, 0, 0, 0, 1);
+}
+
+
+template
+Mat33 diagonal(T a, T b, T c)
+{
+ return Mat33(a, 0, 0, 0, b, 0, 0, 0, c);
+}
+
+
+template
+Mat33 transpose(T const m[3][3])
+{
+ return Mat33(m[0][0], m[1][0], m[2][0],
+ m[0][1], m[1][1], m[2][1],
+ m[0][2], m[1][2], m[2][2]);
+}
+
+template
+Mat33 transpose(const Mat33 &m)
+{
+ return transpose(static_cast::Data>(m));
+}
+
+
+template
+bool inverse(T const m[3][3], Mat33 &out)
+{
+ const T res00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
+ const T res10 = m[2][0] * m[1][2] - m[1][0] * m[2][2];
+ const T res20 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
+
+ const T det = m[0][0] * res00 + m[0][1] * res10 + m[0][2] * res20;
+
+ if (std::abs(det) >= 1.0e-10) {
+ out[0][0] = res00 / det;
+ out[0][1] = (m[2][1] * m[0][2] - m[0][1] * m[2][2]) / det;
+ out[0][2] = (m[0][1] * m[1][2] - m[1][1] * m[0][2]) / det;
+ out[1][0] = res10 / det;
+ out[1][1] = (m[0][0] * m[2][2] - m[2][0] * m[0][2]) / det;
+ out[1][2] = (m[1][0] * m[0][2] - m[0][0] * m[1][2]) / det;
+ out[2][0] = res20 / det;
+ out[2][1] = (m[2][0] * m[0][1] - m[0][0] * m[2][1]) / det;
+ out[2][2] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) / det;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+template
+Mat33 inverse(const Mat33 &m)
+{
+ Mat33 res;
+ inverse(static_cast::Data>(m), res);
+ return res;
+}
+
+template
+Mat33 inverse(T const m[3][3])
+{
+ Mat33 res;
+ inverse(m, res);
+ return res;
+}
+
+template
+bool inverse(const Mat33 &m, Mat33 &out)
+{
+ return inverse(static_cast::Data>(m), out);
+}
+
+
+template
+Mat33 dot_product(T const a[3][3], T const b[3][3])
+{
+ Mat33 res;
+
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ res[i][j] = 0;
+
+ for (int k = 0; k < 3; ++k) {
+ res[i][j] += a[i][k] * b[k][j];
+ }
+ }
+ }
+
+ return res;
+}
+
+template
+Mat33 dot_product(const Mat33 &a, T const b[3][3])
+{
+ return dot_product(static_cast::Data>(a), b);
+}
+
+template
+Mat33 dot_product(T const a[3][3], const Mat33 &b)
+{
+ return dot_product(a, static_cast::Data>(b));
+}
+
+template
+Mat33 dot_product(const Mat33 &a, const Mat33 &b)
+{
+ return dot_product(static_cast::Data>(a), static_cast::Data>(b));
+}
+
+
+template
+Vec3 dot_product(T const a[3][3], T const b[3])
+{
+ Vec3 res;
+
+ for (int i = 0; i < 3; ++i) {
+ res[i] = 0;
+ for (int k = 0; k < 3; ++k) {
+ res[i] += a[i][k] * b[k];
+ }
+ }
+
+ return res;
+}
+
+
+template
+Vec3 dot_product(const Mat33 &a, T const b[3])
+{
+ return dot_product(static_cast::Data>(a), b);
+}
+
+template
+Vec3 dot_product(T const a[3][3], const Vec3 &b)
+{
+ return dot_product(a, static_cast(b));
+}
+
+template
+Vec3 dot_product(const Mat33 &a, const Vec3 &b)
+{
+ return dot_product(static_cast::Data>(a), static_cast(b));
+}
+
+
+template
+Mat33 operator*(const Mat33 &m, T v)
+{
+ return Mat33(m[0][0] * v, m[0][1] * v, m[0][2] * v,
+ m[1][0] * v, m[1][1] * v, m[1][2] * v,
+ m[2][0] * v, m[2][1] * v, m[2][2] * v);
+}
+
+template
+Vec3 operator*(const Vec3 &a, T v)
+{
+ return Vec3(a[0] * v, a[1] * v, a[2] * v);
+}
+
+} // namespace rtengine
diff --git a/rtengine/perspectivecorrection.cc b/rtengine/perspectivecorrection.cc
index 7a56ef5a8..f4428faf2 100644
--- a/rtengine/perspectivecorrection.cc
+++ b/rtengine/perspectivecorrection.cc
@@ -297,7 +297,7 @@ PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *sr
neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST);
neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST);
neutral.icm.outputProfile = ColorManagementParams::NoICMString;
- src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw);
+ src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw, 0);
src->convertColorSpace(img.get(), pparams->icm, src->getWB());
neutral.commonTrans.autofill = false; // Ensures crop factor is correct.
diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc
index de1603f1c..1afe72c92 100644
--- a/rtengine/previewimage.cc
+++ b/rtengine/previewimage.cc
@@ -121,7 +121,7 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext
double contrastThresholdDummy = 0.0;
rawImage.demosaic(params.raw, false, contrastThresholdDummy);
Imagefloat image(fw, fh);
- rawImage.getImage (wb, TR_NONE, &image, pp, params.toneCurve, params.raw);
+ rawImage.getImage (wb, TR_NONE, &image, pp, params.toneCurve, params.raw, 0);
rtengine::Image8 output(fw, fh);
rawImage.convertColorSpace(&image, params.icm, wb);
#ifdef _OPENMP
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index e6bdc9619..9323bd9e7 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -373,7 +373,7 @@ ToneCurveParams::ToneCurveParams() :
autoexp(false),
clip(0.02),
hrenabled(false),
- method("Blend"),
+ method("Coloropp"),
expcomp(0),
curve{
DCT_Linear
@@ -390,6 +390,7 @@ ToneCurveParams::ToneCurveParams() :
shcompr(50),
hlcompr(0),
hlbl(0),
+ hlth(1.0),
hlcomprthresh(0),
histmatching(false),
fromHistMatching(false),
@@ -416,6 +417,7 @@ bool ToneCurveParams::isPanningRelatedChange(const ToneCurveParams& other) const
&& shcompr == other.shcompr
&& hlcompr == other.hlcompr
&& hlbl == other.hlbl
+ && hlth == other.hlth
&& hlcomprthresh == other.hlcomprthresh
&& histmatching == other.histmatching
&& clampOOG == other.clampOOG);
@@ -440,6 +442,7 @@ bool ToneCurveParams::operator ==(const ToneCurveParams& other) const
&& shcompr == other.shcompr
&& hlcompr == other.hlcompr
&& hlbl == other.hlbl
+ && hlth == other.hlth
&& hlcomprthresh == other.hlcomprthresh
&& histmatching == other.histmatching
&& fromHistMatching == other.fromHistMatching
@@ -5912,6 +5915,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->toneCurve.hrenabled, "HLRecovery", "Enabled", toneCurve.hrenabled, keyFile);
saveToKeyfile(!pedited || pedited->toneCurve.method, "HLRecovery", "Method", toneCurve.method, keyFile);
saveToKeyfile(!pedited || pedited->toneCurve.hlbl, "HLRecovery", "Hlbl", toneCurve.hlbl, keyFile);
+ saveToKeyfile(!pedited || pedited->toneCurve.hlth, "HLRecovery", "Hlth", toneCurve.hlth, keyFile);
const std::map tc_mapping = {
{ToneCurveMode::STD, "Standard"},
@@ -7697,6 +7701,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
assignFromKeyfile(keyFile, "HLRecovery", "Enabled", pedited, toneCurve.hrenabled, pedited->toneCurve.hrenabled);
assignFromKeyfile(keyFile, "HLRecovery", "Method", pedited, toneCurve.method, pedited->toneCurve.method);
assignFromKeyfile(keyFile, "HLRecovery", "Hlbl", pedited, toneCurve.hlbl, pedited->toneCurve.hlbl);
+ assignFromKeyfile(keyFile, "HLRecovery", "Hlth", pedited, toneCurve.hlth, pedited->toneCurve.hlth);
}
if (keyFile.has_group("Channel Mixer")) {
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index e86272b0a..33d95a619 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -299,6 +299,7 @@ struct ToneCurveParams {
int shcompr;
int hlcompr; // Highlight Recovery's compression
int hlbl; // Highlight Recovery's compression
+ double hlth; // Highlight Recovery's threshold
int hlcomprthresh; // Highlight Recovery's threshold
bool histmatching; // histogram matching
bool fromHistMatching;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 550c59e9c..7ff9c4d0f 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -468,6 +468,7 @@ RawImageSource::RawImageSource ()
{
embProfile = nullptr;
rgbSourceModified = false;
+
for (int i = 0; i < 4; ++i) {
psRedBrightness[i] = psGreenBrightness[i] = psBlueBrightness[i] = 1.f;
}
@@ -639,6 +640,57 @@ float calculate_scale_mul(float scale_mul[4], const float pre_mul_[4], const flo
return gain;
}
+void RawImageSource::wbMul2Camera(double &rm, double &gm, double &bm)
+{
+ double r = rm;
+ double g = gm;
+ double b = bm;
+
+ auto imatrices = getImageMatrices();
+
+ if (imatrices) {
+ double rr = imatrices->cam_rgb[0][0] * r + imatrices->cam_rgb[0][1] * g + imatrices->cam_rgb[0][2] * b;
+ double gg = imatrices->cam_rgb[1][0] * r + imatrices->cam_rgb[1][1] * g + imatrices->cam_rgb[1][2] * b;
+ double bb = imatrices->cam_rgb[2][0] * r + imatrices->cam_rgb[2][1] * g + imatrices->cam_rgb[2][2] * b;
+ r = rr;
+ g = gg;
+ b = bb;
+ }
+
+ rm = ri->get_pre_mul(0) / r;
+ gm = ri->get_pre_mul(1) / g;
+ bm = ri->get_pre_mul(2) / b;
+
+ rm /= gm;
+ bm /= gm;
+ gm = 1.0;
+}
+
+
+void RawImageSource::wbCamera2Mul(double &rm, double &gm, double &bm)
+{
+ auto imatrices = getImageMatrices();
+
+ double r = ri->get_pre_mul(0) / rm;
+ double g = ri->get_pre_mul(1) / gm;
+ double b = ri->get_pre_mul(2) / bm;
+
+ if (imatrices) {
+ double rr = imatrices->rgb_cam[0][0] * r + imatrices->rgb_cam[0][1] * g + imatrices->rgb_cam[0][2] * b;
+ double gg = imatrices->rgb_cam[1][0] * r + imatrices->rgb_cam[1][1] * g + imatrices->rgb_cam[1][2] * b;
+ double bb = imatrices->rgb_cam[2][0] * r + imatrices->rgb_cam[2][1] * g + imatrices->rgb_cam[2][2] * b;
+ r = rr;
+ g = gg;
+ b = bb;
+ }
+
+ rm = r / g;
+ bm = b / g;
+ gm = 1.0;
+}
+
+
+
void RawImageSource::getWBMults (const ColorTemp &ctemp, const RAWParams &raw, std::array& out_scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const
{
@@ -689,10 +741,9 @@ void RawImageSource::getWBMults (const ColorTemp &ctemp, const RAWParams &raw, s
autoGainComp = camInitialGain / initialGain;
}
-void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw)
-{
+void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw, int opposed)
+{// added int opposed to force getimage to use inpaint-opposed if enable, only once
MyMutex::MyLock lock(getImageMutex);
-
tran = defTransform (tran);
// compute channel multipliers
@@ -705,7 +756,9 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima
gm = ri->get_pre_mul(1);
bm = ri->get_pre_mul(2);
} else {
- ctemp.getMultipliers (r, g, b);
+ // ctemp.getMultipliers (r, g, b);
+ r = g = b = 1;
+ wbCamera2Mul(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;
@@ -790,22 +843,52 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima
int maxx = this->W, maxy = this->H, skip = pp.getSkip();
- // raw clip levels after white balance
+ 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 (!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);
+ }
+ rgbSourceModified = true;
+ }
+ }
+
+ // now apply the wb coefficients
+ if (ctemp.getTemp() >= 0) {
+ double r, g, b;
+ ctemp.getMultipliers(r, g, b);
+ wbMul2Camera(r, g, b);
+
+ rm *= r;
+ gm *= g;
+ bm *= b;
+ }
hlmax[0] = clmax[0] * rm;
hlmax[1] = clmax[1] * gm;
hlmax[2] = clmax[2] * bm;
- const bool doClip = (chmax[0] >= clmax[0] || chmax[1] >= clmax[1] || chmax[2] >= clmax[2]) && !hrp.hrenabled && hrp.clampOOG;
+ const float expcomp = std::pow(2, ri->getBaselineExposure());
+ rm *= expcomp;
+ gm *= expcomp;
+ bm *= expcomp;
float area = skip * skip;
rm /= area;
gm /= area;
bm /= area;
- bool doHr = (hrp.hrenabled && hrp.method != "Color");
- const float expcomp = std::pow(2, ri->getBaselineExposure());
- rm *= expcomp;
- gm *= expcomp;
- bm *= expcomp;
+
#ifdef _OPENMP
#pragma omp parallel if(!d1x) // omp disabled for D1x to avoid race conditions (see Issue 1088 http://code.google.com/p/rawtherapee/issues/detail?id=1088)
@@ -1697,7 +1780,6 @@ void RawImageSource::demosaic(const RAWParams &raw, bool autoContrast, double &c
rgbSourceModified = false;
-
if (cache) {
if (!redCache) {
redCache = new array2D(W, H);
@@ -2396,7 +2478,6 @@ void RawImageSource::retinex(const ColorManagementParams& cmp, const RetinexPara
}
rgbSourceModified = false; // tricky handling for Color propagation
-
t5.set();
if (settings->verbose) {
@@ -2442,16 +2523,17 @@ void RawImageSource::flush()
void RawImageSource::HLRecovery_Global(const ToneCurveParams &hrp)
{
- if (hrp.hrenabled && hrp.method == "Color") {
- if (!rgbSourceModified) {
- if (settings->verbose) {
- printf ("Applying Highlight Recovery: Color propagation...\n");
- }
-
- HLRecovery_inpaint (red, green, blue, hrp.hlbl);
- rgbSourceModified = true;
- }
- }
+ // if (hrp.hrenabled && hrp.method == "Color") {
+ // if (!rgbSourceModified) {
+ // if (settings->verbose) {
+ // printf ("Applying Highlight Recovery: Color propagation...\n");
+ // }
+//
+ // HLRecovery_inpaint (red, green, blue, hrp.hlbl);
+//
+// rgbSourceModified = true;
+ // }
+// }
}
@@ -3460,6 +3542,7 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed
// very effective to reduce (or remove) the magenta, but with levels of grey !
void RawImageSource::HLRecovery_blend(float* rin, float* gin, float* bin, int width, float maxval, float* hlmax)
{
+
constexpr int ColorCount = 3;
// Transform matrixes rgb>lab and back
@@ -3684,6 +3767,7 @@ void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, floa
void RawImageSource::hlRecovery (const std::string &method, float* red, float* green, float* blue, int width, float* hlmax)
{
+// BENCHFUN
if (method == "Luminance") {
HLRecovery_Luminance (red, green, blue, red, green, blue, width, 65535.0);
@@ -3953,12 +4037,12 @@ void RawImageSource::getRowStartEnd (int x, int &start, int &end)
}
}
-
-static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const array2D & yc, const array2D & Yc, LUTf &xxx, LUTf &yyy, LUTf &YYY, LUTu &histxy)
+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 190 colors
- //this "choice" are guided by generally colors who are in nature skin, sky, etc. in those cases "steps" are small
+ // calculate histogram x y in a range of 236 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
+ // purp enable or not purple color in xyY - approximation...
#ifdef _OPENMP
#pragma omp parallel
#endif
@@ -3971,434 +4055,528 @@ static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const ar
yyythr.clear();
LUTf YYYthr(YYY.getSize());
YYYthr.clear();
+ // bool purp = false;
#ifdef _OPENMP
#pragma omp for schedule(dynamic, 4) nowait
#endif
- for (int y = 0; y < bfhitc ; y++) {
+
+ 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) {
+ } else if (yc[y][x] < 0.25f) {
nh = 1;
- //blue
- } else if (yc[y][x] < 0.4f) {
+ } else if (yc[y][x] < 0.3f) {
nh = 2;
-
+ //blue
+ } else if (yc[y][x] < 0.35f) {
+ nh = 3;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 4;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 5;
} else if (yc[y][x] < 0.5f) {
//blue green
- nh = 3;
+ nh = 6;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 7;
} else if (yc[y][x] < 0.6f) {
- nh = 4;
+ nh = 8;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 9;
} else if (yc[y][x] < 0.82f) {
//green
- nh = 5;
+ nh = 10;
}
} 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 = 12;
+ } else if (yc[y][x] < 0.3f) {
nh = 13;
- } else if (yc[y][x] < 0.29f) {
+ } else if (yc[y][x] < 0.35f) {
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;
+ nh = 15;
} else if (yc[y][x] < 0.45f) {
- nh = 18;
+ nh = 16;
} else if (yc[y][x] < 0.5f) {
- nh = 19;
+ nh = 17;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 18;
} else if (yc[y][x] < 0.6f) {
+ nh = 19;
+ } else if (yc[y][x] < 0.67f) {
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
+ } else if (xc[y][x] < 0.28f && yc[y][x] > 0.1f) {//blue sky and other
if (yc[y][x] < 0.2f) {
nh = 22;
- } else if (yc[y][x] < 0.24f) {
+ } else if (yc[y][x] < 0.23f) {
nh = 23;
- } else if (yc[y][x] < 0.29f) {
+ } else if (yc[y][x] < 0.25f) {
nh = 24;
- } else if (yc[y][x] < 0.32f) {
+ } else if (yc[y][x] < 0.27f) {
nh = 25;
- } else if (yc[y][x] < 0.36f) {
+ } else if (yc[y][x] < 0.29f) {
nh = 26;
- } else if (yc[y][x] < 0.4f) {
+ } else if (yc[y][x] < 0.31f) {
nh = 27;
- } else if (yc[y][x] < 0.5f) {
+ } else if (yc[y][x] < 0.33f) {
nh = 28;
- } else if (yc[y][x] < 0.7f) {
+ } else if (yc[y][x] < 0.35f) {
nh = 29;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 30;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 31;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 32;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 33;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 34;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 35;
+ } else if (yc[y][x] < 0.67f) {
+ nh = 36;
+ } else if (yc[y][x] < 0.75f) {
+ nh = 37;
+ }
+ } else if (xc[y][x] < 0.31f && yc[y][x] > 0.1f) {//near neutral others
+ if (yc[y][x] < 0.2f) {
+ nh = 38;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 39;
+ } else if (yc[y][x] < 0.24f) {
+ nh = 40;
+ } else if (yc[y][x] < 0.26f) {
+ nh = 41;
+ } else if (yc[y][x] < 0.29f) {
+ nh = 42;
+ } else if (yc[y][x] < 0.32f) {
+ nh = 43;
+ } else if (yc[y][x] < 0.36f) {
+ nh = 44;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 45;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 46;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 47;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 48;
+ } else if (yc[y][x] < 0.7f) {
+ nh = 49;
}
} else if (xc[y][x] < 0.325f && yc[y][x] > 0.1f) {//neutral 34
if (yc[y][x] < 0.2f) {
- nh = 30;
+ nh = 50;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 51;
} else if (yc[y][x] < 0.24f) {
- nh = 31;
+ nh = 52;
} else if (yc[y][x] < 0.29f) {
- nh = 32;
+ nh = 53;
} else if (yc[y][x] < 0.32f) {
- nh = 33;
+ nh = 54;
} else if (yc[y][x] < 0.33f) {
- nh = 34;
+ nh = 55;
} else if (yc[y][x] < 0.335f) {
- nh = 35;
+ nh = 56;
} else if (yc[y][x] < 0.34f) {
- nh = 36;
+ nh = 57;
} else if (yc[y][x] < 0.35f) {
- nh = 37;
+ nh = 58;
} else if (yc[y][x] < 0.37f) {
- nh = 38;
+ nh = 59;
} else if (yc[y][x] < 0.4f) {
- nh = 39;
+ nh = 60;
} else if (yc[y][x] < 0.45f) {
- nh = 40;
+ nh = 61;
} else if (yc[y][x] < 0.5f) {
- nh = 41;
+ nh = 62;
} else if (yc[y][x] < 0.55f) {
- nh = 42;
+ nh = 63;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 64;
+ } else if (yc[y][x] < 0.65f) {
+ nh = 65;
} else if (yc[y][x] < 0.7f) {
- nh = 43;
+ nh = 66;
}
} else if (xc[y][x] < 0.335f && yc[y][x] > 0.1f) {//neutral
if (yc[y][x] < 0.2f) {
- nh = 44;
+ nh = 67;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 68;
} else if (yc[y][x] < 0.24f) {
- nh = 45;
+ nh = 69;
+ } else if (yc[y][x] < 0.27f) {
+ nh = 70;
} else if (yc[y][x] < 0.29f) {
- nh = 46;
+ nh = 71;
} else if (yc[y][x] < 0.32f) {
- nh = 47;
+ nh = 72;
} else if (yc[y][x] < 0.33f) {
- nh = 48;
+ nh = 73;
} else if (yc[y][x] < 0.335f) {
- nh = 49;
+ nh = 74;
} else if (yc[y][x] < 0.34f) {
- nh = 50;
+ nh = 75;
} else if (yc[y][x] < 0.345f) {
- nh = 51;
+ nh = 76;
} else if (yc[y][x] < 0.35f) {
- nh = 52;
+ nh = 77;
} else if (yc[y][x] < 0.355f) {
- nh = 53;
+ nh = 78;
} else if (yc[y][x] < 0.36f) {
- nh = 54;
+ nh = 79;
} else if (yc[y][x] < 0.37f) {
- nh = 55;
+ nh = 80;
} else if (yc[y][x] < 0.38f) {
- nh = 56;
+ nh = 81;
} else if (yc[y][x] < 0.4f) {
- nh = 57;
+ nh = 82;
} else if (yc[y][x] < 0.45f) {
- nh = 58;
+ nh = 83;
} else if (yc[y][x] < 0.5f) {
- nh = 59;
+ nh = 84;
} else if (yc[y][x] < 0.55f) {
- nh = 60;
+ nh = 85;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 86;
+ } else if (yc[y][x] < 0.65f) {
+ nh = 87;
} else if (yc[y][x] < 0.7f) {
- nh = 61;
+ nh = 88;
}
} else if (xc[y][x] < 0.340f && yc[y][x] > 0.1f) {//neutral
if (yc[y][x] < 0.2f) {
- nh = 62;
+ nh = 89;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 90;
} else if (yc[y][x] < 0.24f) {
- nh = 63;
+ nh = 91;
} else if (yc[y][x] < 0.29f) {
- nh = 64;
+ nh = 92;
} else if (yc[y][x] < 0.32f) {
- nh = 65;
+ nh = 93;
} else if (yc[y][x] < 0.325f) {
- nh = 66;
+ nh = 94;
} else if (yc[y][x] < 0.33f) {
- nh = 67;
+ nh = 95;
} else if (yc[y][x] < 0.335f) {
- nh = 68;
+ nh = 96;
} else if (yc[y][x] < 0.34f) {
- nh = 69;
+ nh = 97;
} else if (yc[y][x] < 0.345f) {
- nh = 70;
+ nh = 98;
} else if (yc[y][x] < 0.35f) {
- nh = 71;
+ nh = 99;
} else if (yc[y][x] < 0.355f) {
- nh = 72;
+ nh = 100;
} else if (yc[y][x] < 0.36f) {
- nh = 73;
+ nh = 101;
} else if (yc[y][x] < 0.37f) {
- nh = 74;
+ nh = 102;
} else if (yc[y][x] < 0.38f) {
- nh = 75;
+ nh = 103;
} else if (yc[y][x] < 0.4f) {
- nh = 76;
+ nh = 104;
} else if (yc[y][x] < 0.45f) {
- nh = 77;
+ nh = 105;
} else if (yc[y][x] < 0.5f) {
- nh = 78;
+ nh = 106;
} else if (yc[y][x] < 0.55f) {
- nh = 79;
+ nh = 107;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 108;
+ } else if (yc[y][x] < 0.65f) {
+ nh = 109;
} else if (yc[y][x] < 0.7f) {
- nh = 80;
+ nh = 110;
}
} else if (xc[y][x] < 0.345f && yc[y][x] > 0.1f) {//neutral 37
if (yc[y][x] < 0.2f) {
- nh = 81;
+ nh = 111;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 112;
} else if (yc[y][x] < 0.24f) {
- nh = 82;
+ nh = 113;
+ } else if (yc[y][x] < 0.26f) {
+ nh = 114;
} else if (yc[y][x] < 0.29f) {
- nh = 83;
+ nh = 115;
} else if (yc[y][x] < 0.32f) {
- nh = 84;
+ nh = 116;
} else if (yc[y][x] < 0.33f) {
- nh = 85;
+ nh = 117;
} else if (yc[y][x] < 0.335f) {
- nh = 86;
+ nh = 118;
} else if (yc[y][x] < 0.34f) {
- nh = 87;
+ nh = 119;
} else if (yc[y][x] < 0.345f) {
- nh = 88;
+ nh = 120;
} else if (yc[y][x] < 0.35f) {
- nh = 89;
+ nh = 121;
} else if (yc[y][x] < 0.355f) {
- nh = 90;
+ nh = 122;
} else if (yc[y][x] < 0.36f) {
- nh = 91;
+ nh = 123;
} else if (yc[y][x] < 0.37f) {
- nh = 92;
+ nh = 124;
} else if (yc[y][x] < 0.38f) {
- nh = 93;
+ nh = 125;
} else if (yc[y][x] < 0.39f) {
- nh = 94;
+ nh = 126;
} else if (yc[y][x] < 0.4f) {
- nh = 95;
+ nh = 127;
} else if (yc[y][x] < 0.42f) {
- nh = 96;
+ nh = 128;
} else if (yc[y][x] < 0.45f) {
- nh = 97;
+ nh = 129;
} else if (yc[y][x] < 0.48f) {
- nh = 98;
+ nh = 130;
} else if (yc[y][x] < 0.5f) {
- nh = 99;
+ nh = 131;
} else if (yc[y][x] < 0.55f) {
- nh = 100;
+ nh = 132;
} else if (yc[y][x] < 0.65f) {
- nh = 101;
+ nh = 133;
}
} else if (xc[y][x] < 0.355f && yc[y][x] > 0.1f) {//neutral 37
if (yc[y][x] < 0.2f) {
- nh = 102;
+ nh = 134;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 135;
} else if (yc[y][x] < 0.24f) {
- nh = 103;
+ nh = 136;
+ } else if (yc[y][x] < 0.26f) {
+ nh = 137;
} else if (yc[y][x] < 0.29f) {
- nh = 104;
+ nh = 138;
} else if (yc[y][x] < 0.32f) {
- nh = 105;
+ nh = 139;
} else if (yc[y][x] < 0.33f) {
- nh = 106;
+ nh = 140;
} else if (yc[y][x] < 0.335f) {
- nh = 107;
+ nh = 141;
} else if (yc[y][x] < 0.34f) {
- nh = 108;
+ nh = 142;
} else if (yc[y][x] < 0.345f) {
- nh = 109;
+ nh = 143;
} else if (yc[y][x] < 0.35f) {
- nh = 110;
+ nh = 144;
} else if (yc[y][x] < 0.355f) {
- nh = 111;
+ nh = 145;
} else if (yc[y][x] < 0.36f) {
- nh = 112;
+ nh = 146;
} else if (yc[y][x] < 0.37f) {
- nh = 113;
+ nh = 147;
} else if (yc[y][x] < 0.38f) {
- nh = 114;
+ nh = 148;
} else if (yc[y][x] < 0.39f) {
- nh = 115;
+ nh = 149;
} else if (yc[y][x] < 0.4f) {
- nh = 116;
+ nh = 150;
} else if (yc[y][x] < 0.42f) {
- nh = 117;
+ nh = 151;
} else if (yc[y][x] < 0.45f) {
- nh = 118;
+ nh = 152;
} else if (yc[y][x] < 0.48f) {
- nh = 119;
+ nh = 153;
} else if (yc[y][x] < 0.5f) {
- nh = 120;
+ nh = 154;
} else if (yc[y][x] < 0.55f) {
- nh = 121;
+ nh = 155;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 156;
} else if (yc[y][x] < 0.65f) {
- nh = 122;
+ nh = 157;
}
} else if (xc[y][x] < 0.365f && yc[y][x] > 0.15f) { //0.4
if (yc[y][x] < 0.2f) {
- nh = 123;
+ nh = 158;
+ } else if (yc[y][x] < 0.22f) {
+ nh = 159;
} else if (yc[y][x] < 0.24f) {
- nh = 124;
+ nh = 160;
+ } else if (yc[y][x] < 0.26f) {
+ nh = 161;
} else if (yc[y][x] < 0.29f) {
- nh = 125;
+ nh = 162;
} else if (yc[y][x] < 0.32f) {
- nh = 126;
+ nh = 163;
} else if (yc[y][x] < 0.33f) {
- nh = 127;
+ nh = 164;
} else if (yc[y][x] < 0.34f) {
- nh = 128;
+ nh = 165;
} else if (yc[y][x] < 0.35f) {
- nh = 129;
+ nh = 166;
} else if (yc[y][x] < 0.36f) {
- nh = 130;
+ nh = 167;
} else if (yc[y][x] < 0.37f) {
- nh = 131;
+ nh = 168;
} else if (yc[y][x] < 0.38f) {
- nh = 132;
+ nh = 169;
} else if (yc[y][x] < 0.39f) {
- nh = 133;
+ nh = 170;
} else if (yc[y][x] < 0.4f) {
- nh = 134;
+ nh = 171;
} else if (yc[y][x] < 0.42f) {
- nh = 135;
+ nh = 172;
} else if (yc[y][x] < 0.45f) {
- nh = 136;
+ nh = 173;
} else if (yc[y][x] < 0.5f) {
- nh = 137;
+ nh = 174;
} else if (yc[y][x] < 0.55f) {
- nh = 138;
+ nh = 175;
} else if (yc[y][x] < 0.63f) {
- nh = 139;
+ nh = 176;
}
} 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) {
+ if (yc[y][x] < 0.2f && purp) {//no take into account if purp = false
nh = 177;
- } else if (yc[y][x] < 0.4f) {
+ } else if (yc[y][x] < 0.22f && purp) {
nh = 178;
- } else if (yc[y][x] < 0.45f) {
+ } else if (yc[y][x] < 0.24f && purp) {
nh = 179;
- } else if (yc[y][x] < 0.5f) {
+ } else if (yc[y][x] < 0.26f && purp) {
nh = 180;
- }
- } else if (xc[y][x] < 0.595f && yc[y][x] > 0.15f) {
- if (yc[y][x] < 0.22f) {
+ } else if (yc[y][x] < 0.29f && purp) {
nh = 181;
- } else if (yc[y][x] < 0.25f) {
+ } else if (yc[y][x] < 0.32f) {
nh = 182;
- } else if (yc[y][x] < 0.3f) {
+ } else if (yc[y][x] < 0.34f) {
nh = 183;
- } else if (yc[y][x] < 0.35f) {
+ } else if (yc[y][x] < 0.37f) {
nh = 184;
} else if (yc[y][x] < 0.4f) {
nh = 185;
} else if (yc[y][x] < 0.45f) {
nh = 186;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 187;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 188;
+ } else if (yc[y][x] < 0.6f) {
+ nh = 189;
+ }
+ } else if (xc[y][x] < 0.445f && yc[y][x] > 0.15f) {//45
+ if (yc[y][x] < 0.2f && purp) {
+ nh = 190;
+ } else if (yc[y][x] < 0.22f && purp) {
+ nh = 191;
+ } else if (yc[y][x] < 0.24f && purp) {
+ nh = 192;
+ } else if (yc[y][x] < 0.26f && purp) {
+ nh = 193;
+ } else if (yc[y][x] < 0.29f && purp) {
+ nh = 194;
+ } else if (yc[y][x] < 0.32f && purp) {
+ nh = 195;
+ } else if (yc[y][x] < 0.34f && purp) {
+ nh = 196;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 197;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 198;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 199;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 200;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 201;
+ } else if (yc[y][x] < 0.58f) {
+ nh = 202;
+ }
+ } else if (xc[y][x] < 0.495f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.2f && purp) {
+ nh = 203;
+ } else if (yc[y][x] < 0.22f && purp) {
+ nh = 204;
+ } else if (yc[y][x] < 0.24f && purp) {
+ nh = 205;
+ } else if (yc[y][x] < 0.26f && purp) {
+ nh = 206;
+ } else if (yc[y][x] < 0.29f && purp) {
+ nh = 207;
+ } else if (yc[y][x] < 0.32f && purp) {
+ nh = 208;
+ } else if (yc[y][x] < 0.34f && purp) {
+ nh = 209;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 210;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 211;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 212;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 213;
+ } else if (yc[y][x] < 0.55f) {
+ nh = 214;
+ }
+ } else if (xc[y][x] < 0.545f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.2f && purp) {
+ nh = 215;
+ } else if (yc[y][x] < 0.22f && purp) {
+ nh = 216;
+ } else if (yc[y][x] < 0.24f && purp) {
+ nh = 217;
+ } else if (yc[y][x] < 0.26f && purp) {
+ nh = 218;
+ } else if (yc[y][x] < 0.29f && purp) {
+ nh = 219;
+ } else if (yc[y][x] < 0.32f && purp) {
+ nh = 220;
+ } else if (yc[y][x] < 0.34f && purp) {
+ nh = 221;
+ } else if (yc[y][x] < 0.37f) {
+ nh = 222;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 223;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 224;
+ } else if (yc[y][x] < 0.5f) {
+ nh = 225;
+ }
+ } else if (xc[y][x] < 0.595f && yc[y][x] > 0.15f) {
+ if (yc[y][x] < 0.22f) {
+ nh = 226;
+ } else if (yc[y][x] < 0.25f) {
+ nh = 227;
+ } else if (yc[y][x] < 0.3f) {
+ nh = 228;
+ } else if (yc[y][x] < 0.35f) {
+ nh = 229;
+ } else if (yc[y][x] < 0.4f) {
+ nh = 230;
+ } else if (yc[y][x] < 0.45f) {
+ nh = 231;
}
} else if (xc[y][x] < 0.65f && yc[y][x] > 0.12f) {
if (yc[y][x] < 0.25f) {
- nh = 187;
+ nh = 232;
} else if (yc[y][x] < 0.3f) {
- nh = 188;
+ nh = 233;
} else if (yc[y][x] < 0.35f) {
- nh = 189;
+ nh = 234;
} else if (yc[y][x] < 0.45f) {
- nh = 190;
+ nh = 235;
}
} else if (xc[y][x] < 0.75f && yc[y][x] > 0.1f) {
- nh = 191;
+ nh = 236; //191
}
+
if (nh >= 0) {
histxythr[nh]++;
xxxthr[nh] += xc[y][x];
@@ -4407,6 +4585,7 @@ static void histoxyY(int bfhitc, int bfwitc, const array2D & xc, const ar
}
}
}
+
#ifdef _OPENMP
#pragma omp critical
#endif
@@ -4431,24 +4610,28 @@ float static studentXY(const array2D & YYcurr, const array2D & ref
somcurrY += YYcurr[i][tt];
//sum observations first group
}
+
somcurrY *= 100.f;
for (int i = 0; i < Nc; i++) {
somreffY += reffYY[i][tt];
//sum observations second group
}
+
somreffY *= 100.f;
for (int i = 0; i < sizcurr; i++) {
somcurr2Y += SQR(YYcurr[i][tt]);
//sum sqr observations first group
}
+
somcurr2Y *= SQR(100.f);
for (int i = 0; i < Nc; i++) {
somreff2Y += SQR(reffYY[i][tt]);
//sum sqr observations second group
}
+
somreff2Y *= SQR(100.f);
const float somsqueccurrY = somcurr2Y - SQR(somcurrY) / sizcurr;
@@ -4465,19 +4648,22 @@ float static studentXY(const array2D & YYcurr, const array2D & ref
//student coeeficient
}
-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)
+
+
+
+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
+ Copyright (c) Jacques Desmis 6 - 2018 jdesmis@gmail.com, update 1 - 2023
Copyright (c) Ingo Weyrich 3 - 2020 (heckflosse67@gmx.de)
- This algorithm try to find temperature correlation between 20 to 201 color between 201 spectral color and about 20 to 55 color found in the image between 192, 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.
+ 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.
I have test many many algorithms to find the first one that work :)
Probably (sure) there are improvement to do...
I have create a table temperature with temp and white point with 118 values between 2000K and 12000K we can obviously change these values, more...with different steps
- I have create a table for tint (green)with 134 values between 0.4 to 4.
+ I have create a table for tint (green)with 134 values between 0.4 to 4.
I have create or recuparate and transformed 201 spectral colors from Colorchecker24, others color and my 468 colors target, or from web flowers, etc. with a step of 5nm, I think it is large enough.
I think this value of 201 is now complete: I tested correlation with 60, 90, 100, 120, 155...better student increase with number of color, but now it seems stabilized
Of course we can increase this number :)
@@ -4520,17 +4706,18 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
You can change parameters in option.cc
Itcwb_thres : 34 by default ==> number of color used in final algorithm - between 10 and max 55
- Itcwb_sort : false by default, can improve algorithm if true, ==> sort value in something near chroma order, instead of histogram number
+ 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 : false - if true force algorithm "extra" ("extra" is used when camera wbsettings are wrong) to all images
+ 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_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 : 5 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 : 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...
*/
-// BENCHFUN
-
+ BENCHFUN
+
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix("sRGB");
const float wp[3][3] = {
{static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])},
@@ -4570,7 +4757,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{0.590, 1.f},
{0.600, 1.f},
{0.610, 1.f},
- {0.620, 1.f},
+ {0.620, 1.f},//extended range
{0.630, 1.f},
{0.640, 1.f},
{0.650, 1.f},
@@ -4579,7 +4766,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},
+ {0.714, 1.f},//usual range
{0.727, 1.f},
{0.741, 1.f},
{0.755, 1.f},
@@ -4610,7 +4797,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{0.971, 1.f},
{0.980, 1.f},
{0.990, 1.f},
- {1.000, 1.f},//55
+ {1.000, 1.f},//55 reference
{1.010, 1.f},
{1.020, 1.f},
{1.030, 1.f},
@@ -4641,14 +4828,14 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{1.325, 1.f},
{1.350, 1.f},
{1.375, 1.f},
- {1.400, 1.f},
+ {1.400, 1.f},//usual range
{1.425, 1.f},
{1.450, 1.f},
{1.475, 1.f},
{1.500, 1.f},
{1.525, 1.f},
{1.550, 1.f},
- {1.575, 1.f},
+ {1.575, 1.f},//extended range
{1.600, 1.f},
{1.633, 1.f},
{1.666, 1.f},
@@ -4697,7 +4884,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
int end;
} RangeGreen;
- constexpr RangeGreen Rangestandard = {24, 86};
+ constexpr RangeGreen Rangestandard = {24, 86};//usual green range
constexpr RangeGreen Rangeextended = {15, 93};
const RangeGreen Rangemax = {0, N_g};
@@ -4778,7 +4965,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
{4927., 0.965414, 0.809229},
{4952., 0.964908, 0.814366},
{4977., 0.964415, 0.819412},
- {5002., 0.963934, 0.824438},
+ {5002., 0.963934, 0.824438},//57 reference
{5027., 0.963465, 0.829444},
{5052., 0.963008, 0.834429},
{5077., 0.962563, 0.839395},
@@ -4857,10 +5044,10 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
float gmm[N_t];
float bmm[N_t];
- constexpr int siza = 192;//size of histogram
+ constexpr int siza = 237; //192 untill 01/2023 size of histogram
- //tempref and greenref are camera wb values.
- // I used them by default to select good spectral values !!
+ // 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);
int repref = 0;
@@ -4874,7 +5061,8 @@ 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));
+ || (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;
@@ -4924,19 +5112,27 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
} ;
LUTu histxy(siza); //number of values for each pair xy
+
histxy.clear();
LUTf xxx(siza);//for color references calculated ==> max in images "like histogram"
+
xxx.clear();
+
LUTf yyy(siza);
+
yyy.clear();
+
LUTf YYY(siza);//not used directly, but necessary to keep good range
+
YYY.clear();
bool separated = true;
+
int w = -1;
array2D reff_spect_yy_camera(N_t, 2 * Nc + 2);
+
array2D reff_spect_xx_camera(N_t, 2 * Nc + 2);
//here we select the good spectral color inside the 113 values
@@ -4965,6 +5161,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
#ifdef _OPENMP
#pragma omp parallel for
#endif
+
for (int y = 0; y < bfh ; ++y) {
for (int x = 0; x < bfw ; ++x) {
const float RR = rmm[rep] * redloc[y][x];
@@ -4973,6 +5170,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
Color::rgbxyY(RR, GG, BB, xc[y][x], yc[y][x], Yc[y][x], wp);
}
}
+
//histogram xy depend of temp...but in most cases D45 ..D65..
//calculate for this image the mean values for each family of color, near histogram x y (number)
//xy vary from x 0..0.77 y 0..0.82
@@ -4982,8 +5180,14 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
// step about 0.02 x 0.32 0.34 y= 0.34 0.36 skin -- sky x 0.24 0.30 y 0.28 0.32
//big step about 0.2
- histoxyY(bfhitc, bfwitc, xc, yc, Yc, xxx, yyy, YYY, histxy);
- //return histogram x and y for each temp and in a range of 158 colors (siza)
+ 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...)
+ 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)
}
// free some memory
@@ -5014,15 +5218,19 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
int n4 = 0;
int n15 = 0;
int n30 = 0;
+
//part to improve
//determined the number of colors who be used after
for (int nh = 0; nh < siza; nh++) {
if (Wbhis[nh].histnum < 30) {
n30++; //keep only existing color but avoid to small
+
if (Wbhis[nh].histnum < 15) {
n15++; //keep only existing color but avoid to small
+
if (Wbhis[nh].histnum < 4) {
n4++; //keep only existing color but avoid to small
+
if (Wbhis[nh].histnum < 1) {
n1++; //keep only existing color but avoid to small
}
@@ -5047,7 +5255,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);
+ const int sizcu4 = rtengine::min(sizcu30, 55);//
+
+ if (settings->verbose) {
+ printf("ntr=%i sizcurr2ref=%i sizcu30=%i sizcu4=%i\n", ntr, sizcurr2ref, sizcu30, sizcu4);
+ }
chrom wbchro[sizcu4];
const float swpr = Txyz[repref].XX + Txyz[repref].ZZ + 1.f;
@@ -5062,6 +5274,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
float estimchrom = 0.f;
+
//estimate chromaticity for references
for (int nh = 0; nh < sizcu4; ++nh) {
const float chxy = std::sqrt(SQR(xx_curref[nh][repref] - xwpr) + SQR(yy_curref[nh][repref] - ywpr));
@@ -5075,10 +5288,12 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
estimchrom /= sizcu4;
- if (settings->verbose) {
+
+ if (settings->verbose) {
printf("estimchrom=%f\n", estimchrom);
}
- if (settings->itcwb_sort) { //sort in ascending with chroma values
+
+ if (settings->itcwb_sorted) { //sort in ascending with chroma values
std::sort(wbchro, wbchro + sizcu4, wbchro[0]);
}
@@ -5105,7 +5320,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
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
for (int i = 0; i < w; ++i) {
- float mindeltaE = 100000.f;
+ float mindeltaE = 100000.f;//we can change this value...
int kN = 0;
for (int j = 0; j < Nc ; j++) {
@@ -5192,7 +5407,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
}
- if (extra) {//always used because I made this choice, brings better results
+ if (extra) {//always used if extra = true because I made this choice, brings better results
struct Tempgreen {
float student;
int tempref;
@@ -5206,14 +5421,15 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
for (int i = 0; i < N_g; ++i) {//init variables with
Tgstud[i].student = 1000.f;//max value to initialize
- Tgstud[i].tempref = 57;//5002K
- Tgstud[i].greenref = 55;// 1.f
+ 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);
const int scantempbeg = rtengine::max(goodref - (dgoodref + 1), 1);
const int scantempend = rtengine::min(goodref + dgoodref, N_t - 1);
+
for (int gr = Rangegreenused.begin; gr < Rangegreenused.end; ++gr) {
float minstudgr = 100000.f;
int goodrefgr = 1;
@@ -5249,6 +5465,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
const float BB = bmm[tt] * B_curref_reduc[i][repref];
Color::rgbxyY(RR, GG, BB, xxyycurr_reduc[2 * i][tt], xxyycurr_reduc[2 * i + 1][tt], unused, wp);
}
+
//recalculate xy spectral now with good range of temp and green
for (int j = 0; j < Nc ; ++j) {
@@ -5257,6 +5474,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
}
int kkg = -1;
+
for (int i = 0; i < Nc ; ++i) {
if (good_spectral[i]) {
kkg++;
@@ -5264,6 +5482,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
reff_spect_xxyy[2 * kkg + 1][tt] = reff_spect_xxyy_prov[2 * i + 1][tt];
}
}
+
//now we have good spectral data
//calculate student correlation
const float abstudgr = std::fabs(studentXY(xxyycurr_reduc, reff_spect_xxyy, 2 * w, 2 * kkg, tt));
@@ -5272,6 +5491,7 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
minstudgr = abstudgr;
goodrefgr = tt;
}
+
//found the values
Tgstud[gr].tempref = goodrefgr;
Tgstud[gr].greenref = gr;
@@ -5282,48 +5502,35 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
std::sort(Tgstud, Tgstud + N_g, Tgstud[0]);
- //now search the value of green the nearest of 1 with a good student value
- // I take the 3 first values
- //I admit a symetrie in green coefiicient for rgb multiplier...probably not exactly true
- //perhaps we can used a Snedecor test ? but why...at least we have confidence interval > 90%
- int greengood;
- int greengoodprov;
- int goodrefprov;
- float studprov;
- const int goodref0 = Tgstud[0].tempref;
- const int greengood0 = Tgstud[0].greenref - 55;//55 green = 1
- const float stud0 = Tgstud[0].student;
- const int goodref1 = Tgstud[1].tempref;
- const float stud1 = Tgstud[1].student;
- const int greengood1 = Tgstud[1].greenref - 55;
- const int goodref2 = Tgstud[2].tempref;
- const int greengood2 = Tgstud[2].greenref - 55;
- const float stud2 = Tgstud[2].student;
+ // now search the value of green the nearest of 1 with a good student value, I think it is a good choice, perhaps no...
+ // I take the 5 first values
+ // I admit a symetrie in green coefiicient for rgb multiplier...probably not exactly true
+ // perhaps we can used a Snedecor test ? but why...at least we have confidence interval > 90%
+ int greengood = 55;
- if (std::fabs(greengood2) < std::fabs(greengood1)) {
- greengoodprov = greengood2;
- goodrefprov = goodref2;
- studprov = stud2;
- } else {
- greengoodprov = greengood1;
- goodrefprov = goodref1;
- studprov = stud1;
+ int maxkgood = 5;//we can change ...to test 3, 4, 5. High values perhaps less good student, but it is a compromise...
+ int mingood = std::min(std::fabs(Tgstud[0].greenref - 55), std::fabs(Tgstud[1].greenref - 55));
+ for (int k = 2; k < maxkgood; ++k) {
+ mingood = std::min(std::fabs(mingood), std::fabs(Tgstud[k].greenref - 55));
}
- if (std::fabs(greengoodprov) < std::fabs(greengood0)) {
- goodref = goodrefprov;
- greengood = greengoodprov + 55;
- studgood = studprov;
+ for (int k = 0; k < maxkgood ; ++k) {
+ if (mingood == fabs(Tgstud[k].greenref - 55)) {
+ greengood = Tgstud[k].greenref ;
+ goodref = Tgstud[k].tempref;
+ studgood = Tgstud[k].student;;
+ }
+ }
- } else {
- goodref = goodref0;
- greengood = greengood0 + 55;
- studgood = stud0;
+ if (settings->verbose) {
+ printf("Student_0=%f Student_k= %f\n", Tgstud[0].student, Tgstud[maxkgood - 1].student);
+ printf("mingood=%i greeng=%i goodref=%i stud=%f\n", mingood, greengood, goodref, (double) studgood);
}
tempitc = Txyz[goodref].Tem;
greenitc = gree[greengood].green;
+
if (estimchrom < 0.025f) {
float ac = -2.40f * estimchrom + 0.06f;//small empirical correction, maximum 0.06 if chroma=0 for all image, currently for very low chroma +0.02
greenitc += ac;
@@ -5337,13 +5544,14 @@ void RawImageSource::ItcWB(bool extra, double &tempref, double &greenref, double
if (!extra) {
tempitc = Txyz[goodref].Tem;
}
+
//now we have temp green and student
if (settings->verbose) {
printf("ITCWB tempitc=%f gritc=%f stud=%f \n", tempitc, greenitc, studgood);
}
}
-void RawImageSource::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 WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams & cmp, const RAWParams & raw)
+void RawImageSource::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 WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams & cmp, const RAWParams & raw, const ToneCurveParams &hrp)
{
// BENCHFUN
//auto white balance
@@ -5364,8 +5572,7 @@ void RawImageSource::WBauto(double & tempref, double & greenref, array2D
}
tempitc = 5000.;
-
- ItcWB(extra, tempref, greenref, tempitc, greenitc, studgood, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, cmp, raw, wbpar);
+ ItcWB(extra, tempref, greenref, tempitc, greenitc, studgood, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, cmp, raw, wbpar, hrp);
}
}
@@ -5373,15 +5580,18 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
{
// BENCHFUN
//used by auto WB local to calculate red, green, blue in local region
+
int precision = 5;
+
if (settings->itcwb_precis == 5) {
precision = 5;
} else if (settings->itcwb_precis < 5) {
- precision = 3;
+ 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);
@@ -5404,6 +5614,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
#ifdef _OPENMP
#pragma omp parallel for reduction(+:avgL, nn)
#endif
+
for (int i = 0; i < H; i ++) {
for (int j = 0; j < W; j++) {
const float LL = 0.299f * red[i][j] + 0.587f * green[i][j] + 0.114f * blue[i][j];
@@ -5411,6 +5622,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
nn++;
}
}
+
avgL /= nn;
double vari = 0.f;
@@ -5419,6 +5631,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
#ifdef _OPENMP
#pragma omp parallel for reduction(+:vari, mm)
#endif
+
for (int i = 0; i < H; i++)
for (int j = 0; j < W; j++) {
const float LL = 0.299f * red[i][j] + 0.587f * green[i][j] + 0.114f * blue[i][j];
@@ -5432,8 +5645,10 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
#ifdef _OPENMP
#pragma omp parallel for
#endif
+
for (int i = 0; i < bfh; ++i) {
const int ii = i * precision;
+
if (ii < H) {
for (int j = 0, jj = 0; j < bfw; ++j, jj += precision) {
redloc[i][j] = red[ii][jj] * multip;
@@ -5444,7 +5659,7 @@ void RawImageSource::getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int
}
}
-void RawImageSource::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 WBParams & wbpar, const ColorManagementParams & cmp, const RAWParams & raw)
+void RawImageSource::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 WBParams & wbpar, const ColorManagementParams & cmp, const RAWParams & raw, const ToneCurveParams &hrp)
{
// BENCHFUN
constexpr double clipHigh = 64000.0;
@@ -5459,6 +5674,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
double avg_b = 0;
int rn = 0, gn = 0, bn = 0;
double avg_rm, avg_gm, avg_bm;
+
if (wbpar.method == "autold") {
if (fuji) {
for (int i = 32; i < H - 32; i++) {
@@ -5468,7 +5684,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
for (int j = start; j < end; j++) {
if (ri->getSensorType() != ST_BAYER) {
- double dr = CLIP(initialGain * (rawData[i][3 * j] ));
+ double dr = CLIP(initialGain * (rawData[i][3 * j]));
double dg = CLIP(initialGain * (rawData[i][3 * j + 1]));
double db = CLIP(initialGain * (rawData[i][3 * j + 2]));
@@ -5507,18 +5723,18 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
if (ri->getSensorType() == ST_FUJI_XTRANS) {
const double compval = clipHigh / initialGain;
#ifdef _OPENMP
- #pragma omp parallel
+ #pragma omp parallel
#endif
{
double avg_c[3] = {0.0};
int cn[3] = {0};
#ifdef _OPENMP
- #pragma omp for schedule(dynamic,16) nowait
+ #pragma omp for schedule(dynamic,16) nowait
#endif
for (int i = 32; i < H - 32; i++) {
for (int j = 32; j < W - 32; j++) {
- // each loop read 1 rgb triplet value
+ // each loop read 1 rgb triplet value
double d = rawData[i][j];
if (d > compval) {
@@ -5532,7 +5748,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
}
#ifdef _OPENMP
- #pragma omp critical
+ #pragma omp critical
#endif
{
avg_r += avg_c[0];
@@ -5549,9 +5765,9 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
} else {
for (int i = 32; i < H - 32; i++)
for (int j = 32; j < W - 32; j++) {
- // each loop read 1 rgb triplet value
+ // each loop read 1 rgb triplet value
- double dr = CLIP(initialGain * (rawData[i][3 * j] ));
+ double dr = CLIP(initialGain * (rawData[i][3 * j]));
double dg = CLIP(initialGain * (rawData[i][3 * j + 1]));
double db = CLIP(initialGain * (rawData[i][3 * j + 2]));
@@ -5569,7 +5785,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
bn = rn;
}
} else {
- //determine GRBG coset; (ey,ex) is the offset of the R subarray
+ //determine GRBG coset; (ey,ex) is the offset of the R subarray
int ey, ex;
if (ri->ISGREEN(0, 0)) { //first pixel is G
@@ -5592,12 +5808,12 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
const double compval = clipHigh / initialGain;
#ifdef _OPENMP
- #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,rn,gn,bn) schedule(dynamic,8)
+ #pragma omp parallel for reduction(+:avg_r,avg_g,avg_b,rn,gn,bn) schedule(dynamic,8)
#endif
for (int i = 32; i < H - 32; i += 2)
for (int j = 32; j < W - 32; j += 2) {
- //average each Bayer quartet component individually if non-clipped
+ //average each Bayer quartet component individually if non-clipped
double d[2][2];
d[0][0] = rawData[i][j];
d[0][1] = rawData[i][j + 1];
@@ -5636,17 +5852,18 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
if (wbpar.method == "autitcgreen") {
bool twotimes = false;
int precision = 5;
+
if (settings->itcwb_precis == 5) {
precision = 5;
} else if (settings->itcwb_precis < 5) {
- precision = 3;
+ 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);
- WBauto(tempref, greenref, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, tempitc, greenitc, studgood, twotimes, wbpar, begx, begy, yEn, xEn, cx, cy, cmp, raw);
+ WBauto(tempref, greenref, redloc, greenloc, blueloc, bfw, bfh, avg_rm, avg_gm, avg_bm, tempitc, greenitc, studgood, twotimes, wbpar, begx, begy, yEn, xEn, cx, cy, cmp, raw, hrp);
}
redloc(0, 0);
@@ -5654,7 +5871,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
blueloc(0, 0);
if (settings->verbose) {
- printf ("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn));
+ printf("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn));
}
if (wbpar.method == "autitcgreen") {
@@ -5673,7 +5890,7 @@ void RawImageSource::getAutoWBMultipliersitc(double & tempref, double & greenref
}
-void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
+void RawImageSource::getAutoWBMultipliers(double &rm, double &gm, double &bm)
{
// BENCHFUN
constexpr double clipHigh = 64000.0;
@@ -5710,7 +5927,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
for (int j = start; j < end; j++) {
if (ri->getSensorType() != ST_BAYER) {
- double dr = CLIP(initialGain * (rawData[i][3 * j] ));
+ double dr = CLIP(initialGain * (rawData[i][3 * j]));
double dg = CLIP(initialGain * (rawData[i][3 * j + 1]));
double db = CLIP(initialGain * (rawData[i][3 * j + 2]));
@@ -5793,7 +6010,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
for (int j = 32; j < W - 32; j++) {
// each loop read 1 rgb triplet value
- double dr = CLIP(initialGain * (rawData[i][3 * j] ));
+ double dr = CLIP(initialGain * (rawData[i][3 * j]));
double dg = CLIP(initialGain * (rawData[i][3 * j + 1]));
double db = CLIP(initialGain * (rawData[i][3 * j + 2]));
@@ -5875,7 +6092,7 @@ void RawImageSource::getAutoWBMultipliers (double &rm, double &gm, double &bm)
}
if (settings->verbose) {
- printf ("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn));
+ printf("AVG: %g %g %g\n", avg_r / std::max(1, rn), avg_g / std::max(1, gn), avg_b / std::max(1, bn));
}
// return ColorTemp (pow(avg_r/rn, 1.0/6.0)*img_r, pow(avg_g/gn, 1.0/6.0)*img_g, pow(avg_b/bn, 1.0/6.0)*img_b);
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index d7549fe71..fabea5ffc 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -112,7 +112,7 @@ protected:
void hlRecovery(const std::string &method, float* red, float* green, float* blue, int width, float* hlmax);
void transformRect(const PreviewProps &pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw);
void transformPosition(int x, int y, int tran, int& tx, int& ty);
- void 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 procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::WBParams & wbpar);
+ void 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 procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::WBParams & wbpar, const procparams::ToneCurveParams &hrp);
unsigned FC(int row, int col) const;
inline void getRowStartEnd (int x, int &start, int &end);
@@ -141,12 +141,12 @@ public:
void processFlatField(const procparams::RAWParams &raw, const RawImage *riFlatFile, array2D &rawData, const float black[4]);
void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D &rawData );
void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D &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) 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) 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;
void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w) 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) override;
+ void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override;
eSensorType getSensorType () const override;
bool isMono () const override;
ColorTemp getWB () const override
@@ -199,7 +199,8 @@ public:
void MSR(float** luminance, float **originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const procparams::RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
void HLRecovery_inpaint (float** red, float** green, float** blue, int blur);
- static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval);
+ void highlight_recovery_opposed(float scale_mul[3], const ColorTemp &wb, float gainth);
+ static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval);
static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]);
static void HLRecovery_blend (float* rin, float* gin, float* bin, int width, float maxval, float* hlmax);
static void init ();
@@ -308,6 +309,9 @@ protected:
void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override;
void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override;
void applyDngGainMap(const float black[4], const std::vector &gainMaps);
+public:
+ void wbMul2Camera(double &rm, double &gm, double &bm) override;
+ void wbCamera2Mul(double &rm, double &gm, double &bm) override;
};
}
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index 3916adfbe..eb4a3f888 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -94,7 +94,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
HDR, // EvCACorr,
ALLNORAW, // EvHREnabled,
0, // EvHRAmount : obsolete,
- ALLNORAW, // EvHRMethod,
+ ALLNORAW|M_RAW, // EvHRMethod,
DEMOSAIC, // EvWProfile,
OUTPUTPROFILE, // EvOProfile,
ALLNORAW, // EvIProfile,
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 86f1c1372..84c33a734 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -349,7 +349,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml
PreviewProps pp(0, 0, w, h, 1);
Imagefloat tmp(w, h);
- src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw);
+ src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw, 0);
src.convertColorSpace(&tmp, neutral.icm, src.getWB());
Image8 *img = new Image8(w, h);
diff --git a/rtengine/settings.h b/rtengine/settings.h
index 1c8c73630..6e787a112 100644
--- a/rtengine/settings.h
+++ b/rtengine/settings.h
@@ -44,6 +44,7 @@ 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
@@ -94,7 +95,7 @@ public:
// bool showtooltip;
int itcwb_thres;
- bool itcwb_sort;
+ bool itcwb_sorted;
int itcwb_greenrange;
int itcwb_greendeltatemp;
bool itcwb_forceextra;
@@ -102,6 +103,7 @@ public:
int itcwb_delta;
bool itcwb_stdobserver10;
int itcwb_precis;
+ bool itcwb_nopurple;
//wavelet levels
double edghi;
double edglo;
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index c542cf726..5de3b08b0 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -261,7 +261,7 @@ private:
pl->setProgress(0.40);
}
- imgsrc->HLRecovery_Global(params.toneCurve);
+ // imgsrc->HLRecovery_Global(params.toneCurve);
if (pl) {
@@ -372,7 +372,7 @@ private:
int beg_tileW = wcr * tileWskip + tileWskip / 2.f - crW / 2.f;
int beg_tileH = hcr * tileHskip + tileHskip / 2.f - crH / 2.f;
PreviewProps ppP(beg_tileW, beg_tileH, crW, crH, skipP);
- imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw);
+ imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0);
//baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve);
// we only need image reduced to 1/4 here
@@ -596,7 +596,7 @@ private:
for (int wcr = 0; wcr <= 2; wcr++) {
for (int hcr = 0; hcr <= 2; hcr++) {
PreviewProps ppP(coordW[wcr], coordH[hcr], crW, crH, 1);
- imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw);
+ imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0);
//baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve);
@@ -756,7 +756,7 @@ private:
}
baseImg = new Imagefloat(fw, fh);
- imgsrc->getImage(currWB, tr, baseImg, pp, params.toneCurve, params.raw);
+ imgsrc->getImage(currWB, tr, baseImg, pp, params.toneCurve, params.raw, 1);
if (pl) {
pl->setProgress(0.50);
diff --git a/rtengine/spot.cc b/rtengine/spot.cc
index 5ed090712..09186a399 100644
--- a/rtengine/spot.cc
+++ b/rtengine/spot.cc
@@ -459,7 +459,7 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s
}
}
- imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw);
+ imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw, 0);
if (cmp) {
imgsrc->convertColorSpace(srcImage, *cmp, currWB);
}
@@ -479,7 +479,7 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s
dstImage->b(y, x) = 60000.f;
}
}
- imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw);
+ imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw, 0);
if (cmp) {
imgsrc->convertColorSpace(dstImage, *cmp, currWB);
}
diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc
index 8cb8fa792..a3f2502f0 100644
--- a/rtengine/stdimagesource.cc
+++ b/rtengine/stdimagesource.cc
@@ -193,7 +193,7 @@ int StdImageSource::load (const Glib::ustring &fname)
return 0;
}
-void StdImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw)
+void StdImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw, int opposed)
{
// the code will use OpenMP as of now.
@@ -311,11 +311,11 @@ void StdImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr)
}
}
-void StdImageSource::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 WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams &cmp, const RAWParams &raw)
+void StdImageSource::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 WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const ColorManagementParams &cmp, const RAWParams &raw, const ToneCurveParams &hrp)
{
}
-void StdImageSource::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 WBParams & wbpar, const ColorManagementParams &cmp, const RAWParams &raw)
+void StdImageSource::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 WBParams & wbpar, const ColorManagementParams &cmp, const RAWParams &raw, const ToneCurveParams &hrp)
{
if (redAWBMul != -1.) {
rm = redAWBMul;
@@ -324,7 +324,7 @@ void StdImageSource::getAutoWBMultipliersitc(double &tempref, double &greenref,
return;
}
- img->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc,studgood, begx, begy, yEn, xEn, cx, cy, bf_h, bf_w, rm, gm, bm, params->wb, params->icm, params->raw);
+ img->getAutoWBMultipliersitc(tempref, greenref, tempitc, greenitc,studgood, begx, begy, yEn, xEn, cx, cy, bf_h, bf_w, rm, gm, bm, params->wb, params->icm, params->raw, params->toneCurve);
redAWBMul = rm;
greenAWBMul = gm;
@@ -367,6 +367,20 @@ void StdImageSource::flush() {
img->allocate(0, 0);
};
+void StdImageSource::wbMul2Camera(double &rm, double &gm, double &bm)
+{
+ rm = 1.0 / rm;
+ gm = 1.0 / gm;
+ bm = 1.0 / bm;
+}
+
+
+void StdImageSource::wbCamera2Mul(double &rm, double &gm, double &bm)
+{
+ rm = 1.0 / rm;
+ gm = 1.0 / gm;
+ bm = 1.0 / bm;
+}
}
diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h
index f83c58a04..90c4be654 100644
--- a/rtengine/stdimagesource.h
+++ b/rtengine/stdimagesource.h
@@ -58,7 +58,7 @@ public:
int load (const Glib::ustring &fname) 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) 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 {};
ColorTemp getWB () const override
{
@@ -66,8 +66,8 @@ public:
}
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;
- 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) 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) 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;
eSensorType getSensorType() const override {return ST_NONE;}
bool isMono() const override {return false;}
@@ -123,6 +123,8 @@ public:
void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override { R = G = B = 0;}
+ void wbMul2Camera(double &rm, double &gm, double &bm) override;
+ void wbCamera2Mul(double &rm, double &gm, double &bm) override;
void flush () override;
void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override {};
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 3ce97567c..66b9e92a1 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -594,6 +594,7 @@ 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,14 +624,15 @@ void Options::setDefaults()
rtSettings.fftwsigma = true; //choice between sigma^2 or empirical formula
rtSettings.itcwb_thres = 34;//between 10 to 55
- rtSettings.itcwb_sort = false;
+ 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 = 5;//3 or 5 or 9
+ rtSettings.itcwb_precis = 3;//3 or 5 or 9
+ rtSettings.itcwb_nopurple = true;
// end locallab
//wavelet
@@ -1760,6 +1762,10 @@ 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");
}
@@ -1795,14 +1801,18 @@ void Options::readFromFile(Glib::ustring fname)
rtSettings.itcwb_thres = keyFile.get_integer("Color Management", "Itcwb_thres");
}
- if (keyFile.has_key("Color Management", "Itcwb_sort")) {
- rtSettings.itcwb_sort = keyFile.get_boolean("Color Management", "Itcwb_sort");
+ 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");
}
@@ -2563,6 +2573,7 @@ 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);
@@ -2596,10 +2607,11 @@ void Options::saveToFile(Glib::ustring fname)
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_sort", rtSettings.itcwb_sort);
+ 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);
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index 7d641d753..abd4e8608 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -48,6 +48,7 @@ void ParamsEdited::set(bool v)
toneCurve.shcompr = v;
toneCurve.hlcompr = v;
toneCurve.hlbl = v;
+ toneCurve.hlth = v;
toneCurve.hlcomprthresh = v;
toneCurve.autoexp = v;
toneCurve.clip = v;
@@ -749,6 +750,7 @@ void ParamsEdited::initFrom(const std::vector&
toneCurve.shcompr = toneCurve.shcompr && p.toneCurve.shcompr == other.toneCurve.shcompr;
toneCurve.hlcompr = toneCurve.hlcompr && p.toneCurve.hlcompr == other.toneCurve.hlcompr;
toneCurve.hlbl = toneCurve.hlbl && p.toneCurve.hlbl == other.toneCurve.hlbl;
+ toneCurve.hlth = toneCurve.hlth && p.toneCurve.hlth == other.toneCurve.hlth;
toneCurve.hlcomprthresh = toneCurve.hlcomprthresh && p.toneCurve.hlcomprthresh == other.toneCurve.hlcomprthresh;
toneCurve.autoexp = toneCurve.autoexp && p.toneCurve.autoexp == other.toneCurve.autoexp;
toneCurve.clip = toneCurve.clip && p.toneCurve.clip == other.toneCurve.clip;
@@ -2192,6 +2194,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.toneCurve.hlbl = mods.toneCurve.hlbl;
}
+ if (toneCurve.hlth) {
+ toEdit.toneCurve.hlth = mods.toneCurve.hlth;
+ }
+
if (toneCurve.histmatching) {
toEdit.toneCurve.histmatching = mods.toneCurve.histmatching;
}
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 616e6d261..66db8346f 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -52,6 +52,7 @@ struct ToneCurveParamsEdited {
bool shcompr;
bool hlcompr;
bool hlbl;
+ bool hlth;
bool hlcomprthresh;
bool autoexp;
bool clip;
diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc
index c39bd3bda..bf81c6f22 100644
--- a/rtgui/tonecurve.cc
+++ b/rtgui/tonecurve.cc
@@ -42,6 +42,7 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL
EvHistMatchingBatch = m->newEvent(M_VOID, "HISTORY_MSG_HISTMATCHING");
EvClampOOG = m->newEvent(DARKFRAME, "HISTORY_MSG_CLAMPOOG");
EvHLbl = m->newEvent(DEMOSAIC, "HISTORY_MSG_HLBL");
+ EvHLth = m->newEvent(DEMOSAIC, "HISTORY_MSG_HLTH");
CurveListener::setMulti(true);
@@ -97,13 +98,14 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL
method = Gtk::manage (new MyComboBoxText ());
method->append (M("TP_HLREC_LUMINANCE"));
method->append (M("TP_HLREC_CIELAB"));
- method->append (M("TP_HLREC_COLOR"));
method->append (M("TP_HLREC_BLEND"));
+ method->append (M("TP_HLREC_COLOR"));
+ method->append (M("TP_HLREC_COLOROPP"));
Gtk::Box *hrVBox;
hrVBox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
hrVBox->set_spacing(2);
- method->set_active(0);
+ method->set_active(4);
Gtk::Frame* const hrFrame = Gtk::manage(new Gtk::Frame());
hrFrame->set_label_align(0.025, 0.5);
hrFrame->set_label_widget(*hrenabled);
@@ -113,9 +115,11 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL
hlrbox->pack_start (*lab, Gtk::PACK_SHRINK);
hlrbox->pack_start (*method);
hlbl = Gtk::manage(new Adjuster(M("TP_HLREC_HLBLUR"), 0, 4, 1, 0));
+ hlth = Gtk::manage(new Adjuster(M("TP_HLREC_HLTH"), 0.25, 1.75, 0.01, 1.));
hrVBox->pack_start(*hlrbox, Gtk::PACK_SHRINK);
hrVBox->pack_start(*hlbl);
+ hrVBox->pack_start(*hlth);
hrFrame->add(*hrVBox);
pack_start(*hrFrame);
@@ -223,6 +227,7 @@ ToneCurve::ToneCurve() : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOSURE_LABEL
black->setAdjusterListener(this);
hlcompr->setAdjusterListener(this);
hlbl->setAdjusterListener(this);
+ hlth->setAdjusterListener(this);
hlcomprthresh->setAdjusterListener(this);
shcompr->setAdjusterListener(this);
contrast->setAdjusterListener(this);
@@ -254,6 +259,7 @@ void ToneCurve::read(const ProcParams* pp, const ParamsEdited* pedited)
black->setValue(pp->toneCurve.black);
hlcompr->setValue(pp->toneCurve.hlcompr);
hlbl->setValue(pp->toneCurve.hlbl);
+ hlth->setValue(pp->toneCurve.hlth);
hlcomprthresh->setValue(pp->toneCurve.hlcomprthresh);
shcompr->setValue(pp->toneCurve.shcompr);
@@ -283,6 +289,7 @@ void ToneCurve::read(const ProcParams* pp, const ParamsEdited* pedited)
black->setEditedState(pedited->toneCurve.black ? Edited : UnEdited);
hlcompr->setEditedState(pedited->toneCurve.hlcompr ? Edited : UnEdited);
hlbl->setEditedState(pedited->toneCurve.hlbl ? Edited : UnEdited);
+ hlth->setEditedState(pedited->toneCurve.hlth ? Edited : UnEdited);
hlcomprthresh->setEditedState(pedited->toneCurve.hlcomprthresh ? Edited : UnEdited);
shcompr->setEditedState(pedited->toneCurve.shcompr ? Edited : UnEdited);
brightness->setEditedState(pedited->toneCurve.brightness ? Edited : UnEdited);
@@ -310,16 +317,18 @@ void ToneCurve::read(const ProcParams* pp, const ParamsEdited* pedited)
hrenabled->set_active(pp->toneCurve.hrenabled);
enaconn.block(false);
- if (pedited && !pedited->toneCurve.method) {
- method->set_active(4);
- } else if (pp->toneCurve.method == "Luminance") {
+ if (pedited && !pedited->toneCurve.method) {
+ method->set_active(5);
+ } else if (pp->toneCurve.method == "Luminance") {
method->set_active(0);
} else if (pp->toneCurve.method == "CIELab blending") {
method->set_active(1);
- } else if (pp->toneCurve.method == "Color") {
- method->set_active(2);
} else if (pp->toneCurve.method == "Blend") {
+ method->set_active(2);
+ } else if (pp->toneCurve.method == "Color") {
method->set_active(3);
+ } else if (pp->toneCurve.method == "Coloropp") {
+ method->set_active(4);
}
hrenabledChanged();
@@ -354,6 +363,7 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited)
pp->toneCurve.black = black->getValue();
pp->toneCurve.hlcompr = hlcompr->getValue();
pp->toneCurve.hlbl = hlbl->getValue();
+ pp->toneCurve.hlth = hlth->getValue();
pp->toneCurve.hlcomprthresh = hlcomprthresh->getValue();
pp->toneCurve.shcompr = shcompr->getValue();
pp->toneCurve.brightness = brightness->getValue();
@@ -403,6 +413,7 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited)
pedited->toneCurve.black = black->getEditedState();
pedited->toneCurve.hlcompr = hlcompr->getEditedState();
pedited->toneCurve.hlbl = hlbl->getEditedState();
+ pedited->toneCurve.hlth = hlth->getEditedState();
pedited->toneCurve.hlcomprthresh = hlcomprthresh->getEditedState();
pedited->toneCurve.shcompr = shcompr->getEditedState();
pedited->toneCurve.brightness = brightness->getEditedState();
@@ -414,7 +425,7 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited)
pedited->toneCurve.curve2 = !shape2->isUnChanged();
pedited->toneCurve.curveMode = toneCurveMode->get_active_row_number() != 6;
pedited->toneCurve.curveMode2 = toneCurveMode2->get_active_row_number() != 6;
- pedited->toneCurve.method = method->get_active_row_number() != 4;
+ pedited->toneCurve.method = method->get_active_row_number() != 5;
pedited->toneCurve.hrenabled = !hrenabled->get_inconsistent();
pedited->toneCurve.histmatching = !histmatching->get_inconsistent();
pedited->toneCurve.fromHistMatching = true;
@@ -428,9 +439,11 @@ void ToneCurve::write(ProcParams* pp, ParamsEdited* pedited)
} else if (method->get_active_row_number() == 1) {
pp->toneCurve.method = "CIELab blending";
} else if (method->get_active_row_number() == 2) {
- pp->toneCurve.method = "Color";
- } else if (method->get_active_row_number() == 3) {
pp->toneCurve.method = "Blend";
+ } else if (method->get_active_row_number() == 3) {
+ pp->toneCurve.method = "Color";
+ } else if (method->get_active_row_number() == 4) {
+ pp->toneCurve.method = "Coloropp";
}
}
@@ -454,15 +467,21 @@ void ToneCurve::hrenabledChanged()
if (hrenabled->get_active()) {
hlrbox->show();
hlrbox->set_sensitive(true);
- if (method->get_active_row_number() == 2) {
+ if (method->get_active_row_number() == 3) {
hlbl->show();
+ hlth->hide();
+ } else if (method->get_active_row_number() == 4){
+ hlbl->hide();
+ hlth->show();
} else {
hlbl->hide();
- }
+ hlth->hide();
+ }
} else {
hlrbox->show();
hlrbox->set_sensitive(false);
hlbl->hide();
+ hlth->hide();
}
}
@@ -487,11 +506,16 @@ void ToneCurve::hrenabledChanged()
void ToneCurve::methodChanged()
{
- if (method->get_active_row_number() == 2) {
+ if (method->get_active_row_number() == 3) {
hlbl->show();
- } else {
+ hlth->hide();
+ } else if (method->get_active_row_number() == 4){
hlbl->hide();
- }
+ hlth->show();
+ } else {
+ hlbl->hide();
+ hlth->hide();
+ }
if (listener) {
setHistmatching(false);
if (hrenabled->get_active()) {
@@ -513,6 +537,7 @@ void ToneCurve::setRaw(bool raw)
disableListener();
method->set_sensitive(raw);
hlbl->set_sensitive(raw);
+ hlth->set_sensitive(raw);
hrenabled->set_sensitive(raw);
histmatching->set_sensitive(raw);
enableListener();
@@ -526,6 +551,7 @@ void ToneCurve::setDefaults(const ProcParams* defParams, const ParamsEdited* ped
black->setDefault(defParams->toneCurve.black);
hlcompr->setDefault(defParams->toneCurve.hlcompr);
hlbl->setDefault(defParams->toneCurve.hlbl);
+ hlth->setDefault(defParams->toneCurve.hlth);
hlcomprthresh->setDefault(defParams->toneCurve.hlcomprthresh);
shcompr->setDefault(defParams->toneCurve.shcompr);
contrast->setDefault(defParams->toneCurve.contrast);
@@ -536,6 +562,7 @@ void ToneCurve::setDefaults(const ProcParams* defParams, const ParamsEdited* ped
black->setDefaultEditedState(pedited->toneCurve.black ? Edited : UnEdited);
hlcompr->setDefaultEditedState(pedited->toneCurve.hlcompr ? Edited : UnEdited);
hlbl->setDefaultEditedState(pedited->toneCurve.hlbl ? Edited : UnEdited);
+ hlth->setDefaultEditedState(pedited->toneCurve.hlth ? Edited : UnEdited);
hlcomprthresh->setDefaultEditedState(pedited->toneCurve.hlcomprthresh ? Edited : UnEdited);
shcompr->setDefaultEditedState(pedited->toneCurve.shcompr ? Edited : UnEdited);
brightness->setDefaultEditedState(pedited->toneCurve.brightness ? Edited : UnEdited);
@@ -546,6 +573,7 @@ void ToneCurve::setDefaults(const ProcParams* defParams, const ParamsEdited* ped
black->setDefaultEditedState(Irrelevant);
hlcompr->setDefaultEditedState(Irrelevant);
hlbl->setDefaultEditedState(Irrelevant);
+ hlth->setDefaultEditedState(Irrelevant);
hlcomprthresh->setDefaultEditedState(Irrelevant);
shcompr->setDefaultEditedState(Irrelevant);
brightness->setDefaultEditedState(Irrelevant);
@@ -660,6 +688,8 @@ void ToneCurve::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged(EvSaturation, costr);
} else if (a == hlbl) {
listener->panelChanged(EvHLbl, costr);
+ } else if (a == hlth) {
+ listener->panelChanged(EvHLth, costr);
} else if (a == hlcompr) {
listener->panelChanged(EvHLCompr, costr);
@@ -695,6 +725,7 @@ void ToneCurve::neutral_pressed()
expcomp->setValue(0);
hlcompr->setValue(0);
hlbl->setValue(0);
+ hlth->setValue(1.0);
hlcomprthresh->setValue(0);
brightness->setValue(0);
black->setValue(0);
@@ -707,6 +738,7 @@ void ToneCurve::neutral_pressed()
hlrbox->show();
hlrbox->set_sensitive(false);
hlbl->hide();
+ hlth->hide();
}
if (!black->getAddMode() && !batchMode) {
@@ -841,6 +873,7 @@ void ToneCurve::waitForAutoExp()
hrenabled->set_sensitive(false);
method->set_sensitive(false);
hlbl->set_sensitive(false);
+ hlth->set_sensitive(false);
histmatching->set_sensitive(false);
}
@@ -853,6 +886,7 @@ void ToneCurve::enableAll()
black->setEnabled(true);
hlcompr->setEnabled(true);
hlbl->setEnabled(true);
+ hlth->setEnabled(true);
hlcomprthresh->setEnabled(true);
shcompr->setEnabled(true);
contrast->setEnabled(true);
@@ -864,6 +898,7 @@ void ToneCurve::enableAll()
hrenabled->set_sensitive(true);
method->set_sensitive(true);
hlbl->set_sensitive(true);
+ hlth->set_sensitive(true);
histmatching->set_sensitive(true);
}
@@ -883,6 +918,7 @@ void ToneCurve::setBatchMode(bool batchMode)
black->showEditedCB();
hlcompr->showEditedCB();
hlbl->showEditedCB();
+ hlth->showEditedCB();
hlcomprthresh->showEditedCB();
shcompr->showEditedCB();
brightness->showEditedCB();
@@ -996,16 +1032,22 @@ void ToneCurve::autoExpChanged(double expcomp, int bright, int contr, int black,
if (nextHLRecons) {
hlrbox->show();
hlrbox->set_sensitive(true);
- if (method->get_active_row_number() == 2) {
+ if (method->get_active_row_number() == 3) {
hlbl->show();
- } else {
+ hlth->hide();
+ } else if (method->get_active_row_number() == 4){
hlbl->hide();
- }
+ hlth->show();
+ } else {
+ hlbl->hide();
+ hlth->hide();
+ }
} else if (!batchMode) {
hlrbox->show();
hlrbox->set_sensitive(false);
hlbl->hide();
- }
+ hlth->hide();
+ }
if (!this->black->getAddMode() && !batchMode) {
shcompr->set_sensitive(static_cast(this->black->getValue())); //at black=0 shcompr value has no effect
diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h
index 7ba2178ac..7f0f1ef69 100644
--- a/rtgui/tonecurve.h
+++ b/rtgui/tonecurve.h
@@ -48,6 +48,7 @@ protected:
sigc::connection enaconn;
bool lasthrEnabled;
Adjuster* hlbl;
+ Adjuster* hlth;
Gtk::Box* abox;
Gtk::Box* hlrbox;
@@ -82,6 +83,7 @@ protected:
rtengine::ProcEvent EvHistMatchingBatch;
rtengine::ProcEvent EvClampOOG;
rtengine::ProcEvent EvHLbl;
+ rtengine::ProcEvent EvHLth;
// used temporarily in eventing
double nextExpcomp;