started work on making RT not clip the image at intermediate stages
This commit is contained in:
@@ -1827,6 +1827,14 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
|
|||||||
const AdobeToneCurve& adobeTC = static_cast<const AdobeToneCurve&>((const ToneCurve&) * this);
|
const AdobeToneCurve& adobeTC = static_cast<const AdobeToneCurve&>((const ToneCurve&) * this);
|
||||||
|
|
||||||
for (size_t i = start; i < end; ++i) {
|
for (size_t i = start; i < end; ++i) {
|
||||||
|
const bool oog_r = OOG(rc[i]);
|
||||||
|
const bool oog_g = OOG(gc[i]);
|
||||||
|
const bool oog_b = OOG(bc[i]);
|
||||||
|
|
||||||
|
if (oog_r && oog_g && oog_b) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
float r = CLIP(rc[i]);
|
float r = CLIP(rc[i]);
|
||||||
float g = CLIP(gc[i]);
|
float g = CLIP(gc[i]);
|
||||||
float b = CLIP(bc[i]);
|
float b = CLIP(bc[i]);
|
||||||
@@ -1848,12 +1856,18 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
|
|||||||
|
|
||||||
if (ar >= 65535.f && ag >= 65535.f && ab >= 65535.f) {
|
if (ar >= 65535.f && ag >= 65535.f && ab >= 65535.f) {
|
||||||
// clip fast path, will also avoid strange colours of clipped highlights
|
// clip fast path, will also avoid strange colours of clipped highlights
|
||||||
rc[i] = gc[i] = bc[i] = 65535.f;
|
//rc[i] = gc[i] = bc[i] = 65535.f;
|
||||||
|
if (!oog_r) rc[i] = 65535.f;
|
||||||
|
if (!oog_g) gc[i] = 65535.f;
|
||||||
|
if (!oog_b) bc[i] = 65535.f;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ar <= 0.f && ag <= 0.f && ab <= 0.f) {
|
if (ar <= 0.f && ag <= 0.f && ab <= 0.f) {
|
||||||
rc[i] = gc[i] = bc[i] = 0;
|
//rc[i] = gc[i] = bc[i] = 0;
|
||||||
|
if (!oog_r) rc[i] = 0.f;
|
||||||
|
if (!oog_g) gc[i] = 0.f;
|
||||||
|
if (!oog_b) bc[i] = 0.f;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1893,9 +1907,9 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
|
|||||||
g = newg;
|
g = newg;
|
||||||
b = newb;
|
b = newb;
|
||||||
}
|
}
|
||||||
rc[i] = r;
|
if (!oog_r) rc[i] = r;
|
||||||
gc[i] = g;
|
if (!oog_g) gc[i] = g;
|
||||||
bc[i] = b;
|
if (!oog_b) bc[i] = b;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2003,9 +2017,9 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
|
|||||||
b = newb;
|
b = newb;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc[i] = r;
|
if (!oog_r) rc[i] = r;
|
||||||
gc[i] = g;
|
if (!oog_g) gc[i] = g;
|
||||||
bc[i] = b;
|
if (!oog_b) bc[i] = b;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2066,9 +2080,9 @@ void PerceptualToneCurve::BatchApply(const size_t start, const size_t end, float
|
|||||||
g = newg;
|
g = newg;
|
||||||
b = newb;
|
b = newb;
|
||||||
}
|
}
|
||||||
rc[i] = r;
|
if (!oog_r) rc[i] = r;
|
||||||
gc[i] = g;
|
if (!oog_g) gc[i] = g;
|
||||||
bc[i] = b;
|
if (!oog_b) bc[i] = b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float PerceptualToneCurve::cf_range[2];
|
float PerceptualToneCurve::cf_range[2];
|
||||||
|
|||||||
@@ -45,6 +45,29 @@ namespace rtengine
|
|||||||
class ToneCurve;
|
class ToneCurve;
|
||||||
class ColorAppearance;
|
class ColorAppearance;
|
||||||
|
|
||||||
|
namespace curves {
|
||||||
|
|
||||||
|
inline void setLutVal(const LUTf &lut, float &val)
|
||||||
|
{
|
||||||
|
if (!OOG(val)) {
|
||||||
|
val = lut[std::max(val, 0.f)];
|
||||||
|
} else {
|
||||||
|
float m = lut[MAXVALF];
|
||||||
|
val += (m - val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setLutVal(float &val, float lutval, float maxval)
|
||||||
|
{
|
||||||
|
if (!OOG(val)) {
|
||||||
|
val = lutval;
|
||||||
|
} else {
|
||||||
|
val += (maxval - val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace curves
|
||||||
|
|
||||||
class CurveFactory
|
class CurveFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -733,7 +756,7 @@ inline void Lightcurve::Apply (float& Li) const
|
|||||||
|
|
||||||
assert (lutColCurve);
|
assert (lutColCurve);
|
||||||
|
|
||||||
Li = lutColCurve[Li];
|
curves::setLutVal(lutColCurve, Li);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Brightcurve : public ColorAppearance
|
class Brightcurve : public ColorAppearance
|
||||||
@@ -748,7 +771,7 @@ inline void Brightcurve::Apply (float& Br) const
|
|||||||
|
|
||||||
assert (lutColCurve);
|
assert (lutColCurve);
|
||||||
|
|
||||||
Br = lutColCurve[Br];
|
curves::setLutVal(lutColCurve, Br);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Chromacurve : public ColorAppearance
|
class Chromacurve : public ColorAppearance
|
||||||
@@ -763,7 +786,7 @@ inline void Chromacurve::Apply (float& Cr) const
|
|||||||
|
|
||||||
assert (lutColCurve);
|
assert (lutColCurve);
|
||||||
|
|
||||||
Cr = lutColCurve[Cr];
|
curves::setLutVal(lutColCurve, Cr);
|
||||||
}
|
}
|
||||||
class Saturcurve : public ColorAppearance
|
class Saturcurve : public ColorAppearance
|
||||||
{
|
{
|
||||||
@@ -777,7 +800,7 @@ inline void Saturcurve::Apply (float& Sa) const
|
|||||||
|
|
||||||
assert (lutColCurve);
|
assert (lutColCurve);
|
||||||
|
|
||||||
Sa = lutColCurve[Sa];
|
curves::setLutVal(lutColCurve, Sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Colorfcurve : public ColorAppearance
|
class Colorfcurve : public ColorAppearance
|
||||||
@@ -792,7 +815,7 @@ inline void Colorfcurve::Apply (float& Cf) const
|
|||||||
|
|
||||||
assert (lutColCurve);
|
assert (lutColCurve);
|
||||||
|
|
||||||
Cf = lutColCurve[Cf];
|
curves::setLutVal(lutColCurve, Cf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -881,9 +904,9 @@ inline void StandardToneCurve::Apply (float& r, float& g, float& b) const
|
|||||||
|
|
||||||
assert (lutToneCurve);
|
assert (lutToneCurve);
|
||||||
|
|
||||||
r = lutToneCurve[r];
|
curves::setLutVal(lutToneCurve, r);
|
||||||
g = lutToneCurve[g];
|
curves::setLutVal(lutToneCurve, g);
|
||||||
b = lutToneCurve[b];
|
curves::setLutVal(lutToneCurve, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void StandardToneCurve::BatchApply(
|
inline void StandardToneCurve::BatchApply(
|
||||||
@@ -910,27 +933,36 @@ inline void StandardToneCurve::BatchApply(
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
r[i] = lutToneCurve[r[i]];
|
curves::setLutVal(lutToneCurve, r[i]);
|
||||||
g[i] = lutToneCurve[g[i]];
|
curves::setLutVal(lutToneCurve, g[i]);
|
||||||
b[i] = lutToneCurve[b[i]];
|
curves::setLutVal(lutToneCurve, b[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __SSE2__
|
#ifdef __SSE2__
|
||||||
|
float tmpr[4];
|
||||||
|
float tmpg[4];
|
||||||
|
float tmpb[4];
|
||||||
|
float mv = lutToneCurve[MAXVALF];
|
||||||
for (; i + 3 < end; i += 4) {
|
for (; i + 3 < end; i += 4) {
|
||||||
__m128 r_val = LVF(r[i]);
|
__m128 r_val = LVF(r[i]);
|
||||||
__m128 g_val = LVF(g[i]);
|
__m128 g_val = LVF(g[i]);
|
||||||
__m128 b_val = LVF(b[i]);
|
__m128 b_val = LVF(b[i]);
|
||||||
STVF(r[i], lutToneCurve[r_val]);
|
STVF(tmpr[0], lutToneCurve[r_val]);
|
||||||
STVF(g[i], lutToneCurve[g_val]);
|
STVF(tmpg[0], lutToneCurve[g_val]);
|
||||||
STVF(b[i], lutToneCurve[b_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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remainder in non-SSE.
|
// Remainder in non-SSE.
|
||||||
for (; i < end; ++i) {
|
for (; i < end; ++i) {
|
||||||
r[i] = lutToneCurve[r[i]];
|
curves::setLutVal(lutToneCurve, r[i]);
|
||||||
g[i] = lutToneCurve[g[i]];
|
curves::setLutVal(lutToneCurve, g[i]);
|
||||||
b[i] = lutToneCurve[b[i]];
|
curves::setLutVal(lutToneCurve, b[i]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -938,10 +970,13 @@ inline void StandardToneCurve::BatchApply(
|
|||||||
// Tone curve according to Adobe's reference implementation
|
// Tone curve according to Adobe's reference implementation
|
||||||
// values in 0xffff space
|
// values in 0xffff space
|
||||||
// inlined to make sure there will be no cache flush when used
|
// inlined to make sure there will be no cache flush when used
|
||||||
inline void AdobeToneCurve::Apply (float& r, float& g, float& b) const
|
inline void AdobeToneCurve::Apply (float& ir, float& ig, float& ib) const
|
||||||
{
|
{
|
||||||
|
|
||||||
assert (lutToneCurve);
|
assert (lutToneCurve);
|
||||||
|
float r = CLIP(ir);
|
||||||
|
float g = CLIP(ig);
|
||||||
|
float b = CLIP(ib);
|
||||||
|
|
||||||
if (r >= g) {
|
if (r >= g) {
|
||||||
if (g > b) {
|
if (g > b) {
|
||||||
@@ -964,6 +999,10 @@ inline void AdobeToneCurve::Apply (float& r, float& g, float& b) const
|
|||||||
RGBTone (g, b, r); // Case 7: g >= b > r
|
RGBTone (g, b, r); // Case 7: g >= b > r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setUnlessOOG(ir, r);
|
||||||
|
setUnlessOOG(ig, g);
|
||||||
|
setUnlessOOG(ib, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AdobeToneCurve::RGBTone (float& r, float& g, float& b) const
|
inline void AdobeToneCurve::RGBTone (float& r, float& g, float& b) const
|
||||||
@@ -976,10 +1015,14 @@ inline void AdobeToneCurve::RGBTone (float& r, float& g, float& b) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Modifying the Luminance channel only
|
// Modifying the Luminance channel only
|
||||||
inline void LuminanceToneCurve::Apply(float &r, float &g, float &b) const
|
inline void LuminanceToneCurve::Apply(float &ir, float &ig, float &ib) const
|
||||||
{
|
{
|
||||||
assert (lutToneCurve);
|
assert (lutToneCurve);
|
||||||
|
|
||||||
|
float r = CLIP(ir);
|
||||||
|
float g = CLIP(ig);
|
||||||
|
float b = CLIP(ib);
|
||||||
|
|
||||||
float currLuminance = r * 0.2126729f + g * 0.7151521f + b * 0.0721750f;
|
float currLuminance = r * 0.2126729f + g * 0.7151521f + b * 0.0721750f;
|
||||||
const float newLuminance = lutToneCurve[currLuminance];
|
const float newLuminance = lutToneCurve[currLuminance];
|
||||||
currLuminance = currLuminance == 0.f ? 0.00001f : currLuminance;
|
currLuminance = currLuminance == 0.f ? 0.00001f : currLuminance;
|
||||||
@@ -987,6 +1030,10 @@ inline void LuminanceToneCurve::Apply(float &r, float &g, float &b) const
|
|||||||
r = LIM<float>(r * coef, 0.f, 65535.f);
|
r = LIM<float>(r * coef, 0.f, 65535.f);
|
||||||
g = LIM<float>(g * coef, 0.f, 65535.f);
|
g = LIM<float>(g * coef, 0.f, 65535.f);
|
||||||
b = LIM<float>(b * coef, 0.f, 65535.f);
|
b = LIM<float>(b * coef, 0.f, 65535.f);
|
||||||
|
|
||||||
|
setUnlessOOG(ir, r);
|
||||||
|
setUnlessOOG(ig, g);
|
||||||
|
setUnlessOOG(ib, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const
|
inline float WeightedStdToneCurve::Triangle(float a, float a1, float b) const
|
||||||
@@ -1020,14 +1067,14 @@ inline vfloat WeightedStdToneCurve::Triangle(vfloat a, vfloat a1, vfloat b) cons
|
|||||||
|
|
||||||
// Tone curve modifying the value channel only, preserving hue and saturation
|
// Tone curve modifying the value channel only, preserving hue and saturation
|
||||||
// values in 0xffff space
|
// values in 0xffff space
|
||||||
inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const
|
inline void WeightedStdToneCurve::Apply (float& ir, float& ig, float& ib) const
|
||||||
{
|
{
|
||||||
|
|
||||||
assert (lutToneCurve);
|
assert (lutToneCurve);
|
||||||
|
|
||||||
r = CLIP(r);
|
float r = CLIP(ir);
|
||||||
g = CLIP(g);
|
float g = CLIP(ig);
|
||||||
b = CLIP(b);
|
float b = CLIP(ib);
|
||||||
float r1 = lutToneCurve[r];
|
float r1 = lutToneCurve[r];
|
||||||
float g1 = Triangle(r, r1, g);
|
float g1 = Triangle(r, r1, g);
|
||||||
float b1 = Triangle(r, r1, b);
|
float b1 = Triangle(r, r1, b);
|
||||||
@@ -1043,6 +1090,10 @@ inline void WeightedStdToneCurve::Apply (float& r, float& g, float& b) const
|
|||||||
r = CLIP<float>(r1 * 0.50f + r2 * 0.25f + r3 * 0.25f);
|
r = CLIP<float>(r1 * 0.50f + r2 * 0.25f + r3 * 0.25f);
|
||||||
g = CLIP<float>(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
|
g = CLIP<float>(g1 * 0.25f + g2 * 0.50f + g3 * 0.25f);
|
||||||
b = CLIP<float>(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f);
|
b = CLIP<float>(b1 * 0.25f + b2 * 0.25f + b3 * 0.50f);
|
||||||
|
|
||||||
|
setUnlessOOG(ir, r);
|
||||||
|
setUnlessOOG(ig, g);
|
||||||
|
setUnlessOOG(ib, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const {
|
inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t end, float *r, float *g, float *b) const {
|
||||||
@@ -1076,6 +1127,10 @@ inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t en
|
|||||||
const vfloat zd5v = F2V(0.5f);
|
const vfloat zd5v = F2V(0.5f);
|
||||||
const vfloat zd25v = F2V(0.25f);
|
const vfloat zd25v = F2V(0.25f);
|
||||||
|
|
||||||
|
float tmpr[4];
|
||||||
|
float tmpg[4];
|
||||||
|
float tmpb[4];
|
||||||
|
|
||||||
for (; i + 3 < end; i += 4) {
|
for (; i + 3 < end; i += 4) {
|
||||||
vfloat r_val = LIMV(LVF(r[i]), ZEROV, c65535v);
|
vfloat r_val = LIMV(LVF(r[i]), ZEROV, c65535v);
|
||||||
vfloat g_val = LIMV(LVF(g[i]), ZEROV, c65535v);
|
vfloat g_val = LIMV(LVF(g[i]), ZEROV, c65535v);
|
||||||
@@ -1092,9 +1147,14 @@ inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t en
|
|||||||
vfloat r3 = Triangle(b_val, b3, r_val);
|
vfloat r3 = Triangle(b_val, b3, r_val);
|
||||||
vfloat g3 = Triangle(b_val, b3, g_val);
|
vfloat g3 = Triangle(b_val, b3, g_val);
|
||||||
|
|
||||||
STVF(r[i], LIMV(r1 * zd5v + r2 * zd25v + r3 * zd25v, ZEROV, c65535v));
|
STVF(tmpr[0], LIMV(r1 * zd5v + r2 * zd25v + r3 * zd25v, ZEROV, c65535v));
|
||||||
STVF(g[i], LIMV(g1 * zd25v + g2 * zd5v + g3 * zd25v, ZEROV, c65535v));
|
STVF(tmpg[0], LIMV(g1 * zd25v + g2 * zd5v + g3 * zd25v, ZEROV, c65535v));
|
||||||
STVF(b[i], LIMV(b1 * zd25v + b2 * zd25v + b3 * zd5v, 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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remainder in non-SSE.
|
// Remainder in non-SSE.
|
||||||
@@ -1106,14 +1166,14 @@ inline void WeightedStdToneCurve::BatchApply(const size_t start, const size_t en
|
|||||||
|
|
||||||
// Tone curve modifying the value channel only, preserving hue and saturation
|
// Tone curve modifying the value channel only, preserving hue and saturation
|
||||||
// values in 0xffff space
|
// values in 0xffff space
|
||||||
inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) const
|
inline void SatAndValueBlendingToneCurve::Apply (float& ir, float& ig, float& ib) const
|
||||||
{
|
{
|
||||||
|
|
||||||
assert (lutToneCurve);
|
assert (lutToneCurve);
|
||||||
|
|
||||||
r = CLIP(r);
|
float r = CLIP(ir);
|
||||||
g = CLIP(g);
|
float g = CLIP(ig);
|
||||||
b = CLIP(b);
|
float b = CLIP(ib);
|
||||||
|
|
||||||
const float lum = (r + g + b) / 3.f;
|
const float lum = (r + g + b) / 3.f;
|
||||||
const float newLum = lutToneCurve[lum];
|
const float newLum = lutToneCurve[lum];
|
||||||
@@ -1137,6 +1197,10 @@ inline void SatAndValueBlendingToneCurve::Apply (float& r, float& g, float& b) c
|
|||||||
dV = v * coef;
|
dV = v * coef;
|
||||||
}
|
}
|
||||||
Color::hsv2rgbdcp(h, s, v + dV, r, g, b);
|
Color::hsv2rgbdcp(h, s, v + dV, r, g, b);
|
||||||
|
|
||||||
|
setUnlessOOG(ir, r);
|
||||||
|
setUnlessOOG(ig, g);
|
||||||
|
setUnlessOOG(ib, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1184,13 +1184,17 @@ void DCPProfile::step2ApplyTile(float* rc, float* gc, float* bc, int width, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// with looktable and tonecurve we need to clip
|
// with looktable and tonecurve we need to clip
|
||||||
newr = FCLIP(newr);
|
// newr = FCLIP(newr);
|
||||||
newg = FCLIP(newg);
|
// newg = FCLIP(newg);
|
||||||
newb = FCLIP(newb);
|
// newb = FCLIP(newb);
|
||||||
|
|
||||||
if (as_in.data->apply_look_table) {
|
if (as_in.data->apply_look_table) {
|
||||||
|
float cnewr = FCLIP(newr);
|
||||||
|
float cnewg = FCLIP(newg);
|
||||||
|
float cnewb = FCLIP(newb);
|
||||||
|
|
||||||
float h, s, v;
|
float h, s, v;
|
||||||
Color::rgb2hsvdcp(newr, newg, newb, h, s, v);
|
Color::rgb2hsvdcp(cnewr, cnewg, cnewb, h, s, v);
|
||||||
|
|
||||||
hsdApply(look_info, look_table, h, s, v);
|
hsdApply(look_info, look_table, h, s, v);
|
||||||
s = CLIP01(s);
|
s = CLIP01(s);
|
||||||
@@ -1203,7 +1207,11 @@ void DCPProfile::step2ApplyTile(float* rc, float* gc, float* bc, int width, int
|
|||||||
h -= 6.0f;
|
h -= 6.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color::hsv2rgbdcp( h, s, v, newr, newg, newb);
|
Color::hsv2rgbdcp( h, s, v, cnewr, cnewg, cnewb);
|
||||||
|
|
||||||
|
setUnlessOOG(newr, cnewr);
|
||||||
|
setUnlessOOG(newg, cnewg);
|
||||||
|
setUnlessOOG(newb, cnewb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (as_in.data->use_tone_curve) {
|
if (as_in.data->use_tone_curve) {
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ void ImProcFunctions :: dirpyr_equalizer(float ** src, float ** dst, int srcwidt
|
|||||||
|
|
||||||
for (int i = 0; i < srcheight; i++)
|
for (int i = 0; i < srcheight; i++)
|
||||||
for (int j = 0; j < srcwidth; j++) {
|
for (int j = 0; j < srcwidth; j++) {
|
||||||
dst[i][j] = CLIP(buffer[i][j]); // TODO: Really a clip necessary?
|
dst[i][j] = /*CLIP*/(buffer[i][j]); // TODO: Really a clip necessary?
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -367,7 +367,7 @@ void ImProcFunctions :: dirpyr_equalizercam (CieImage *ncie, float ** src, float
|
|||||||
for (int i = 0; i < srcheight; i++)
|
for (int i = 0; i < srcheight; i++)
|
||||||
for (int j = 0; j < srcwidth; j++) {
|
for (int j = 0; j < srcwidth; j++) {
|
||||||
if(ncie->J_p[i][j] > 8.f && ncie->J_p[i][j] < 92.f) {
|
if(ncie->J_p[i][j] > 8.f && ncie->J_p[i][j] < 92.f) {
|
||||||
dst[i][j] = CLIP( buffer[i][j] ); // TODO: Really a clip necessary?
|
dst[i][j] = /*CLIP*/( buffer[i][j] ); // TODO: Really a clip necessary?
|
||||||
} else {
|
} else {
|
||||||
dst[i][j] = src[i][j];
|
dst[i][j] = src[i][j];
|
||||||
}
|
}
|
||||||
@@ -375,7 +375,7 @@ void ImProcFunctions :: dirpyr_equalizercam (CieImage *ncie, float ** src, float
|
|||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < srcheight; i++)
|
for (int i = 0; i < srcheight; i++)
|
||||||
for (int j = 0; j < srcwidth; j++) {
|
for (int j = 0; j < srcwidth; j++) {
|
||||||
dst[i][j] = CLIP( buffer[i][j] ); // TODO: Really a clip necessary?
|
dst[i][j] = /*CLIP*/( buffer[i][j] ); // TODO: Really a clip necessary?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ inline void ImageDatas::convertTo(unsigned char src, unsigned short& dst) const
|
|||||||
template<>
|
template<>
|
||||||
inline void ImageDatas::convertTo(float src, unsigned char& dst) const
|
inline void ImageDatas::convertTo(float src, unsigned char& dst) const
|
||||||
{
|
{
|
||||||
dst = uint16ToUint8Rounded(src);
|
dst = uint16ToUint8Rounded(CLIP(src));
|
||||||
}
|
}
|
||||||
template<>
|
template<>
|
||||||
inline void ImageDatas::convertTo(unsigned char src, float& dst) const
|
inline void ImageDatas::convertTo(unsigned char src, float& dst) const
|
||||||
|
|||||||
@@ -146,6 +146,9 @@ void Imagefloat::setScanline (int row, unsigned char* buffer, int bps, float *mi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace rtengine { extern void filmlike_clip(float *r, float *g, float *b); }
|
||||||
|
|
||||||
void Imagefloat::getScanline (int row, unsigned char* buffer, int bps)
|
void Imagefloat::getScanline (int row, unsigned char* buffer, int bps)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -163,18 +166,24 @@ void Imagefloat::getScanline (int row, unsigned char* buffer, int bps)
|
|||||||
sbuffer[ix++] = g(row, i) / 65535.f;
|
sbuffer[ix++] = g(row, i) / 65535.f;
|
||||||
sbuffer[ix++] = b(row, i) / 65535.f;
|
sbuffer[ix++] = b(row, i) / 65535.f;
|
||||||
}
|
}
|
||||||
} else if (bps == 16) {
|
} else {
|
||||||
unsigned short *sbuffer = (unsigned short *)buffer;
|
unsigned short *sbuffer = (unsigned short *)buffer;
|
||||||
for (int i = 0, ix = 0; i < width; i++) {
|
for (int i = 0, ix = 0; i < width; i++) {
|
||||||
sbuffer[ix++] = CLIP(r(row, i));
|
float ri = r(row, i);
|
||||||
sbuffer[ix++] = CLIP(g(row, i));
|
float gi = g(row, i);
|
||||||
sbuffer[ix++] = CLIP(b(row, i));
|
float bi = b(row, i);
|
||||||
}
|
if (ri > 65535.f || gi > 65535.f || bi > 65535.f) {
|
||||||
} else if (bps == 8) {
|
filmlike_clip(&ri, &gi, &bi);
|
||||||
for (int i = 0, ix = 0; i < width; i++) {
|
}
|
||||||
buffer[ix++] = rtengine::uint16ToUint8Rounded(CLIP(r(row, i)));
|
if (bps == 16) {
|
||||||
buffer[ix++] = rtengine::uint16ToUint8Rounded(CLIP(g(row, i)));
|
sbuffer[ix++] = CLIP(ri);
|
||||||
buffer[ix++] = rtengine::uint16ToUint8Rounded(CLIP(b(row, i)));
|
sbuffer[ix++] = CLIP(gi);
|
||||||
|
sbuffer[ix++] = CLIP(bi);
|
||||||
|
} else if (bps == 8) {
|
||||||
|
buffer[ix++] = rtengine::uint16ToUint8Rounded(CLIP(ri));
|
||||||
|
buffer[ix++] = rtengine::uint16ToUint8Rounded(CLIP(gi));
|
||||||
|
buffer[ix++] = rtengine::uint16ToUint8Rounded(CLIP(bi));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,6 +247,8 @@ void Imagefloat::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Prev
|
|||||||
gm /= area;
|
gm /= area;
|
||||||
bm /= area;
|
bm /= area;
|
||||||
|
|
||||||
|
const auto CLIP0 = [](float v) -> float { return std::max(v, 0.f); };
|
||||||
|
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
#pragma omp parallel
|
#pragma omp parallel
|
||||||
{
|
{
|
||||||
@@ -270,9 +281,9 @@ void Imagefloat::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Prev
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineR[dst_x] = CLIP(rm2 * r(src_y, src_x));
|
lineR[dst_x] = CLIP0(rm2 * r(src_y, src_x));
|
||||||
lineG[dst_x] = CLIP(gm2 * g(src_y, src_x));
|
lineG[dst_x] = CLIP0(gm2 * g(src_y, src_x));
|
||||||
lineB[dst_x] = CLIP(bm2 * b(src_y, src_x));
|
lineB[dst_x] = CLIP0(bm2 * b(src_y, src_x));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// source image, first line of the current destination row
|
// source image, first line of the current destination row
|
||||||
@@ -303,15 +314,15 @@ void Imagefloat::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, Prev
|
|||||||
// convert back to gamma and clip
|
// convert back to gamma and clip
|
||||||
if (src_sub_width == skip && src_sub_height == skip) {
|
if (src_sub_width == skip && src_sub_height == skip) {
|
||||||
// Common case where the sub-region is complete
|
// Common case where the sub-region is complete
|
||||||
lineR[dst_x] = CLIP(rm * rtot);
|
lineR[dst_x] = CLIP0(rm * rtot);
|
||||||
lineG[dst_x] = CLIP(gm * gtot);
|
lineG[dst_x] = CLIP0(gm * gtot);
|
||||||
lineB[dst_x] = CLIP(bm * btot);
|
lineB[dst_x] = CLIP0(bm * btot);
|
||||||
} else {
|
} else {
|
||||||
// computing a special factor for this incomplete sub-region
|
// computing a special factor for this incomplete sub-region
|
||||||
float area = src_sub_width * src_sub_height;
|
float area = src_sub_width * src_sub_height;
|
||||||
lineR[dst_x] = CLIP(rm2 * rtot / area);
|
lineR[dst_x] = CLIP0(rm2 * rtot / area);
|
||||||
lineG[dst_x] = CLIP(gm2 * gtot / area);
|
lineG[dst_x] = CLIP0(gm2 * gtot / area);
|
||||||
lineB[dst_x] = CLIP(bm2 * btot / area);
|
lineB[dst_x] = CLIP0(bm2 * btot / area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,9 +368,9 @@ Imagefloat::to8()
|
|||||||
|
|
||||||
for (int h = 0; h < height; ++h) {
|
for (int h = 0; h < height; ++h) {
|
||||||
for (int w = 0; w < width; ++w) {
|
for (int w = 0; w < width; ++w) {
|
||||||
img8->r(h, w) = uint16ToUint8Rounded(r(h, w));
|
img8->r(h, w) = uint16ToUint8Rounded(CLIP(r(h, w)));
|
||||||
img8->g(h, w) = uint16ToUint8Rounded(g(h, w));
|
img8->g(h, w) = uint16ToUint8Rounded(CLIP(g(h, w)));
|
||||||
img8->b(h, w) = uint16ToUint8Rounded(b(h, w));
|
img8->b(h, w) = uint16ToUint8Rounded(CLIP(b(h, w)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,9 +387,9 @@ Imagefloat::to16()
|
|||||||
|
|
||||||
for (int h = 0; h < height; ++h) {
|
for (int h = 0; h < height; ++h) {
|
||||||
for (int w = 0; w < width; ++w) {
|
for (int w = 0; w < width; ++w) {
|
||||||
img16->r(h, w) = r(h, w);
|
img16->r(h, w) = CLIP(r(h, w));
|
||||||
img16->g(h, w) = g(h, w);
|
img16->g(h, w) = CLIP(g(h, w));
|
||||||
img16->b(h, w) = b(h, w);
|
img16->b(h, w) = CLIP(b(h, w));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,13 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace rtengine;
|
using namespace rtengine;
|
||||||
// begin of helper function for rgbProc()
|
|
||||||
void shadowToneCurve(const LUTf &shtonecurve, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize) {
|
|
||||||
|
|
||||||
#ifdef __SSE2__
|
|
||||||
|
// begin of helper function for rgbProc()
|
||||||
|
void shadowToneCurve(const LUTf &shtonecurve, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if defined( __SSE2__ ) && defined( __x86_64__ )
|
||||||
vfloat cr = F2V(0.299f);
|
vfloat cr = F2V(0.299f);
|
||||||
vfloat cg = F2V(0.587f);
|
vfloat cg = F2V(0.587f);
|
||||||
vfloat cb = F2V(0.114f);
|
vfloat cb = F2V(0.114f);
|
||||||
@@ -61,8 +64,9 @@ void shadowToneCurve(const LUTf &shtonecurve, float *rtemp, float *gtemp, float
|
|||||||
|
|
||||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||||
int j = jstart, tj = 0;
|
int j = jstart, tj = 0;
|
||||||
#ifdef __SSE2__
|
#if defined( __SSE2__ ) && defined( __x86_64__ )
|
||||||
for (; j < tW - 3; j+=4, tj+=4) {
|
|
||||||
|
for (; j < tW - 3; j += 4, tj += 4) {
|
||||||
|
|
||||||
vfloat rv = LVF(rtemp[ti * tileSize + tj]);
|
vfloat rv = LVF(rtemp[ti * tileSize + tj]);
|
||||||
vfloat gv = LVF(gtemp[ti * tileSize + tj]);
|
vfloat gv = LVF(gtemp[ti * tileSize + tj]);
|
||||||
@@ -75,7 +79,9 @@ void shadowToneCurve(const LUTf &shtonecurve, float *rtemp, float *gtemp, float
|
|||||||
STVF(gtemp[ti * tileSize + tj], gv * tonefactorv);
|
STVF(gtemp[ti * tileSize + tj], gv * tonefactorv);
|
||||||
STVF(btemp[ti * tileSize + tj], bv * tonefactorv);
|
STVF(btemp[ti * tileSize + tj], bv * tonefactorv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (; j < tW; j++, tj++) {
|
for (; j < tW; j++, tj++) {
|
||||||
|
|
||||||
float r = rtemp[ti * tileSize + tj];
|
float r = rtemp[ti * tileSize + tj];
|
||||||
@@ -92,17 +98,19 @@ void shadowToneCurve(const LUTf &shtonecurve, float *rtemp, float *gtemp, float
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void highlightToneCurve(const LUTf &hltonecurve, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize, float exp_scale, float comp, float hlrange) {
|
void highlightToneCurve(const LUTf &hltonecurve, float *rtemp, float *gtemp, float *btemp, int istart, int tH, int jstart, int tW, int tileSize, float exp_scale, float comp, float hlrange)
|
||||||
|
{
|
||||||
|
|
||||||
#ifdef __SSE2__
|
#if defined( __SSE2__ ) && defined( __x86_64__ )
|
||||||
vfloat threev = F2V(3.f);
|
vfloat threev = F2V(3.f);
|
||||||
vfloat maxvalfv = F2V(MAXVALF);
|
vfloat maxvalfv = F2V(MAXVALF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||||
int j = jstart, tj = 0;
|
int j = jstart, tj = 0;
|
||||||
#ifdef __SSE2__
|
#if defined( __SSE2__ ) && defined( __x86_64__ )
|
||||||
for (; j < tW - 3; j+=4, tj+=4) {
|
|
||||||
|
for (; j < tW - 3; j += 4, tj += 4) {
|
||||||
|
|
||||||
vfloat rv = LVF(rtemp[ti * tileSize + tj]);
|
vfloat rv = LVF(rtemp[ti * tileSize + tj]);
|
||||||
vfloat gv = LVF(gtemp[ti * tileSize + tj]);
|
vfloat gv = LVF(gtemp[ti * tileSize + tj]);
|
||||||
@@ -111,14 +119,15 @@ void highlightToneCurve(const LUTf &hltonecurve, float *rtemp, float *gtemp, flo
|
|||||||
//TODO: proper treatment of out-of-gamut colors
|
//TODO: proper treatment of out-of-gamut colors
|
||||||
//float tonefactor = hltonecurve[(0.299f*r+0.587f*g+0.114f*b)];
|
//float tonefactor = hltonecurve[(0.299f*r+0.587f*g+0.114f*b)];
|
||||||
vmask maxMask = vmaskf_ge(vmaxf(rv, vmaxf(gv, bv)), maxvalfv);
|
vmask maxMask = vmaskf_ge(vmaxf(rv, vmaxf(gv, bv)), maxvalfv);
|
||||||
if(_mm_movemask_ps((vfloat)maxMask)) {
|
|
||||||
|
if (_mm_movemask_ps((vfloat)maxMask)) {
|
||||||
for (int k = 0; k < 4; ++k) {
|
for (int k = 0; k < 4; ++k) {
|
||||||
float r = rtemp[ti * tileSize + tj + k];
|
float r = rtemp[ti * tileSize + tj + k];
|
||||||
float g = gtemp[ti * tileSize + tj + k];
|
float g = gtemp[ti * tileSize + tj + k];
|
||||||
float b = btemp[ti * tileSize + tj + k];
|
float b = btemp[ti * tileSize + tj + k];
|
||||||
float tonefactor = ((r < MAXVALF ? hltonecurve[r] : CurveFactory::hlcurve (exp_scale, comp, hlrange, r) ) +
|
float tonefactor = ((r < MAXVALF ? hltonecurve[r] : CurveFactory::hlcurve(exp_scale, comp, hlrange, r)) +
|
||||||
(g < MAXVALF ? hltonecurve[g] : CurveFactory::hlcurve (exp_scale, comp, hlrange, g) ) +
|
(g < MAXVALF ? hltonecurve[g] : CurveFactory::hlcurve(exp_scale, comp, hlrange, g)) +
|
||||||
(b < MAXVALF ? hltonecurve[b] : CurveFactory::hlcurve (exp_scale, comp, hlrange, b) ) ) / 3.0;
|
(b < MAXVALF ? hltonecurve[b] : CurveFactory::hlcurve(exp_scale, comp, hlrange, b))) / 3.0;
|
||||||
|
|
||||||
// note: tonefactor includes exposure scaling, that is here exposure slider and highlight compression takes place
|
// note: tonefactor includes exposure scaling, that is here exposure slider and highlight compression takes place
|
||||||
rtemp[ti * tileSize + tj + k] = r * tonefactor;
|
rtemp[ti * tileSize + tj + k] = r * tonefactor;
|
||||||
@@ -133,7 +142,9 @@ void highlightToneCurve(const LUTf &hltonecurve, float *rtemp, float *gtemp, flo
|
|||||||
STVF(btemp[ti * tileSize + tj], bv * tonefactorv);
|
STVF(btemp[ti * tileSize + tj], bv * tonefactorv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (; j < tW; j++, tj++) {
|
for (; j < tW; j++, tj++) {
|
||||||
|
|
||||||
float r = rtemp[ti * tileSize + tj];
|
float r = rtemp[ti * tileSize + tj];
|
||||||
@@ -142,9 +153,9 @@ void highlightToneCurve(const LUTf &hltonecurve, float *rtemp, float *gtemp, flo
|
|||||||
|
|
||||||
//TODO: proper treatment of out-of-gamut colors
|
//TODO: proper treatment of out-of-gamut colors
|
||||||
//float tonefactor = hltonecurve[(0.299f*r+0.587f*g+0.114f*b)];
|
//float tonefactor = hltonecurve[(0.299f*r+0.587f*g+0.114f*b)];
|
||||||
float tonefactor = ((r < MAXVALF ? hltonecurve[r] : CurveFactory::hlcurve (exp_scale, comp, hlrange, r) ) +
|
float tonefactor = ((r < MAXVALF ? hltonecurve[r] : CurveFactory::hlcurve(exp_scale, comp, hlrange, r)) +
|
||||||
(g < MAXVALF ? hltonecurve[g] : CurveFactory::hlcurve (exp_scale, comp, hlrange, g) ) +
|
(g < MAXVALF ? hltonecurve[g] : CurveFactory::hlcurve(exp_scale, comp, hlrange, g)) +
|
||||||
(b < MAXVALF ? hltonecurve[b] : CurveFactory::hlcurve (exp_scale, comp, hlrange, b) ) ) / 3.0;
|
(b < MAXVALF ? hltonecurve[b] : CurveFactory::hlcurve(exp_scale, comp, hlrange, b))) / 3.0;
|
||||||
|
|
||||||
// note: tonefactor includes exposure scaling, that is here exposure slider and highlight compression takes place
|
// note: tonefactor includes exposure scaling, that is here exposure slider and highlight compression takes place
|
||||||
rtemp[ti * tileSize + tj] = r * tonefactor;
|
rtemp[ti * tileSize + tj] = r * tonefactor;
|
||||||
@@ -224,9 +235,6 @@ void customToneCurve(const ToneCurve &customToneCurve, ToneCurveParams::TcMode c
|
|||||||
|
|
||||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||||
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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3260,7 +3268,7 @@ filmlike_clip_rgb_tone (float *r, float *g, float *b, const float L)
|
|||||||
*b = b_;
|
*b = b_;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/*static*/ void
|
||||||
filmlike_clip (float *r, float *g, float *b)
|
filmlike_clip (float *r, float *g, float *b)
|
||||||
{
|
{
|
||||||
// This is Adobe's hue-stable film-like curve with a diagonal, ie only used for clipping. Can probably be further optimized.
|
// This is Adobe's hue-stable film-like curve with a diagonal, ie only used for clipping. Can probably be further optimized.
|
||||||
@@ -3670,6 +3678,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
float out_rgbx[4 * TS] ALIGNED16; // Line buffer for CLUT
|
float out_rgbx[4 * TS] ALIGNED16; // Line buffer for CLUT
|
||||||
|
float clutr[TS] ALIGNED16;
|
||||||
|
float clutg[TS] ALIGNED16;
|
||||||
|
float clutb[TS] ALIGNED16;
|
||||||
|
|
||||||
LUTu histToneCurveThr;
|
LUTu histToneCurveThr;
|
||||||
|
|
||||||
@@ -3760,9 +3771,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
filmlike_clip (&r, &g, &b);
|
filmlike_clip (&r, &g, &b);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtemp[ti * TS + tj] = r;
|
setUnlessOOG(rtemp[ti * TS + tj], r);
|
||||||
gtemp[ti * TS + tj] = g;
|
setUnlessOOG(gtemp[ti * TS + tj], g);
|
||||||
btemp[ti * TS + tj] = b;
|
setUnlessOOG(btemp[ti * TS + tj], b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3771,30 +3782,43 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||||
|
|
||||||
//brightness/contrast
|
//brightness/contrast
|
||||||
rtemp[ti * TS + tj] = tonecurve[ rtemp[ti * TS + tj] ];
|
float r = tonecurve[ CLIP(rtemp[ti * TS + tj]) ];
|
||||||
gtemp[ti * TS + tj] = tonecurve[ gtemp[ti * TS + tj] ];
|
float g = tonecurve[ CLIP(gtemp[ti * TS + tj]) ];
|
||||||
btemp[ti * TS + tj] = tonecurve[ btemp[ti * TS + tj] ];
|
float b = tonecurve[ CLIP(btemp[ti * TS + tj]) ];
|
||||||
|
|
||||||
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]]);
|
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]++;
|
histToneCurveThr[y >> histToneCurveCompression]++;
|
||||||
|
|
||||||
|
setUnlessOOG(rtemp[ti * TS + tj], r);
|
||||||
|
setUnlessOOG(gtemp[ti * TS + tj], g);
|
||||||
|
setUnlessOOG(btemp[ti * TS + tj], b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
float tmpr[4];
|
||||||
|
float tmpg[4];
|
||||||
|
float tmpb[4];
|
||||||
|
|
||||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||||
int j = jstart, tj = 0;
|
int j = jstart, tj = 0;
|
||||||
#ifdef __SSE2__
|
#ifdef __SSE2__
|
||||||
for (; j < tW - 3; j+=4, tj+=4) {
|
for (; j < tW - 3; j+=4, tj+=4) {
|
||||||
//brightness/contrast
|
//brightness/contrast
|
||||||
STVF(rtemp[ti * TS + tj], tonecurve(LVF(rtemp[ti * TS + tj])));
|
STVF(tmpr[0], tonecurve(LVF(rtemp[ti * TS + tj])));
|
||||||
STVF(gtemp[ti * TS + tj], tonecurve(LVF(gtemp[ti * TS + tj])));
|
STVF(tmpg[0], tonecurve(LVF(gtemp[ti * TS + tj])));
|
||||||
STVF(btemp[ti * TS + tj], tonecurve(LVF(btemp[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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for (; j < tW; j++, tj++) {
|
for (; j < tW; j++, tj++) {
|
||||||
//brightness/contrast
|
//brightness/contrast
|
||||||
rtemp[ti * TS + tj] = tonecurve[rtemp[ti * TS + tj]];
|
setUnlessOOG(rtemp[ti * TS + tj], tonecurve[rtemp[ti * TS + tj]]);
|
||||||
gtemp[ti * TS + tj] = tonecurve[gtemp[ti * TS + tj]];
|
setUnlessOOG(gtemp[ti * TS + tj], tonecurve[gtemp[ti * TS + tj]]);
|
||||||
btemp[ti * TS + tj] = tonecurve[btemp[ti * TS + tj]];
|
setUnlessOOG(btemp[ti * TS + tj], tonecurve[btemp[ti * TS + tj]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3842,17 +3866,17 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||||
// individual R tone curve
|
// individual R tone curve
|
||||||
if (rCurve) {
|
if (rCurve) {
|
||||||
rtemp[ti * TS + tj] = rCurve[ rtemp[ti * TS + tj] ];
|
setUnlessOOG(rtemp[ti * TS + tj], rCurve[ rtemp[ti * TS + tj] ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// individual G tone curve
|
// individual G tone curve
|
||||||
if (gCurve) {
|
if (gCurve) {
|
||||||
gtemp[ti * TS + tj] = gCurve[ gtemp[ti * TS + tj] ];
|
setUnlessOOG(gtemp[ti * TS + tj], gCurve[ gtemp[ti * TS + tj] ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// individual B tone curve
|
// individual B tone curve
|
||||||
if (bCurve) {
|
if (bCurve) {
|
||||||
btemp[ti * TS + tj] = bCurve[ btemp[ti * TS + tj] ];
|
setUnlessOOG(btemp[ti * TS + tj], bCurve[ btemp[ti * TS + tj] ]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3919,18 +3943,22 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
bool neg = false;
|
bool neg = false;
|
||||||
bool more_rgb = false;
|
bool more_rgb = false;
|
||||||
//gamut control : Lab values are in gamut
|
//gamut control : Lab values are in gamut
|
||||||
Color::gamutLchonly (HH, sincosval, Lpro, Chpro, rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], wip, highlight, 0.15f, 0.96f, neg, more_rgb);
|
Color::gamutLchonly (HH, sincosval, Lpro, Chpro, r, g, b, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
|
||||||
#else
|
#else
|
||||||
//gamut control : Lab values are in gamut
|
//gamut control : Lab values are in gamut
|
||||||
Color::gamutLchonly (HH, sincosval, Lpro, Chpro, rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], wip, highlight, 0.15f, 0.96f);
|
Color::gamutLchonly (HH, sincosval, Lpro, Chpro, r, g, b, wip, highlight, 0.15f, 0.96f);
|
||||||
#endif
|
#endif
|
||||||
//end of gamut control
|
//end of gamut control
|
||||||
} else {
|
} else {
|
||||||
float x_, y_, z_;
|
float x_, y_, z_;
|
||||||
//calculate RGB with L_2 and old value of a and b
|
//calculate RGB with L_2 and old value of a and b
|
||||||
Color::Lab2XYZ (L_2, a_1, b_1, x_, y_, z_) ;
|
Color::Lab2XYZ (L_2, a_1, b_1, x_, y_, z_) ;
|
||||||
Color::xyz2rgb (x_, y_, z_, rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], wip);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4081,9 +4109,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
bo *= preserv;
|
bo *= preserv;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtemp[ti * TS + tj] = CLIP(ro);
|
rtemp[ti * TS + tj] = /*CLIP*/(ro);
|
||||||
gtemp[ti * TS + tj] = CLIP(go);
|
gtemp[ti * TS + tj] = /*CLIP*/(go);
|
||||||
btemp[ti * TS + tj] = CLIP(bo);
|
btemp[ti * TS + tj] = /*CLIP*/(bo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4137,9 +4165,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
float b = btemp[ti * TS + tj];
|
float b = btemp[ti * TS + tj];
|
||||||
float ro, go, bo;
|
float ro, go, bo;
|
||||||
labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip);
|
labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip);
|
||||||
rtemp[ti * TS + tj] = CLIP (ro); //I used CLIP because there is a little bug in gamutLchonly that return 65536.ii intead of 65535 ==> crash
|
rtemp[ti * TS + tj] = /*CLIP*/ (ro); //I used CLIP because there is a little bug in gamutLchonly that return 65536.ii intead of 65535 ==> crash
|
||||||
gtemp[ti * TS + tj] = CLIP (go);
|
gtemp[ti * TS + tj] = /*CLIP*/ (go);
|
||||||
btemp[ti * TS + tj] = CLIP (bo);
|
btemp[ti * TS + tj] = /*CLIP*/ (bo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4386,28 +4414,32 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
Color::rgbxyz (sourceR, sourceG, sourceB, x, y, z, v_work2xyz);
|
Color::rgbxyz (sourceR, sourceG, sourceB, x, y, z, v_work2xyz);
|
||||||
Color::xyz2rgb (x, y, z, sourceR, sourceG, sourceB, v_xyz2clut);
|
Color::xyz2rgb (x, y, z, sourceR, sourceG, sourceB, v_xyz2clut);
|
||||||
|
|
||||||
STVF (rtemp[ti * TS + tj], sourceR);
|
STVF (clutr[tj], sourceR);
|
||||||
STVF (gtemp[ti * TS + tj], sourceG);
|
STVF (clutg[tj], sourceG);
|
||||||
STVF (btemp[ti * TS + tj], sourceB);
|
STVF (clutb[tj], sourceB);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (; j < tW; j++, tj++) {
|
for (; j < tW; j++, tj++) {
|
||||||
float &sourceR = rtemp[ti * TS + tj];
|
float sourceR = rtemp[ti * TS + tj];
|
||||||
float &sourceG = gtemp[ti * TS + tj];
|
float sourceG = gtemp[ti * TS + tj];
|
||||||
float &sourceB = btemp[ti * TS + tj];
|
float sourceB = btemp[ti * TS + tj];
|
||||||
|
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
Color::rgbxyz ( sourceR, sourceG, sourceB, x, y, z, wprof );
|
Color::rgbxyz ( sourceR, sourceG, sourceB, x, y, z, wprof );
|
||||||
Color::xyz2rgb (x, y, z, sourceR, sourceG, sourceB, xyz2clut);
|
Color::xyz2rgb (x, y, z, clutr[tj], clutg[tj], clutb[tj], xyz2clut);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
memcpy(clutr, &rtemp[ti * TS], sizeof(float) * TS);
|
||||||
|
memcpy(clutg, >emp[ti * TS], sizeof(float) * TS);
|
||||||
|
memcpy(clutb, &btemp[ti * TS], sizeof(float) * TS);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||||
float &sourceR = rtemp[ti * TS + tj];
|
float &sourceR = clutr[tj];
|
||||||
float &sourceG = gtemp[ti * TS + tj];
|
float &sourceG = clutg[tj];
|
||||||
float &sourceB = btemp[ti * TS + tj];
|
float &sourceB = clutb[tj];
|
||||||
|
|
||||||
// Apply gamma sRGB (default RT)
|
// Apply gamma sRGB (default RT)
|
||||||
sourceR = Color::gamma_srgbclipped (sourceR);
|
sourceR = Color::gamma_srgbclipped (sourceR);
|
||||||
@@ -4415,20 +4447,19 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
sourceB = Color::gamma_srgbclipped (sourceB);
|
sourceB = Color::gamma_srgbclipped (sourceB);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t line_offset = ti * TS;
|
|
||||||
hald_clut->getRGB (
|
hald_clut->getRGB (
|
||||||
film_simulation_strength,
|
film_simulation_strength,
|
||||||
std::min (TS, tW - jstart),
|
std::min (TS, tW - jstart),
|
||||||
rtemp + line_offset,
|
clutr,
|
||||||
gtemp + line_offset,
|
clutg,
|
||||||
btemp + line_offset,
|
clutb,
|
||||||
out_rgbx
|
out_rgbx
|
||||||
);
|
);
|
||||||
|
|
||||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||||
float &sourceR = rtemp[ti * TS + tj];
|
float &sourceR = clutr[tj];
|
||||||
float &sourceG = gtemp[ti * TS + tj];
|
float &sourceG = clutg[tj];
|
||||||
float &sourceB = btemp[ti * TS + tj];
|
float &sourceB = clutb[tj];
|
||||||
|
|
||||||
// Apply inverse gamma sRGB
|
// Apply inverse gamma sRGB
|
||||||
sourceR = Color::igamma_srgb (out_rgbx[tj * 4 + 0]);
|
sourceR = Color::igamma_srgb (out_rgbx[tj * 4 + 0]);
|
||||||
@@ -4444,9 +4475,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
#ifdef __SSE2__
|
#ifdef __SSE2__
|
||||||
|
|
||||||
for (; j < tW - 3; j += 4, tj += 4) {
|
for (; j < tW - 3; j += 4, tj += 4) {
|
||||||
vfloat sourceR = LVF (rtemp[ti * TS + tj]);
|
vfloat sourceR = LVF (clutr[tj]);
|
||||||
vfloat sourceG = LVF (gtemp[ti * TS + tj]);
|
vfloat sourceG = LVF (clutg[tj]);
|
||||||
vfloat sourceB = LVF (btemp[ti * TS + tj]);
|
vfloat sourceB = LVF (clutb[tj]);
|
||||||
|
|
||||||
vfloat x;
|
vfloat x;
|
||||||
vfloat y;
|
vfloat y;
|
||||||
@@ -4454,23 +4485,31 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
Color::rgbxyz (sourceR, sourceG, sourceB, x, y, z, v_clut2xyz);
|
Color::rgbxyz (sourceR, sourceG, sourceB, x, y, z, v_clut2xyz);
|
||||||
Color::xyz2rgb (x, y, z, sourceR, sourceG, sourceB, v_xyz2work);
|
Color::xyz2rgb (x, y, z, sourceR, sourceG, sourceB, v_xyz2work);
|
||||||
|
|
||||||
STVF (rtemp[ti * TS + tj], sourceR);
|
STVF (clutr[tj], sourceR);
|
||||||
STVF (gtemp[ti * TS + tj], sourceG);
|
STVF (clutg[tj], sourceG);
|
||||||
STVF (btemp[ti * TS + tj], sourceB);
|
STVF (clutb[tj], sourceB);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (; j < tW; j++, tj++) {
|
for (; j < tW; j++, tj++) {
|
||||||
float &sourceR = rtemp[ti * TS + tj];
|
float &sourceR = clutr[tj];
|
||||||
float &sourceG = gtemp[ti * TS + tj];
|
float &sourceG = clutg[tj];
|
||||||
float &sourceB = btemp[ti * TS + tj];
|
float &sourceB = clutb[tj];
|
||||||
|
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
Color::rgbxyz (sourceR, sourceG, sourceB, x, y, z, clut2xyz);
|
Color::rgbxyz (sourceR, sourceG, sourceB, x, y, z, clut2xyz);
|
||||||
Color::xyz2rgb ( x, y, z, sourceR, sourceG, sourceB, wiprof );
|
Color::xyz2rgb ( x, y, z, sourceR, sourceG, sourceB, wiprof );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4598,7 +4637,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
for (int j = 0; j < tW; j++) {
|
for (int j = 0; j < tW; j++) {
|
||||||
|
|
||||||
//mix channel
|
//mix channel
|
||||||
tmpImage->r (i, j) = tmpImage->g (i, j) = tmpImage->b (i, j) = CLIP ((bwr * tmpImage->r (i, j) + bwg * tmpImage->g (i, j) + bwb * tmpImage->b (i, j)) * kcorec);
|
tmpImage->r (i, j) = tmpImage->g (i, j) = tmpImage->b (i, j) = /*CLIP*/ ((bwr * tmpImage->r (i, j) + bwg * tmpImage->g (i, j) + bwb * tmpImage->b (i, j)) * kcorec);
|
||||||
|
|
||||||
#ifndef __SSE2__
|
#ifndef __SSE2__
|
||||||
|
|
||||||
@@ -4694,9 +4733,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
bo *= preserv;
|
bo *= preserv;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpImage->r(i, j) = CLIP(ro);
|
tmpImage->r(i, j) = /*CLIP*/(ro);
|
||||||
tmpImage->g(i, j) = CLIP(go);
|
tmpImage->g(i, j) = /*CLIP*/(go);
|
||||||
tmpImage->b(i, j) = CLIP(bo);
|
tmpImage->b(i, j) = /*CLIP*/(bo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4803,9 +4842,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
|||||||
float b = tmpImage->b (i, j);
|
float b = tmpImage->b (i, j);
|
||||||
float ro, bo, go;
|
float ro, bo, go;
|
||||||
labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip);
|
labtoning (r, g, b, ro, go, bo, algm, metchrom, twoc, satLimit, satLimitOpacity, ctColorCurve, ctOpacityCurve, clToningcurve, cl2Toningcurve, iplow, iphigh, wp, wip);
|
||||||
tmpImage->r (i, j) = CLIP (ro);
|
tmpImage->r (i, j) = /*CLIP*/ (ro);
|
||||||
tmpImage->g (i, j) = CLIP (go);
|
tmpImage->g (i, j) = /*CLIP*/ (go);
|
||||||
tmpImage->b (i, j) = CLIP (bo);
|
tmpImage->b (i, j) = /*CLIP*/ (bo);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5049,9 +5088,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
r += corr;
|
r += corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -5063,9 +5102,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
g += corr;
|
g += corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5079,9 +5118,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
b += corr;
|
b += corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mid tones
|
// mid tones
|
||||||
@@ -5112,9 +5151,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
g -= 20000.f * RedM;
|
g -= 20000.f * RedM;
|
||||||
b -= 20000.f * RedM;
|
b -= 20000.f * RedM;
|
||||||
}
|
}
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -5129,9 +5168,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
g += 10000.f * GreenM;
|
g += 10000.f * GreenM;
|
||||||
b -= 20000.f * GreenM;
|
b -= 20000.f * GreenM;
|
||||||
}
|
}
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -5146,9 +5185,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
g -= 20000.f * BlueM;
|
g -= 20000.f * BlueM;
|
||||||
b += 10000.f * BlueM;
|
b += 10000.f * BlueM;
|
||||||
}
|
}
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
//high tones
|
//high tones
|
||||||
@@ -5173,9 +5212,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
b -= corr;
|
b -= corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -5188,9 +5227,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
b -= corr;
|
b -= corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -5203,9 +5242,9 @@ void ImProcFunctions::toningsmh(float r, float g, float b, float &ro, float &go,
|
|||||||
g -= corr;
|
g -= corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
ro = r;
|
ro = r;
|
||||||
@@ -5262,24 +5301,24 @@ void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &g
|
|||||||
b -= factor * krl;
|
b -= factor * krl;
|
||||||
}
|
}
|
||||||
|
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
|
|
||||||
if (kgl > 0.f) {
|
if (kgl > 0.f) {
|
||||||
r -= factor * kgl;
|
r -= factor * kgl;
|
||||||
b -= factor * kgl;
|
b -= factor * kgl;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
|
|
||||||
if (kbl > 0.f) {
|
if (kbl > 0.f) {
|
||||||
r -= factor * kbl;
|
r -= factor * kbl;
|
||||||
g -= factor * kbl;
|
g -= factor * kbl;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
//high tones
|
//high tones
|
||||||
@@ -5306,9 +5345,9 @@ void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &g
|
|||||||
g += factor * (kgh > 0.f ? kgh : 0.f);
|
g += factor * (kgh > 0.f ? kgh : 0.f);
|
||||||
b += factor * (kbh > 0.f ? kbh : 0.f);
|
b += factor * (kbh > 0.f ? kbh : 0.f);
|
||||||
|
|
||||||
r = CLIP(r);
|
// r = CLIP(r);
|
||||||
g = CLIP(g);
|
// g = CLIP(g);
|
||||||
b = CLIP(b);
|
// b = CLIP(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
float preserv = 1.f;
|
float preserv = 1.f;
|
||||||
@@ -5317,9 +5356,9 @@ void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &g
|
|||||||
preserv = lumbefore / lumafter;
|
preserv = lumbefore / lumafter;
|
||||||
}
|
}
|
||||||
|
|
||||||
ro = CLIP(r * preserv);
|
ro = /*CLIP*/(r * preserv);
|
||||||
go = CLIP(g * preserv);
|
go = /*CLIP*/(g * preserv);
|
||||||
bo = CLIP(b * preserv);
|
bo = /*CLIP*/(b * preserv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,8 +30,66 @@
|
|||||||
namespace rtengine
|
namespace rtengine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
extern void filmlike_clip(float *r, float *g, float *b);
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
inline void clipLAB(float iL, float ia, float ib, float &oL, float &oa, float &ob, const float scale, const float wp[3][3], const float wip[3][3])
|
||||||
|
{
|
||||||
|
if (iL < 0.f) {
|
||||||
|
oL = oa = ob = 0.f;
|
||||||
|
} else if (iL > 32768.f) {
|
||||||
|
|
||||||
|
float X, Y, Z;
|
||||||
|
float r, g, b;
|
||||||
|
Color::Lab2XYZ(iL, ia, ib, X, Y, Z);
|
||||||
|
Color::xyz2rgb(X, Y, Z, r, g, b, wip);
|
||||||
|
filmlike_clip(&r, &g, &b);
|
||||||
|
Color::rgbxyz(r, g, b, X, Y, Z, wp);
|
||||||
|
Color::XYZ2Lab(X, Y, Z, oL, oa, ob);
|
||||||
|
oL /= scale;
|
||||||
|
oa /= scale;
|
||||||
|
ob /= scale;
|
||||||
|
|
||||||
|
// oL = 32768.f / scale;
|
||||||
|
// oa = ob = 0.f;
|
||||||
|
} else {
|
||||||
|
oL = iL / scale;
|
||||||
|
oa = ia / scale;
|
||||||
|
ob = ib / scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void clipLAB(float iL, float ia, float ib, double &oL, double &oa, double &ob, const float scale, const float wp[3][3], const float wip[3][3])
|
||||||
|
{
|
||||||
|
float tL, ta, tb;
|
||||||
|
clipLAB(iL, ia, ib, tL, ta, tb, scale, wp, wip);
|
||||||
|
oL = tL;
|
||||||
|
oa = ta;
|
||||||
|
ob = tb;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
extern const Settings* settings;
|
extern const Settings* settings;
|
||||||
|
|
||||||
|
#define DECLARE_WORKING_MATRICES_(space) \
|
||||||
|
TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix ( space ); \
|
||||||
|
const float wp[3][3] = { \
|
||||||
|
{static_cast<float> (wprof[0][0]), static_cast<float> (wprof[0][1]), static_cast<float> (wprof[0][2])}, \
|
||||||
|
{static_cast<float> (wprof[1][0]), static_cast<float> (wprof[1][1]), static_cast<float> (wprof[1][2])}, \
|
||||||
|
{static_cast<float> (wprof[2][0]), static_cast<float> (wprof[2][1]), static_cast<float> (wprof[2][2])} \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix ( space ); \
|
||||||
|
const float wip[3][3] = { \
|
||||||
|
{static_cast<float> (wiprof[0][0]), static_cast<float> (wiprof[0][1]), static_cast<float> (wiprof[0][2])}, \
|
||||||
|
{static_cast<float> (wiprof[1][0]), static_cast<float> (wiprof[1][1]), static_cast<float> (wiprof[1][2])}, \
|
||||||
|
{static_cast<float> (wiprof[2][0]), static_cast<float> (wiprof[2][1]), static_cast<float> (wiprof[2][2])} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Used in ImProcCoordinator::updatePreviewImage (rtengine/improccoordinator.cc)
|
// Used in ImProcCoordinator::updatePreviewImage (rtengine/improccoordinator.cc)
|
||||||
// Crop::update (rtengine/dcrop.cc)
|
// Crop::update (rtengine/dcrop.cc)
|
||||||
// Thumbnail::processImage (rtengine/rtthumbnail.cc)
|
// Thumbnail::processImage (rtengine/rtthumbnail.cc)
|
||||||
@@ -40,6 +98,8 @@ extern const Settings* settings;
|
|||||||
// otherwise divide by 327.68, convert to xyz and apply the sRGB transform, before converting with gamma2curve
|
// otherwise divide by 327.68, convert to xyz and apply the sRGB transform, before converting with gamma2curve
|
||||||
void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
|
void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
|
||||||
{
|
{
|
||||||
|
DECLARE_WORKING_MATRICES_(params->icm.working);
|
||||||
|
|
||||||
if (monitorTransform) {
|
if (monitorTransform) {
|
||||||
|
|
||||||
int W = lab->W;
|
int W = lab->W;
|
||||||
@@ -68,9 +128,8 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
|
|||||||
float* rb = lab->b[i];
|
float* rb = lab->b[i];
|
||||||
|
|
||||||
for (int j = 0; j < W; j++) {
|
for (int j = 0; j < W; j++) {
|
||||||
buffer[iy++] = rL[j] / 327.68f;
|
clipLAB(rL[j], ra[j], rb[j], buffer[iy], buffer[iy+1], buffer[iy+2], 327.68f, wp, wip);
|
||||||
buffer[iy++] = ra[j] / 327.68f;
|
iy += 3;
|
||||||
buffer[iy++] = rb[j] / 327.68f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmsDoTransform (monitorTransform, buffer, data + ix, W);
|
cmsDoTransform (monitorTransform, buffer, data + ix, W);
|
||||||
@@ -94,12 +153,14 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
|
|||||||
|
|
||||||
float R, G, B;
|
float R, G, B;
|
||||||
float x_, y_, z_;
|
float x_, y_, z_;
|
||||||
|
float L, a, b;
|
||||||
|
|
||||||
for (int j = 0; j < W; ++j) {
|
for (int j = 0; j < W; ++j) {
|
||||||
|
|
||||||
//float L1=rL[j],a1=ra[j],b1=rb[j];//for testing
|
//float L1=rL[j],a1=ra[j],b1=rb[j];//for testing
|
||||||
|
clipLAB(rL[j], ra[j], rb[j], L, a, b, 1.f, wp, wip);
|
||||||
|
|
||||||
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_ );
|
Color::Lab2XYZ(L, a, b, x_, y_, z_ );
|
||||||
|
|
||||||
Color::xyz2srgb(x_, y_, z_, R, G, B);
|
Color::xyz2srgb(x_, y_, z_, R, G, B);
|
||||||
|
|
||||||
@@ -124,6 +185,8 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
|
|||||||
// otherwise divide by 327.68, convert to xyz and apply the RGB transform, before converting with gamma2curve
|
// otherwise divide by 327.68, convert to xyz and apply the RGB transform, before converting with gamma2curve
|
||||||
Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings)
|
Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings)
|
||||||
{
|
{
|
||||||
|
DECLARE_WORKING_MATRICES_(icm.working);
|
||||||
|
|
||||||
//gamutmap(lab);
|
//gamutmap(lab);
|
||||||
|
|
||||||
if (cx < 0) {
|
if (cx < 0) {
|
||||||
@@ -200,9 +263,8 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
|
|||||||
float* rb = lab->b[i];
|
float* rb = lab->b[i];
|
||||||
|
|
||||||
for (int j = cx; j < cx + cw; j++) {
|
for (int j = cx; j < cx + cw; j++) {
|
||||||
buffer[iy++] = rL[j] / 327.68f;
|
clipLAB(rL[j], ra[j], rb[j], buffer[iy], buffer[iy+1], buffer[iy+2], 327.68f, wp, wip);
|
||||||
buffer[iy++] = ra[j] / 327.68f;
|
iy += 3;
|
||||||
buffer[iy++] = rb[j] / 327.68f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmsDoTransform (hTransform, buffer, data + ix, cw);
|
cmsDoTransform (hTransform, buffer, data + ix, cw);
|
||||||
@@ -230,8 +292,10 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
|
|||||||
|
|
||||||
float R, G, B;
|
float R, G, B;
|
||||||
float x_, y_, z_;
|
float x_, y_, z_;
|
||||||
|
float L, a, b;
|
||||||
|
|
||||||
for (int j = cx; j < cx + cw; ++j) {
|
for (int j = cx; j < cx + cw; ++j) {
|
||||||
|
clipLAB(rL[j], ra[j], rb[j], L, a, b, 1.f, wp, wip);
|
||||||
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_);
|
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_);
|
||||||
|
|
||||||
Color::xyz2rgb(x_, y_, z_, R, G, B, xyz_rgb);
|
Color::xyz2rgb(x_, y_, z_, R, G, B, xyz_rgb);
|
||||||
@@ -330,9 +394,9 @@ Imagefloat* ImProcFunctions::lab2rgbOut (LabImage* lab, int cx, int cy, int cw,
|
|||||||
|
|
||||||
Color::xyz2srgb(x_, y_, z_, R, G, B);
|
Color::xyz2srgb(x_, y_, z_, R, G, B);
|
||||||
|
|
||||||
image->r(i - cy, j - cx) = Color::gamma2curve[CLIP(R)];
|
setUnlessOOG(image->r(i - cy, j - cx), Color::gamma2curve[CLIP(R)]);
|
||||||
image->g(i - cy, j - cx) = Color::gamma2curve[CLIP(G)];
|
setUnlessOOG(image->g(i - cy, j - cx), Color::gamma2curve[CLIP(G)]);
|
||||||
image->b(i - cy, j - cx) = Color::gamma2curve[CLIP(B)];
|
setUnlessOOG(image->b(i - cy, j - cx), Color::gamma2curve[CLIP(B)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,9 +162,9 @@ void ImProcFunctions::Lanczos (const Imagefloat* src, Imagefloat* dst, float sca
|
|||||||
b += wh[k] * lb[jj];
|
b += wh[k] * lb[jj];
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->r (i, j) = CLIP (r);//static_cast<int> (r));
|
dst->r (i, j) = /*CLIP*/ (r);//static_cast<int> (r));
|
||||||
dst->g (i, j) = CLIP (g);//static_cast<int> (g));
|
dst->g (i, j) = /*CLIP*/ (g);//static_cast<int> (g));
|
||||||
dst->b (i, j) = CLIP (b);//static_cast<int> (b));
|
dst->b (i, j) = /*CLIP*/ (b);//static_cast<int> (b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,4 +137,20 @@ constexpr std::uint8_t uint16ToUint8Rounded(std::uint16_t i)
|
|||||||
return ((i + 128) - ((i + 128) >> 8)) >> 8;
|
return ((i + 128) - ((i + 128) >> 8)) >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool OOG(const T &val, const T &high=T(MAXVAL))
|
||||||
|
{
|
||||||
|
return (val > high);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void setUnlessOOG(T &out, const T &val)
|
||||||
|
{
|
||||||
|
if (!OOG(out)) {
|
||||||
|
out = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1038,11 +1038,11 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||||||
|
|
||||||
for (int j = 0; j < rwidth; j++) {
|
for (int j = 0; j < rwidth; j++) {
|
||||||
float red = baseImg->r (i, j) * rmi;
|
float red = baseImg->r (i, j) * rmi;
|
||||||
baseImg->r (i, j) = CLIP (red);
|
baseImg->r (i, j) = /*CLIP*/ (red);
|
||||||
float green = baseImg->g (i, j) * gmi;
|
float green = baseImg->g (i, j) * gmi;
|
||||||
baseImg->g (i, j) = CLIP (green);
|
baseImg->g (i, j) = /*CLIP*/ (green);
|
||||||
float blue = baseImg->b (i, j) * bmi;
|
float blue = baseImg->b (i, j) * bmi;
|
||||||
baseImg->b (i, j) = CLIP (blue);
|
baseImg->b (i, j) = /*CLIP*/ (blue);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1234,6 +1234,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// luminance processing
|
// luminance processing
|
||||||
// ipf.EPDToneMap(labView,0,6);
|
// ipf.EPDToneMap(labView,0,6);
|
||||||
|
|
||||||
@@ -1303,7 +1304,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||||||
ipf.ciecam_02float (cieView, adap, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, sk, execsharp, d, dj, yb, rtt);
|
ipf.ciecam_02float (cieView, adap, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, sk, execsharp, d, dj, yb, rtt);
|
||||||
delete cieView;
|
delete cieView;
|
||||||
}
|
}
|
||||||
|
|
||||||
// color processing
|
// color processing
|
||||||
//ipf.colorCurve (labView, labView);
|
//ipf.colorCurve (labView, labView);
|
||||||
|
|
||||||
|
|||||||
@@ -1978,6 +1978,11 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm
|
|||||||
{
|
{
|
||||||
rtengine::procparams::ProcParams pparams;
|
rtengine::procparams::ProcParams pparams;
|
||||||
ipc->getParams (&pparams);
|
ipc->getParams (&pparams);
|
||||||
|
|
||||||
|
if (gimpPlugin) {
|
||||||
|
pparams.icm.gamma = "linear_g1.0";
|
||||||
|
}
|
||||||
|
|
||||||
rtengine::ProcessingJob *job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
|
rtengine::ProcessingJob *job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
|
||||||
|
|
||||||
// save immediately
|
// save immediately
|
||||||
@@ -1985,7 +1990,9 @@ bool EditorPanel::saveImmediately (const Glib::ustring &filename, const SaveForm
|
|||||||
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (sf.format == "tif") {
|
if (gimpPlugin) {
|
||||||
|
err = img->saveAsTIFF (filename, 32, true);
|
||||||
|
} else if (sf.format == "tif") {
|
||||||
err = img->saveAsTIFF (filename, sf.tiffBits, sf.tiffUncompressed);
|
err = img->saveAsTIFF (filename, sf.tiffBits, sf.tiffUncompressed);
|
||||||
} else if (sf.format == "png") {
|
} else if (sf.format == "png") {
|
||||||
err = img->saveAsPNG (filename, sf.pngBits);
|
err = img->saveAsPNG (filename, sf.pngBits);
|
||||||
|
|||||||
@@ -674,15 +674,8 @@ int main (int argc, char **argv)
|
|||||||
m.run (*rtWindow);
|
m.run (*rtWindow);
|
||||||
gdk_threads_leave();
|
gdk_threads_leave();
|
||||||
|
|
||||||
if (gimpPlugin &&
|
if (gimpPlugin && rtWindow->epanel && rtWindow->epanel->isRealized()) {
|
||||||
rtWindow->epanel && rtWindow->epanel->isRealized()) {
|
if (!rtWindow->epanel->saveImmediately(argv2, SaveFormat())) {
|
||||||
SaveFormat sf;
|
|
||||||
sf.format = "tif";
|
|
||||||
sf.tiffBits = 16;
|
|
||||||
sf.tiffUncompressed = true;
|
|
||||||
sf.saveParams = true;
|
|
||||||
|
|
||||||
if (!rtWindow->epanel->saveImmediately (argv2, sf)) {
|
|
||||||
ret = -2;
|
ret = -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user