diff --git a/rtdata/languages/default b/rtdata/languages/default index 763e9fd97..8605d53f5 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2187,13 +2187,17 @@ TP_LOCALLAB_MERTHR;Difference TP_LOCALLAB_MERFOU;Multiply TP_LOCALLAB_MERFIV;Addition TP_LOCALLAB_MERSIX;Divide -TP_LOCALLAB_MERSEV;Soft Light +TP_LOCALLAB_MERSEV;Soft Light Photshop +TP_LOCALLAB_MERSEV0;Soft Light Illusion +TP_LOCALLAB_MERSEV1;Soft Light W3C TP_LOCALLAB_MERSEV2;Hard Light TP_LOCALLAB_MERHEI;Overlay TP_LOCALLAB_MERNIN;Screen TP_LOCALLAB_MERTEN;Darken only TP_LOCALLAB_MERELE;Lighten only TP_LOCALLAB_MERTWE;Exclusion +TP_LOCALLAB_MERTHI;Color Burn +TP_LOCALLAB_MERFOR;Color Dodge TP_LOCALLAB_MASFRAME_TOOLTIP;For all masks.\nTake into account deltaE image to avoid retouching the selection area when sliders gamma mask, slope mask, chroma mask and contrast curves and levels contrasts curves and structure mask (if enabled tool) are used.\nDisabled in Inverse TP_LOCALLAB_WAMASKCOL;Mask Wavelet level TP_LOCALLAB_CSTHRESHOLDBLUR;Mask Wavelet level diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index c7d990aa2..db7391863 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -612,18 +612,26 @@ static void calcLocalParams(int sp, int oW, int oH, const LocallabParams& locall lp.mergecolMethod = 5; } else if (locallab.spots.at(sp).mergecolMethod == "sev") { lp.mergecolMethod = 6; - } else if (locallab.spots.at(sp).mergecolMethod == "sev2") { + } else if (locallab.spots.at(sp).mergecolMethod == "sev0") { lp.mergecolMethod = 7; - } else if (locallab.spots.at(sp).mergecolMethod == "hei") { + } else if (locallab.spots.at(sp).mergecolMethod == "sev1") { lp.mergecolMethod = 8; - } else if (locallab.spots.at(sp).mergecolMethod == "nin") { + } else if (locallab.spots.at(sp).mergecolMethod == "sev2") { lp.mergecolMethod = 9; - } else if (locallab.spots.at(sp).mergecolMethod == "ten") { + } else if (locallab.spots.at(sp).mergecolMethod == "hei") { lp.mergecolMethod = 10; - } else if (locallab.spots.at(sp).mergecolMethod == "ele") { + } else if (locallab.spots.at(sp).mergecolMethod == "nin") { lp.mergecolMethod = 11; - } else if (locallab.spots.at(sp).mergecolMethod == "twe") { + } else if (locallab.spots.at(sp).mergecolMethod == "ten") { lp.mergecolMethod = 12; + } else if (locallab.spots.at(sp).mergecolMethod == "ele") { + lp.mergecolMethod = 13; + } else if (locallab.spots.at(sp).mergecolMethod == "twe") { + lp.mergecolMethod = 14; + } else if (locallab.spots.at(sp).mergecolMethod == "thi") { + lp.mergecolMethod = 15; + } else if (locallab.spots.at(sp).mergecolMethod == "for") { + lp.mergecolMethod = 16; } lp.opacol = 0.01f * locallab.spots.at(sp).opacol; @@ -5437,9 +5445,9 @@ const int fftw_size[] = {18144, 18000, 17920, 17836, 17820, 17640, 17600, 17550, int N_fftwsize = sizeof(fftw_size) / sizeof(fftw_size[0]); -/* + static void softlig(float &a, float &b, float minc, float maxc) -{ +{ // as Photoshop float alpha = 0.5f * (maxc - minc); if (b <= alpha) { @@ -5448,12 +5456,45 @@ static void softlig(float &a, float &b, float minc, float maxc) a = 2.f * a * (maxc - b) + sqrt(LIM(a, 0.f, 2.f)) * (2.f * b - maxc); } } -*/ + + +static void softlig3(float &a, float &b) +{// as w3C + if (b <= 0.5f){ + a = a - (1.f - 2.f * b) * a * (1.f - a); + } else if(((2.f * b) > 1.f) && ((4.f * a) <= 1.f)) { + a = a + ((2.f * b) - 1.f) * (4.f * a * ((4.f * a) + 1.f) * (a - 1.f) + 7.f * a); + } else if(((2.f * b) > 1.f) && ((4.f * a) > 1.f)){ + a = a + ((2.f * a) - 1.f) * (pow(a, 0.5f) -a); + } + +} + + + static void softlig2(float &a, float &b) -{ +{ // illusions.hu a = pow(b, pow(2.f, (2.f * (0.5f - a)))); } +static void colburn(float &a, float &b) +{ // w3C + if(b == 0.f) { + a = 0.f; + } else { + a = 1.f - std::min(1.f, (1.f - a) / b); + } +} + +static void coldodge(float &a, float &b) +{ // w3C + if(b == 1.f) { + a = 1.f; + } else { + a = std::min(1.f, a / (1.f - b)); + } +} + static void overlay(float &a, float &b, float minc, float maxc) { float alpha = 0.5f * (maxc - minc); @@ -12452,7 +12493,28 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * (tmpImageorig->b(y, x) / (tmpImagereserv->b(y, x) + 0.00001f)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 6) { //soft light softlig (float &a, float &b) + } else if (lp.mergecolMethod == 6) { //soft light as Photoshop +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = tmpImageorig->r(y, x); + float b = tmpImagereserv->r(y, x); + softlig(a, b, minR, maxR); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = tmpImageorig->g(y, x); + b = tmpImagereserv->g(y, x); + softlig(a, b, minG, maxG); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = tmpImageorig->b(y, x); + b = tmpImagereserv->b(y, x); + softlig(a, b, minB, maxB); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 7) { //soft light as illusions.hu #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12461,22 +12523,40 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o for (int x = 0; x < bfw; x++) { float a = LIM01(tmpImageorig->r(y, x)); float b = tmpImagereserv->r(y, x); - // softlig(a, b, minR, maxR); softlig2(a, b); tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); a = LIM01(tmpImageorig->g(y, x)); b = tmpImagereserv->g(y, x); - // softlig(a, b, minG, maxG); softlig2(a, b); tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); a = LIM01(tmpImageorig->b(y, x)); b = tmpImagereserv->b(y, x); - // softlig(a, b, minB, maxB); softlig2(a, b); tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 7) { //hard light overlay (float &b, float &a) + } else if (lp.mergecolMethod == 8) { //soft light as W3C +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = tmpImagereserv->r(y, x); + softlig3(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = tmpImagereserv->g(y, x); + softlig3(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = tmpImagereserv->b(y, x); + softlig3(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 9) { //hard light overlay (float &b, float &a) #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12497,7 +12577,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 8) { //overlay overlay(float &a, float &b) + } else if (lp.mergecolMethod == 10) { //overlay overlay(float &a, float &b) #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12518,7 +12598,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 9) { //screen screen (float &a, float &b) + } else if (lp.mergecolMethod == 11) { //screen screen (float &a, float &b) #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12539,7 +12619,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 10) { //darken only + } else if (lp.mergecolMethod == 12) { //darken only #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12551,7 +12631,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * std::min(tmpImageorig->b(y, x), tmpImagereserv->b(y, x)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 11) { //lighten only + } else if (lp.mergecolMethod == 13) { //lighten only #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12563,7 +12643,7 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * std::max(tmpImageorig->b(y, x), tmpImagereserv->b(y, x)) + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } else if (lp.mergecolMethod == 12) { //exclusion exclusion (float &a, float &b) + } else if (lp.mergecolMethod == 14) { //exclusion exclusion (float &a, float &b) #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) #endif @@ -12584,8 +12664,50 @@ void ImProcFunctions::Lab_Local(int call, int sp, float** shbuffer, LabImage * o tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); } } - } + + } else if (lp.mergecolMethod == 15) { //Color burn +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = LIM01(tmpImagereserv->r(y, x)); + colburn(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = LIM01(tmpImagereserv->g(y, x)); + colburn(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = LIM01(tmpImagereserv->b(y, x)); + colburn(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } else if (lp.mergecolMethod == 16) { //Color dodge +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for (int y = 0; y < bfh ; y++) { + for (int x = 0; x < bfw; x++) { + float a = LIM01(tmpImageorig->r(y, x)); + float b = LIM01(tmpImagereserv->r(y, x)); + coldodge(a, b); + tmpImageorig->r(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->r(y, x); + a = LIM01(tmpImageorig->g(y, x)); + b = LIM01(tmpImagereserv->g(y, x)); + coldodge(a, b); + tmpImageorig->g(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->g(y, x); + a = LIM01(tmpImageorig->b(y, x)); + b = LIM01(tmpImagereserv->b(y, x)); + coldodge(a, b); + tmpImageorig->b(y, x) = lp.opacol * a + (1.f - lp.opacol) * tmpImageorig->b(y, x); + } + } + } tmpImageorig->normalizeFloatTo65535(); rgb2lab(*tmpImageorig, *bufcolfin, params->icm.workingProfile); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 59dc8b084..c8fb506c4 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2487,8 +2487,8 @@ LocallabParams::LocallabSpot::LocallabSpot() : // HHhmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 1.0, 0.35, 0.35, 0.50, 1.0, 0.35, 0.35, 1.00, 1.0, 0.35, 0.35 }, HHhmaskcurve{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 0.50, 0.5, 0.35, 0.35, 1.00, 0.5, 0.35, 0.35 }, softradiuscol(0.0), - opacol(100.0), - conthrcol(0.0), + opacol(40.0), + conthrcol(20.0), Lmaskcurve{(double)DCT_NURBS, 0.0, 0.0, 1.0, 1.0}, LLmaskcolcurvewav{(double)FCT_MinMaxCPoints, 0.0, 0.5, 0.35, 0.35, 1., 0.5, 0.35, 0.35}, csthresholdcol(0, 0, 6, 5, false), diff --git a/rtgui/locallab.cc b/rtgui/locallab.cc index d26bd83e3..7f60d07d9 100644 --- a/rtgui/locallab.cc +++ b/rtgui/locallab.cc @@ -266,8 +266,8 @@ Locallab::Locallab(): lapmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_LAPMASKCOL"), 0.0, 100.0, 0.1, 0.))), shadmaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SHAMASKCOL"), 0, 100, 1, 0))), softradiuscol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_SOFTRADIUSCOL"), 0.0, 100.0, 0.5, 0.))), - opacol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_OPACOL"), 0.0, 100.0, 0.5, 100.))), - conthrcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTTHR"), 0.0, 100.0, 0.5, 0.))), + opacol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_OPACOL"), 0.0, 100.0, 0.5, 40.))), + conthrcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_CONTTHR"), 0.0, 100.0, 0.5, 20.))), strumaskcol(Gtk::manage(new Adjuster(M("TP_LOCALLAB_STRUMASKCOL"), 0., 200., 0.1, 0.))), // Exposure expcomp(Gtk::manage(new Adjuster(M("TP_EXPOSURE_EXPCOMP"), -2.0, 3.0, 0.05, 0.0))), @@ -793,12 +793,16 @@ pe(nullptr) mergecolMethod->append(M("TP_LOCALLAB_MERFIV")); mergecolMethod->append(M("TP_LOCALLAB_MERSIX")); mergecolMethod->append(M("TP_LOCALLAB_MERSEV")); + mergecolMethod->append(M("TP_LOCALLAB_MERSEV0")); + mergecolMethod->append(M("TP_LOCALLAB_MERSEV1")); mergecolMethod->append(M("TP_LOCALLAB_MERSEV2")); mergecolMethod->append(M("TP_LOCALLAB_MERHEI")); mergecolMethod->append(M("TP_LOCALLAB_MERNIN")); mergecolMethod->append(M("TP_LOCALLAB_MERTEN")); mergecolMethod->append(M("TP_LOCALLAB_MERELE")); mergecolMethod->append(M("TP_LOCALLAB_MERTWE")); + mergecolMethod->append(M("TP_LOCALLAB_MERTHI")); + mergecolMethod->append(M("TP_LOCALLAB_MERFOR")); mergecolMethod->set_active(0); mergecolMethodConn = mergecolMethod->signal_changed().connect(sigc::mem_fun(*this, &Locallab::mergecolMethodChanged)); @@ -3714,17 +3718,25 @@ void Locallab::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited } else if (mergecolMethod->get_active_row_number() == 6) { pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "sev"; } else if (mergecolMethod->get_active_row_number() == 7) { - pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "sev2"; + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "sev0"; } else if (mergecolMethod->get_active_row_number() == 8) { - pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "hei"; + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "sev1"; } else if (mergecolMethod->get_active_row_number() == 9) { - pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "nin"; + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "sev2"; } else if (mergecolMethod->get_active_row_number() == 10) { - pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "ten"; + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "hei"; } else if (mergecolMethod->get_active_row_number() == 11) { - pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "ele"; + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "nin"; } else if (mergecolMethod->get_active_row_number() == 12) { + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "ten"; + } else if (mergecolMethod->get_active_row_number() == 13) { + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "ele"; + } else if (mergecolMethod->get_active_row_number() == 14) { pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "twe"; + } else if (mergecolMethod->get_active_row_number() == 15) { + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "thi"; + } else if (mergecolMethod->get_active_row_number() == 16) { + pp->locallab.spots.at(pp->locallab.selspot).mergecolMethod = "for"; } pp->locallab.spots.at(pp->locallab.selspot).llcurve = llshape->getCurve(); @@ -9003,18 +9015,26 @@ void Locallab::updateLocallabGUI(const rtengine::procparams::ProcParams* pp, con mergecolMethod->set_active(5); } else if (pp->locallab.spots.at(index).mergecolMethod == "sev") { mergecolMethod->set_active(6); - } else if (pp->locallab.spots.at(index).mergecolMethod == "sev2") { + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev0") { mergecolMethod->set_active(7); - } else if (pp->locallab.spots.at(index).mergecolMethod == "hei") { + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev1") { mergecolMethod->set_active(8); - } else if (pp->locallab.spots.at(index).mergecolMethod == "nin") { + } else if (pp->locallab.spots.at(index).mergecolMethod == "sev2") { mergecolMethod->set_active(9); - } else if (pp->locallab.spots.at(index).mergecolMethod == "ten") { + } else if (pp->locallab.spots.at(index).mergecolMethod == "hei") { mergecolMethod->set_active(10); - } else if (pp->locallab.spots.at(index).mergecolMethod == "ele") { + } else if (pp->locallab.spots.at(index).mergecolMethod == "nin") { mergecolMethod->set_active(11); - } else if (pp->locallab.spots.at(index).mergecolMethod == "twe") { + } else if (pp->locallab.spots.at(index).mergecolMethod == "ten") { mergecolMethod->set_active(12); + } else if (pp->locallab.spots.at(index).mergecolMethod == "ele") { + mergecolMethod->set_active(13); + } else if (pp->locallab.spots.at(index).mergecolMethod == "twe") { + mergecolMethod->set_active(14); + } else if (pp->locallab.spots.at(index).mergecolMethod == "thi") { + mergecolMethod->set_active(15); + } else if (pp->locallab.spots.at(index).mergecolMethod == "for") { + mergecolMethod->set_active(16); }