Merge pull request #4275 from Beep6581/svb_tonecurve_speedup
Speedup for 'Saturation and Value Blending' tonecurve
This commit is contained in:
@@ -298,6 +298,36 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rgb2hsvtc(float r, float g, float b, float &h, float &s, float &v)
|
||||
{
|
||||
const float var_Min = min(r, g, b);
|
||||
const float var_Max = max(r, g, b);
|
||||
const float del_Max = var_Max - var_Min;
|
||||
|
||||
v = var_Max / 65535.f;
|
||||
|
||||
if (del_Max < 0.00001f) {
|
||||
h = 0.f;
|
||||
s = 0.f;
|
||||
} else {
|
||||
s = del_Max / var_Max;
|
||||
|
||||
if (r == var_Max) {
|
||||
h = (g - b) / del_Max;
|
||||
} else if (g == var_Max) {
|
||||
h = 2.f + (b - r) / del_Max;
|
||||
} else { /*if ( b == var_Max ) */
|
||||
h = 4.f + (r - g) / del_Max;
|
||||
}
|
||||
|
||||
if (h < 0.f) {
|
||||
h += 6.f;
|
||||
} else if (h > 6.f) {
|
||||
h -= 6.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert hue saturation value in red green blue
|
||||
* @param h hue channel [0 ; 1]
|
||||
@@ -312,14 +342,14 @@ public:
|
||||
static inline void hsv2rgbdcp (float h, float s, float v, float &r, float &g, float &b)
|
||||
{
|
||||
// special version for dcp which saves 1 division (in caller) and six multiplications (inside this function)
|
||||
int sector = h; // sector 0 to 5, floor() is very slow, and h is always >0
|
||||
float f = h - sector; // fractional part of h
|
||||
const int sector = h; // sector 0 to 5, floor() is very slow, and h is always > 0
|
||||
const float f = h - sector; // fractional part of h
|
||||
|
||||
v *= 65535.f;
|
||||
float vs = v * s;
|
||||
float p = v - vs;
|
||||
float q = v - f * vs;
|
||||
float t = p + v - q;
|
||||
const float vs = v * s;
|
||||
const float p = v - vs;
|
||||
const float q = v - f * vs;
|
||||
const float t = p + v - q;
|
||||
|
||||
switch (sector) {
|
||||
case 1:
|
||||
|
||||
@@ -1111,29 +1111,28 @@ inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) c
|
||||
|
||||
assert (lutToneCurve);
|
||||
|
||||
r = CLIP(r);
|
||||
g = CLIP(g);
|
||||
b = CLIP(b);
|
||||
|
||||
const float lum = (r + g + b) / 3.f;
|
||||
const float newLum = lutToneCurve[lum];
|
||||
|
||||
float h, s, v;
|
||||
float lum = (r + g + b) / 3.f;
|
||||
//float lum = Color::rgbLuminance(r, g, b);
|
||||
float newLum = lutToneCurve[lum];
|
||||
|
||||
if (newLum == lum) {
|
||||
return;
|
||||
}
|
||||
|
||||
Color::rgb2hsv(r, g, b, h, s, v);
|
||||
Color::rgb2hsvtc(r, g, b, h, s, v);
|
||||
|
||||
float dV;
|
||||
if (newLum > lum) {
|
||||
// Linearly targeting Value = 1 and Saturation = 0
|
||||
float coef = (newLum - lum) / (65535.f - lum);
|
||||
const float coef = (newLum - lum) / (65535.f - lum);
|
||||
dV = (1.f - v) * coef;
|
||||
s *= 1.f - coef;
|
||||
} else {
|
||||
// Linearly targeting Value = 0
|
||||
float coef = (newLum - lum) / lum ;
|
||||
const float coef = (newLum - lum) / lum ;
|
||||
dV = v * coef;
|
||||
}
|
||||
Color::hsv2rgb(h, s, v + dV, r, g, b);
|
||||
Color::hsv2rgbdcp(h, s, v + dV, r, g, b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -197,27 +197,22 @@ void proPhotoBlue(float *rtemp, float *gtemp, float *btemp, int istart, int tH,
|
||||
void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode curveMode, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize, PerceptualToneCurveState ptcApplyState) {
|
||||
|
||||
if (curveMode == ToneCurveParams::TcMode::STD) { // Standard
|
||||
const StandardToneCurve& userToneCurve = static_cast<const StandardToneCurve&> (customToneCurve);
|
||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||
const StandardToneCurve& userToneCurve = static_cast<const StandardToneCurve&> (customToneCurve);
|
||||
userToneCurve.BatchApply (
|
||||
0, tW - jstart,
|
||||
&rtemp[ti * tileSize], >emp[ti * tileSize], &btemp[ti * tileSize]);
|
||||
userToneCurve.BatchApply(0, tW - jstart, &rtemp[ti * tileSize], >emp[ti * tileSize], &btemp[ti * tileSize]);
|
||||
}
|
||||
} else if (curveMode == ToneCurveParams::TcMode::FILMLIKE) { // Adobe like
|
||||
const AdobeToneCurve& userToneCurve = static_cast<const AdobeToneCurve&> (customToneCurve);
|
||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||
const AdobeToneCurve& userToneCurve = static_cast<const AdobeToneCurve&> (customToneCurve);
|
||||
userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
|
||||
userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
|
||||
}
|
||||
}
|
||||
} else if (curveMode == ToneCurveParams::TcMode::SATANDVALBLENDING) { // apply the curve on the saturation and value channels
|
||||
const SatAndValueBlendingToneCurve& userToneCurve = static_cast<const SatAndValueBlendingToneCurve&> (customToneCurve);
|
||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||
const SatAndValueBlendingToneCurve& userToneCurve = static_cast<const SatAndValueBlendingToneCurve&> (customToneCurve);
|
||||
rtemp[ti * tileSize + tj] = CLIP<float> (rtemp[ti * tileSize + tj]);
|
||||
gtemp[ti * tileSize + tj] = CLIP<float> (gtemp[ti * tileSize + tj]);
|
||||
btemp[ti * tileSize + tj] = CLIP<float> (btemp[ti * tileSize + tj]);
|
||||
userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
|
||||
userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
|
||||
}
|
||||
}
|
||||
} else if (curveMode == ToneCurveParams::TcMode::WEIGHTEDSTD) { // apply the curve to the rgb channels, weighted
|
||||
@@ -233,7 +228,7 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode c
|
||||
rtemp[ti * tileSize + tj] = CLIP<float> (rtemp[ti * tileSize + tj]);
|
||||
gtemp[ti * tileSize + tj] = CLIP<float> (gtemp[ti * tileSize + tj]);
|
||||
btemp[ti * tileSize + tj] = CLIP<float> (btemp[ti * tileSize + tj]);
|
||||
userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
|
||||
userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj]);
|
||||
}
|
||||
}
|
||||
} else if (curveMode == ToneCurveParams::TcMode::PERCEPTUAL) { // apply curve while keeping color appearance constant
|
||||
@@ -244,7 +239,7 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode c
|
||||
rtemp[ti * tileSize + tj] = CLIP<float> (rtemp[ti * tileSize + tj]);
|
||||
gtemp[ti * tileSize + tj] = CLIP<float> (gtemp[ti * tileSize + tj]);
|
||||
btemp[ti * tileSize + tj] = CLIP<float> (btemp[ti * tileSize + tj]);
|
||||
userToneCurve.Apply (rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj], ptcApplyState);
|
||||
userToneCurve.Apply(rtemp[ti * tileSize + tj], gtemp[ti * tileSize + tj], btemp[ti * tileSize + tj], ptcApplyState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user