From 4344603a3d9c50e8268e33fd40f71edd95edf81b Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Wed, 4 Apr 2018 01:05:23 +0200 Subject: [PATCH] further fixes to ensure smooth transitions to clipped colours --- rtengine/curves.h | 67 ++++++++++++++++++++++---------------- rtengine/dcp.cc | 9 ++++-- rtengine/improcfun.cc | 75 +++++++++++++++++++------------------------ 3 files changed, 78 insertions(+), 73 deletions(-) diff --git a/rtengine/curves.h b/rtengine/curves.h index f10e9d5fc..42f5403bf 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -45,6 +45,16 @@ namespace rtengine class ToneCurve; class ColorAppearance; +template +void setUnlessOOG(T &r, T &g, T &b, const T &rr, const T &gg, const T &bb) +{ + if (!OOG(r) || !OOG(g) || !OOG(b)) { + r = rr; + g = gg; + b = bb; + } +} + namespace curves { inline void setLutVal(const LUTf &lut, float &val) @@ -60,6 +70,21 @@ inline void setLutVal(const LUTf &lut, float &val) } } + +inline void setLutVal(const LUTf &lut, float &rval, float &gval, float &bval) +{ + if (!OOG(rval) || !OOG(gval) || !OOG(bval)) { + rval = lut[std::max(rval, 0.f)]; + gval = lut[std::max(rval, 0.f)]; + bval = lut[std::max(rval, 0.f)]; + } else { + setLutVal(lut, rval); + setLutVal(lut, gval); + setLutVal(lut, bval); + } +} + + inline void setLutVal(float &val, float lutval, float maxval) { if (!OOG(val)) { @@ -69,6 +94,7 @@ inline void setLutVal(float &val, float lutval, float maxval) } } + } // namespace curves class CurveFactory @@ -907,9 +933,7 @@ inline void StandardToneCurve::Apply (float& r, float& g, float& b) const assert (lutToneCurve); - curves::setLutVal(lutToneCurve, r); - curves::setLutVal(lutToneCurve, g); - curves::setLutVal(lutToneCurve, b); + curves::setLutVal(lutToneCurve, r, g, b); } inline void StandardToneCurve::BatchApply( @@ -936,9 +960,7 @@ inline void StandardToneCurve::BatchApply( break; #endif } - curves::setLutVal(lutToneCurve, r[i]); - curves::setLutVal(lutToneCurve, g[i]); - curves::setLutVal(lutToneCurve, b[i]); + curves::setLutVal(lutToneCurve, r[i], g[i], b[i]); i++; } @@ -946,7 +968,7 @@ inline void StandardToneCurve::BatchApply( float tmpr[4] ALIGNED16; float tmpg[4] ALIGNED16; float tmpb[4] ALIGNED16; - float mv = lutToneCurve[MAXVALF]; + // float mv = lutToneCurve[MAXVALF]; for (; i + 3 < end; i += 4) { __m128 r_val = LVF(r[i]); __m128 g_val = LVF(g[i]); @@ -955,17 +977,16 @@ inline void StandardToneCurve::BatchApply( STVF(tmpg[0], lutToneCurve[g_val]); STVF(tmpb[0], lutToneCurve[b_val]); for (int j = 0; j < 4; ++j) { - curves::setLutVal(r[i+j], tmpr[j], mv); - curves::setLutVal(g[i+j], tmpg[j], mv); - curves::setLutVal(b[i+j], tmpb[j], mv); + setUnlessOOG(r[i+j], g[i+j], b[i+j], tmpr[j], tmpg[j], tmpb[j]); + // curves::setLutVal(r[i+j], tmpr[j], mv); + // curves::setLutVal(g[i+j], tmpg[j], mv); + // curves::setLutVal(b[i+j], tmpb[j], mv); } } // Remainder in non-SSE. for (; i < end; ++i) { - curves::setLutVal(lutToneCurve, r[i]); - curves::setLutVal(lutToneCurve, g[i]); - curves::setLutVal(lutToneCurve, b[i]); + curves::setLutVal(lutToneCurve, r[i], g[i], b[i]); } #endif } @@ -1003,9 +1024,7 @@ inline void AdobeToneCurve::Apply (float& ir, float& ig, float& ib) const } } - setUnlessOOG(ir, r); - setUnlessOOG(ig, g); - setUnlessOOG(ib, b); + setUnlessOOG(ir, ig, ib, r, g, b); } inline void AdobeToneCurve::RGBTone (float& r, float& g, float& b) const @@ -1034,9 +1053,7 @@ inline void LuminanceToneCurve::Apply(float &ir, float &ig, float &ib) const g = LIM(g * coef, 0.f, 65535.f); b = LIM(b * coef, 0.f, 65535.f); - setUnlessOOG(ir, r); - setUnlessOOG(ig, g); - setUnlessOOG(ib, b); + setUnlessOOG(ir, ig, ib, r, g, b); } inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const @@ -1094,9 +1111,7 @@ inline void WeightedStdToneCurve::Apply (float& ir, float& ig, float& ib) const g = CLIP(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f); b = CLIP(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f); - setUnlessOOG(ir, r); - setUnlessOOG(ig, g); - setUnlessOOG(ib, b); + setUnlessOOG(ir, ig, ib, r, g, b); } inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const { @@ -1154,9 +1169,7 @@ inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t en STVF(tmpg[0], LIMV(g1 * zd25v + g2 * zd5v + g3 * zd25v, ZEROV, c65535v)); STVF(tmpb[0], LIMV(b1 * zd25v + b2 * zd25v + b3 * zd5v, ZEROV, c65535v)); for (int j = 0; j < 4; ++j) { - setUnlessOOG(r[i+j], tmpr[j]); - setUnlessOOG(g[i+j], tmpg[j]); - setUnlessOOG(b[i+j], tmpb[j]); + setUnlessOOG(r[i+j], g[i+j], b[i+j], tmpr[j], tmpg[j], tmpb[j]); } } @@ -1201,9 +1214,7 @@ inline void SatAndValueBlendingToneCurve::Apply (float& ir, float& ig, float& ib } Color::hsv2rgbdcp(h, s, v + dV, r, g, b); - setUnlessOOG(ir, r); - setUnlessOOG(ig, g); - setUnlessOOG(ib, b); + setUnlessOOG(ir, ig, ib, r, g, b); } } diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 09d6bb263..fe798cb99 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -1190,6 +1190,11 @@ void DCPProfile::step2ApplyTile(float* rc, float* gc, float* bc, int width, int } // with looktable and tonecurve we need to clip + if (as_in.data->apply_look_table || as_in.data->use_tone_curve) { + newr = max(newr, 0.f); + newg = max(newg, 0.f); + newb = max(newb, 0.f); + } // newr = FCLIP(newr); // newg = FCLIP(newg); // newb = FCLIP(newb); @@ -1215,9 +1220,7 @@ void DCPProfile::step2ApplyTile(float* rc, float* gc, float* bc, int width, int Color::hsv2rgbdcp( h, s, v, cnewr, cnewg, cnewb); - setUnlessOOG(newr, cnewr); - setUnlessOOG(newg, cnewg); - setUnlessOOG(newb, cnewb); + setUnlessOOG(newr, newg, newb, cnewr, cnewg, cnewb); } if (as_in.data->use_tone_curve) { diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 231262a06..a49d00bdd 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3750,13 +3750,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } } - highlightToneCurve(hltonecurve, rtemp, gtemp, btemp, istart, tH, jstart, tW, TS, exp_scale, comp, hlrange); - shadowToneCurve(shtonecurve, rtemp, gtemp, btemp, istart, tH, jstart, tW, TS); - - if (dcpProf) { - dcpProf->step2ApplyTile (rtemp, gtemp, btemp, tW - jstart, tH - istart, TS, asIn); - } - for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { // clip out of gamut colors, without distorting colour too bad @@ -3764,7 +3757,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float g = std::max(gtemp[ti * TS + tj], 0.f); float b = std::max(btemp[ti * TS + tj], 0.f); - if (max(r, g, b) > MAXVALF && min(r, g, b) < MAXVALF) { + if (OOG(r) || OOG(g) || OOG(b)) { filmlike_clip (&r, &g, &b); } rtemp[ti * TS + tj] = r; @@ -3773,6 +3766,29 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } } + highlightToneCurve(hltonecurve, rtemp, gtemp, btemp, istart, tH, jstart, tW, TS, exp_scale, comp, hlrange); + shadowToneCurve(shtonecurve, rtemp, gtemp, btemp, istart, tH, jstart, tW, TS); + + if (dcpProf) { + dcpProf->step2ApplyTile (rtemp, gtemp, btemp, tW - jstart, tH - istart, TS, asIn); + } + + // for (int i = istart, ti = 0; i < tH; i++, ti++) { + // for (int j = jstart, tj = 0; j < tW; j++, tj++) { + // // clip out of gamut colors, without distorting colour too bad + // float r = std::max(rtemp[ti * TS + tj], 0.f); + // float g = std::max(gtemp[ti * TS + tj], 0.f); + // float b = std::max(btemp[ti * TS + tj], 0.f); + + // if (OOG(r) || OOG(g) || OOG(b)) { + // filmlike_clip (&r, &g, &b); + // } + // rtemp[ti * TS + tj] = r; + // gtemp[ti * TS + tj] = g; + // btemp[ti * TS + tj] = b; + // } + // } + if (histToneCurveThr) { for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { @@ -3785,9 +3801,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer int y = CLIP (lumimulf[0] * Color::gamma2curve[rtemp[ti * TS + tj]] + lumimulf[1] * Color::gamma2curve[gtemp[ti * TS + tj]] + lumimulf[2] * Color::gamma2curve[btemp[ti * TS + tj]]); histToneCurveThr[y >> histToneCurveCompression]++; - setUnlessOOG(rtemp[ti * TS + tj], r); - setUnlessOOG(gtemp[ti * TS + tj], g); - setUnlessOOG(btemp[ti * TS + tj], b); + setUnlessOOG(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], r, g, b); } } } else { @@ -3804,17 +3818,13 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer STVF(tmpg[0], tonecurve(LVF(gtemp[ti * TS + tj]))); STVF(tmpb[0], tonecurve(LVF(btemp[ti * TS + tj]))); for (int k = 0; k < 4; ++k) { - setUnlessOOG(rtemp[ti * TS + tj + k], tmpr[k]); - setUnlessOOG(gtemp[ti * TS + tj + k], tmpg[k]); - setUnlessOOG(btemp[ti * TS + tj + k], tmpb[k]); + setUnlessOOG(rtemp[ti * TS + tj + k], gtemp[ti * TS + tj + k], btemp[ti * TS + tj + k], tmpr[k], tmpg[k], tmpb[k]); } } #endif for (; j < tW; j++, tj++) { //brightness/contrast - setUnlessOOG(rtemp[ti * TS + tj], tonecurve[rtemp[ti * TS + tj]]); - setUnlessOOG(gtemp[ti * TS + tj], tonecurve[gtemp[ti * TS + tj]]); - setUnlessOOG(btemp[ti * TS + tj], tonecurve[btemp[ti * TS + tj]]); + setUnlessOOG(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], tonecurve[rtemp[ti * TS + tj]], tonecurve[gtemp[ti * TS + tj]], tonecurve[btemp[ti * TS + tj]]); } } } @@ -3952,9 +3962,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer Color::xyz2rgb (x_, y_, z_, r, g, b, wip); } - setUnlessOOG(rtemp[ti * TS + tj], r); - setUnlessOOG(gtemp[ti * TS + tj], g); - setUnlessOOG(btemp[ti * TS + tj], b); + setUnlessOOG(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], r, g, b); } } } @@ -4105,9 +4113,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer bo *= preserv; } - setUnlessOOG(rtemp[ti * TS + tj], CLIP(ro)); - setUnlessOOG(gtemp[ti * TS + tj], CLIP(go)); - setUnlessOOG(btemp[ti * TS + tj], CLIP(bo)); + setUnlessOOG(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], CLIP(ro), CLIP(go), CLIP(bo)); } } } @@ -4161,11 +4167,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float b = btemp[ti * TS + tj]; float ro, go, bo; labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip); - if (!OOG(rtemp[ti * TS + tj]) || !OOG(gtemp[ti * TS + tj]) || !OOG(btemp[ti * TS + tj])) { - rtemp[ti * TS + tj] = ro; - gtemp[ti * TS + tj] = go; - btemp[ti * TS + tj] = bo; - } + setUnlessOOG(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], ro, go, bo); } } } @@ -4502,11 +4504,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } for (int j = jstart, tj = 0; j < tW; j++, tj++) { - if (!OOG(rtemp[ti * TS + tj]) || !OOG(gtemp[ti * TS + tj]) || !OOG(btemp[ti * TS + tj])) { - rtemp[ti * TS + tj] = clutr[tj]; - gtemp[ti * TS + tj] = clutg[tj]; - btemp[ti * TS + tj] = clutb[tj]; - } + setUnlessOOG(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], clutr[tj], clutg[tj], clutb[tj]); } } } @@ -4840,12 +4838,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer float b = tmpImage->b (i, j); float ro, bo, go; labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip); - if (!OOG(tmpImage->r(i, j)) || !OOG(tmpImage->g(i, j)) || !OOG(tmpImage->b(i, j))) { - tmpImage->r (i, j) = ro; - tmpImage->g (i, j) = go; - tmpImage->b (i, j) = bo; - } - + setUnlessOOG(tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j), ro, go, bo); } } } @@ -5356,9 +5349,7 @@ void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &g preserv = lumbefore / lumafter; } - setUnlessOOG(ro, CLIP(r * preserv)); - setUnlessOOG(go, CLIP(g * preserv)); - setUnlessOOG(bo, CLIP(b * preserv)); + setUnlessOOG(ro, go, bo, CLIP(r * preserv), CLIP(g * preserv), CLIP(b * preserv)); } /**