Merge pull request #4444 from Beep6581/vibrance_review
Code review and speedup for ImProcFunctions::vibrance()
This commit is contained in:
commit
0a88a36ed9
@ -2317,6 +2317,46 @@ void Color::AllMunsellLch(bool lumaMuns, float Lprov1, float Loldd, float HH, fl
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* AllMunsellLch correction
|
||||
* Copyright (c) 2012 Jacques Desmis <jdesmis@gmail.com>
|
||||
*
|
||||
* This function corrects the color (hue) for changes in chromaticity and luminance
|
||||
* to use in a "for" or "do while" statement
|
||||
*
|
||||
* Parameters:
|
||||
* float Lprov1: luminance
|
||||
* float HH: hue before
|
||||
* float Chprov1, CC : chroma after and before
|
||||
* float coorectionHuechroma : correction Hue for chromaticity (saturation)
|
||||
*/
|
||||
void Color::AllMunsellLch(float Lprov1, float HH, float Chprov1, float CC, float &correctionHuechroma)
|
||||
{
|
||||
|
||||
float correctionHue = 0.f, correctionHueLum = 0.f;
|
||||
bool correctL;
|
||||
|
||||
if(CC >= 6.f && CC < 140.f) { //if C > 140 we say C=140 (only in Prophoto ...with very large saturation)
|
||||
static const float huelimit[8] = { -2.48f, -0.55f, 0.44f, 1.52f, 1.87f, 3.09f, -0.27f, 0.44f}; //limits hue of blue-purple, red-yellow, green-yellow, red-purple
|
||||
|
||||
if (Chprov1 > 140.f) {
|
||||
Chprov1 = 139.f; //limits of LUTf
|
||||
}
|
||||
|
||||
Chprov1 = rtengine::max(Chprov1, 6.f);
|
||||
|
||||
for(int zo = 1; zo <= 4; zo++) {
|
||||
if(HH > huelimit[2 * zo - 2] && HH < huelimit[2 * zo - 1]) {
|
||||
//zone=zo;
|
||||
correctL = false;
|
||||
MunsellLch (Lprov1, HH, Chprov1, CC, correctionHue, zo, correctionHueLum, correctL); //munsell chroma correction
|
||||
correctionHuechroma = correctionHue; //preserve
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* GamutLchonly correction
|
||||
* Copyright (c)2012 Jacques Desmis <jdesmis@gmail.com> and Jean-Christophe Frisch <natureh@free.fr>
|
||||
@ -2413,7 +2453,7 @@ void Color::gamutLchonly (float HH, float &Lprov1, float &Chprov1, float &R, flo
|
||||
}
|
||||
|
||||
inGamut = false;
|
||||
} else if (!isHLEnabled && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) {
|
||||
} else if (!isHLEnabled && rtengine::max(R, G, B) > ClipLevel && rtengine::min(R, G, B) <= ClipLevel) {
|
||||
|
||||
// if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut
|
||||
#ifdef _DEBUG
|
||||
@ -2538,7 +2578,7 @@ void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chpr
|
||||
}
|
||||
|
||||
inGamut = false;
|
||||
} else if (!isHLEnabled && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) {
|
||||
} else if (!isHLEnabled && rtengine::max(R, G, B) > ClipLevel && rtengine::min(R, G, B) <= ClipLevel) {
|
||||
|
||||
// if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut
|
||||
#ifdef _DEBUG
|
||||
@ -2562,6 +2602,109 @@ void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chpr
|
||||
//end first gamut control
|
||||
}
|
||||
|
||||
/*
|
||||
* GamutLchonly correction
|
||||
* Copyright (c)2012 Jacques Desmis <jdesmis@gmail.com> and Jean-Christophe Frisch <natureh@free.fr>
|
||||
*
|
||||
* This function puts the data (Lab) in the gamut of "working profile":
|
||||
* it returns the corrected values of the chromaticity and luminance
|
||||
*
|
||||
* float HH : hue
|
||||
* float2 sincosval : sin and cos of HH
|
||||
* float Lprov1 : input luminance value, sent back corrected
|
||||
* float Chprov1: input chroma value, sent back corrected
|
||||
* float wip : working profile
|
||||
* bool isHLEnabled : if "highlight reconstruction " is enabled
|
||||
* float coef : a float number between [0.95 ; 1.0[... the nearest it is from 1.0, the more precise it will be... and the longer too as more iteration will be necessary)
|
||||
*/
|
||||
void Color::gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &saturation, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef)
|
||||
{
|
||||
constexpr float ClipLevel = 1.f;
|
||||
bool inGamut;
|
||||
float R, G, B;
|
||||
|
||||
do {
|
||||
inGamut = true;
|
||||
|
||||
float aprov1 = Chprov1 * sincosval.y;
|
||||
float bprov1 = Chprov1 * sincosval.x;
|
||||
|
||||
//conversion Lab RGB to limit Lab values - this conversion is useful before Munsell correction
|
||||
float fy = c1By116 * Lprov1 + c16By116;
|
||||
float fx = 0.002f * aprov1 + fy;
|
||||
float fz = fy - 0.005f * bprov1;
|
||||
|
||||
float x_ = f2xyz(fx) * D50x;
|
||||
float z_ = f2xyz(fz) * D50z;
|
||||
float y_ = (Lprov1 > epskap) ? fy * fy * fy : Lprov1 / kappaf;
|
||||
|
||||
xyz2rgb(x_, y_, z_, R, G, B, wip);
|
||||
|
||||
// gamut control before saturation to put Lab values in future gamut, but not RGB
|
||||
if (rtengine::min(R, G, B) < 0.f) {
|
||||
|
||||
Lprov1 = rtengine::max(Lprov1, 0.1f);
|
||||
|
||||
//gamut for L with ultra blue : we can improve the algorithm ... thinner, and other color ???
|
||||
if(HH < -0.9f && HH > -1.55f ) {//ultra blue
|
||||
if(Chprov1 > 160.f) if (Lprov1 < 5.f) {
|
||||
Lprov1 = 5.f; //very very very very high chroma
|
||||
}
|
||||
|
||||
if(Chprov1 > 140.f) if (Lprov1 < 3.5f) {
|
||||
Lprov1 = 3.5f;
|
||||
}
|
||||
|
||||
if(Chprov1 > 120.f) if (Lprov1 < 2.f) {
|
||||
Lprov1 = 2.f;
|
||||
}
|
||||
|
||||
if(Chprov1 > 105.f) if (Lprov1 < 1.f) {
|
||||
Lprov1 = 1.f;
|
||||
}
|
||||
|
||||
if(Chprov1 > 90.f) if (Lprov1 < 0.7f) {
|
||||
Lprov1 = 0.7f;
|
||||
}
|
||||
|
||||
if(Chprov1 > 50.f) if (Lprov1 < 0.5f) {
|
||||
Lprov1 = 0.5f;
|
||||
}
|
||||
|
||||
if(Chprov1 > 20.f) if (Lprov1 < 0.4f) {
|
||||
Lprov1 = 0.4f;
|
||||
}
|
||||
}
|
||||
|
||||
Chprov1 *= higherCoef; // decrease the chromaticity value
|
||||
|
||||
if (Chprov1 <= 3.f) {
|
||||
Lprov1 += lowerCoef;
|
||||
}
|
||||
|
||||
inGamut = false;
|
||||
} else if (!isHLEnabled && rtengine::max(R, G, B) > ClipLevel && rtengine::min(R, G, B) <= ClipLevel) {
|
||||
|
||||
// if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut
|
||||
|
||||
if (Lprov1 > 99.999f) {
|
||||
Lprov1 = 99.98f;
|
||||
}
|
||||
|
||||
Chprov1 *= higherCoef;
|
||||
|
||||
if (Chprov1 <= 3.f) {
|
||||
Lprov1 -= lowerCoef;
|
||||
}
|
||||
|
||||
inGamut = false;
|
||||
}
|
||||
} while (!inGamut);
|
||||
|
||||
saturation = 1.f - (rtengine::min(R, G, B) / rtengine::max(R, G, B));
|
||||
//end first gamut control
|
||||
}
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef, bool &neg, bool &more_rgb)
|
||||
@ -2612,7 +2755,7 @@ void Color::gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const
|
||||
}
|
||||
|
||||
inGamut = false;
|
||||
} else if (!isHLEnabled && (R > ClipLevel || G > ClipLevel || B > ClipLevel)) {
|
||||
} else if (!isHLEnabled && rtengine::max(R, G, B) > ClipLevel && rtengine::min(R, G, B) <= ClipLevel) {
|
||||
|
||||
// if "highlight reconstruction" is enabled or the point is completely white (clipped, no color), don't control Gamut
|
||||
#ifdef _DEBUG
|
||||
@ -4187,12 +4330,12 @@ void Color::SkinSat (float lum, float hue, float chrom, float &satreduc)
|
||||
{
|
||||
|
||||
// to be adapted...by tests
|
||||
float reduction = 0.3f; // use "reduction" for "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1
|
||||
float extendedreduction = 0.4f; // use "extendedreduction" for wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation
|
||||
float extendedreduction2 = 0.6f; // use "extendedreduction2" for wide area for transition
|
||||
constexpr float reduction = 0.3f; // use "reduction" for "real" skin color : take into account a slightly usage of contrast and saturation in RT if option "skin" = 1
|
||||
constexpr float extendedreduction = 0.4f; // use "extendedreduction" for wide area skin color, useful if not accurate colorimetry or if the user has changed hue and saturation
|
||||
constexpr float extendedreduction2 = 0.6f; // use "extendedreduction2" for wide area for transition
|
||||
|
||||
float C9 = 8.0, C8 = 15.0, C7 = 12.0, C4 = 7.0, C3 = 5.0, C2 = 5.0, C1 = 5.0;
|
||||
float H9 = 0.05, H8 = 0.25, H7 = 0.1, H4 = 0.02, H3 = 0.02, H2 = 0.1, H1 = 0.1, H10 = -0.2, H11 = -0.2; //H10 and H11 are curious...H11=-0.8 ??
|
||||
constexpr float C9 = 8.f, C8 = 15.f, C7 = 12.f, C4 = 7.f, C3 = 5.f, C2 = 5.f, C1 = 5.f;
|
||||
constexpr float H9 = 0.05f, H8 = 0.25f, H7 = 0.1f, H4 = 0.02f, H3 = 0.02f, H2 = 0.1f, H1 = 0.1f, H10 = -0.2f, H11 = -0.2f; //H10 and H11 are curious...H11=-0.8 ??
|
||||
|
||||
if (lum >= 85.f) {
|
||||
if((hue > (0.78f - H9) && hue < (1.18f + H9)) && (chrom > 8.f && chrom < (14.f + C9))) {
|
||||
|
@ -1384,6 +1384,7 @@ public:
|
||||
#else
|
||||
static void AllMunsellLch (bool lumaMuns, float Lprov1, float Loldd, float HH, float Chprov1, float CC, float &correctionHueChroma, float &correctlum);
|
||||
#endif
|
||||
static void AllMunsellLch (float Lprov1, float HH, float Chprov1, float CC, float &correctionHueChroma);
|
||||
|
||||
|
||||
/**
|
||||
@ -1416,6 +1417,7 @@ public:
|
||||
static void gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &R, float &G, float &B, const double wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef);
|
||||
static void gamutLchonly (float2 sincosval, float &Lprov1, float &Chprov1, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef);
|
||||
#endif
|
||||
static void gamutLchonly (float HH, float2 sincosval, float &Lprov1, float &Chprov1, float &saturation, const float wip[3][3], const bool isHLEnabled, const float lowerCoef, const float higherCoef);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -19,7 +19,6 @@
|
||||
*/
|
||||
|
||||
#include "rt_math.h"
|
||||
//#include <algorithm>
|
||||
|
||||
#include "rtengine.h"
|
||||
#include "improcfun.h"
|
||||
@ -28,7 +27,7 @@
|
||||
#include "../rtgui/thresholdselector.h"
|
||||
#include "curves.h"
|
||||
#include "color.h"
|
||||
|
||||
#include "StopWatch.h"
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
@ -41,8 +40,6 @@ namespace rtengine
|
||||
|
||||
using namespace procparams;
|
||||
|
||||
#define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c)
|
||||
|
||||
extern const Settings* settings;
|
||||
|
||||
void fillCurveArrayVib (DiagonalCurve* diagCurve, LUTf &outCurve)
|
||||
@ -75,6 +72,7 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
if (!params->vibrance.enabled) {
|
||||
return;
|
||||
}
|
||||
BENCHFUN
|
||||
|
||||
// int skip=1; //scale==1 ? 1 : 16;
|
||||
bool skinCurveIsSet = false;
|
||||
@ -101,42 +99,23 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
const int width = lab->W;
|
||||
const int height = lab->H;
|
||||
|
||||
#ifdef _DEBUG
|
||||
MyTime t1e, t2e;
|
||||
t1e.set();
|
||||
int negat = 0, moreRGB = 0, negsat = 0, moresat = 0;
|
||||
#endif
|
||||
|
||||
// skin hue curve
|
||||
// I use diagonal because I think it's better
|
||||
LUTf skin_curve (65536, 0);
|
||||
|
||||
if (skinCurveIsSet) {
|
||||
fillCurveArrayVib (dcurve, skin_curve);
|
||||
}
|
||||
|
||||
if (dcurve) {
|
||||
delete dcurve;
|
||||
dcurve = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// skin_curve.dump("skin_curve");
|
||||
|
||||
const float chromaPastel = float (params->vibrance.pastels) / 100.0f;
|
||||
const float chromaSatur = float (params->vibrance.saturated) / 100.0f;
|
||||
const float p00 = 0.07f;
|
||||
const float limitpastelsatur = (static_cast<float>(params->vibrance.psthreshold.getTopLeft()) / 100.0f) * (1.0f - p00) + p00;
|
||||
const float maxdp = (limitpastelsatur - p00) / 4.0f;
|
||||
const float maxds = (1.0 - limitpastelsatur) / 4.0f;
|
||||
const float chromaPastel = params->vibrance.pastels / 100.f;
|
||||
const float chromaSatur = params->vibrance.saturated / 100.f;
|
||||
constexpr float p00 = 0.07f;
|
||||
const float limitpastelsatur = (static_cast<float>(params->vibrance.psthreshold.getTopLeft()) / 100.f) * (1.f - p00) + p00;
|
||||
const float maxdp = (limitpastelsatur - p00) / 4.f;
|
||||
const float maxds = (1.f - limitpastelsatur) / 4.f;
|
||||
const float p0 = p00 + maxdp;
|
||||
const float p1 = p00 + 2.0f * maxdp;
|
||||
const float p2 = p00 + 3.0f * maxdp;
|
||||
const float p1 = p00 + 2.f * maxdp;
|
||||
const float p2 = p00 + 3.f * maxdp;
|
||||
const float s0 = limitpastelsatur + maxds;
|
||||
const float s1 = limitpastelsatur + 2.0f * maxds;
|
||||
const float s2 = limitpastelsatur + 3.0f * maxds;
|
||||
const float transitionweighting = static_cast<float>(params->vibrance.psthreshold.getBottomLeft()) / 100.0f;
|
||||
float chromamean = 0.0f;
|
||||
const float s1 = limitpastelsatur + 2.f * maxds;
|
||||
const float s2 = limitpastelsatur + 3.f * maxds;
|
||||
const float transitionweighting = static_cast<float>(params->vibrance.psthreshold.getBottomLeft()) / 100.f;
|
||||
float chromamean = 0.f;
|
||||
|
||||
if (chromaPastel != chromaSatur) {
|
||||
//if sliders pastels and saturated are different: transition with a double linear interpolation: between p2 and limitpastelsatur, and between limitpastelsatur and s0
|
||||
@ -144,9 +123,9 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
chromamean = maxdp * (chromaSatur - chromaPastel) / (s0 - p2) + chromaPastel;
|
||||
|
||||
// move chromaMean up or down depending on transitionCtrl
|
||||
if (transitionweighting > 0.0f) {
|
||||
if (transitionweighting > 0.f) {
|
||||
chromamean = (chromaSatur - chromamean) * transitionweighting + chromamean;
|
||||
} else if (transitionweighting < 0.0f) {
|
||||
} else if (transitionweighting < 0.f) {
|
||||
chromamean = (chromamean - chromaPastel) * transitionweighting + chromamean;
|
||||
}
|
||||
}
|
||||
@ -157,13 +136,26 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
const float chromaSatur_a = (chromaSatur - chromamean) / (s0 - limitpastelsatur);
|
||||
const float chromaSatur_b = chromaSatur - chromaSatur_a * s0;
|
||||
|
||||
const float dhue = 0.15f; //hue transition
|
||||
const float dchr = 20.0f; //chroma transition
|
||||
const float skbeg = -0.05f; //begin hue skin
|
||||
const float skend = 1.60f; //end hue skin
|
||||
const float xx = 0.5f; //soft : between 0.3 and 1.0
|
||||
const float ask = 65535.0f / (skend - skbeg);
|
||||
const float bsk = -skbeg * ask;
|
||||
constexpr float dhue = 0.15f; //hue transition
|
||||
constexpr float dchr = 20.f; //chroma transition
|
||||
constexpr float skbeg = -0.05f; //begin hue skin
|
||||
constexpr float skend = 1.60f; //end hue skin
|
||||
constexpr float xx = 0.5f; //soft : between 0.3 and 1.0
|
||||
constexpr float ask = 65535.f / (skend - skbeg);
|
||||
constexpr float bsk0 = -skbeg;
|
||||
constexpr float bsk = -skbeg * ask;
|
||||
|
||||
LUTf skin_curve (65536, 0);
|
||||
|
||||
if (skinCurveIsSet) {
|
||||
fillCurveArrayVib (dcurve, skin_curve);
|
||||
skin_curve /= ask;
|
||||
}
|
||||
|
||||
if (dcurve) {
|
||||
delete dcurve;
|
||||
dcurve = nullptr;
|
||||
}
|
||||
|
||||
|
||||
const bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated
|
||||
@ -172,139 +164,118 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
|
||||
TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working);
|
||||
//inverse matrix user select
|
||||
const double wip[3][3] = {
|
||||
{wiprof[0][0], wiprof[0][1], wiprof[0][2]},
|
||||
{wiprof[1][0], wiprof[1][1], wiprof[1][2]},
|
||||
{wiprof[2][0], wiprof[2][1], wiprof[2][2]}
|
||||
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])}
|
||||
};
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
MunsellDebugInfo* MunsDebugInfo = nullptr;
|
||||
|
||||
if (avoidcolorshift) {
|
||||
MunsDebugInfo = new MunsellDebugInfo();
|
||||
if (settings->verbose) {
|
||||
printf ("vibrance: p0=%1.2f p1=%1.2f p2=%1.2f s0=%1.2f s1=%1.2f s2=%1.2f\n", p0, p1, p2, s0, s1, s2);
|
||||
printf (" pastel=%f satur=%f limit= %1.2f chromamean=%0.5f\n", 1.0f + chromaPastel, 1.0f + chromaSatur, limitpastelsatur, chromamean);
|
||||
}
|
||||
|
||||
#pragma omp parallel default(shared) firstprivate(lab, MunsDebugInfo) reduction(+: negat, moreRGB, negsat, moresat) if (multiThread)
|
||||
#else
|
||||
#pragma omp parallel default(shared) if (multiThread)
|
||||
#endif
|
||||
#pragma omp parallel if (multiThread)
|
||||
{
|
||||
|
||||
float sathue[5], sathue2[4]; // adjust sat in function of hue
|
||||
|
||||
/*
|
||||
// Fitting limitpastelsatur into the real 0.07->1.0 range
|
||||
// limitpastelsatur = limitpastelsatur*(1.0f-p00) + p00;
|
||||
float p0,p1,p2;//adapt limit of pyramid to psThreshold
|
||||
float s0,s1,s2;
|
||||
*/
|
||||
|
||||
#ifdef _OPENMP
|
||||
|
||||
if (settings->verbose && omp_get_thread_num() == 0) {
|
||||
#else
|
||||
|
||||
if (settings->verbose) {
|
||||
#ifdef __SSE2__
|
||||
float HHbuffer[width] ALIGNED16;
|
||||
float CCbuffer[width] ALIGNED16;
|
||||
#endif
|
||||
printf ("vibrance: p0=%1.2f p1=%1.2f p2=%1.2f s0=%1.2f s1=%1.2f s2=%1.2f\n", p0, p1, p2, s0, s1, s2);
|
||||
printf (" pastel=%f satur=%f limit= %1.2f chromamean=%0.5f\n", 1.0f + chromaPastel, 1.0f + chromaSatur, limitpastelsatur, chromamean);
|
||||
}
|
||||
float sathue[5], sathue2[4]; // adjust sat in function of hue
|
||||
|
||||
#pragma omp for schedule(dynamic, 16)
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int i = 0; i < height; i++) {
|
||||
#ifdef __SSE2__
|
||||
// vectorized per row calculation of HH and CC
|
||||
vfloat c327d68v = F2V(327.68f);
|
||||
int k = 0;
|
||||
for (; k < width - 3; k += 4) {
|
||||
vfloat av = LVFU(lab->a[i][k]);
|
||||
vfloat bv = LVFU(lab->b[i][k]);
|
||||
STVF(HHbuffer[k], xatan2f(bv, av));
|
||||
STVF(CCbuffer[k], vsqrtf(SQRV(av) + SQRV(bv)) / c327d68v);
|
||||
}
|
||||
for (; k < width; k++) {
|
||||
HHbuffer[k] = xatan2f (lab->b[i][k], lab->a[i][k]);
|
||||
CCbuffer[k] = sqrt (SQR (lab->a[i][k]) + SQR (lab->b[i][k])) / 327.68f;
|
||||
}
|
||||
#endif
|
||||
for (int j = 0; j < width; j++) {
|
||||
float LL = lab->L[i][j] / 327.68f;
|
||||
float CC = sqrt (SQR (lab->a[i][j]) + SQR (lab->b[i][j])) / 327.68f;
|
||||
#ifdef __SSE2__
|
||||
float HH = HHbuffer[j];
|
||||
float CC = CCbuffer[j];
|
||||
#else
|
||||
float HH = xatan2f (lab->b[i][j], lab->a[i][j]);
|
||||
|
||||
float satredu = 1.0f; //reduct sat in function of skin
|
||||
|
||||
if (protectskins) {
|
||||
Color::SkinSat (LL, HH, CC, satredu);// for skin colors
|
||||
}
|
||||
float CC = sqrt (SQR (lab->a[i][j]) + SQR (lab->b[i][j])) / 327.68f;
|
||||
#endif
|
||||
|
||||
// here we work on Chromaticity and Hue
|
||||
// variation of Chromaticity ==> saturation via RGB
|
||||
// Munsell correction, then conversion to Lab
|
||||
float Lprov = LL;
|
||||
float Chprov = CC;
|
||||
float R, G, B;
|
||||
float2 sincosval;
|
||||
|
||||
if (CC == 0.0f) {
|
||||
if (CC == 0.f) {
|
||||
sincosval.y = 1.f;
|
||||
sincosval.x = 0.0f;
|
||||
sincosval.x = 0.f;
|
||||
} else {
|
||||
sincosval.y = lab->a[i][j] / (CC * 327.68f);
|
||||
sincosval.x = lab->b[i][j] / (CC * 327.68f);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
bool neg = false;
|
||||
bool more_rgb = false;
|
||||
//gamut control : Lab values are in gamut
|
||||
Color::gamutLchonly (HH, sincosval, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f, neg, more_rgb);
|
||||
float saturation;
|
||||
Color::gamutLchonly(HH, sincosval, Lprov, Chprov, saturation, wip, highlight, 0.15f, 0.98f);
|
||||
|
||||
if (neg) {
|
||||
negat++;
|
||||
}
|
||||
if (Chprov > 6.f) {
|
||||
float satredu = 1.f; //reduct sat in function of skin
|
||||
|
||||
if (more_rgb) {
|
||||
moreRGB++;
|
||||
}
|
||||
if (protectskins) {
|
||||
Color::SkinSat (LL, HH, CC, satredu);// for skin colors
|
||||
}
|
||||
|
||||
#else
|
||||
//gamut control : Lab values are in gamut
|
||||
Color::gamutLchonly (HH, sincosval, Lprov, Chprov, R, G, B, wip, highlight, 0.15f, 0.98f);
|
||||
#endif
|
||||
|
||||
if (Chprov > 6.0f) {
|
||||
const float saturation = SAT (R, G, B);
|
||||
|
||||
if (saturation > 0.0f) {
|
||||
if (satredu != 1.0f) {
|
||||
if (saturation > 0.f) {
|
||||
if (satredu != 1.f) {
|
||||
// for skin, no differentiation
|
||||
sathue [0] = sathue [1] = sathue [2] = sathue [3] = sathue[4] = 1.0f;
|
||||
sathue2[0] = sathue2[1] = sathue2[2] = sathue2[3] = 1.0f;
|
||||
sathue [0] = sathue [1] = sathue [2] = sathue [3] = sathue[4] = 1.f;
|
||||
sathue2[0] = sathue2[1] = sathue2[2] = sathue2[3] = 1.f;
|
||||
} else {
|
||||
//double pyramid: LL and HH
|
||||
//I try to take into account: Munsell response (human vision) and Gamut..(less response for red): preferably using Prophoto or WideGamut
|
||||
//blue: -1.80 -3.14 green = 2.1 3.14 green-yellow=1.4 2.1 red:0 1.4 blue-purple:-0.7 -1.4 purple: 0 -0.7
|
||||
//these values allow a better and differential response
|
||||
if (LL < 20.0f) { //more for blue-purple, blue and red modulate
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[3] = 1.f;
|
||||
if (/*HH> -3.1415f &&*/ HH < -1.5f ) {
|
||||
sathue[0] = 1.3f; //blue
|
||||
sathue[1] = 1.2f;
|
||||
sathue[2] = 1.1f;
|
||||
sathue[3] = 1.05f;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.05f;
|
||||
sathue2[1] = 1.1f ;
|
||||
sathue2[2] = 1.05f;
|
||||
sathue2[3] = 1.0f;
|
||||
} else if (/*HH>=-1.5f &&*/ HH < -0.7f ) {
|
||||
sathue[0] = 1.6f; //blue purple 1.2 1.1
|
||||
sathue[1] = 1.4f;
|
||||
sathue[2] = 1.3f;
|
||||
sathue[3] = 1.2f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.2f ;
|
||||
sathue2[1] = 1.15f;
|
||||
sathue2[2] = 1.1f ;
|
||||
sathue2[3] = 1.0f;
|
||||
} else if (/*HH>=-0.7f &&*/ HH < 0.0f ) {
|
||||
sathue[0] = 1.2f; //purple
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 1.0f;
|
||||
sathue[3] = 1.0f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.0f ;
|
||||
sathue2[1] = 1.0f ;
|
||||
sathue2[2] = 1.0f ;
|
||||
sathue2[3] = 1.0f;
|
||||
}
|
||||
// else if( HH>= 0.0f && HH<= 1.4f ) {sathue[0]=1.1f;sathue[1]=1.1f;sathue[2]=1.1f;sathue[3]=1.0f ;sathue[4]=0.4f;sathue2[0]=1.0f ;sathue2[1]=1.0f ;sathue2[2]=1.0f ;sathue2[3]=1.0f;}//red 0.8 0.7
|
||||
else if (/*HH>= 0.0f &&*/ HH <= 1.4f ) {
|
||||
@ -312,39 +283,33 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.2f;
|
||||
sathue[2] = 1.1f;
|
||||
sathue[3] = 1.0f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.0f ;
|
||||
sathue2[1] = 1.0f ;
|
||||
sathue2[2] = 1.0f ;
|
||||
sathue2[3] = 1.0f;
|
||||
} else if (/*HH> 1.4f &&*/ HH <= 2.1f ) {
|
||||
sathue[0] = 1.0f; //green yellow 1.2 1.1
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 1.0f;
|
||||
sathue[3] = 1.0f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.0f ;
|
||||
sathue2[1] = 1.0f ;
|
||||
sathue2[2] = 1.0f ;
|
||||
sathue2[3] = 1.0f;
|
||||
} else { /*if(HH> 2.1f && HH<= 3.1415f)*/
|
||||
sathue[0] = 1.4f; //green
|
||||
sathue[1] = 1.3f;
|
||||
sathue[2] = 1.2f;
|
||||
sathue[3] = 1.15f;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.15f;
|
||||
sathue2[1] = 1.1f ;
|
||||
sathue2[2] = 1.05f;
|
||||
sathue2[3] = 1.0f;
|
||||
}
|
||||
} else if (LL < 50.0f) { //more for blue and green, less for red and green-yellow
|
||||
sathue[4] = 0.4f;
|
||||
if (/*HH> -3.1415f &&*/ HH < -1.5f ) {
|
||||
sathue[0] = 1.5f; //blue
|
||||
sathue[1] = 1.4f;
|
||||
sathue[2] = 1.3f;
|
||||
sathue[3] = 1.2f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.2f ;
|
||||
sathue2[1] = 1.1f ;
|
||||
sathue2[2] = 1.05f;
|
||||
@ -354,7 +319,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.2f;
|
||||
sathue[2] = 1.1f;
|
||||
sathue[3] = 1.05f;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.05f;
|
||||
sathue2[1] = 1.05f;
|
||||
sathue2[2] = 1.0f ;
|
||||
@ -364,7 +328,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 1.0f;
|
||||
sathue[3] = 1.0f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.0f ;
|
||||
sathue2[1] = 1.0f ;
|
||||
sathue2[2] = 1.0f ;
|
||||
@ -376,7 +339,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 0.9f;
|
||||
sathue[3] = 0.8f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 0.8f ;
|
||||
sathue2[1] = 0.8f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -386,7 +348,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.1f;
|
||||
sathue[2] = 1.1f;
|
||||
sathue[3] = 1.05f;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 0.9f ;
|
||||
sathue2[1] = 0.8f ;
|
||||
sathue2[2] = 0.7f ;
|
||||
@ -396,7 +357,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.4f;
|
||||
sathue[2] = 1.3f;
|
||||
sathue[3] = 1.2f ;
|
||||
sathue[4] = 0.4f;
|
||||
sathue2[0] = 1.2f ;
|
||||
sathue2[1] = 1.1f ;
|
||||
sathue2[2] = 1.05f;
|
||||
@ -404,12 +364,12 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
}
|
||||
|
||||
} else if (LL < 80.0f) { //more for green, less for red and green-yellow
|
||||
sathue[4] = 0.3f;
|
||||
if (/*HH> -3.1415f &&*/ HH < -1.5f ) {
|
||||
sathue[0] = 1.3f; //blue
|
||||
sathue[1] = 1.2f;
|
||||
sathue[2] = 1.15f;
|
||||
sathue[3] = 1.1f ;
|
||||
sathue[4] = 0.3f;
|
||||
sathue2[0] = 1.1f ;
|
||||
sathue2[1] = 1.1f ;
|
||||
sathue2[2] = 1.05f;
|
||||
@ -419,7 +379,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.2f;
|
||||
sathue[2] = 1.15f;
|
||||
sathue[3] = 1.1f ;
|
||||
sathue[4] = 0.3f;
|
||||
sathue2[0] = 1.1f ;
|
||||
sathue2[1] = 1.05f;
|
||||
sathue2[2] = 1.0f ;
|
||||
@ -429,7 +388,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 1.0f ;
|
||||
sathue[3] = 1.0f ;
|
||||
sathue[4] = 0.3f;
|
||||
sathue2[0] = 1.0f ;
|
||||
sathue2[1] = 1.0f ;
|
||||
sathue2[2] = 1.0f ;
|
||||
@ -441,7 +399,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 0.9f ;
|
||||
sathue[3] = 0.8f ;
|
||||
sathue[4] = 0.3f;
|
||||
sathue2[0] = 0.8f ;
|
||||
sathue2[1] = 0.8f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -451,7 +408,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.2f;
|
||||
sathue[2] = 1.1f ;
|
||||
sathue[3] = 1.05f;
|
||||
sathue[4] = 0.3f;
|
||||
sathue2[0] = 1.0f ;
|
||||
sathue2[1] = 0.9f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -461,19 +417,18 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.4f;
|
||||
sathue[2] = 1.3f ;
|
||||
sathue[3] = 1.25f;
|
||||
sathue[4] = 0.3f;
|
||||
sathue2[0] = 1.25f;
|
||||
sathue2[1] = 1.2f ;
|
||||
sathue2[2] = 1.15f;
|
||||
sathue2[3] = 1.05f;
|
||||
}
|
||||
} else { /*if (LL>=80.0f)*/ //more for green-yellow, less for red and purple
|
||||
sathue[4] = 0.2f;
|
||||
if (/*HH> -3.1415f &&*/ HH < -1.5f ) {
|
||||
sathue[0] = 1.0f; //blue
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 0.9f;
|
||||
sathue[3] = 0.8f;
|
||||
sathue[4] = 0.2f;
|
||||
sathue2[0] = 0.8f;
|
||||
sathue2[1] = 0.8f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -483,7 +438,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 0.9f;
|
||||
sathue[3] = 0.8f;
|
||||
sathue[4] = 0.2f;
|
||||
sathue2[0] = 0.8f;
|
||||
sathue2[1] = 0.8f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -493,7 +447,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 1.0f;
|
||||
sathue[3] = 0.9f;
|
||||
sathue[4] = 0.2f;
|
||||
sathue2[0] = 0.9f;
|
||||
sathue2[1] = 0.9f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -505,7 +458,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.0f;
|
||||
sathue[2] = 0.9f;
|
||||
sathue[3] = 0.8f;
|
||||
sathue[4] = 0.2f;
|
||||
sathue2[0] = 0.8f;
|
||||
sathue2[1] = 0.8f ;
|
||||
sathue2[2] = 0.8f ;
|
||||
@ -515,7 +467,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.5f;
|
||||
sathue[2] = 1.4f;
|
||||
sathue[3] = 1.2f;
|
||||
sathue[4] = 0.2f;
|
||||
sathue2[0] = 1.1f;
|
||||
sathue2[1] = 1.05f;
|
||||
sathue2[2] = 1.0f ;
|
||||
@ -525,7 +476,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
sathue[1] = 1.3f;
|
||||
sathue[2] = 1.2f;
|
||||
sathue[3] = 1.1f;
|
||||
sathue[4] = 0.2f;
|
||||
sathue2[0] = 1.1f;
|
||||
sathue2[1] = 1.05f;
|
||||
sathue2[2] = 1.05f;
|
||||
@ -534,97 +484,83 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
}
|
||||
}
|
||||
|
||||
float chmodpastel = 0.f, chmodsat = 0.f;
|
||||
float chmod = 0.f;
|
||||
// variables to improve transitions
|
||||
float pa, pb;// transition = pa*saturation + pb
|
||||
float chl00 = chromaPastel * satredu * sathue[4];
|
||||
float chl0 = chromaPastel * satredu * sathue[0];
|
||||
float chl1 = chromaPastel * satredu * sathue[1];
|
||||
float chl2 = chromaPastel * satredu * sathue[2];
|
||||
float chl3 = chromaPastel * satredu * sathue[3];
|
||||
float chs0 = chromaSatur * satredu * sathue2[0];
|
||||
float chs1 = chromaSatur * satredu * sathue2[1];
|
||||
float chs2 = chromaSatur * satredu * sathue2[2];
|
||||
float chs3 = chromaSatur * satredu * sathue2[3];
|
||||
float s3 = 1.0f;
|
||||
|
||||
// We handle only positive values here ; improve transitions
|
||||
if (saturation < p00) {
|
||||
chmodpastel = chl00 ; //neutral tones
|
||||
pa = 0.f;
|
||||
pb = chromaPastel * sathue[4];
|
||||
} else if (saturation < p0 ) {
|
||||
float chl00 = chromaPastel * sathue[4];
|
||||
float chl0 = chromaPastel * sathue[0];
|
||||
pa = (chl00 - chl0) / (p00 - p0);
|
||||
pb = chl00 - pa * p00;
|
||||
chmodpastel = pa * saturation + pb;
|
||||
} else if (saturation < p1) {
|
||||
float chl0 = chromaPastel * sathue[0];
|
||||
float chl1 = chromaPastel * sathue[1];
|
||||
pa = (chl0 - chl1) / (p0 - p1);
|
||||
pb = chl0 - pa * p0;
|
||||
chmodpastel = pa * saturation + pb;
|
||||
} else if (saturation < p2) {
|
||||
float chl1 = chromaPastel * sathue[1];
|
||||
float chl2 = chromaPastel * sathue[2];
|
||||
pa = (chl1 - chl2) / (p1 - p2);
|
||||
pb = chl1 - pa * p1;
|
||||
chmodpastel = pa * saturation + pb;
|
||||
} else if (saturation < limitpastelsatur) {
|
||||
float chl2 = chromaPastel * sathue[2];
|
||||
float chl3 = chromaPastel * sathue[3];
|
||||
pa = (chl2 - chl3) / (p2 - limitpastelsatur);
|
||||
pb = chl2 - pa * p2;
|
||||
chmodpastel = pa * saturation + pb;
|
||||
} else if (saturation < s0) {
|
||||
float chl3 = chromaPastel * sathue[3];
|
||||
float chs0 = chromaSatur * sathue2[0];
|
||||
pa = (chl3 - chs0) / (limitpastelsatur - s0) ;
|
||||
pb = chl3 - pa * limitpastelsatur;
|
||||
chmodsat = pa * saturation + pb;
|
||||
} else if (saturation < s1) {
|
||||
float chs0 = chromaSatur * sathue2[0];
|
||||
float chs1 = chromaSatur * sathue2[1];
|
||||
pa = (chs0 - chs1) / (s0 - s1);
|
||||
pb = chs0 - pa * s0;
|
||||
chmodsat = pa * saturation + pb;
|
||||
} else if (saturation < s2) {
|
||||
float chs1 = chromaSatur * sathue2[1];
|
||||
float chs2 = chromaSatur * sathue2[2];
|
||||
pa = (chs1 - chs2) / (s1 - s2);
|
||||
pb = chs1 - pa * s1;
|
||||
chmodsat = pa * saturation + pb;
|
||||
} else {
|
||||
pa = (chs2 - chs3) / (s2 - s3);
|
||||
float chs2 = chromaSatur * sathue2[2];
|
||||
float chs3 = chromaSatur * sathue2[3];
|
||||
pa = (chs2 - chs3) / (s2 - 1.f);
|
||||
pb = chs2 - pa * s2;
|
||||
chmodsat = pa * saturation + pb;
|
||||
}
|
||||
chmod = pa * saturation + pb;
|
||||
chmod *= satredu;
|
||||
|
||||
if (chromaPastel != chromaSatur) {
|
||||
|
||||
// Pastels
|
||||
if (saturation > p2 && saturation < limitpastelsatur) {
|
||||
float newchromaPastel = chromaPastel_a * saturation + chromaPastel_b;
|
||||
chmodpastel = newchromaPastel * satredu * sathue[3];
|
||||
chmod = newchromaPastel * satredu * sathue[3];
|
||||
}
|
||||
|
||||
// Saturated
|
||||
if (saturation < s0 && saturation >= limitpastelsatur) {
|
||||
float newchromaSatur = chromaSatur_a * saturation + chromaSatur_b;
|
||||
chmodsat = newchromaSatur * satredu * sathue2[0];
|
||||
chmod = newchromaSatur * satredu * sathue2[0];
|
||||
}
|
||||
}// end transition
|
||||
|
||||
if (saturation <= limitpastelsatur) {
|
||||
if (chmodpastel > 2.0f ) {
|
||||
chmodpastel = 2.0f; //avoid too big values
|
||||
} else if (chmodpastel < -0.93f) {
|
||||
chmodpastel = -0.93f; //avoid negative values
|
||||
}
|
||||
chmod = rtengine::LIM(chmod, -0.93f, 2.f);
|
||||
Chprov *= 1.0f + chmod;
|
||||
|
||||
Chprov *= (1.0f + chmodpastel);
|
||||
|
||||
if (Chprov < 6.0f) {
|
||||
Chprov = 6.0f;
|
||||
}
|
||||
} else { //if (saturation > limitpastelsatur)
|
||||
if (chmodsat > 1.8f ) {
|
||||
chmodsat = 1.8f; //saturated
|
||||
} else if (chmodsat < -0.93f) {
|
||||
chmodsat = -0.93f;
|
||||
}
|
||||
chmod = rtengine::LIM(chmod, -0.93f, 1.8f);
|
||||
Chprov *= 1.0f + chmod;
|
||||
|
||||
Chprov *= 1.0f + chmodsat;
|
||||
|
||||
if (Chprov < 6.0f) {
|
||||
Chprov = 6.0f;
|
||||
}
|
||||
}
|
||||
Chprov = rtengine::max(Chprov, 6.f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -633,36 +569,36 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
// Vibrance's Skin curve
|
||||
if (skinCurveIsSet) {
|
||||
if (HH > skbeg && HH < skend) {
|
||||
if (Chprov < 60.0f) { //skin hue : todo ==> transition
|
||||
if (Chprov < 60.f) { //skin hue : todo ==> transition
|
||||
float HHsk = ask * HH + bsk;
|
||||
float Hn = (skin_curve[HHsk] - bsk) / ask;
|
||||
float Hc = (Hn * xx + HH * (1.0f - xx));
|
||||
float Hn = skin_curve[HHsk] - bsk0;
|
||||
float Hc = Hn * xx + HH * (1.f - xx);
|
||||
HH = Hc;
|
||||
hhModified = true;
|
||||
} else if (Chprov < (60.0f + dchr)) { //transition chroma
|
||||
} else if (Chprov < (60.f + dchr)) { //transition chroma
|
||||
float HHsk = ask * HH + bsk;
|
||||
float Hn = (skin_curve[HHsk] - bsk) / ask;
|
||||
float Hc = (Hn * xx + HH * (1.0f - xx));
|
||||
float Hn = skin_curve[HHsk] - bsk0;
|
||||
float Hc = Hn * xx + HH * (1.f - xx);
|
||||
float aa = (HH - Hc) / dchr ;
|
||||
float bb = HH - (60.0f + dchr) * aa;
|
||||
float bb = HH - (60.f + dchr) * aa;
|
||||
HH = aa * Chprov + bb;
|
||||
hhModified = true;
|
||||
}
|
||||
}
|
||||
//transition hue
|
||||
else if (HH > (skbeg - dhue) && HH <= skbeg && Chprov < (60.0f + dchr * 0.5f)) {
|
||||
else if (HH > (skbeg - dhue) && HH <= skbeg && Chprov < (60.f + dchr * 0.5f)) {
|
||||
float HHsk = ask * skbeg + bsk;
|
||||
float Hn = (skin_curve[HHsk] - bsk) / ask;
|
||||
float Hcc = (Hn * xx + skbeg * (1.0f - xx));
|
||||
float adh = (Hcc - (skbeg - dhue)) / (dhue);
|
||||
float Hn = skin_curve[HHsk] - bsk0;
|
||||
float Hcc = Hn * xx + skbeg * (1.f - xx);
|
||||
float adh = (Hcc - (skbeg - dhue)) / dhue;
|
||||
float bdh = Hcc - adh * skbeg;
|
||||
HH = adh * HH + bdh;
|
||||
hhModified = true;
|
||||
} else if (HH >= skend && HH < (skend + dhue) && Chprov < (60.0f + dchr * 0.5f)) {
|
||||
} else if (HH >= skend && HH < (skend + dhue) && Chprov < (60.f + dchr * 0.5f)) {
|
||||
float HHsk = ask * skend + bsk;
|
||||
float Hn = (skin_curve[HHsk] - bsk) / ask;
|
||||
float Hcc = (Hn * xx + skend * (1.0f - xx));
|
||||
float adh = (skend + dhue - Hcc) / (dhue);
|
||||
float Hn = skin_curve[HHsk] - bsk0;
|
||||
float Hcc = Hn * xx + skend * (1.f - xx);
|
||||
float adh = (skend + dhue - Hcc) / dhue;
|
||||
float bdh = Hcc - adh * skend;
|
||||
HH = adh * HH + bdh;
|
||||
hhModified = true;
|
||||
@ -670,7 +606,6 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
} // end skin hue
|
||||
|
||||
//Munsell correction
|
||||
// float2 sincosval;
|
||||
if (!avoidcolorshift && hhModified) {
|
||||
sincosval = xsincosf (HH);
|
||||
}
|
||||
@ -678,21 +613,18 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
float aprovn, bprovn;
|
||||
bool inGamut;
|
||||
|
||||
const float fyy = Color::c1By116 * Lprov + Color::c16By116;
|
||||
const float yy_ = (Lprov > Color::epskap) ? fyy * fyy*fyy : Lprov / Color::kappaf;
|
||||
do {
|
||||
inGamut = true;
|
||||
|
||||
if (avoidcolorshift) {
|
||||
float correctionHue = 0.0f;
|
||||
float correctlum = 0.0f;
|
||||
|
||||
#ifdef _DEBUG
|
||||
Color::AllMunsellLch (/*lumaMuns*/false, Lprov, Lprov, HH, Chprov, CC, correctionHue, correctlum, MunsDebugInfo);
|
||||
#else
|
||||
Color::AllMunsellLch (/*lumaMuns*/false, Lprov, Lprov, HH, Chprov, CC, correctionHue, correctlum);
|
||||
#endif
|
||||
Color::AllMunsellLch(Lprov, HH, Chprov, CC, correctionHue);
|
||||
|
||||
if (correctionHue != 0.f || hhModified) {
|
||||
sincosval = xsincosf (HH + correctionHue);
|
||||
sincosval = xsincosf(HH + correctionHue);
|
||||
hhModified = false;
|
||||
}
|
||||
}
|
||||
@ -700,29 +632,21 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
aprovn = Chprov * sincosval.y;
|
||||
bprovn = Chprov * sincosval.x;
|
||||
|
||||
float fyy = (Color::c1By116 * Lprov ) + Color::c16By116;
|
||||
float fxx = (0.002f * aprovn) + fyy;
|
||||
float fzz = fyy - (0.005f * bprovn);
|
||||
float xx_ = 65535.f * Color::f2xyz (fxx) * Color::D50x;
|
||||
// float yy_ = 65535.0f * Color::f2xyz(fyy);
|
||||
float zz_ = 65535.f * Color::f2xyz (fzz) * Color::D50z;
|
||||
float yy_ = 65535.f * ((Lprov > Color::epskap) ? fyy * fyy*fyy : Lprov / Color::kappa);
|
||||
float fxx = 0.002f * aprovn + fyy;
|
||||
float fzz = fyy - 0.005f * bprovn;
|
||||
float xx_ = Color::f2xyz(fxx) * Color::D50x;
|
||||
float zz_ = Color::f2xyz(fzz) * Color::D50z;
|
||||
|
||||
float R, G, B;
|
||||
Color::xyz2rgb (xx_, yy_, zz_, R, G, B, wip);
|
||||
|
||||
if (R < 0.0f || G < 0.0f || B < 0.0f) {
|
||||
#ifdef _DEBUG
|
||||
negsat++;
|
||||
#endif
|
||||
if (rtengine::min(R, G, B) < 0.0f) {
|
||||
Chprov *= 0.98f;
|
||||
inGamut = false;
|
||||
}
|
||||
|
||||
// if "highlight reconstruction" enabled don't control Gamut for highlights
|
||||
if ((!highlight) && (R > 65535.0f || G > 65535.0f || B > 65535.0f)) {
|
||||
#ifdef _DEBUG
|
||||
moresat++;
|
||||
#endif
|
||||
if (!highlight && max(R, G, B) > 1.f && min(R, G, B) <= 1.f) {
|
||||
Chprov *= 0.98f;
|
||||
inGamut = false;
|
||||
}
|
||||
@ -733,27 +657,8 @@ void ImProcFunctions::vibrance (LabImage* lab)
|
||||
lab->a[i][j] = aprovn * 327.68f;
|
||||
lab->b[i][j] = bprovn * 327.68f;
|
||||
}
|
||||
|
||||
} // end of parallelization
|
||||
|
||||
#ifdef _DEBUG
|
||||
t2e.set();
|
||||
|
||||
if (settings->verbose) {
|
||||
printf ("Vibrance (performed in %d usec):\n", t2e.etime (t1e));
|
||||
printf (" Gamut: G1negat=%iiter G165535=%iiter G2negsat=%iiter G265535=%iiter\n", negat, moreRGB, negsat, moresat);
|
||||
|
||||
if (MunsDebugInfo) {
|
||||
printf (" Munsell chrominance: MaxBP=%1.2frad MaxRY=%1.2frad MaxGY=%1.2frad MaxRP=%1.2frad depass=%u\n", MunsDebugInfo->maxdhue[0], MunsDebugInfo->maxdhue[1], MunsDebugInfo->maxdhue[2], MunsDebugInfo->maxdhue[3], MunsDebugInfo->depass);
|
||||
}
|
||||
}
|
||||
|
||||
if (MunsDebugInfo) {
|
||||
delete MunsDebugInfo;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end of parallelization
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user