Speedup for ImProcFunctions::chromiLuminanceCurve, Issue 2772

This commit is contained in:
Ingo
2015-05-17 22:19:59 +02:00
parent 181a952dd0
commit c8508a95bd
3 changed files with 344 additions and 332 deletions

View File

@@ -4286,7 +4286,7 @@ void ImProcFunctions::luminanceCurve (LabImage* lold, LabImage* lnew, LUTf & cur
void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve,LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) {
SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabImage* lold, LabImage* lnew, LUTf & acurve, LUTf & bcurve, LUTf & satcurve,LUTf & lhskcurve, LUTf & clcurve, LUTf & curve, bool utili, bool autili, bool butili, bool ccutili, bool cclutili, bool clcutili, LUTu &histCCurve, LUTu &histCLurve, LUTu &histLLCurve, LUTu &histLCurve) {
int W = lold->W;
int H = lold->H;
// lhskcurve.dump("lh_curve");
@@ -4297,9 +4297,11 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
LabImage* editLab = NULL;
PlanarWhateverData<float>* editWhatever = NULL;
EditUniqueID editID = EUID_None;
bool editPipette = false;
if (editBuffer) {
editID = editBuffer->getEditID();
if (editID != EUID_None) {
editPipette = true;
switch (editBuffer->getDataProvider()->getCurrSubscriber()->getEditBufferType()) {
case (BT_IMAGEFLOAT):
editImgFloat = editBuffer->getImgFloatBuffer();
@@ -4359,38 +4361,25 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
LUTf dLcurve;
LUTu hist16Clad;
// LUTu hist16CLlad;
// LUTu hist16LLClad;
LUTu hist16Llad;
bool chrop=false;
float val;
//preparate for histograms CIECAM
if(pW!=1){//only with improccoordinator
dCcurve(65536,0);
dCcurve(48000,0);
dLcurve(65536,0);
hist16Clad(65536);
// hist16CLlad(65536);
// hist16LLClad(65536);
hist16Llad(65536);
chrop = true;
float val;
for (int i=0; i<48000; i++) { //# 32768*1.414 approximation maxi for chroma
val = (double)i / 47999.0;
dCcurve[i] = CLIPD(val);
}
// for (int i=0; i<65535; i++) { // a
// val = (double)i / 65534.0;
// dLcurve[i] = CLIPD(val);
// }
for (int i=0; i<65535; i++) { // a
val = (double)i / 65534.0;
dLcurve[i] = CLIPD(val);
}
hist16Clad.clear();
// hist16CLlad.clear();
// hist16LLClad.clear();
hist16Llad.clear();
}
@@ -4401,68 +4390,56 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo();
#endif
float adjustr=1.0f, adjustbg=1.0f;
float adjustr=1.0f;
// if(params->labCurve.avoidclip ){
// parameter to adapt curve C=f(C) to gamut
if (params->icm.working=="ProPhoto") {adjustr = adjustbg = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170..
else if (params->icm.working=="Adobe RGB") {adjustr = 1.8f; adjustbg = 1.4f;}
else if (params->icm.working=="sRGB") {adjustr = 2.0f; adjustbg = 1.7f;}
else if (params->icm.working=="WideGamut") {adjustr = adjustbg = 1.2f;}
else if (params->icm.working=="Beta RGB") {adjustr = adjustbg = 1.4f;}
else if (params->icm.working=="BestRGB") {adjustr = adjustbg = 1.4f;}
else if (params->icm.working=="BruceRGB") {adjustr = 1.8f; adjustbg = 1.5f;}
//adjustr=1.f;
if (params->icm.working=="ProPhoto") {adjustr = 1.2f;}// 1.2 instead 1.0 because it's very rare to have C>170..
else if (params->icm.working=="Adobe RGB") {adjustr = 1.8f;}
else if (params->icm.working=="sRGB") {adjustr = 2.0f;}
else if (params->icm.working=="WideGamut") {adjustr = 1.2f;}
else if (params->icm.working=="Beta RGB") {adjustr = 1.4f;}
else if (params->icm.working=="BestRGB") {adjustr = 1.4f;}
else if (params->icm.working=="BruceRGB") {adjustr = 1.8f;}
// reference to the params structure has to be done outside of the parallelization to avoid CPU cache problem
bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated
int chromaticity = params->labCurve.chromaticity;
bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled;
bool bwToning = params->labCurve.chromaticity==-100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly;
const bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated
const int chromaticity = params->labCurve.chromaticity;
const float chromapro = (chromaticity + 100.0f)/100.0f;
const bool bwonly = params->blackwhite.enabled && !params->colorToning.enabled;
const bool bwToning = params->labCurve.chromaticity ==- 100 /*|| params->blackwhite.method=="Ch" || params->blackwhite.enabled */ || bwonly;
//if(chromaticity==-100) chromaticity==-99;
bool LCredsk = params->labCurve.lcredsk;
bool ccut = ccutili;
bool clut = clcutili;
bool aut = autili;
bool but = butili;
double rstprotection = 100.-params->labCurve.rstprotection; // Red and Skin Tones Protection
const bool LCredsk = params->labCurve.lcredsk;
const bool ccut = ccutili;
const bool clut = clcutili;
const double rstprotection = 100.-params->labCurve.rstprotection; // Red and Skin Tones Protection
// avoid color shift is disabled when bwToning is activated and enabled if gamut is true in colorappearanace
bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ;
int protectRed = settings->protectred;
double protectRedH = settings->protectredh;
bool gamutLch = settings->gamutLch;
float amountchroma = (float) settings->amchroma;
// only if user activate Lab adjustements
if (avoidColorShift) {
if(autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity) {
unsigned int N = W*H;
float *L = lold->L[0];
float *a= lold->a[0];
float *b= lold->b[0];
float* Lold = new float [N];//to save L before any used
float* Cold = new float [N];//to save C before any used
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif // _OPENMP
for (unsigned int j=0; j<N; j++){
Lold[j]=L[j]/327.68f;
Cold[j]=sqrt(SQR(a[j]/327.68f)+SQR(b[j]/327.68f));
}
Color::LabGamutMunsell(lold, Lold, Cold, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, params->icm.working, multiThread);
delete [] Lold;
delete [] Cold;
}
}
const bool avoidColorShift = (params->labCurve.avoidcolorshift || (params->colorappearance.gamut && params->colorappearance.enabled)) && !bwToning ;
const float protectRed = (float)settings->protectred;
const double protectRedH = settings->protectredh;
float protect_red,protect_redh;
protect_red = protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160
if(protect_red < 20.0f) protect_red=20.0; // avoid too low value
if(protect_red > 180.0f) protect_red=180.0; // avoid too high value
protect_redh=float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0
if(protect_redh<0.1f) protect_redh=0.1f;//avoid divide by 0 and negatives values
if(protect_redh>1.0f) protect_redh=1.0f;//avoid too big values
float protect_redhcur = protectRedH;//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1
if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values:minimal protection for transition
if(protect_redhcur>3.5f) protect_redhcur=3.5f;//avoid too big values
#ifdef _DEBUG
#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, MunsDebugInfo, pW) if (multiThread)
#else
#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, pW) if (multiThread)
#endif
{
//increase saturation after denoise : ...approximation
float factnoise=1.f;
if(params->dirpyrDenoise.enabled) {
factnoise=(1.f+params->dirpyrDenoise.chroma/500.f);//levels=5
// if(yyyy) factnoise=(1.f+params->dirpyrDenoise.chroma/100.f);//levels=7
}
const float scaleConst = 100.0f/100.1f;
const bool gamutLch = settings->gamutLch;
const float amountchroma = (float) settings->amchroma;
TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working);
double wip[3][3] = {
@@ -4470,96 +4447,148 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
{wiprof[1][0],wiprof[1][1],wiprof[1][2]},
{wiprof[2][0],wiprof[2][1],wiprof[2][2]}
};
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working);
double wp[3][3] = {
{wprof[0][0],wprof[0][1],wprof[0][2]},
{wprof[1][0],wprof[1][1],wprof[1][2]},
{wprof[2][0],wprof[2][1],wprof[2][2]}};
#ifdef _DEBUG
#pragma omp parallel default(shared) firstprivate(highlight, ccut, clut, chromaticity, bwToning, rstprotection, avoidColorShift, LCredsk, protectRed, protectRedH, gamutLch, lold, lnew, MunsDebugInfo, pW) if (multiThread)
#else
#pragma omp parallel if (multiThread)
#endif
{
#ifdef __SSE2__
float HHBuffer[W] ALIGNED16;
float CCBuffer[W] ALIGNED16;
#endif
#pragma omp for schedule(dynamic, 16)
for (int i=0; i<H; i++)
for (int i=0; i<H; i++) {
if (avoidColorShift)
// only if user activate Lab adjustments
if(autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity) {
Color::LabGamutMunsell(lold->L[i],lold->a[i], lold->b[i], W, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, wip, multiThread);
}
#ifdef __SSE2__
// precalculate some values using SSE
if(bwToning || (!autili && !butili)) {
__m128 c327d68v = _mm_set1_ps(327.68f);
__m128 av,bv;
int k;
for (k=0; k<W-3; k+=4) {
av = LVFU(lold->a[i][k]);
bv = LVFU(lold->b[i][k]);
STVF(HHBuffer[k],xatan2f(bv,av));
STVF(CCBuffer[k],_mm_sqrt_ps(SQRV(av)+SQRV(bv))/c327d68v);
}
for(;k<W;k++) {
HHBuffer[k] = xatan2f(lold->b[i][k],lold->a[i][k]);
CCBuffer[k] = sqrt(SQR(lold->a[i][k]) + SQR(lold->b[i][k]))/327.68f;
}
}
#endif // __SSE2__
for (int j=0; j<W; j++) {
float LL=lold->L[i][j]/327.68f;
const float Lin=lold->L[i][j];
float LL=Lin/327.68f;
float CC;
CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f;
float HH;
HH=xatan2f(lold->b[i][j],lold->a[i][j]);
// According to mathematical laws we can get the sin and cos of HH by simple operations
float2 sincosval;
if(CC==0.0f) {
sincosval.y = 1.0f;
sincosval.x = 0.0f;
} else {
sincosval.y = lold->a[i][j]/(CC*327.68f);
sincosval.x = lold->b[i][j]/(CC*327.68f);
}
float Chprov;
float Chprov1;
float memChprov;
float2 sincosval;
if(bwToning) { // this values will be also set when bwToning is false some lines down
#ifdef __SSE2__
// use precalculated values from above
HH = HHBuffer[j];
CC = CCBuffer[j];
#else
HH=xatan2f(lold->b[i][j],lold->a[i][j]);
CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f;
#endif
// According to mathematical laws we can get the sin and cos of HH by simple operations
if(CC==0.0f) {
sincosval.y = 1.0f;
sincosval.x = 0.0f;
} else {
sincosval.y = lold->a[i][j]/(CC*327.68f);
sincosval.x = lold->b[i][j]/(CC*327.68f);
}
float Chprov=CC;
float Chprov1=CC;
float memChprov=Chprov;
float Lin=lold->L[i][j];
float Lprov2=Lin/327.68f;
Chprov=CC;
Chprov1=CC;
memChprov=Chprov;
}
if (editID == EUID_Lab_LCurve)
if (editPipette && editID == EUID_Lab_LCurve)
editWhatever->v(i,j) = LIM01<float>(Lin/32768.0f);// Lab L pipette
lnew->L[i][j] = curve[Lin];
float Lprov1=(lnew->L[i][j])/327.68f;
float chromaChfactor=1.0f;
if (editID == EUID_Lab_aCurve){
float chromapipa =lold->a[i][j]+(32768.f*1.28f);
editWhatever->v(i,j) = LIM01<float>((chromapipa)/(65536.f*1.28f));}// Lab a pipette
if (editID == EUID_Lab_bCurve){
float chromapipb =lold->b[i][j]+(32768.f*1.28f);
editWhatever->v(i,j) = LIM01<float>((chromapipb)/(65536.f*1.28f));}//Lab b pipette
if(editPipette) {
if (editID == EUID_Lab_aCurve) { // Lab a pipette
float chromapipa =lold->a[i][j]+(32768.f*1.28f);
editWhatever->v(i,j) = LIM01<float>((chromapipa)/(65536.f*1.28f));
} else if (editID == EUID_Lab_bCurve) { //Lab b pipette
float chromapipb =lold->b[i][j]+(32768.f*1.28f);
editWhatever->v(i,j) = LIM01<float>((chromapipb)/(65536.f*1.28f));
}
}
float atmp, btmp;
atmp = acurve[lold->a[i][j]+32768.0f]-32768.0f;// curves Lab a
btmp = bcurve[lold->b[i][j]+32768.0f]-32768.0f;// curves Lab b
atmp = lold->a[i][j];
if(autili)
atmp = acurve[atmp+32768.0f]-32768.0f;// curves Lab a
btmp = lold->b[i][j];
if(butili)
btmp = bcurve[btmp+32768.0f]-32768.0f;// curves Lab b
if(!bwToning) { //take into account modification of 'a' and 'b'
lold->a[i][j]=atmp;
lold->b[i][j]=btmp;
CC=sqrt(SQR(lold->a[i][j]) + SQR(lold->b[i][j]))/327.68f;
HH=xatan2f(lold->b[i][j],lold->a[i][j]);
#ifdef __SSE2__
if(!autili && !butili) {
// use precalculated values from above
HH = HHBuffer[j];
CC = CCBuffer[j];
} else {
CC = sqrt(SQR(atmp) + SQR(btmp))/327.68f;
HH = xatan2f(btmp,atmp);
}
#else
CC=sqrt(SQR(atmp) + SQR(btmp))/327.68f;
HH=xatan2f(btmp,atmp);
#endif
// According to mathematical laws we can get the sin and cos of HH by simple operations
//float2 sincosval;
if(CC==0.0f) {
sincosval.y = 1.0f;
sincosval.x = 0.0f;
if(CC == 0.f) {
sincosval.y = 1.f;
sincosval.x = 0.f;
} else {
sincosval.y = lold->a[i][j]/(CC*327.68f);
sincosval.x = lold->b[i][j]/(CC*327.68f);
sincosval.y = atmp/(CC*327.68f);
sincosval.x = btmp/(CC*327.68f);
}
Chprov=CC;
Chprov1=CC;
memChprov=Chprov;
} // now new values of lold with 'a' and 'b'
float Chprov2=Chprov1;
int poscc,posp,posl;
bool inRGB;
const float ClipLevel = 65535.0f;
if (editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve) {//H pipette
float valpar =Color::huelab_to_huehsv2(HH);
editWhatever->v(i,j) = valpar;
}
if(editPipette)
if (editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve) {//H pipette
float valpar =Color::huelab_to_huehsv2(HH);
editWhatever->v(i,j) = valpar;
}
if (lhutili) { // L=f(H)
const float ClipLevel = 65535.f;
float l_r;//Luminance Lab in 0..1
l_r = Lprov1/100.f;
{
double lr;
float khue=1.9f;//in reserve in case of!
float valparam = float((lhCurve->getVal(lr=Color::huelab_to_huehsv2(HH))-0.5f));//get l_r=f(H)
float valparam = float((lhCurve->getVal(Color::huelab_to_huehsv2(HH))-0.5f));//get l_r=f(H)
float valparamneg;
valparamneg=valparam;
float kcc=(CC/amountchroma);//take Chroma into account...40 "middle low" of chromaticity (arbitrary and simple), one can imagine other algorithme
@@ -4575,8 +4604,9 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
Lprov1=l_r*100.f;
Chprov2 = sqrt(SQR(atmp/327.68f)+SQR(btmp/327.68f));
float Chprov2 = sqrt(SQR(atmp)+SQR(btmp))/327.68f;
//Gamut control especialy fot negative values slightly different of gamutlchonly
bool inRGB;
do {
inRGB=true;
float aprov1=Chprov2*sincosval.y;
@@ -4602,9 +4632,8 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
inRGB = false;
}
}
while (!inRGB) ;
// float2 sincosval = xsincosf(HH);
while (!inRGB);
atmp=327.68f*Chprov2*sincosval.y;
btmp=327.68f*Chprov2*sincosval.x;
}
@@ -4613,87 +4642,59 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
if (chutili) {
double hr = Color::huelab_to_huehsv2(HH);
float chparam = float((chCurve->getVal(hr)-0.5f) * 2.0f);//get C=f(H)
chromaChfactor=1.0f+chparam;
float chromaChfactor=1.0f+chparam;
atmp *= chromaChfactor;//apply C=f(H)
btmp *= chromaChfactor;
}
atmp *= chromaChfactor;//apply C=f(H)
btmp *= chromaChfactor;
if (hhutili) { // H=f(H)
//hue Lab in -PI +PI
double hr;
float valparam = float((hhCurve->getVal(hr=Color::huelab_to_huehsv2(HH))-0.5f) * 1.7f) +HH;//get H=f(H) 1.7 optimisation !
float valparam = float((hhCurve->getVal(Color::huelab_to_huehsv2(HH))-0.5f) * 1.7f) +HH;//get H=f(H) 1.7 optimisation !
HH = valparam;
sincosval = xsincosf(HH);
}
//simulate very approximative gamut f(L) : with pyramid transition
float dred=55.0f;//C red value limit
if (Lprov1<25.0f) dred = 40.0f;
else if(Lprov1<30.0f) dred = 3.0f*Lprov1 -35.0f;
else if(Lprov1<70.0f) dred = 55.0f;
else if(Lprov1<75.0f) dred = -3.0f*Lprov1 +265.0f;
else dred = 40.0f;
// end pyramid
// if(params->dirpyrDenoise.enabled && chromaticity ==0) chromaticity = 0.5f;
if(!bwToning){
float factorskin, factorsat, factor, factorskinext, interm;
float scale = 100.0f/100.1f;//reduction in normal zone
float scaleext=1.0f;//reduction in transition zone
float protect_red,protect_redh;
float deltaHH;//HH value transition
protect_red=float(protectRed);//default=60 chroma: one can put more or less if necessary...in 'option' 40...160
if(protect_red < 20.0f) protect_red=20.0; // avoid too low value
if(protect_red > 180.0f) protect_red=180.0; // avoid too high value
protect_redh=float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0
if(protect_redh<0.1f) protect_redh=0.1f;//avoid divide by 0 and negatives values
if(protect_redh>1.0f) protect_redh=1.0f;//avoid too big values
float factorskin, factorsat, factorskinext;
if(chromapro > 1.f) {
float scale = scaleConst;//reduction in normal zone
float scaleext = 1.f;//reduction in transition zone
Color::scalered ( rstprotection, chromapro, 0.0, HH, protect_redh, scale, scaleext);//1.0
float interm = (chromapro - 1.f);
factorskin = 1.f + (interm*scale);
factorskinext = 1.f+ (interm*scaleext);
} else {
factorskin = chromapro ; // +(chromapro)*scale;
factorskinext = chromapro ;// +(chromapro)*scaleext;
}
factorsat = chromapro * factnoise;
//simulate very approximative gamut f(L) : with pyramid transition
float dred /*=55.f*/;//C red value limit
if (Lprov1<25.f) dred = 40.f;
else if(Lprov1<30.f) dred = 3.f * Lprov1 -35.f;
else if(Lprov1<70.f) dred = 55.f;
else if(Lprov1<75.f) dred = -3.f * Lprov1 + 265.f;
else dred = 40.f;
// end pyramid
deltaHH=protect_redh;//transition hue
float chromapro = (chromaticity + 100.0f)/100.0f;
if(chromapro>0.0) Color::scalered ( rstprotection, chromapro, 0.0, HH, deltaHH, scale, scaleext);//1.0
if(chromapro>1.0) {
interm=(chromapro-1.0f)*100.0f;
factorskin= 1.0f+(interm*scale)/100.0f;
factorskinext=1.0f+(interm*scaleext)/100.0f;
}
else {
//factorskin= chromapro*scale;
//factorskinext= chromapro*scaleext;
factorskin= chromapro ; // +(chromapro)*scale;
factorskinext= chromapro ;// +(chromapro)*scaleext;
}
factorsat=chromapro;
//increase saturation after denoise : ...approximation
float factnoise=1.f;
if(params->dirpyrDenoise.enabled) {
factnoise=(1.f+params->dirpyrDenoise.chroma/500.f);//levels=5
// if(yyyy) factnoise=(1.f+params->dirpyrDenoise.chroma/100.f);//levels=7
}
factorsat*=factnoise;
factor=factorsat;
// Test if chroma is in the normal range first
Color::transitred ( HH, Chprov1, dred, factorskin, protect_red, factorskinext, deltaHH, factorsat, factor);
atmp *= factor;
btmp *= factor;
if (editID == EUID_Lab_CLCurve)
editWhatever->v(i,j) = LIM01<float>(Lprov2/100.f);// Lab C=f(L) pipette
Color::transitred ( HH, Chprov1, dred, factorskin, protect_red, factorskinext, protect_redh, factorsat, factorsat);
atmp *= factorsat;
btmp *= factorsat;
if (editPipette && editID == EUID_Lab_CLCurve)
editWhatever->v(i,j) = LIM01<float>(LL/100.f);// Lab C=f(L) pipette
if (clut) { // begin C=f(L)
float factorskin,factorsat,factor,factorskinext,interm;
float chroma = sqrt(SQR(atmp)+SQR(btmp)+0.001f);
float chromaCfactor=(clcurve[Lprov2*655.35f])/(Lprov2*655.35f);//apply C=f(L)
float chromaCfactor=(clcurve[LL*655.35f])/(LL*655.35f);//apply C=f(L)
float curf=0.7f;//empirical coeff because curve is more progressive
float scale = 100.0f/100.1f;//reduction in normal zone for curve C
float scaleext=1.0f;//reduction in transition zone for curve C
float protect_redcur,protect_redhcur;//perhaps the same value than protect_red and protect_redh
float deltaHH;//HH value transition for C curve
protect_redcur=curf*float(protectRed);//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive
protect_redcur=curf*protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive
if(protect_redcur < 20.0f) protect_redcur=20.0; // avoid too low value
if(protect_redcur > 180.0f) protect_redcur=180.0; // avoid too high value
protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive
@@ -4723,7 +4724,7 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
// editWhatever->v(i,j) = LIM01<float>(Lprov2/100.f);// Lab C=f(L) pipette
// I have placed C=f(C) after all C treatments to assure maximum amplitude of "C"
if (editID == EUID_Lab_CCurve){
if (editPipette && editID == EUID_Lab_CCurve){
float chromapip = sqrt(SQR(atmp)+SQR(btmp)+0.001f);
editWhatever->v(i,j) = LIM01<float>((chromapip)/(48000.f));}//Lab C=f(C) pipette
@@ -4736,7 +4737,7 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
float scaleext=1.0f;//reduction in transition zone for curve CC
float protect_redcur,protect_redhcur;//perhaps the same value than protect_red and protect_redh
float deltaHH;//HH value transition for CC curve
protect_redcur=curf*float(protectRed);//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive
protect_redcur=curf*protectRed;//default=60 chroma: one can put more or less if necessary...in 'option' 40...160==> curf =because curve is more progressive
if(protect_redcur < 20.0f) protect_redcur=20.0; // avoid too low value
if(protect_redcur > 180.0f) protect_redcur=180.0; // avoid too high value
protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1.0 ==> curf =because curve is more progressive
@@ -4764,38 +4765,27 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
atmp *= factor;
btmp *= factor;
}
// if (editID == EUID_Lab_CCurve){
// float chromapip = sqrt(SQR(atmp)+SQR(btmp)+0.001f);
// editWhatever->v(i,j) = LIM01<float>((chromapip)/(48000.f));}//Lab C=f(C) pipette
}
// end chroma C=f(C)
//update histogram C
if(pW!=1){//only with improccoordinator
posp=CLIP((int)sqrt((atmp*atmp + btmp*btmp)));
int posp=CLIP((int)sqrt((atmp*atmp + btmp*btmp)));
hist16Clad[posp]++;
// hist16CLlad[posp]++;
// hist16LLClad[posp]++;
}
if (editID == EUID_Lab_LCCurve){
float chromapiplc = sqrt(SQR(atmp)+SQR(btmp)+0.001f);
editWhatever->v(i,j) = LIM01<float>((chromapiplc)/(48000.f));}//Lab L=f(C) pipette
if (editPipette && editID == EUID_Lab_LCCurve){
float chromapiplc = sqrt(SQR(atmp)+SQR(btmp)+0.001f);
editWhatever->v(i,j) = LIM01<float>((chromapiplc)/(48000.f));
}//Lab L=f(C) pipette
if (!bwToning) { //apply curve L=f(C) for skin and rd...but also for extended color ==> near green and blue (see 'curf')
if (cclutili && !bwToning) { //apply curve L=f(C) for skin and rd...but also for extended color ==> near green and blue (see 'curf')
const float xx=0.25f;//soft : between 0.2 and 0.4
float protect_redhcur;
float curf=1.0f;
float deltaHH;
protect_redhcur=curf*float(protectRedH);//default=0.4 rad : one can put more or less if necessary...in 'option' 0.2 ..1
if(protect_redhcur<0.1f) protect_redhcur=0.1f;//avoid divide by 0 and negatives values:minimal protection for transition
if(protect_redhcur>3.5f) protect_redhcur=3.5f;//avoid too big values
float skdeltaHH;
deltaHH=protect_redhcur;//transition hue
skdeltaHH=protect_redhcur;//transition hue
float skbeg=-0.05f;//begin hue skin
float skend=1.60f;//end hue skin
@@ -4803,28 +4793,39 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
float aa,bb;
float zz=0.0f;
float yy=0.0f;
if(Chprov1 < chrmin) yy=(Chprov1/chrmin)*(Chprov1/chrmin)*xx;else yy=xx;//avoid artifact for low C
if(!LCredsk) {skbeg=-3.1415; skend=3.14159; deltaHH=0.001f;}
if(HH>skbeg && HH < skend ) zz=yy;
else if(HH>skbeg-deltaHH && HH<=skbeg) {aa=yy/deltaHH;bb=-aa*(skbeg-deltaHH); zz=aa*HH+bb;}//transition
else if(HH>=skend && HH < skend+deltaHH) {aa=-yy/deltaHH;bb=-aa*(skend+deltaHH);zz=aa*HH+bb;}//transition
if(Chprov1 < chrmin)
yy=SQR(Chprov1/chrmin)*xx;
else
yy=xx;//avoid artifact for low C
if(!LCredsk) {
skbeg=-3.1415;
skend=3.14159;
skdeltaHH=0.001f;
}
if(HH>skbeg && HH < skend ) {
zz=yy;
} else if(HH>skbeg-skdeltaHH && HH<=skbeg) { //transition
aa=yy/skdeltaHH;
bb=-aa*(skbeg-skdeltaHH);
zz=aa*HH+bb;
} else if(HH>=skend && HH < skend+skdeltaHH) { //transition
aa=-yy/skdeltaHH;
bb=-aa*(skend+skdeltaHH);
zz=aa*HH+bb;
}
float chroma=sqrt(SQR(atmp)+SQR(btmp)+0.001f);
float Lc = (lhskcurve[chroma*adjustr])/(chroma*adjustr);//apply L=f(C)
Lc=(Lc-1.0f)*zz+1.0f;//reduct action
Lprov1*=Lc;//adjust luminance
}
//update histo LC
if(pW!=1){//only with improccoordinator
posl=CLIP((int(Lprov1*327.68f)));
int posll=CLIP((int(Chprov1*327.68f)));
//hist16LLClad[posll]++;
hist16Llad[posl]++;
}
}
//update histo LC
if(pW!=1){//only with improccoordinator
int posl=CLIP((int(Lprov1*327.68f)));
hist16Llad[posl]++;
}
Chprov1 = sqrt(SQR(atmp/327.68f)+SQR(btmp/327.68f));
Chprov1 = sqrt(SQR(atmp)+SQR(btmp))/327.68f;
// labCurve.bwtoning option allows to decouple modulation of a & b curves by saturation
// with bwtoning enabled the net effect of a & b curves is visible
@@ -4842,17 +4843,16 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
bool neg=false;
bool more_rgb=false;
//gamut control : Lab values are in gamut
Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
Color::gamutLchonly(HH, sincosval, Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f, neg, more_rgb);
#else
//gamut control : Lab values are in gamut
Color::gamutLchonly(HH,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
Color::gamutLchonly(HH, sincosval,Lprov1,Chprov1, R, G, B, wip, highlight, 0.15f, 0.96f);
#endif
lnew->L[i][j]=Lprov1*327.68f;
// float2 sincosval = xsincosf(HH);
lnew->a[i][j]=327.68f*Chprov1*sincosval.y;
lnew->b[i][j]=327.68f*Chprov1*sincosval.x;
}
else {
} else {
//use gamutbdy
//Luv limiter
float Y,u,v;
@@ -4862,32 +4862,32 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
}
if (utili || autili || butili || ccut || clut || cclutili || chutili || lhutili || hhutili || clcutili || chromaticity) {
float correctionHue=0.0f; // Munsell's correction
float correctlum=0.0f;
float correctionHue=0.f; // Munsell's correction
float correctlum=0.f;
Lprov1=lnew->L[i][j]/327.68f;
Chprov=sqrt(SQR(lnew->a[i][j]/327.68f)+ SQR(lnew->b[i][j]/327.68f));
Chprov=sqrt(SQR(lnew->a[i][j])+ SQR(lnew->b[i][j]))/327.68f;
#ifdef _DEBUG
Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo);
Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,LL,HH,Chprov,memChprov,correctionHue,correctlum, MunsDebugInfo);
#else
Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,Lprov2,HH,Chprov,memChprov,correctionHue,correctlum);
Color::AllMunsellLch(/*lumaMuns*/true, Lprov1,LL,HH,Chprov,memChprov,correctionHue,correctlum);
#endif
if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little.
/* if((HH>0.0f && HH < 1.6f) && memChprov < 70.0f) HH+=correctlum;//skin correct
else if(fabs(correctionHue) < 0.3f) HH+=0.08f*correctlum;
else if(fabs(correctionHue) < 0.2f) HH+=0.25f*correctlum;
else if(fabs(correctionHue) < 0.1f) HH+=0.35f*correctlum;
else if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little.
*/
float2 sincosval = xsincosf(HH+correctionHue);
if(correctionHue != 0.f || correctlum != 0.f) {
if(fabs(correctionHue) < 0.015f)
HH+=correctlum; // correct only if correct Munsell chroma very little.
/* if((HH>0.0f && HH < 1.6f) && memChprov < 70.0f) HH+=correctlum;//skin correct
else if(fabs(correctionHue) < 0.3f) HH+=0.08f*correctlum;
else if(fabs(correctionHue) < 0.2f) HH+=0.25f*correctlum;
else if(fabs(correctionHue) < 0.1f) HH+=0.35f*correctlum;
else if(fabs(correctionHue) < 0.015f) HH+=correctlum; // correct only if correct Munsell chroma very little.
*/
sincosval = xsincosf(HH+correctionHue);
}
lnew->a[i][j]=327.68f*Chprov*sincosval.y;// apply Munsell
lnew->b[i][j]=327.68f*Chprov*sincosval.x;
}
}
else {
} else {
// if(Lprov1 > maxlp) maxlp=Lprov1;
// if(Lprov1 < minlp) minlp=Lprov1;
if(!bwToning){
@@ -4902,34 +4902,23 @@ void ImProcFunctions::chromiLuminanceCurve (EditBuffer *editBuffer, int pW, LabI
lnew->b[i][j] = btmp;
}
}
// }
}
}
} // end of parallelization
//update histogram C with data chromaticity and not with CC curve
if(pW!=1){//only with improccoordinator
for (int i=0; i<48000; i++) {//32768*1.414 + ...
if (chrop) {
float hval = dCcurve[i];
int hi = (int)(255.0*CLIPD(hval)); //
histCCurve[hi] += hist16Clad[i] ;
// histCLurve[hi] += hist16CLlad[i] ;
// histLLCurve[hi] += hist16LLClad[i] ;
}
float hval = dCcurve[i];
int hi = (int)(255.0*CLIPD(hval)); //
histCCurve[hi] += hist16Clad[i] ;
}
//update histogram L with data luminance
for (int i=0; i<65535; i++) {
if (chrop) {
float hlval = dLcurve[i];
int hli = (int)(255.0*CLIPD(hlval));
histLCurve[hli] += hist16Llad[i] ;
// histLLCurve[hli] += hist16LLClad[i] ;
}
}
float hlval = dLcurve[i];
int hli = (int)(255.0*CLIPD(hlval));
histLCurve[hli] += hist16Llad[i] ;
}
}
#ifdef _DEBUG