further fixes to ensure smooth transitions to clipped colours
This commit is contained in:
parent
acfdf220ec
commit
4344603a3d
@ -45,6 +45,16 @@ namespace rtengine
|
||||
class ToneCurve;
|
||||
class ColorAppearance;
|
||||
|
||||
template <typename T>
|
||||
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<float>(g * coef, 0.f, 65535.f);
|
||||
b = LIM<float>(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<float>(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
|
||||
b = CLIP<float>(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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<int> (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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user