Fixed Auto Levels Clip malfunction issue 2104

This commit is contained in:
jdc 2013-12-16 17:27:07 +01:00
parent 489d6bfd83
commit aa15edd1e8
33 changed files with 399 additions and 149 deletions

View File

@ -1176,10 +1176,10 @@ TP_EPD_STRENGTH;Strength
TP_EPD_TOOLTIP;Tone mapping is possible via Lab mode (standard) and CIECAM02 mode.\n\nTo engage CIECAM02 tone mapping mode enable the following settings:\n1. CIECAM02\n2. Algorithm="Brightness + Colorfulness (QM)"\n3. "Tone mapping using CIECAM02 brightness (Q)"
TP_EXPOSCORR_LABEL;Raw White & Black Points
TP_EXPOSURE_AUTOLEVELS;Auto Levels
TP_EXPOSURE_AUTOLEVELS_TIP;Toggle execution of auto levels to automatically set parameter values based on image analysis
TP_EXPOSURE_AUTOLEVELS_TIP;Toggle execution of auto levels to automatically set parameter values based on image analysis\nEnable Highlight Reconstruction if necessary
TP_EXPOSURE_BLACKLEVEL;Black
TP_EXPOSURE_BRIGHTNESS;Lightness
TP_EXPOSURE_CLIP;Clip
TP_EXPOSURE_CLIP;Clip %
TP_EXPOSURE_CLIP_TIP;The fraction of pixels to be clipped in auto level's operation
TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD;Highlight Recovery Threshold
TP_EXPOSURE_COMPRHIGHLIGHTS;Highlight Recovery Amount
@ -1221,6 +1221,7 @@ TP_GRADIENT_FEATHER_TOOLTIP;Gradient width in percent of the image diagonal
TP_GRADIENT_LABEL;Graduated Filter
TP_GRADIENT_STRENGTH;Strength
TP_GRADIENT_STRENGTH_TOOLTIP;Filter strength in stops
TP_HLREC_ENA_TOOLTIP;Could be activated by automatic exposure
TP_HLREC_BLEND;Blend
TP_HLREC_CIELAB;CIELab Blending
TP_HLREC_COLOR;Color Propagation

View File

@ -114,7 +114,7 @@ void Crop::update (int todo) {
if (!needsinitupdate)
setCropSizes (rqcropx, rqcropy, rqcropw, rqcroph, skip, true);
PreviewProps pp (trafx, trafy, trafw*skip, trafh*skip, skip);
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.hlrecovery, params.icm, params.raw );
parent->imgsrc->getImage (parent->currWB, tr, origCrop, pp, params.toneCurve, params.icm, params.raw );
//ColorTemp::CAT02 (origCrop, &params) ;
//parent->imgsrc->convertColorSpace(origCrop, params.icm);

View File

@ -110,7 +110,7 @@ Image16* Image16::copy () {
return cp;
}
void Image16::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp)
void Image16::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp)
{
// compute channel multipliers

View File

@ -43,7 +43,7 @@ class Image16 : public IImage16, public ImageIO {
Image8* to8();
Imagefloat* tofloat();
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp);
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp);
virtual const char* getType () const { return sImage16; }
virtual int getBPS () { return 8*sizeof(unsigned short); }

View File

@ -80,7 +80,7 @@ Image8* Image8::copy () {
return cp;
}
void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp)
void Image8::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp)
{
// compute channel multipliers
double drm, dgm, dbm;

View File

@ -38,7 +38,7 @@ class Image8 : public IImage8, public ImageIO {
Image8* copy ();
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp);
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp);
virtual const char* getType () const { return sImage8; }
virtual int getBPS () { return 8*sizeof(unsigned char); }

View File

@ -106,7 +106,7 @@ Imagefloat* Imagefloat::copy () {
}
// This is called by the StdImageSource class. We assume that fp images from StdImageSource don't have to deal with gamma
void Imagefloat::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp)
void Imagefloat::getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp)
{
// compute channel multipliers

View File

@ -47,7 +47,7 @@ class Imagefloat : public IImagefloat, public ImageIO {
Image8* to8();
Image16* to16();
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp);
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp);
virtual const char* getType () const { return sImagefloat; }
virtual int getBPS () { return 8*sizeof(float); }

View File

@ -90,7 +90,7 @@ class ImageIO : virtual public ImageDatas {
void setSampleArrangement(IIOSampleArrangement sArrangement) { sampleArrangement = sArrangement; }
IIOSampleArrangement getSampleArrangement() { return sampleArrangement; }
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::HRecParams hrp) {
virtual void getStdImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, bool first, procparams::ToneCurveParams hrp) {
printf("getStdImage NULL!\n");
}

View File

@ -67,13 +67,13 @@ class ImageSource : public InitialImage {
virtual void demosaic (const RAWParams &raw){};
virtual void flushRawData (){};
virtual void flushRGB (){};
virtual void HLRecovery_Global (HRecParams hrp){};
virtual void HLRecovery_Global (ToneCurveParams hrp){};
virtual void HLRecovery_inpaint (float** red, float** green, float** blue){};
virtual bool IsrgbSourceModified() =0; // tracks whether cached rgb output of demosaic has been modified
// use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat*
virtual void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hlp, ColorManagementParams cmp, RAWParams raw) {}
virtual void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hlp, ColorManagementParams cmp, RAWParams raw) {}
// true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource
virtual bool isWBProviderReady () =0;

View File

@ -81,7 +81,7 @@ ImProcCoordinator::ImProcCoordinator ()
pW(-1), pH(-1),
plistener(NULL), imageListener(NULL), aeListener(NULL), hListener(NULL),acListener(NULL), abwListener(NULL),
resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false)
ahlListener(NULL),resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false)
{}
void ImProcCoordinator::assign (ImageSource* imgsrc) {
@ -173,8 +173,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
// If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST
if ( (todo & M_RAW)
|| (!highDetailRawComputed && highDetailNeeded)
|| ( params.hlrecovery.enabled && params.hlrecovery.method!="Color" && imgsrc->IsrgbSourceModified())
|| (!params.hlrecovery.enabled && params.hlrecovery.method=="Color" && imgsrc->IsrgbSourceModified()))
|| ( params.toneCurve.hrenabled && params.toneCurve.method!="Color" && imgsrc->IsrgbSourceModified())
|| (!params.toneCurve.hrenabled && params.toneCurve.method=="Color" && imgsrc->IsrgbSourceModified()))
{
if (settings->verbose) printf("Demosaic %s\n",rp.dmethod.c_str());
@ -183,7 +183,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (highDetailNeeded) {
highDetailRawComputed = true;
if (params.hlrecovery.enabled && params.hlrecovery.method=="Color") {
if (params.toneCurve.hrenabled && params.toneCurve.method=="Color") {
todo |= M_INIT;
}
}
@ -195,8 +195,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (todo & (M_INIT|M_LINDENOISE)) {
MyMutex::MyLock initLock(minit); // Also used in crop window
imgsrc->HLRecovery_Global( params.hlrecovery ); // this handles Color HLRecovery
imgsrc->HLRecovery_Global( params.toneCurve ); // this handles Color HLRecovery
if (settings->verbose) printf ("Applying white balance, color correction & sRBG conversion...\n");
currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
if (params.wb.method=="Camera")
@ -234,8 +233,17 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
// Will (re)allocate the preview's buffers
setScale (scale);
bool hlrbool=false;
int thresholdHLR=50;
if (settings->verbose) printf("HLredzero=%i HLgreenzero=%i HLblurzero=%i \n", histRedRaw[0], histGreenRaw[0], histBlueRaw[0]);
if (settings->verbose) printf("HLredMax=%i HLgreenMax=%i HLblueMax=%i \n", histRedRaw[255], histGreenRaw[255], histBlueRaw[255]);
if (params.toneCurve.autoexp) {// this enabled HLRecovery
//500 arbitrary values to enabled HLrecovery : not to enabled for too low values
if(histRedRaw[255]>thresholdHLR || histGreenRaw[255]>thresholdHLR || histBlueRaw[255]>thresholdHLR || histRedRaw[0]>thresholdHLR || histGreenRaw[0]>thresholdHLR || histBlueRaw[0]>thresholdHLR) {params.toneCurve.hrenabled=true;hlrbool=true;} }
if (ahlListener) {if(hlrbool==true) ahlListener->HLChanged (hlrbool);//enabled Highlight recovery
}
imgsrc->getImage (currWB, tr, orig_prev, pp, params.hlrecovery, params.icm, params.raw);
imgsrc->getImage (currWB, tr, orig_prev, pp, params.toneCurve, params.icm, params.raw);
//ColorTemp::CAT02 (orig_prev, &params) ;
//imgsrc->convertColorSpace(orig_prev, params.icm, params.raw);
@ -278,6 +286,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
if (todo & M_AUTOEXP) {
if (params.toneCurve.autoexp) {
LUTu aehist; int aehistcompr;
//histRedRaw, histGreenRaw, histBlueRaw
imgsrc->getAutoExpHistogram (aehist, aehistcompr);
ipf.getAutoExp (aehist, aehistcompr, imgsrc->getDefGain(), params.toneCurve.clip, params.toneCurve.expcomp,
params.toneCurve.brightness, params.toneCurve.contrast, params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh);
@ -778,7 +787,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
imgsrc->getFullSize (fW, fH, 0);
PreviewProps pp (0, 0, fW, fH, 1);
ProcParams ppar = params;
ppar.hlrecovery.enabled = false;
ppar.toneCurve.hrenabled = false;
ppar.icm.input = "(none)";
Imagefloat* im = new Imagefloat (fW, fH);
imgsrc->preprocess( ppar.raw, ppar.lensProf, ppar.coarse );
@ -804,7 +813,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
}
params.wb.temperature = currWB.getTemp ();
params.wb.green = currWB.getGreen ();
imgsrc->getImage (currWB, 0, im, pp, ppar.hlrecovery, ppar.icm, ppar.raw);
imgsrc->getImage (currWB, 0, im, pp, ppar.toneCurve, ppar.icm, ppar.raw);
imgsrc->convertColorSpace(im, ppar.icm, currWB, params.raw);
Image16* im16 = im->to16();
delete im;

View File

@ -141,6 +141,7 @@ class ImProcCoordinator : public StagedImageProcessor {
AutoExpListener* aeListener;
AutoCamListener* acListener;
AutoBWListener* abwListener;
AutoHLListener* ahlListener;
HistogramListener* hListener;
std::vector<SizeListener*> sizeListeners;
@ -213,6 +214,7 @@ class ImProcCoordinator : public StagedImageProcessor {
void setHistogramListener(HistogramListener *h) {hListener = h; }
void setAutoCamListener (AutoCamListener* acl) {acListener = acl; }
void setAutoBWListener (AutoBWListener* abw) {abwListener = abw; }
void setAutoHLListener (AutoHLListener* ahl) {ahlListener = ahl; }
void saveInputICCReference (const Glib::ustring& fname);

View File

@ -444,7 +444,7 @@ if(params->colorappearance.enabled) {
else yb=90.0;
int gamu=0;
bool highlight = params->hlrecovery.enabled; //Get the value if "highlight reconstruction" is activated
bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated
if(params->colorappearance.gamut==true) gamu=1;//enabled gamut control
xw=100.0*Xw;
@ -1276,7 +1276,7 @@ if(params->colorappearance.enabled) {
else yb=90.0f;
int gamu=0;
bool highlight = params->hlrecovery.enabled; //Get the value if "highlight reconstruction" is activated
bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated
if(params->colorappearance.gamut==true) gamu=1;//enabled gamut control
xw=100.0f*Xw;
@ -2319,7 +2319,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, LUTf & hltone
#endif
for (int i=0; i<tH; i++) {
for (int j=0; j<tW; j++) {
bool highlight = params->hlrecovery.enabled;//Get the value if "highlight reconstruction" is activated
bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated
float r1,g1,b1, r2,g2,b2, L_1,L_2, Lfactor,a_1,b_1,x_,y_,z_,R,G,B ;
float y,fy, yy,fyy,x,z,fx,fz;
@ -2543,7 +2543,7 @@ if(blackwhite){
#endif
for (int i=0; i<tH; i++) {
for (int j=0; j<tW; j++) {
bool highlight = params->hlrecovery.enabled;//Get the value if "highlight reconstruction" is activated
bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated
//rgb=>lab
float r = tmpImage->r(i,j);
float g = tmpImage->g(i,j);
@ -2962,7 +2962,7 @@ void ImProcFunctions::chromiLuminanceCurve (int pW, LabImage* lold, LabImage* ln
// reference to the params structure has to be done outside of the parallelization to avoid CPU cache problem
bool highlight = params->hlrecovery.enabled; //Get the value if "highlight reconstruction" is activated
bool highlight = params->toneCurve.hrenabled; //Get the value if "highlight reconstruction" is activated
int chromaticity = params->labCurve.chromaticity;
bool bwToning = params->labCurve.chromaticity==-100 /*|| params->blackwhite.method=="Ch" */ || params->blackwhite.enabled;
//if(chromaticity==-100) chromaticity==-99;
@ -2980,8 +2980,9 @@ void ImProcFunctions::chromiLuminanceCurve (int pW, LabImage* lold, LabImage* ln
// only if user activate Lab adjustements
if (avoidColorShift) {
if(autili || butili || ccutili || cclutili || chutili || lhutili || hhutili || clcutili || utili || chromaticity)
Color::LabGamutMunsell(lold, Lold, Cold, /*corMunsell*/true, /*lumaMuns*/false, params->hlrecovery.enabled, /*gamut*/true, params->icm.working, multiThread);
}
Color::LabGamutMunsell(lold, Lold, Cold, /*corMunsell*/true, /*lumaMuns*/false, params->toneCurve.hrenabled, /*gamut*/true, params->icm.working, multiThread);
}
#ifdef _DEBUG
@ -3664,13 +3665,13 @@ fclose(f);*/
void ImProcFunctions::getAutoExp (LUTu & histogram, int histcompr, double defgain, double clip,
double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh) {
float scale = 65536.0;
float midgray=0.15;//0.18445f;//middle gray in linear gamma = 0.18445*65535
float scale = 65536.0f;
float midgray=0.1842f;//middle gray in linear gamma =1 50% luminance
int imax=65536>>histcompr;
float sum = 0, hisum=0, losum=0;
float ave = 0, hidev=0, lodev=0;
int overex=0;
float sum = 0.f, hisum=0.f, losum=0.f;
float ave = 0.f, hidev=0.f, lodev=0.f;
//find average luminance
for (int i=0; i<imax; i++) {
sum += histogram[i];
@ -3684,8 +3685,8 @@ fclose(f);*/
median++;
count += histogram[median];
}
if (median==0 || ave<1) {//probably the image is a blackframe
expcomp=0;
if (median==0 || ave<1.f) {//probably the image is a blackframe
expcomp=0.;
black=0;
bright=0;
contr=0;
@ -3696,29 +3697,29 @@ fclose(f);*/
// compute std dev on the high and low side of median
// and octiles of histogram
float octile[8]={0,0,0,0,0,0,0,0},ospread=0;
float octile[8]={0.f,0.f,0.f,0.f,0.f,0.f,0.f,0.f},ospread=0.f;
count=0;
for (int i=0; i<imax; i++) {
if (count<8) {
octile[count] += histogram[i];
if (octile[count]>sum/8 || (count==7 && octile[count]>sum/16)) {
octile[count]=log(1+i)/log(2);
if (octile[count]>sum/8.f || (count==7 && octile[count]>sum/16.f)) {
octile[count]=log(1.+(float)i)/log(2.f);
count++;// = min(count+1,7);
}
}
if (i<ave) {
//lodev += SQR(ave-i)*histogram[i];
lodev += (log(ave+1)-log(i+1))*histogram[i];
lodev += (log(ave+1.f)-log((float)i+1.))*histogram[i];
losum += histogram[i];
} else {
//hidev += SQR(i-ave)*histogram[i];
hidev += (log(i+1)-log(ave+1))*histogram[i];
hidev += (log((float)i+1.)-log(ave+1.f))*histogram[i];
hisum += histogram[i];
}
}
if (losum==0 || hisum==0) {//probably the image is a blackframe
expcomp=0;
expcomp=0.;
black=0;
bright=0;
contr=0;
@ -3726,13 +3727,20 @@ fclose(f);*/
hlcomprthresh=0;
return;
}
lodev = (lodev/(log(2)*losum));
hidev = (hidev/(log(2)*hisum));
if (octile[7]>log(imax+1)/log2(2)) {
octile[7]=1.5*octile[6]-0.5*octile[5];
lodev = (lodev/(log(2.f)*losum));
hidev = (hidev/(log(2.f)*hisum));
if (octile[6]>log((float)imax+1.f)/log2(2.f)) {//if very overxposed image
octile[6]=1.5f*octile[5]-0.5f*octile[4];
overex=2;
}
if (octile[7]>log((float)imax+1.f)/log2(2.f)) {//if overexposed
octile[7]=1.5f*octile[6]-0.5f*octile[5];
overex=1;
}
for(int i=1; i<8; i++) {
if (octile[i] == 0.0)
if (octile[i] == 0.0f)
octile[i] = octile[i-1];
}
// compute weighted average separation of octiles
@ -3740,9 +3748,9 @@ fclose(f);*/
for (int i=1; i<6; i++) {
ospread += (octile[i+1]-octile[i])/max(0.5f,(i>2 ? (octile[i+1]-octile[3]) : (octile[3]-octile[i])));
}
ospread /= 5;
if (ospread<=0) {//probably the image is a blackframe
expcomp=0;
ospread /= 5.f;
if (ospread<=0.f) {//probably the image is a blackframe
expcomp=0.;
black=0;
bright=0;
contr=0;
@ -3761,7 +3769,7 @@ fclose(f);*/
}
//compute clipped white point
int clippable = (int)(sum * clip );
int clippable = (int)(sum * clip/100.f );
clipped = 0;
int whiteclip = (imax) - 1;
while (whiteclip>1 && histogram[whiteclip]+clipped <= clippable) {
@ -3772,11 +3780,11 @@ fclose(f);*/
//compute clipped black point
clipped = 0;
int shc = 0;
while (shc<whiteclip-1 && histogram[shc]+clipped <= clippable) {
clipped += histogram[shc];
shc++;
}
//rescale to 65535 max
rawmax <<= histcompr;
whiteclip <<= histcompr;
@ -3785,41 +3793,40 @@ fclose(f);*/
shc <<= histcompr;
//prevent division by 0
if (lodev==0) lodev=1;
if (lodev==0.f) lodev=1.f;
//compute exposure compensation as geometric mean of the amount that
//sets the mean or median at middle gray, and the amount that sets the estimated top
//of the histogram at or near clipping.
float expcomp1 = log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc))/log(2);
float expcomp2 = 0.5*( (15.5f-histcompr-(2*octile[7]-octile[6])) + log(scale/rawmax)/log(2) );
/*expcomp = (expcomp1*fabs(expcomp2)+expcomp2*fabs(expcomp1))/(fabs(expcomp1)+fabs(expcomp2));
if (expcomp<0) {
float expo=log(midgray*scale/(ave-shc+midgray*shc));
//float expcomp1 = (log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc))+log((hidev/lodev)))/log(2.f);
float expcomp1 = (log(/*(median/ave)*//*(hidev/lodev)*/midgray*scale/(ave-shc+midgray*shc)))/log(2.f);
float expcomp2 = 0.5f*( (15.5f-histcompr-(2.f*octile[7]-octile[6])) + log(scale/rawmax)/log(2.f) );
if(fabs(expcomp1)-fabs(expcomp2)> 1.f) {//for great expcomp
expcomp = (expcomp1*fabs(expcomp2)+expcomp2*fabs(expcomp1))/(fabs(expcomp1)+fabs(expcomp2));
if (expcomp<0.f) {
min(0.0f,max(expcomp1,expcomp2));
}*/
expcomp = 0.5 * (expcomp1 + expcomp2);
float gain = exp(expcomp*log(2));
}
}
else expcomp = 0.5 * (double)expcomp1 + 0.5 *(double) expcomp2;//for small expcomp
float gain = exp((float)expcomp*log(2.f));
float corr = sqrt(gain*scale/rawmax);
black = (int) shc*corr;
gain = /*(median/ave)*/sqrt(gain*scale/rawmax);
black = shc*gain;
expcomp = log(gain)/log(2.0);//convert to stops
black = shc*gain;
//now tune hlcompr to bring back rawmax to 65535
hlcomprthresh = 33;
//this is a series approximation of the actual formula for comp,
//which is a transcendental equation
float comp = (gain*((float)whiteclip)/scale - 1)*2;//*(1-shoulder/scale);
hlcompr=(int)(100*comp/(max(0.0,expcomp) + 1.0));
float comp = (gain*((float)whiteclip)/scale - 1.f)*2.3f;// 2.3 instead of 2 to increase slightly comp
hlcompr=(int)(100.*comp/(max(0.0,expcomp) + 1.0));
hlcompr = max(0,min(100,hlcompr));
//now find brightness if gain didn't bring ave to midgray using
//the envelope of the actual 'control cage' brightness curve for simplicity
float midtmp = gain*sqrt(median*ave)/scale;
if (midtmp<0.1) {
if (midtmp<0.1f) {
bright = (midgray-midtmp)*15.0/(midtmp);
} else {
bright = (midgray-midtmp)*15.0/(0.10833-0.0833*midtmp);
@ -3828,23 +3835,42 @@ fclose(f);*/
bright = 0.25*/*(median/ave)*(hidev/lodev)*/max(0,bright);
//compute contrast that spreads the average spacing of octiles
contr = 50.0*(1.1-ospread);
contr = (int) 50.0f*(1.1f-ospread);
contr = max(0,min(100,contr));
//take gamma into account
double whiteclipg = (int)(CurveFactory::gamma2 (whiteclip * corr / 65536.0) * 65536.0);
double gavg = 0.;
for (int i=0; i<65536>>histcompr; i++)
gavg += histogram[i] * CurveFactory::gamma2((int)(corr*(i<<histcompr)<65535 ? corr*(i<<histcompr) : 65535)) / sum;
if (black < gavg) {
int maxwhiteclip = (gavg - black) * 4 / 3 + black; // dont let whiteclip be such large that the histogram average goes above 3/4
if (whiteclipg < maxwhiteclip)
whiteclipg = maxwhiteclip;
}
whiteclipg = CurveFactory::igamma2 ((float)(whiteclipg/65535.0)) * 65535.0; //need to inverse gamma transform to get correct exposure compensation parameter
//corection with gamma
black = (int)((65535*black)/whiteclipg);
//expcomp = log(65535.0 / (whiteclipg)) / log(2.0);
//diagnostics
//printf ("**************** AUTO LEVELS ****************\n");
//printf ("gain1= %f gain2= %f gain= %f\n",expcomp1,expcomp2,gain);
//printf ("median: %i average: %f median/average: %f\n",median,ave, median/ave);
//printf ("average: %f\n",ave);
//printf ("median/average: %f\n",median/ave);
//printf ("lodev: %f hidev: %f hidev/lodev: %f\n",lodev,hidev,hidev/lodev);
//printf ("lodev: %f\n",lodev);
//printf ("hidev: %f\n",hidev);
//printf ("rawmax= %d whiteclip= %d gain= %f\n",rawmax,whiteclip,gain);
//printf ("octiles: %f %f %f %f %f %f %f %f\n",octile[0],octile[1],octile[2],octile[3],octile[4],octile[5],octile[6],octile[7]);
//printf ("ospread= %f\n",ospread);
if (settings->verbose) {
printf ("expcomp1= %f expcomp2= %f gain= %f expcomp=%f\n",expcomp1,expcomp2,gain,expcomp);
printf ("expo=%f\n",expo);
printf ("median: %i average: %f median/average: %f\n",median,ave, median/ave);
printf ("average: %f\n",ave);
printf("comp=%f hlcomp: %i\n",comp, hlcompr);
printf ("median/average: %f\n",median/ave);
printf ("lodev: %f hidev: %f hidev/lodev: %f\n",lodev,hidev,hidev/lodev);
printf ("lodev: %f\n",lodev);
printf ("hidev: %f\n",hidev);
printf ("imax=%d rawmax= %d whiteclip= %d gain= %f\n",imax,rawmax,whiteclip,gain);
printf ("octiles: %f %f %f %f %f %f %f %f\n",octile[0],octile[1],octile[2],octile[3],octile[4],octile[5],octile[6],octile[7]);
printf ("ospread= %f\n",ospread);
printf ("overexp= %i\n",overex);
}
/*
// %%%%%%%%%% LEGACY AUTOEXPOSURE CODE %%%%%%%%%%%%%
@ -3871,7 +3897,6 @@ fclose(f);*/
expcomp = log(65535.0 / (whiteclipg)) / log(2.0);
if (expcomp<0.0) expcomp = 0.0;*/
if (expcomp<-5.0) expcomp = -5.0;
if (expcomp>10.0) expcomp = 10.0;
}

View File

@ -122,7 +122,7 @@ void ImProcFunctions::vibrance (LabImage* lab) {
float limitpastelsatur = static_cast<float>(params->vibrance.psthreshold.value[ThresholdSelector::TS_TOPLEFT]) / 100.0f;
float transitionweighting = static_cast<float>(params->vibrance.psthreshold.value[ThresholdSelector::TS_BOTTOMLEFT]) / 100.0f;
bool highlight = params->hlrecovery.enabled;//Get the value if "highlight reconstruction" is activated
bool highlight = params->toneCurve.hrenabled;//Get the value if "highlight reconstruction" is activated
bool protectskins = params->vibrance.protectskins;
bool avoidcolorshift = params->vibrance.avoidcolorshift;

View File

@ -145,8 +145,9 @@ void ProcParams::setDefaults () {
toneCurve.curve2.push_back(DCT_Linear);
toneCurve.curveMode = ToneCurveParams::TC_MODE_STD;
toneCurve.curveMode2 = ToneCurveParams::TC_MODE_STD;
labCurve.brightness = 0;
toneCurve.hrenabled = false;
toneCurve.method = "Blend";
labCurve.brightness = 0;
labCurve.contrast = 0;
labCurve.chromaticity = 0;
labCurve.avoidcolorshift = true;
@ -352,8 +353,6 @@ void ProcParams::setDefaults () {
cacorrection.red = 0;
cacorrection.blue = 0;
hlrecovery.enabled = false;
hlrecovery.method = "Blend";
vignetting.amount = 0;
vignetting.radius = 50;
@ -532,6 +531,9 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
if (!pedited || pedited->toneCurve.hlcompr) keyFile.set_integer ("Exposure", "HighlightCompr", toneCurve.hlcompr);
if (!pedited || pedited->toneCurve.hlcomprthresh) keyFile.set_integer ("Exposure", "HighlightComprThreshold", toneCurve.hlcomprthresh);
if (!pedited || pedited->toneCurve.shcompr) keyFile.set_integer ("Exposure", "ShadowCompr", toneCurve.shcompr);
// save highlight recovery settings
if (!pedited || pedited->toneCurve.hrenabled) keyFile.set_boolean ("HLRecovery", "Enabled", toneCurve.hrenabled);
if (!pedited || pedited->toneCurve.method) keyFile.set_string ("HLRecovery", "Method", toneCurve.method);
if (!pedited || pedited->toneCurve.curveMode) {
Glib::ustring method;
switch (toneCurve.curveMode) {
@ -967,9 +969,6 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
if (!pedited || pedited->vignetting.centerX) keyFile.set_integer ("Vignetting Correction", "CenterX", vignetting.centerX);
if (!pedited || pedited->vignetting.centerY) keyFile.set_integer ("Vignetting Correction", "CenterY", vignetting.centerY);
// save highlight recovery settings
if (!pedited || pedited->hlrecovery.enabled) keyFile.set_boolean ("HLRecovery", "Enabled", hlrecovery.enabled);
if (!pedited || pedited->hlrecovery.method) keyFile.set_string ("HLRecovery", "Method", hlrecovery.method);
if (!pedited || pedited->resize.enabled) keyFile.set_boolean ("Resize", "Enabled",resize.enabled);
if (!pedited || pedited->resize.scale) keyFile.set_double ("Resize", "Scale", resize.scale);
@ -1160,6 +1159,7 @@ if (keyFile.has_group ("Exposure")) {
if (keyFile.has_key ("Exposure", "HighlightCompr")) { toneCurve.hlcompr = keyFile.get_integer ("Exposure", "HighlightCompr"); if (pedited) pedited->toneCurve.hlcompr = true; }
if (keyFile.has_key ("Exposure", "HighlightComprThreshold")) { toneCurve.hlcomprthresh = keyFile.get_integer ("Exposure", "HighlightComprThreshold"); if (pedited) pedited->toneCurve.hlcomprthresh = true; }
if (keyFile.has_key ("Exposure", "ShadowCompr")) { toneCurve.shcompr = keyFile.get_integer ("Exposure", "ShadowCompr"); if (pedited) pedited->toneCurve.shcompr = true; }
// load highlight recovery settings
if (toneCurve.shcompr > 100) toneCurve.shcompr = 100; // older pp3 files can have values above 100.
if (keyFile.has_key ("Exposure", "CurveMode")) {
Glib::ustring sMode = keyFile.get_string ("Exposure", "CurveMode");
@ -1182,6 +1182,10 @@ if (keyFile.has_group ("Exposure")) {
if (keyFile.has_key ("Exposure", "Curve2")) { toneCurve.curve2 = keyFile.get_double_list ("Exposure", "Curve2"); if (pedited) pedited->toneCurve.curve2 = true; }
}
}
if (keyFile.has_group ("HLRecovery")) {
if (keyFile.has_key ("HLRecovery", "Enabled")) { toneCurve.hrenabled = keyFile.get_boolean ("HLRecovery", "Enabled"); if (pedited) pedited->toneCurve.hrenabled = true; }
if (keyFile.has_key ("HLRecovery", "Method")) { toneCurve.method = keyFile.get_string ("HLRecovery", "Method"); if (pedited) pedited->toneCurve.method = true; }
}
// load channel mixer curve
if (keyFile.has_group ("Channel Mixer")) {
@ -1584,11 +1588,6 @@ if (keyFile.has_group ("Vignetting Correction")) {
if (keyFile.has_key ("Vignetting Correction", "CenterY")) { vignetting.centerY = keyFile.get_integer ("Vignetting Correction", "CenterY"); if (pedited) pedited->vignetting.centerY = true; }
}
// load highlight recovery settings
if (keyFile.has_group ("HLRecovery")) {
if (keyFile.has_key ("HLRecovery", "Enabled")) { hlrecovery.enabled = keyFile.get_boolean ("HLRecovery", "Enabled"); if (pedited) pedited->hlrecovery.enabled = true; }
if (keyFile.has_key ("HLRecovery", "Method")) { hlrecovery.method = keyFile.get_string ("HLRecovery", "Method"); if (pedited) pedited->hlrecovery.method = true; }
}
// load resize settings
if (keyFile.has_group ("Resize")) {
if (keyFile.has_key ("Resize", "Enabled")) { resize.enabled = keyFile.get_boolean ("Resize", "Enabled"); if (pedited) pedited->resize.enabled = true; }
@ -1773,6 +1772,8 @@ bool ProcParams::operator== (const ProcParams& other) {
&& toneCurve.expcomp == other.toneCurve.expcomp
&& toneCurve.curveMode == other.toneCurve.curveMode
&& toneCurve.curveMode2 == other.toneCurve.curveMode2
&& toneCurve.hrenabled == other.toneCurve.hrenabled
&& toneCurve.method == other.toneCurve.method
&& labCurve.lcurve == other.labCurve.lcurve
&& labCurve.acurve == other.labCurve.acurve
&& labCurve.bcurve == other.labCurve.bcurve
@ -1946,8 +1947,6 @@ bool ProcParams::operator== (const ProcParams& other) {
&& blackwhite.beforeCurveMode == other.blackwhite.beforeCurveMode
&& blackwhite.afterCurveMode == other.blackwhite.afterCurveMode
&& blackwhite.autoc == other.blackwhite.autoc
&& hlrecovery.enabled == other.hlrecovery.enabled
&& hlrecovery.method == other.hlrecovery.method
&& resize.scale == other.resize.scale
&& resize.appliesTo == other.resize.appliesTo
&& resize.method == other.resize.method

View File

@ -180,6 +180,8 @@ class Threshold {
class ToneCurveParams {
public:
bool hrenabled;
Glib::ustring method;
enum eTCModeId {
TC_MODE_STD, // Standard modes, the curve is applied on all component individually
@ -202,6 +204,7 @@ class ToneCurveParams {
int shcompr;
int hlcompr;
int hlcomprthresh;
};
/**
@ -676,13 +679,14 @@ class CACorrParams {
/**
* Parameters of the highlight recovery
*/
/*
class HRecParams {
public:
bool enabled;
Glib::ustring method;
};
*/
/**
* Parameters of the resizing
*/
@ -841,7 +845,7 @@ class ProcParams {
VignettingParams vignetting; ///< Lens vignetting correction parameters
ChannelMixerParams chmixer; ///< Channel mixer parameters
BlackWhiteParams blackwhite; ///< Black & White parameters
HRecParams hlrecovery; ///< Highlight recovery parameters
// HRecParams hlrecovery; ///< Highlight recovery parameters
ResizeParams resize; ///< Resize parameters
ColorManagementParams icm; ///< profiles/color spaces used during the image processing
RAWParams raw; ///< RAW parameters before demosaicing

View File

@ -202,7 +202,8 @@ void RawImageSource::transformRect (PreviewProps pp, int tran, int &ssx1, int &s
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw )
void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw )
{
MyMutex::MyLock lock(getImageMutex);
@ -317,7 +318,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre
rtot*=rm;
gtot*=gm;
btot*=bm;
if (!hrp.enabled)
if (!hrp.hrenabled)
{
rtot=CLIP(rtot);
gtot=CLIP(gtot);
@ -341,7 +342,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre
rtot*=rm;
gtot*=gm;
btot*=bm;
if (!hrp.enabled)
if (!hrp.hrenabled)
{
rtot=CLIP(rtot);
gtot=CLIP(gtot);
@ -355,7 +356,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre
}
//process all highlight recovery other than "Color"
if (hrp.enabled && hrp.method!="Color")
if (hrp.hrenabled && hrp.method!="Color")
hlRecovery (hrp.method, line_red, line_grn, line_blue, i, sx1, imwidth, skip, raw, hlmax);
transLine (line_red, line_grn, line_blue, ix, image, tran, imwidth, imheight, fw);
@ -1195,10 +1196,10 @@ void RawImageSource::flushRGB() {
}
}
void RawImageSource::HLRecovery_Global(HRecParams hrp )
void RawImageSource::HLRecovery_Global(ToneCurveParams hrp )
{
//color propagation highlight recovery
if (hrp.enabled && hrp.method=="Color"){
if (hrp.hrenabled && hrp.method=="Color"){
if (settings->verbose) printf ("Applying Highlight Recovery: Color propagation...\n");
HLRecovery_inpaint (red,green,blue);
rgbSourceModified = true;

View File

@ -142,7 +142,7 @@ class RawImageSource : public ImageSource {
void demosaic (const RAWParams &raw);
void flushRawData ();
void flushRGB ();
void HLRecovery_Global (HRecParams hrp);
void HLRecovery_Global (ToneCurveParams hrp);
void refinement_lassus (int PassCount);
void refinement(int PassCount);
@ -152,7 +152,7 @@ class RawImageSource : public ImageSource {
void cfaboxblur (RawImage *riFlatFile, float* cfablur, int boxH, int boxW );
void scaleColors (int winx,int winy,int winw,int winh, const RAWParams &raw);// raw for cblack
void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw);
void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw);
ColorTemp getWB () { return camera_wb; }
void getAutoWBMultipliers (double &rm, double &gm, double &bm);
ColorTemp getSpotWB (std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, int tran, double equal);

View File

@ -31,7 +31,7 @@ RGBCURVE, // EvExpComp,
RGBCURVE, // EvHLCompr,
RGBCURVE, // EvSHCompr,
RGBCURVE, // EvToneCurve1,
AUTOEXP, // EvAutoExp,
ALLNORAW, // EvAutoExp,
AUTOEXP, // EvClip,
LUMINANCECURVE, // EvLBrightness,
LUMINANCECURVE, // EvLContrast,

View File

@ -264,6 +264,12 @@ namespace rtengine {
};
class AutoHLListener {
public :
virtual ~AutoHLListener() {}
virtual void HLChanged (bool hlrbool) {}
};
/** This class represents a detailed part of the image (looking through a kind of window).
* It can be created and destroyed with the appropriate members of StagedImageProcessor.
@ -346,6 +352,7 @@ namespace rtengine {
virtual void setPreviewImageListener (PreviewImageListener* l) =0;
virtual void setAutoCamListener (AutoCamListener* l) =0;
virtual void setAutoBWListener (AutoBWListener* l) =0;
virtual void setAutoHLListener (AutoHLListener* l) =0;
virtual ~StagedImageProcessor () {}

View File

@ -103,7 +103,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
if (pl) pl->setProgress (0.20);
imgsrc->demosaic( params.raw);
if (pl) pl->setProgress (0.30);
imgsrc->HLRecovery_Global( params.hlrecovery );
imgsrc->HLRecovery_Global( params.toneCurve );
if (pl) pl->setProgress (0.40);
// set the color temperature
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method);
@ -115,7 +115,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
currWB.update(rm, gm, bm, params.wb.equal);
}
Imagefloat* baseImg = new Imagefloat (fw, fh);
imgsrc->getImage (currWB, tr, baseImg, pp, params.hlrecovery, params.icm, params.raw);
imgsrc->getImage (currWB, tr, baseImg, pp, params.toneCurve, params.icm, params.raw);
if (pl) pl->setProgress (0.45);

View File

@ -194,7 +194,7 @@ int StdImageSource::load (Glib::ustring fname, bool batch) {
return 0;
}
void StdImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw) {
void StdImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp,ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw) {
// the code will use OpenMP as of now.

View File

@ -43,7 +43,7 @@ class StdImageSource : public ImageSource {
~StdImageSource ();
int load (Glib::ustring fname, bool batch = false);
void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, HRecParams hrp, ColorManagementParams cmp, RAWParams raw);
void getImage (ColorTemp ctemp, int tran, Imagefloat* image, PreviewProps pp, ToneCurveParams hrp, ColorManagementParams cmp, RAWParams raw);
ColorTemp getWB () { return wb; }
void getAutoWBMultipliers (double &rm, double &gm, double &bm);
ColorTemp getSpotWB (std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, int tran, double equal);

View File

@ -5,7 +5,7 @@ set (BASESOURCEFILES
ilabel.cc thumbbrowserbase.cc adjuster.cc filebrowserentry.cc filebrowser.cc filethumbnailbuttonset.cc
cachemanager.cc cacheimagedata.cc shcselector.cc perspective.cc thresholdselector.cc thresholdadjuster.cc
clipboard.cc thumbimageupdater.cc bqentryupdater.cc lensgeom.cc coloredbar.cc
coarsepanel.cc cacorrection.cc hlrec.cc chmixer.cc blackwhite.cc
coarsepanel.cc cacorrection.cc chmixer.cc blackwhite.cc
resize.cc icmpanel.cc crop.cc shadowshighlights.cc
impulsedenoise.cc dirpyrdenoise.cc epd.cc
exifpanel.cc toolpanel.cc lensprofile.cc

View File

@ -28,6 +28,8 @@ HLRecovery::HLRecovery () : Gtk::VBox(), FoldableToolPanel(this) {
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLE")));
enabled->set_active (false);
enabled->set_tooltip_markup (M("TP_HLREC_ENA_TOOLTIP"));
pack_start (*enabled);
method = Gtk::manage (new MyComboBoxText ());
@ -49,6 +51,27 @@ HLRecovery::HLRecovery () : Gtk::VBox(), FoldableToolPanel(this) {
show_all ();
}
int HLChangedUI (void* data) {
GThreadLock lock;
(static_cast<HLRecovery*>(data))->HLComputed_ ();
return 0;
}
void HLRecovery::HLChanged (bool hlrbool){
nexthlrbool= hlrbool;
g_idle_add (HLChangedUI, this);
}
bool HLRecovery::HLComputed_ () {
enaconn.block (true);
enabled->set_active (nexthlrbool);
enaconn.block (false);
return false;
}
void HLRecovery::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener ();

View File

@ -23,7 +23,7 @@
#include "toolpanel.h"
#include "guiutils.h"
class HLRecovery : public Gtk::VBox, public FoldableToolPanel {
class HLRecovery : public Gtk::VBox, public FoldableToolPanel, public rtengine::AutoHLListener{
protected:
Gtk::CheckButton* enabled;
@ -31,16 +31,21 @@ class HLRecovery : public Gtk::VBox, public FoldableToolPanel {
sigc::connection methconn;
sigc::connection enaconn;
bool lastEnabled;
bool nexthlrbool;
public:
HLRecovery ();
// ~HLRecovery ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
void setBatchMode (bool batchMode);
void setRaw (bool raw);
void HLChanged (bool hlrbool);
bool HLComputed_ ();
void enabledChanged ();
void methodChanged ();

View File

@ -46,6 +46,8 @@ void ParamsEdited::set (bool v) {
toneCurve.autoexp = v;
toneCurve.clip = v;
toneCurve.expcomp = v;
toneCurve.hrenabled = v;
toneCurve.method = v;
labCurve.lcurve = v;
labCurve.acurve = v;
labCurve.bcurve = v;
@ -241,8 +243,6 @@ void ParamsEdited::set (bool v) {
blackwhite.afterCurveMode = v;
blackwhite.autoc = v;
hlrecovery.enabled = v;
hlrecovery.method = v;
resize.scale = v;
resize.appliesTo = v;
resize.method = v;
@ -325,6 +325,8 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
toneCurve.autoexp = toneCurve.autoexp && p.toneCurve.autoexp == other.toneCurve.autoexp;
toneCurve.clip = toneCurve.clip && p.toneCurve.clip == other.toneCurve.clip;
toneCurve.expcomp = toneCurve.expcomp && p.toneCurve.expcomp == other.toneCurve.expcomp;
toneCurve.hrenabled = toneCurve.hrenabled && p.toneCurve.hrenabled == other.toneCurve.hrenabled;
toneCurve.method = toneCurve.method && p.toneCurve.method == other.toneCurve.method;
labCurve.lcurve = labCurve.lcurve && p.labCurve.lcurve == other.labCurve.lcurve;
labCurve.acurve = labCurve.acurve && p.labCurve.acurve == other.labCurve.acurve;
labCurve.bcurve = labCurve.bcurve && p.labCurve.bcurve == other.labCurve.bcurve;
@ -523,8 +525,6 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
blackwhite.afterCurve = blackwhite.afterCurve && p.blackwhite.afterCurve == other.blackwhite.afterCurve;
blackwhite.afterCurveMode = blackwhite.afterCurveMode && p.blackwhite.afterCurveMode == other.blackwhite.afterCurveMode;
blackwhite.autoc = blackwhite.autoc && p.blackwhite.autoc == other.blackwhite.autoc;
hlrecovery.enabled = hlrecovery.enabled && p.hlrecovery.enabled == other.hlrecovery.enabled;
hlrecovery.method = hlrecovery.method && p.hlrecovery.method == other.hlrecovery.method;
resize.scale = resize.scale && p.resize.scale == other.resize.scale;
resize.appliesTo = resize.appliesTo && p.resize.appliesTo == other.resize.appliesTo;
resize.method = resize.method && p.resize.method == other.resize.method;
@ -601,6 +601,8 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (toneCurve.expcomp) toEdit.toneCurve.expcomp = dontforceSet && options.baBehav[ADDSET_TC_EXPCOMP] ? toEdit.toneCurve.expcomp + mods.toneCurve.expcomp : mods.toneCurve.expcomp;
if (toneCurve.hlcompr) toEdit.toneCurve.hlcompr = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPAMOUNT] ? toEdit.toneCurve.hlcompr + mods.toneCurve.hlcompr : mods.toneCurve.hlcompr;
if (toneCurve.hlcomprthresh) toEdit.toneCurve.hlcomprthresh = dontforceSet && options.baBehav[ADDSET_TC_HLCOMPTHRESH] ? toEdit.toneCurve.hlcomprthresh + mods.toneCurve.hlcomprthresh : mods.toneCurve.hlcomprthresh;
if (toneCurve.hrenabled) toEdit.toneCurve.hrenabled = mods.toneCurve.hrenabled;
if (toneCurve.method) toEdit.toneCurve.method = mods.toneCurve.method;
if (labCurve.lcurve) toEdit.labCurve.lcurve = mods.labCurve.lcurve;
if (labCurve.acurve) toEdit.labCurve.acurve = mods.labCurve.acurve;
if (labCurve.bcurve) toEdit.labCurve.bcurve = mods.labCurve.bcurve;
@ -801,8 +803,6 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (blackwhite.afterCurve) toEdit.blackwhite.afterCurve = mods.blackwhite.afterCurve;
if (blackwhite.afterCurveMode) toEdit.blackwhite.afterCurveMode = mods.blackwhite.afterCurveMode;
if (hlrecovery.enabled) toEdit.hlrecovery.enabled = mods.hlrecovery.enabled;
if (hlrecovery.method) toEdit.hlrecovery.method = mods.hlrecovery.method;
if (resize.scale) toEdit.resize.scale = mods.resize.scale;
if (resize.appliesTo) toEdit.resize.appliesTo = mods.resize.appliesTo;
if (resize.method) toEdit.resize.method = mods.resize.method;

View File

@ -49,6 +49,9 @@ class ToneCurveParamsEdited {
bool autoexp;
bool clip;
bool expcomp;
bool hrenabled;
bool method;
};
class LCurveParamsEdited {
@ -69,6 +72,10 @@ class LCurveParamsEdited {
bool hhcurve;
bool lccurve;
bool clcurve;
bool enabled;
bool method;
};
class RGBCurvesParamsEdited {
@ -384,14 +391,14 @@ class CACorrParamsEdited {
bool red;
bool blue;
};
/*
class HRecParamsEdited {
public:
bool enabled;
bool method;
};
*/
class ResizeParamsEdited {
public:
@ -503,7 +510,7 @@ class ParamsEdited {
VignettingParamsEdited vignetting;
ChannelMixerParamsEdited chmixer;
BlackWhiteParamsEdited blackwhite;
HRecParamsEdited hlrecovery;
// HRecParamsEdited hlrecovery;
ResizeParamsEdited resize;
ColorManagementParamsEdited icm;
RAWParamsEdited raw;

View File

@ -46,7 +46,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
// options in basic:
wb = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_WHITEBALANCE")));
exposure = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_EXPOSURE")));
hlrec = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_HLRECONSTRUCTION")));
// hlrec = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_HLRECONSTRUCTION")));
sh = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_SHADOWSHIGHLIGHTS")));
epd = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_EPD")));
pcvignette = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PCVIGNETTE")));
@ -126,7 +126,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
vboxes[0]->pack_start (*hseps[0], Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*wb, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*exposure, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*hlrec, Gtk::PACK_SHRINK, 2);
// vboxes[0]->pack_start (*hlrec, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*sh, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*epd, Gtk::PACK_SHRINK, 2);
vboxes[0]->pack_start (*pcvignette, Gtk::PACK_SHRINK, 2);
@ -249,7 +249,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
wbConn = wb->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
exposureConn = exposure->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
hlrecConn = hlrec->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
// hlrecConn = hlrec->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
shConn = sh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
epdConn = epd->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
pcvignetteConn = pcvignette->signal_toggled().connect (sigc::bind (sigc::mem_fun(*basic, &Gtk::CheckButton::set_inconsistent), true));
@ -433,7 +433,7 @@ void PartialPasteDlg::basicToggled () {
wbConn.block (true);
exposureConn.block (true);
hlrecConn.block (true);
// hlrecConn.block (true);
shConn.block (true);
epdConn.block(true);
pcvignetteConn.block (true);
@ -445,7 +445,7 @@ void PartialPasteDlg::basicToggled () {
wb->set_active (basic->get_active ());
exposure->set_active (basic->get_active ());
hlrec->set_active (basic->get_active ());
// hlrec->set_active (basic->get_active ());
sh->set_active (basic->get_active ());
epd->set_active (basic->get_active ());
pcvignette->set_active (basic->get_active ());
@ -455,7 +455,7 @@ void PartialPasteDlg::basicToggled () {
wbConn.block (false);
exposureConn.block (false);
hlrecConn.block (false);
// hlrecConn.block (false);
shConn.block (false);
epdConn.block (false);
pcvignetteConn.block (false);
@ -613,7 +613,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
// Now we filter out the filter depending on the checked items
if (!wb->get_active ()) filterPE.wb = falsePE.wb;
if (!exposure->get_active ()) filterPE.toneCurve = falsePE.toneCurve;
if (!hlrec->get_active ()) filterPE.hlrecovery = falsePE.hlrecovery;
// if (!hlrec->get_active ()) filterPE.toneCurve = falsePE.toneCurve;
if (!sh->get_active ()) filterPE.sh = falsePE.sh;
if (!epd->get_active ()) filterPE.edgePreservingDecompositionUI = falsePE.edgePreservingDecompositionUI;
if (!pcvignette->get_active ()) filterPE.pcvignette = falsePE.pcvignette;

View File

@ -44,10 +44,10 @@ ToneCurve::ToneCurve () : Gtk::VBox(), FoldableToolPanel(this) {
autoconn = autolevels->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::autolevels_toggled) );
sclip = Gtk::manage (new MySpinButton ());
sclip->set_range (0.0, 0.9999);
sclip->set_increments (0.001, 0.01);
sclip->set_value (0.002);
sclip->set_digits (4);
sclip->set_range (0.0, 0.99);
sclip->set_increments (0.01, 0.01);
sclip->set_value (0.02);
sclip->set_digits (2);
sclip->set_tooltip_text (M("TP_EXPOSURE_CLIP_TIP"));
sclip->signal_value_changed().connect( sigc::mem_fun(*this, &ToneCurve::clip_changed) );
@ -64,16 +64,56 @@ ToneCurve::ToneCurve () : Gtk::VBox(), FoldableToolPanel(this) {
abox->pack_end (*Gtk::manage (new Gtk::Label (M("TP_EXPOSURE_CLIP"))));
pack_start (*abox);
pack_start (*Gtk::manage (new Gtk::HSeparator()));
//----------- Exposure Compensation ------------------------
expcomp = Gtk::manage (new Adjuster (M("TP_EXPOSURE_EXPCOMP"), -5, 10, 0.05, 0));
pack_start (*expcomp);
hlcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0));
pack_start (*hlcompr);
hlcomprthresh = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 33));
pack_start (*hlcomprthresh);
pack_start (*Gtk::manage (new Gtk::Label (" "))); //spacer
pack_start (*Gtk::manage (new Gtk::HSeparator()));
//--------------HLRecovery from HLREC and Hl compress
hlrbox = Gtk::manage (new Gtk::HBox ());
hlrbox->set_border_width (2);
Gtk::Label* hlrLabel = Gtk::manage (new Gtk::Label (M("TP_HLREC_LABEL")));
hrenabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLE")));
hrenabled->set_active (false);
hrenabled->set_tooltip_markup (M("TP_HLREC_ENA_TOOLTIP"));
hlrbox->pack_start (*hlrLabel,Gtk::PACK_SHRINK);
hlrbox->pack_end (*hrenabled, Gtk::PACK_SHRINK);
hlrbox->pack_end (*Gtk::manage (new Gtk::Label (" "))); //spacer
pack_start (*hlrbox);
method = Gtk::manage (new MyComboBoxText ());
method->append_text (M("TP_HLREC_LUMINANCE"));
method->append_text (M("TP_HLREC_CIELAB"));
method->append_text (M("TP_HLREC_COLOR"));
method->append_text (M("TP_HLREC_BLEND"));
method->set_active (0);
Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ());
Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_HLREC_METHOD")));
hb->pack_start (*lab, Gtk::PACK_SHRINK, 4);
hb->pack_start (*method);
pack_start (*hb);
enaconn = hrenabled->signal_toggled().connect( sigc::mem_fun(*this, &ToneCurve::hrenabledChanged) );
methconn = method->signal_changed().connect ( sigc::mem_fun(*this, &ToneCurve::methodChanged) );
pack_start (*Gtk::manage (new Gtk::Label (" "))); //spacer
pack_start (*Gtk::manage (new Gtk::HSeparator()));
hlcompr = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTS"), 0, 500, 1, 0));
pack_start (*hlcompr);
hlcomprthresh = Gtk::manage (new Adjuster (M("TP_EXPOSURE_COMPRHIGHLIGHTSTHRESHOLD"), 0, 100, 1, 33));
pack_start (*hlcomprthresh);
//----------- Black Level ----------------------------------
black = Gtk::manage (new Adjuster (M("TP_EXPOSURE_BLACKLEVEL"), -16384, 32768, 50, 0));
pack_start (*black);
@ -202,8 +242,28 @@ void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
if (!pedited->toneCurve.curveMode2) {
toneCurveMode2->set_active(4);
}
}
if (pedited)
hrenabled->set_inconsistent (!pedited->toneCurve.hrenabled);
enaconn.block (true);
hrenabled->set_active (pp->toneCurve.hrenabled);
enaconn.block (false);
if (pedited && !pedited->toneCurve.method)
method->set_active (4);
else if (pp->toneCurve.method=="Luminance")
method->set_active (0);
else if (pp->toneCurve.method=="CIELab blending")
method->set_active (1);
else if (pp->toneCurve.method=="Color")
method->set_active (2);
else if (pp->toneCurve.method=="Blend")
method->set_active (3);
lasthrEnabled = pp->toneCurve.hrenabled;
autoconn.block (false);
tcmode2conn.block(false);
tcmodeconn.block(false);
@ -215,6 +275,22 @@ void ToneCurve::autoOpenCurve () {
shape->openIfNonlinear();
shape2->openIfNonlinear();
}
int HLChangedUI (void* data) {
GThreadLock lock;
(static_cast<ToneCurve*>(data))->HLComputed_ ();
return 0;
}
void ToneCurve::HLChanged (bool hlrbool){
nexthlrbool= hlrbool;
g_idle_add (HLChangedUI, this);
}
bool ToneCurve::HLComputed_ () {
enaconn.block (true);
hrenabled->set_active (nexthlrbool);
enaconn.block (false);
return false;
}
void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) {
@ -260,8 +336,69 @@ void ToneCurve::write (ProcParams* pp, ParamsEdited* pedited) {
pedited->toneCurve.curveMode = toneCurveMode->get_active_row_number() != 4;
pedited->toneCurve.curveMode2 = toneCurveMode2->get_active_row_number() != 4;
}
if (pedited) {
pedited->toneCurve.method = method->get_active_row_number()!=4;
pedited->toneCurve.hrenabled = !hrenabled->get_inconsistent();
}
pp->toneCurve.hrenabled = hrenabled->get_active();
if (method->get_active_row_number()==0)
pp->toneCurve.method = "Luminance";
else if (method->get_active_row_number()==1)
pp->toneCurve.method = "CIELab blending";
else if (method->get_active_row_number()==2)
pp->toneCurve.method = "Color";
else if (method->get_active_row_number()==3)
pp->toneCurve.method = "Blend";
}
void ToneCurve::hrenabledChanged () {
if (batchMode) {
if (hrenabled->get_inconsistent()) {
hrenabled->set_inconsistent (false);
enaconn.block (true);
hrenabled->set_active (false);
enaconn.block (false);
}
else if (lasthrEnabled)
hrenabled->set_inconsistent (true);
lasthrEnabled = hrenabled->get_active ();
}
if (listener) {
if (hrenabled->get_active ()){
listener->panelChanged (EvHREnabled, M("GENERAL_ENABLED"));
}
else { // Switch off auto exposure if user changes enabled manually
if (autolevels->get_active() ) {
autoconn.block(true);
autolevels->set_active (false);
autoconn.block(false);
autolevels->set_inconsistent (false);
}
listener->panelChanged (EvHREnabled, M("GENERAL_DISABLED"));}
}
}
void ToneCurve::methodChanged () {
if (listener) {
if (hrenabled->get_active ())
listener->panelChanged (EvHRMethod, method->get_active_text ());
}
}
void ToneCurve::setRaw (bool raw) {
disableListener ();
method->set_sensitive (raw);
hrenabled->set_sensitive (raw);
enableListener ();
}
void ToneCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
expcomp->setDefault (defParams->toneCurve.expcomp);
@ -365,7 +502,7 @@ void ToneCurve::adjusterChanged (Adjuster* a, double newval) {
}
void ToneCurve::neutral_pressed () {
// This method deselects auto levels
// This method deselects auto levels and HL reconstruction auto
// and sets neutral values to params in exposure panel
if (batchMode) {
@ -387,6 +524,7 @@ void ToneCurve::neutral_pressed () {
brightness->setValue(0);
black->setValue(0);
shcompr->setValue(50);
hrenabled->set_active (false);
if (!black->getAddMode()) shcompr->set_sensitive(!((int)black->getValue ()==0)); //at black=0 shcompr value has no effect
contrast->setValue(0);
//saturation->setValue(0);
@ -425,6 +563,7 @@ void ToneCurve::autolevels_toggled () {
hlcompr->setValue (0);
if (hlcomprthresh->getAddMode())
hlcomprthresh->setValue (0);
if (listener) {
if (!autolevels->get_inconsistent()) {
if (autolevels->get_active ())
@ -529,6 +668,11 @@ bool ToneCurve::autoExpComputed_ () {
}
void ToneCurve::setBatchMode (bool batchMode) {
//from HLrecovery
ToolPanel::setBatchMode (batchMode);
method->append_text (M("GENERAL_UNCHANGED"));
//---------------
removeIfThere (abox, autolevels, false);
autolevels = Gtk::manage (new Gtk::CheckButton (M("TP_EXPOSURE_AUTOLEVELS")));

View File

@ -27,10 +27,20 @@
#include "mycurve.h"
#include "guiutils.h"
class ToneCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoExpListener, public CurveListener {
class ToneCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public rtengine::AutoExpListener, public rtengine::AutoHLListener,public CurveListener {
protected:
// from HLRecovery
Gtk::CheckButton* hrenabled;
MyComboBoxText* method;
sigc::connection methconn;
sigc::connection enaconn;
bool lasthrEnabled;
bool nexthlrbool;
Gtk::HBox* abox;
Gtk::HBox* hlrbox;
Gtk::ToggleButton* autolevels;
MySpinButton* sclip;
Gtk::Button* neutral;
@ -45,7 +55,6 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public FoldableTool
MyComboBoxText* toneCurveMode;
MyComboBoxText* toneCurveMode2;
bool clipDirty, lastAuto;
sigc::connection autoconn, neutralconn, tcmodeconn, tcmode2conn;
CurveEditorGroup* curveEditorG;
@ -60,6 +69,9 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public FoldableTool
int nextBlack;
int nextHlcompr;
int nextHlcomprthresh;
public:
@ -92,6 +104,16 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public FoldableTool
void expandCurve (bool isExpanded);
bool isCurveExpanded ();
void updateCurveBackgroundHistogram (LUTu & histToneCurve, LUTu & histLCurve, LUTu & histCCurve, LUTu & histCLurve, LUTu & histLLCurve, LUTu & histLCAM, LUTu & histCCAM, LUTu & histRed, LUTu & histGreen, LUTu & histBlue, LUTu & histLuma);
};
//from HLrecovery
void setRaw (bool raw);
void HLChanged (bool hlrbool);
bool HLComputed_ ();
void hrenabledChanged ();
void methodChanged ();
};
#endif

View File

@ -63,7 +63,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
pcvignette = Gtk::manage (new PCVignette ());
perspective = Gtk::manage (new PerspCorrection ());
cacorrection = Gtk::manage (new CACorrection ());
hlrecovery = Gtk::manage (new HLRecovery ());
// hlrecovery = Gtk::manage (new HLRecovery ());
chmixer = Gtk::manage (new ChMixer ());
blackwhite = Gtk::manage (new BlackWhite ());
resize = Gtk::manage (new Resize ());
@ -82,7 +82,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
addPanel (colorPanel, whitebalance, M("TP_WBALANCE_LABEL")); toolPanels.push_back (whitebalance);
addPanel (exposurePanel, toneCurve, M("TP_EXPOSURE_LABEL")); toolPanels.push_back (toneCurve);
addPanel (exposurePanel, hlrecovery, M("TP_HLREC_LABEL")); toolPanels.push_back (hlrecovery);
// addPanel (exposurePanel, hlrecovery, M("TP_HLREC_LABEL")); toolPanels.push_back (hlrecovery);
addPanel (colorPanel, vibrance, M("TP_VIBRANCE_LABEL")); toolPanels.push_back (vibrance);
addPanel (colorPanel, chmixer, M("TP_CHMIXER_LABEL")); toolPanels.push_back (chmixer);
addPanel (colorPanel, blackwhite, M("TP_BWMIX_LABEL")); toolPanels.push_back (blackwhite);
@ -365,6 +365,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool
ipc->setAutoExpListener (toneCurve);
ipc->setAutoCamListener (colorappearance);
ipc->setAutoBWListener (blackwhite);
ipc->setAutoHLListener (toneCurve);
ipc->setSizeListener (crop);
ipc->setSizeListener (resize);
@ -374,7 +375,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool
icm->setRawMeta (raw, (const rtengine::ImageData*)pMetaData);
lensProf->setRawMeta (raw, pMetaData);
hlrecovery->setRaw (raw);
toneCurve->setRaw (raw);
hasChanged = true;
}

View File

@ -45,7 +45,7 @@
#include "resize.h"
#include "chmixer.h"
#include "blackwhite.h"
#include "hlrec.h"
//#include "hlrec.h"
#include "cacorrection.h"
#include "lensprofile.h"
#include "distortion.h"
@ -97,7 +97,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
Distortion* distortion;
PerspCorrection* perspective;
CACorrection* cacorrection;
HLRecovery* hlrecovery;
// HLRecovery* hlrecovery;
ColorAppearance* colorappearance;
Vibrance* vibrance;
ChMixer* chmixer;