From 8b911d47896f000c4f9a2eb9423f054bd3ab48f0 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 3 Sep 2015 17:34:05 +0200 Subject: [PATCH] DeHaze enhancements (Desmis) and some bugfixes (heckflosse) --- rtdata/languages/default | 29 +- rtengine/curves.cc | 33 ++ rtengine/curves.h | 26 + rtengine/imagesource.h | 8 +- rtengine/improccoordinator.cc | 38 +- rtengine/improccoordinator.h | 1 + rtengine/ipdehaz.cc | 282 +++++++++-- rtengine/previewimage.cc | 3 +- rtengine/procevents.h | 6 +- rtengine/procparams.cc | 120 +++-- rtengine/procparams.h | 9 +- rtengine/rawimagesource.cc | 179 +++---- rtengine/rawimagesource.h | 8 +- rtengine/refreshmap.cc | 26 +- rtengine/simpleprocess.cc | 19 +- rtgui/dehaz.cc | 913 ++++++++++++++++++---------------- rtgui/dehaz.h | 13 +- rtgui/paramsedited.cc | 38 +- rtgui/paramsedited.h | 6 +- 19 files changed, 1100 insertions(+), 657 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 9ee60ab9b..86962a8c0 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -84,7 +84,7 @@ EXPORT_FASTEXPORTOPTIONS;Fast Export Options EXPORT_INSTRUCTIONS;Fast Export options provide overrides to bypass time and resource consuming development settings and to run queue processing using the fast export settings instead. This method is recommended for quicker generation of lower resolution images when speed is a priority or when resized output is desired for one or many images without making modifications to their saved development parameters. EXPORT_MAXHEIGHT;Maximum height: EXPORT_MAXWIDTH;Maximum width: -EXPORT_PUTTOQUEUEFAST; Put to queue for fast export +EXPORT_PUTTOQUEUEFAST; Put to queue for fast export EXPORT_RAW_DMETHOD;Demosaic method EXTPROGTARGET_1;raw EXTPROGTARGET_2;queue-processed @@ -151,7 +151,7 @@ FILEBROWSER_POPUPUNRANK;Unrank FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_QUERYBUTTONHINT;Clear the Find query FILEBROWSER_QUERYHINT;Type filenames to search for. Supports partial filenames. Separate the search terms using commas, e.g.\n1001,1004,1199\n\nExclude search terms by prefixing them with !=\ne.g.\n!=1001,1004,1199\n\nShortcuts:\nCtrl-f - focus the Find box,\nEnter - search,\nEsc - clear the Find box,\nShift-Esc - defocus the Find box. -FILEBROWSER_QUERYLABEL; Find: +FILEBROWSER_QUERYLABEL; Find: FILEBROWSER_RANK1_TOOLTIP;Rank 1 *\nShortcut: Shift-1 FILEBROWSER_RANK2_TOOLTIP;Rank 2 *\nShortcut: Shift-2 FILEBROWSER_RANK3_TOOLTIP;Rank 3 *\nShortcut: Shift-3 @@ -636,16 +636,19 @@ HISTORY_MSG_403;W - ES - Edge sensitivity HISTORY_MSG_404;W - ES - Base amplification HISTORY_MSG_405;W - Denoise - Level 4 HISTORY_MSG_406;W - ES - Neighboring pixels -HISTORY_MSG_407;Dehaze met +HISTORY_MSG_407;Dehaze method HISTORY_MSG_408;Dehaze neighboring HISTORY_MSG_409;Dehaze gain HISTORY_MSG_410;Dehaze offset HISTORY_MSG_411;Dehaze strength HISTORY_MSG_412;Dehaze scales -HISTORY_MSG_413;Dehaze var +HISTORY_MSG_413;Dehaze variance HISTORY_MSG_414;Dehaze histogram -HISTORY_MSG_415;Dehaze enabled -HISTORY_MSG_416;Dehaze transmission +HISTORY_MSG_415;Dehaze transmission +HISTORY_MSG_416;Dehaze enabled +HISTORY_MSG_417;Dehaze Retinex complete +HISTORY_MSG_418;Dehaze transmission median +HISTORY_MSG_419;Dehaze threshold HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s HISTORY_SNAPSHOTS;Snapshots @@ -728,12 +731,12 @@ MAIN_TAB_COLOR;Color MAIN_TAB_COLOR_TOOLTIP;Shortcut: Alt-c MAIN_TAB_DETAIL;Detail MAIN_TAB_DETAIL_TOOLTIP;Shortcut: Alt-d -MAIN_TAB_DEVELOP; Develop +MAIN_TAB_DEVELOP; Develop MAIN_TAB_EXIF;Exif -MAIN_TAB_EXPORT; Fast Export +MAIN_TAB_EXPORT; Fast Export MAIN_TAB_EXPOSURE;Exposure MAIN_TAB_EXPOSURE_TOOLTIP;Shortcut: Alt-e -MAIN_TAB_FILTER; Filter +MAIN_TAB_FILTER; Filter MAIN_TAB_INSPECT; Inspect MAIN_TAB_IPTC;IPTC MAIN_TAB_METADATA;Metadata @@ -1557,21 +1560,25 @@ TP_DEHAZ_LAB_TOOLTIP;Use all component of Retinex algorihm, to improve results TP_DEHAZ_LABEL;Dehaze TP_DEHAZ_SCAL;Scales TP_DEHAZ_SCAL_TOOLTIP;Low scales increase contrast but give relief effect\nHigh scales can increase noise, but give more natural images +TP_DEHAZ_LIMD;Threshold +TP_DEHAZ_LIMD_TOOLTIP;Limits in/out - in = image source - out = image Gauss +TP_DEHAZ_MEDI;Transmission median filter TP_DEHAZ_NEIGH;Neighboring pixels TP_DEHAZ_NEIGH_TOOLTIP;Take into account, neighboring pixels, by Gauss function TP_DEHAZ_GAIN;Gain TP_DEHAZ_OFFS;Offset TP_DEHAZ_GAIN_TOOLTIP;Acts on the transmission in combination with offset, this is very different from others settings\nUsed for black or white pixels, and for better balance the histogram -TP_DEHAZE_LAB;Dehaze +TP_DEHAZE_LAB;Dehaze TP_DEHAZ_CONTEDIT;Histogram equalizer TP_DEHAZ_CURVEEDITOR_CD;L=f(L) TP_DEHAZ_CURVEEDITOR_CD_TOOLTIP;Correct Raw data, to reduce halos and artifacts TP_DEHAZ_TRANSMISSION;Transmission map +TP_DEHAZ_TRANS_TOOLTIP;Modify transmission in function of transmission\nAbscissa : transmission from negatives values (min), mean, and positives values (max)\nOrdonate : amplification - reduction TP_DEHAZE_LAB_TOOLTIP;Use Retinex algorithm (Lab) to improve dehaze..defog... TP_DEHAZ_VART;Variance TP_DEHAZ_VART_TOOLTIP;Low variance increase local contrast and saturation, but can leeds to artifacts TP_DEHAZE_MET;Dehaze method -TP_DEHAZ_MET_TOOLTIP;Low :reinforce low light\nUniform :expect to equalize action\nHigh : reinforce high light +TP_DEHAZ_MET_TOOLTIP;For Retinex algorithm\nLow :reinforce low light\nUniform :expect to equalize action\nHigh : reinforce high light TP_DEHAZ_NONE;None TP_DEHAZ_UNI;Uniform TP_DEHAZ_LOW;Low diff --git a/rtengine/curves.cc b/rtengine/curves.cc index ba1be089a..accbea8dc 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -1342,6 +1342,39 @@ void ColorAppearance::Set(Curve *pCurve) } } +// +DehaztransmissionCurve::DehaztransmissionCurve() {}; + +void DehaztransmissionCurve::Reset() +{ + luttransmission.reset(); +} + +void DehaztransmissionCurve::Set(const Curve &pCurve) +{ + if (pCurve.isIdentity()) { + luttransmission.reset(); // raise this value if the quality suffers from this number of samples + return; + } + + luttransmission(501); // raise this value if the quality suffers from this number of samples + + for (int i = 0; i < 501; i++) { + luttransmission[i] = pCurve.getVal(double(i) / 500.); + } +} + +void DehaztransmissionCurve::Set(const std::vector &curvePoints) +{ + if (!curvePoints.empty() && curvePoints[0] > FCT_Linear && curvePoints[0] < FCT_Unchanged) { + FlatCurve tcurve(curvePoints, false, CURVES_MIN_POLY_POINTS / 2); + tcurve.setIdentityValue(0.); + Set(tcurve); + } else { + Reset(); + } +} + void ToneCurve::Reset() { lutToneCurve.reset(); diff --git a/rtengine/curves.h b/rtengine/curves.h index 22f0d77fa..128882eca 100644 --- a/rtengine/curves.h +++ b/rtengine/curves.h @@ -429,6 +429,32 @@ public: }; }; +class DehaztransmissionCurve +{ +private: + LUTf luttransmission; // 0xffff range + void Set(const Curve &pCurve); + +public: + virtual ~DehaztransmissionCurve() {}; + DehaztransmissionCurve(); + + void Reset(); + void Set(const Curve *pCurve); + void Set(const std::vector &curvePoints); + float operator[](float index) const + { + return luttransmission[index]; + } + + operator bool (void) const + { + return luttransmission; + } +}; + + + class ToneCurve { public: diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 0d7c32b52..de4bdbe8d 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -69,15 +69,17 @@ public: virtual int load (Glib::ustring fname, bool batch = false) = 0; virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse) {}; virtual void demosaic (const RAWParams &raw) {}; - virtual void dehaz (RAWParams raw, ColorManagementParams cmp, DehazParams lcur, LUTf & cdcurve, bool dehacontlutili) {}; +// virtual void // dehaz (RAWParams raw, ColorManagementParams cmp, DehazParams lcur, LUTf & cdcurve, bool dehacontlutili) {}; + virtual void dehaz (RAWParams raw, ColorManagementParams cmp, DehazParams deh, LUTf & cdcurve, const DehaztransmissionCurve & dehatransmissionCurve, bool dehacontlutili) {}; virtual void flushRawData () {}; virtual void flushRGB () {}; virtual void HLRecovery_Global (ToneCurveParams hrp) {}; virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; - virtual void MSR(LabImage* lab, int width, int height, int skip, DehazParams lcur) {}; +// virtual void MSR(LabImage* lab, int width, int height, int skip, DehazParams lcur) {}; + virtual void MSR(LabImage* lab, int width, int height, int skip, DehazParams deh, const DehaztransmissionCurve & dehatransmissionCurve) {}; virtual bool IsrgbSourceModified() = 0; // tracks whether cached rgb output of demosaic has been modified - // virtual void MSR(LabImage* lab, int width, int height, int skip, const LCurveParams &lcur); + // virtual void MSR(LabImage* lab, int width, int height, int skip, const LCurveParams &lcur); // 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, ToneCurveParams hlp, ColorManagementParams cmp, RAWParams raw) {} diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index fdcb8bf27..4c329c550 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -166,6 +166,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) RAWParams rp = params.raw; ColorManagementParams cmp = params.icm; LCurveParams lcur = params.labCurve; + if( !highDetailNeeded ) { // if below 100% magnification, take a fast path if(rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::none] && rp.bayersensor.method != RAWParams::BayerSensor::methodstring[RAWParams::BayerSensor::mono]) { @@ -208,11 +209,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) OR HLR gets disabled when Color method was selected */ // If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST - - //I forced dehazmet with toneCurve.hrenabled=true==> probably another way ?? - - bool hrdehaz=false; - if(!params.toneCurve.hrenabled) if(params.dehaz.enabled) {hrdehaz=true; params.toneCurve.hrenabled=true;} if ( (todo & M_RAW) || (!highDetailRawComputed && highDetailNeeded) @@ -228,7 +224,6 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } imgsrc->demosaic( rp);//enabled demosaic - if (highDetailNeeded) { highDetailRawComputed = true; @@ -239,18 +234,17 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) } else { highDetailRawComputed = false; } + + if (params.dehaz.enabled) { + bool dehacontlutili = false; + CurveFactory::curveDehaContL (dehacontlutili, params.dehaz.cdcurve, cdcurve, 1); + DehazParams DehaParams = params.dehaz; + DehaParams.getCurves(dehatransmissionCurve); + imgsrc->dehaz( params.raw, params.icm, params.dehaz, cdcurve, dehatransmissionCurve, dehacontlutili);//enabled Dehaze + + } } - bool dehacontlutili=false; - CurveFactory::curveDehaContL (dehacontlutili, params.dehaz.cdcurve, cdcurve, 1); - - if (todo & M_INIT || params.dehaz.enabled){ - if(params.dehaz.enabled) - imgsrc->dehaz( params.raw, params.icm, params.dehaz, cdcurve, dehacontlutili);//enabled Dehaze - - } - if(hrdehaz==true) params.toneCurve.hrenabled=false; - - + // Updating toneCurve.hrenabled if necessary // It has to be done there, because the next 'if' statement will use the value computed here if (todo & M_AUTOEXP) { @@ -267,9 +261,9 @@ 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.toneCurve); // 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"); @@ -314,7 +308,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) imgsrc->getImage (currWB, tr, orig_prev, pp, params.toneCurve, params.icm, params.raw); //ColorTemp::CAT02 (orig_prev, ¶ms) ; - // printf("orig_prevW=%d\n scale=%d",orig_prev->width, scale); + // printf("orig_prevW=%d\n scale=%d",orig_prev->width, scale); /* Issue 2785, disabled some 1:1 tools if (todo & M_LINDENOISE) { DirPyrDenoiseParams denoiseParams = params.dirpyrDenoise; @@ -596,7 +590,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) nprevl->CopyFrom(oprevl); progress ("Applying Color Boost...", 100 * readyphase / numofphases); - // ipf.MSR(nprevl, nprevl->W, nprevl->H, 1); + // ipf.MSR(nprevl, nprevl->W, nprevl->H, 1); ipf.chromiLuminanceCurve (NULL, pW, nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, histCCurve, histCLurve, histLLCurve, histLCurve); ipf.vibrance(nprevl); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index cce71995e..0c2f8f459 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -129,6 +129,7 @@ protected: WavOpacityCurveBY waOpacityCurveBY; WavOpacityCurveW waOpacityCurveW; WavOpacityCurveWL waOpacityCurveWL; + DehaztransmissionCurve dehatransmissionCurve; ColorAppearance customColCurve1; ColorAppearance customColCurve2; diff --git a/rtengine/ipdehaz.cc b/rtengine/ipdehaz.cc index 66e3789f5..6b922e503 100644 --- a/rtengine/ipdehaz.cc +++ b/rtengine/ipdehaz.cc @@ -34,9 +34,19 @@ #include "improcfun.h" #include "opthelper.h" #include "StopWatch.h" -#define MAX_DEHAZE_SCALES 6 +#define MAX_DEHAZE_SCALES 8 #define clipdehaz( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) +#define med3(a0,a1,a2,a3,a4,a5,a6,a7,a8,median) { \ +pp[0]=a0; pp[1]=a1; pp[2]=a2; pp[3]=a3; pp[4]=a4; pp[5]=a5; pp[6]=a6; pp[7]=a7; pp[8]=a8; \ +PIX_SORT(pp[1],pp[2]); PIX_SORT(pp[4],pp[5]); PIX_SORT(pp[7],pp[8]); \ +PIX_SORT(pp[0],pp[1]); PIX_SORT(pp[3],pp[4]); PIX_SORT(pp[6],pp[7]); \ +PIX_SORT(pp[1],pp[2]); PIX_SORT(pp[4],pp[5]); PIX_SORT(pp[7],pp[8]); \ +PIX_SORT(pp[0],pp[3]); PIX_SORT(pp[5],pp[8]); PIX_SORT(pp[4],pp[7]); \ +PIX_SORT(pp[3],pp[6]); PIX_SORT(pp[1],pp[4]); PIX_SORT(pp[2],pp[5]); \ +PIX_SORT(pp[4],pp[7]); PIX_SORT(pp[4],pp[2]); PIX_SORT(pp[6],pp[4]); \ +PIX_SORT(pp[4],pp[2]); median=pp[4];} //pp4 = median + namespace rtengine { @@ -44,7 +54,7 @@ extern const Settings* settings; static float DehazeScales[MAX_DEHAZE_SCALES]; -void dehaze_scales( float* scales, int nscales, int mode, int s) +void dehaze_scales( float* scales, int nscales, int mode, int s) { if ( nscales == 1 ) { scales[0] = (float)s / 2.f; @@ -73,24 +83,103 @@ void dehaze_scales( float* scales, int nscales, int mode, int s) } } } - -void mean_stddv( float **dst, float &mean, float &stddv, int W_L, int H_L, const float factor ) +void mean_stddv2( float **dst, float &mean, float &stddv, int W_L, int H_L, float &maxtr, float &mintr) { // summation using double precision to avoid too large summation error for large pictures double vsquared = 0.f; double sum = 0.f; - + maxtr = -999999.f; + mintr = 999999.f; #ifdef _OPENMP - #pragma omp parallel for reduction(+:sum,vsquared) // this can lead to differences, but parallel summation is more accurate + #pragma omp parallel +#endif + { + float lmax = -999999.f, lmin = 999999.f; +#ifdef _OPENMP + #pragma omp for reduction(+:sum,vsquared) nowait // this leads to differences, but parallel summation is more accurate #endif - for (int i = 0; i < H_L; i++ ) - for (int j = 0; j < W_L; j++) { - sum += dst[i][j]; - vsquared += (dst[i][j] * dst[i][j]); + for (int i = 0; i < H_L; i++ ) + for (int j = 0; j < W_L; j++) { + sum += dst[i][j]; + vsquared += (dst[i][j] * dst[i][j]); + + if ( dst[i][j] > lmax) { + lmax = dst[i][j] ; + } + + if ( dst[i][j] < lmin) { + lmin = dst[i][j] ; + } + + } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + maxtr = maxtr > lmax ? maxtr : lmax; + mintr = mintr < lmin ? mintr : lmin; } + } + mean = sum / (double) (W_L * H_L); + vsquared /= (double) W_L * H_L; + stddv = ( vsquared - (mean * mean) ); + stddv = (float)sqrt(stddv); +} + + + + + + +void mean_stddv( float **dst, float &mean, float &stddv, int W_L, int H_L, const float factor, float &maxtr, float &mintr) + +{ + // summation using double precision to avoid too large summation error for large pictures + double vsquared = 0.f; + double sum = 0.f; + maxtr = 0.f; + mintr = 0.f; +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float lmax = 0.f, lmin = 0.f; + +#ifdef _OPENMP + #pragma omp for reduction(+:sum,vsquared) // this can lead to differences, but parallel summation is more accurate +#endif + + for (int i = 0; i < H_L; i++ ) + for (int j = 0; j < W_L; j++) { + sum += dst[i][j]; + vsquared += (dst[i][j] * dst[i][j]); + + if ( dst[i][j] > lmax) { + lmax = dst[i][j] ; + } + + if ( dst[i][j] < lmin) { + lmin = dst[i][j] ; + } + + } + +#ifdef _OPENMP + #pragma omp critical +#endif + { + maxtr = maxtr > lmax ? maxtr : lmax; + mintr = mintr < lmin ? mintr : lmin; + } + + } + sum *= factor; + maxtr *= factor; + mintr *= factor; vsquared *= (factor * factor); mean = sum / (float) (W_L * H_L); vsquared /= (float) W_L * H_L; @@ -98,27 +187,31 @@ void mean_stddv( float **dst, float &mean, float &stddv, int W_L, int H_L, const stddv = (float)sqrt(stddv); } -void RawImageSource::MSR(float** luminance, float** originalLuminance, int width, int height, DehazParams lcur) +void RawImageSource::MSR(float** luminance, float** originalLuminance, int width, int height, DehazParams deh, const DehaztransmissionCurve & dehatransmissionCurve) { - if (lcur.enabled) {//enabled + if (deh.enabled) {//enabled StopWatch Stop1("MSR"); - float mean, stddv; + float mean, stddv, maxtr, mintr; float mini, delta, maxi; float eps = 2.f; - float gain2 = (float) lcur.gain / 100.f; //def =1 not use - float offse = (float) lcur.offs; //def = 0 not use - int scal = lcur.scal; //def=3 - int nei = (int) 2.5f * lcur.neigh; //def = 200 - float vart = (float)lcur.vart / 100.f;//variance - float strength = (float) lcur.str / 100.f; // Blend with original L channel data + float gain2 = (float) deh.gain / 100.f; //def =1 not use + float offse = (float) deh.offs; //def = 0 not use + int scal = deh.scal; //def=3 + int nei = (int) 2.8f * deh.neigh; //def = 220 + float vart = (float)deh.vart / 100.f;//variance + float strength = (float) deh.str / 100.f; // Blend with original L channel data + float limD = (float) deh.limd; + limD = pow(limD, 1.7f);//about 2500 enough + float ilimD = 1.f / limD; - int modedehaz = 0; // default to 0 ( lcur.dehazmet == "uni" ) + int modedehaz = 0; // default to 0 ( deh.dehazmet == "uni" ) + bool execcur = false; - if (lcur.dehazmet == "low") { + if (deh.dehazmet == "low") { modedehaz = 1; } - if (lcur.dehazmet == "high") { + if (deh.dehazmet == "high") { modedehaz = 2; } @@ -157,22 +250,23 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, int width #pragma omp parallel #endif { - AlignedBufferMP* pBuffer = new AlignedBufferMP (max(W_L, H_L)); + AlignedBufferMP* pBuffer = new AlignedBufferMP (max(W_L, H_L)); - for ( int scale = 0; scale < scal; scale++ ) { + for ( int scale = 0; scale < scal; scale++ ) { gaussHorizontal (src, out, *pBuffer, W_L, H_L, DehazeScales[scale]); gaussVertical (out, out, *pBuffer, W_L, H_L, DehazeScales[scale]); + #ifdef __SSE2__ vfloat pondv = F2V(pond); - vfloat limMinv = F2V(0.0001f); - vfloat limMaxv = F2V(10000.f); + vfloat limMinv = F2V(ilimD); + vfloat limMaxv = F2V(limD); + #endif #ifdef _OPENMP #pragma omp for #endif - for (int i = 0; i < H_L; i++) - { + for (int i = 0; i < H_L; i++) { int j = 0; #ifdef __SSE2__ @@ -183,10 +277,11 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, int width #endif for (; j < W_L; j++) { - luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], 0.0001f, 10000.f)); + luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimD, limD)); } } } + delete pBuffer; } @@ -195,14 +290,136 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, int width float logBetaGain = xlogf(16384.f); + if (dehatransmissionCurve) { + execcur = true; + } + +//I re-execute luminance[i][j] = logBetaGain * luminance[i][j] because I call 2 times (or one) mean_stdvv +// no difference or very little in time +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = 0; i < H_L; i++ ) + for (int j = 0; j < W_L; j++) { + luminance[i][j] = logBetaGain * luminance[i][j]; + } + mean = 0.f; stddv = 0.f; - mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain); + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + + mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr); +// printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr); + + // mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr); + if (execcur) { //if curve + float asig = 0.166666f / stddv; + float bsig = 0.5f - asig * mean; + //float insigma = 0.66666f; //SD + float amean = 0.5f / mean; + float asign = 0.166666f / stddv; + float bsign = 0.5f - asign * mean; + float amax = 0.333333f / (maxtr - mean - stddv); + float bmax = 1.f - amax * maxtr; + float amin = 0.333333f / (mean - stddv - mintr); + float bmin = -amin * mintr; + +#ifdef _OPENMP + #pragma omp parallel +#endif + { + float absciss; +#ifdef _OPENMP + #pragma omp for schedule(dynamic,16) +#endif + + for (int i = 0; i < H_L; i++ ) + for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission + if (luminance[i][j] >= mean && luminance[i][j] < mean + stddv) { + absciss = asig * luminance[i][j] + bsig; + } else if (luminance[i][j] >= mean + stddv) { + absciss = amax * luminance[i][j] + bmax; + } else if (/*luminance[i][j] < mean && */luminance[i][j] > mean - stddv) { + absciss = asign * luminance[i][j] + bsign; + } else { /*if(luminance[i][j] <= mean - stddv)*/ + absciss = amin * luminance[i][j] + bmin; + } + + float kmul = 2.5f; + float kinterm = 1.f + kmul * (dehatransmissionCurve[absciss * 500.f] - 0.5f); //new transmission + luminance[i][j] *= kinterm; +// luminance[i][j] *= 1.000001f; + } + } + + // median filter on transmission ==> reduce artifacts + if (deh.medianmap) { + int wid = W_L; + int hei = H_L; + float *tmL[hei] ALIGNED16; + float *tmLBuffer = new float[wid * hei]; + int borderL = 1; + + for (int i = 0; i < hei; i++) { + tmL[i] = &tmLBuffer[i * wid]; + } + + /* + for(int i = borderL; i < hei - borderL; i++ ) { + for(int j = borderL; j < wid - borderL; j++) { + tmL[i][j] = luminance[i][j]; + } + } + */ +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = borderL; i < hei - borderL; i++) { + float pp[9], temp; + + for (int j = borderL; j < wid - borderL; j++) { + med3(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1], tmL[i][j]); //3x3 + } + } + +#ifdef _OPENMP + #pragma omp parallel for +#endif + + for (int i = borderL; i < hei - borderL; i++ ) { + for (int j = borderL; j < wid - borderL; j++) { + luminance[i][j] = tmL[i][j]; + } + } + + delete [] tmLBuffer; + + } + + // I call mean_stddv2 instead of mean_stddv ==> logBetaGain + // mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr); + mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr); + + } + + float epsil = 0.1f; mini = mean - vart * stddv; + + if (mini < mintr) { + mini = mintr + epsil; + } + maxi = mean + vart * stddv; + + if (maxi > maxtr) { + maxi = maxtr - epsil; + } + delta = maxi - mini; - printf("maxi=%f mini=%f mean=%f std=%f delta=%f\n", maxi, mini, mean, stddv, delta); + printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr); if ( !delta ) { delta = 1.0f; @@ -215,7 +432,8 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, int width for ( int i = 0; i < H_L; i ++ ) for (int j = 0; j < W_L; j++) { - float cd = cdfactor * ( luminance[i][j] * logBetaGain - mini ) + offse; + // float cd = cdfactor * ( luminance[i][j] * logBetaGain - mini ) + offse; + float cd = cdfactor * ( luminance[i][j] - mini ) + offse; luminance[i][j] = clipdehaz( cd, 0.f, 32768.f ) * strength + (1.f - strength) * originalLuminance[i][j]; } } diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index d68ce3229..5f7ea8ad6 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -122,7 +122,7 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext const unsigned char *data = NULL; int fw, fh; LUTf cdcurve; - bool dehacontlutili=false; + bool dehacontlutili = false; procparams::ProcParams params; /*rtengine::RAWParams raw; @@ -140,7 +140,6 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext params.raw.xtranssensor.method = RAWParams::XTransSensor::methodstring[RAWParams::XTransSensor::fast]; rawImage.preprocess(params.raw, params.lensProf, params.coarse); rawImage.demosaic(params.raw); - rawImage.dehaz(params.raw, params.icm, params.dehaz, cdcurve, dehacontlutili); Imagefloat* image = new rtengine::Imagefloat (fw, fh); rawImage.getImage (wb, TR_NONE, image, pp, params.toneCurve, params.icm, params.raw); output = new Image8(fw, fh); diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 0c890d11d..c61782da5 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -439,11 +439,13 @@ enum ProcEvent { EvLstr = 410, EvLscal = 411, EvLvart = 412, - EvLCDCurve = 413, + EvLCDCurve = 413, EvDehaztransmission = 414, EvDehazEnabled = 415, EvDehazretinex = 416, - + EvDehazmedianmap = 417, + EvLlimd = 418, + NUMOFEVENTS }; } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 58668db0d..3b40dd949 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -123,12 +123,17 @@ DehazParams::DehazParams () void DehazParams::getDefaulttransmissionCurve(std::vector &curve) { - double v[16] = { 0.00, 0.3, 0.35, 0.00, - 0.25, 0.5, 0.35, 0.35, - 0.70, 0.5, 0.35, 0.35, - 1.00, 0.7, 0.00, 0.00 - }; - curve.resize(17); + /* double v[8] = { 0.0, 0.50, 0.35, 0.35, + 1.0, 0.50, 0.35, 0.35, + }; + */ + double v[12] = { 0.00, 0.25, 0.35, 0.35, + 0.60, 0.90, 0.35, 0.35, + 1.00, 0.50, 0.35, 0.35, + }; + + + curve.resize(13); curve.at(0 ) = double(FCT_MinMaxCPoints); for (size_t i = 1; i < curve.size(); ++i) { @@ -139,12 +144,12 @@ void DehazParams::getDefaulttransmissionCurve(std::vector &curve) void DehazParams::getDefaultCDCurve(std::vector &curve) { double v[12] = { 0.00, 0.00, - 0.185, 0., - 0.235, 0.25, - 0.5, 0.5, - 0.8, 0.8, - 1.0, 1.0, - }; + 0.185, 0., + 0.235, 0.25, + 0.5, 0.5, + 0.8, 0.8, + 1.0, 1.0, + }; curve.resize(13); curve.at(0) = double(DCT_NURBS); @@ -163,16 +168,19 @@ void DehazParams::setDefaults() gain = 100; offs = 0; vart = 125; + limd = 8; getDefaulttransmissionCurve(transmissionCurve); getDefaultCDCurve(cdcurve); dehazmet = "uni"; retinex = false; + medianmap = true; + } -//void DehazParams::getCurves(transmissionCurve &transmissionCurveLUT) const -//{ - // opacityCurveLUT.Set(this->opacityCurve); -//} +void DehazParams::getCurves(DehaztransmissionCurve &transmissionCurveLUT) const +{ + transmissionCurveLUT.Set(this->transmissionCurve); +} ColorToningParams::ColorToningParams () : hlColSat(60, 80, false), shadowsColSat(80, 208, false) @@ -1438,48 +1446,63 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol } //save dehaz - + if (!pedited || pedited->dehaz.str) { keyFile.set_integer ("Dehaz", "Str", dehaz.str); } + if (!pedited || pedited->dehaz.scal) { keyFile.set_integer ("Dehaz", "Scal", dehaz.scal); } + if (!pedited || pedited->dehaz.enabled) { keyFile.set_boolean ("Dehaz", "Enabled", dehaz.enabled); } - + if (!pedited || pedited->dehaz.retinex) { keyFile.set_boolean ("Dehaz", "Retinex", dehaz.retinex); } + if (!pedited || pedited->dehaz.medianmap) { + keyFile.set_boolean ("Dehaz", "Median", dehaz.medianmap); + } + + + if (!pedited || pedited->dehaz.neigh) { keyFile.set_integer ("Dehaz", "Neigh", dehaz.neigh); } + if (!pedited || pedited->dehaz.gain) { keyFile.set_integer ("Dehaz", "Gain", dehaz.gain); } + if (!pedited || pedited->dehaz.offs) { - keyFile.set_integer ("Dehaz","Offs", dehaz.offs); + keyFile.set_integer ("Dehaz", "Offs", dehaz.offs); } + if (!pedited || pedited->dehaz.vart) { - keyFile.set_integer ("Dehaz","Vart", dehaz.vart); + keyFile.set_integer ("Dehaz", "Vart", dehaz.vart); } - + + if (!pedited || pedited->dehaz.limd) { + keyFile.set_integer ("Dehaz", "Limd", dehaz.limd); + } + if (!pedited || pedited->dehaz.dehazmet) { - keyFile.set_string ("Dehaz", "Dehazmet",dehaz.dehazmet); + keyFile.set_string ("Dehaz", "Dehazmet", dehaz.dehazmet); } - + if (!pedited || pedited->dehaz.cdcurve) { Glib::ArrayHandle cdcurve = dehaz.cdcurve; keyFile.set_double_list("Dehaz", "CDCurve", cdcurve); } - + if (!pedited || pedited->dehaz.transmissionCurve) { Glib::ArrayHandle transmissionCurve = dehaz.transmissionCurve; keyFile.set_double_list("Dehaz", "TransmissionCurve", transmissionCurve); } - + // save channel mixer if (!pedited || pedited->chmixer.red[0] || pedited->chmixer.red[1] || pedited->chmixer.red[2]) { Glib::ArrayHandle rmix (chmixer.red, 3, Glib::OWNERSHIP_NONE); @@ -1691,6 +1714,7 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol Glib::ArrayHandle lccurve = labCurve.lccurve; keyFile.set_double_list("Luminance Curve", "LcCurve", lccurve); } + if (!pedited || pedited->labCurve.clcurve) { Glib::ArrayHandle clcurve = labCurve.clcurve; keyFile.set_double_list("Luminance Curve", "ClCurve", clcurve); @@ -3736,9 +3760,10 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } } + //load dehaz if (keyFile.has_group ("Dehaz")) { - + if (keyFile.has_key ("Dehaz", "Retinex")) { dehaz.retinex = keyFile.get_boolean ("Dehaz", "Retinex"); @@ -3746,7 +3771,15 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.retinex = true; } } - + + if (keyFile.has_key ("Dehaz", "Median")) { + dehaz.medianmap = keyFile.get_boolean ("Dehaz", "Median"); + + if (pedited) { + pedited->dehaz.medianmap = true; + } + } + if (keyFile.has_key ("Dehaz", "Dehazmet")) { dehaz.dehazmet = keyFile.get_string ("Dehaz", "Dehazmet"); @@ -3754,20 +3787,23 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.dehazmet = true; } } - if (keyFile.has_key ("Dehaz", "Enabled")) { + + if (keyFile.has_key ("Dehaz", "Enabled")) { dehaz.enabled = keyFile.get_boolean ("Dehaz", "Enabled"); + if (pedited) { pedited->dehaz.enabled = true; } } - - if (keyFile.has_key ("Dehaz", "Neigh")) { + + if (keyFile.has_key ("Dehaz", "Neigh")) { dehaz.neigh = keyFile.get_integer ("Dehaz", "Neigh"); if (pedited) { pedited->dehaz.neigh = true; } } + if (keyFile.has_key ("Dehaz", "Str")) { dehaz.str = keyFile.get_integer ("Dehaz", "Str"); @@ -3775,6 +3811,7 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.str = true; } } + if (keyFile.has_key ("Dehaz", "Scal")) { dehaz.scal = keyFile.get_integer ("Dehaz", "Scal"); @@ -3790,6 +3827,7 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.gain = true; } } + if (keyFile.has_key ("Dehaz", "Offs")) { dehaz.offs = keyFile.get_integer ("Dehaz", "Offs"); @@ -3797,6 +3835,7 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.offs = true; } } + if (keyFile.has_key ("Dehaz", "Vart")) { dehaz.vart = keyFile.get_integer ("Dehaz", "Vart"); @@ -3804,7 +3843,15 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.vart = true; } } - + + if (keyFile.has_key ("Dehaz", "Limd")) { + dehaz.limd = keyFile.get_integer ("Dehaz", "Limd"); + + if (pedited) { + pedited->dehaz.limd = true; + } + } + if (keyFile.has_key ("Dehaz", "CDCurve")) { dehaz.cdcurve = keyFile.get_double_list ("Dehaz", "CDCurve"); @@ -3812,6 +3859,7 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->dehaz.cdcurve = true; } } + if (keyFile.has_key ("Dehaz", "TransmissionCurve")) { dehaz.transmissionCurve = keyFile.get_double_list ("Dehaz", "TransmissionCurve"); @@ -3820,8 +3868,8 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) } } } - - + + // load luma curve if (keyFile.has_group ("Luminance Curve")) { if (keyFile.has_key ("Luminance Curve", "Brightness")) { @@ -3839,6 +3887,7 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->labCurve.contrast = true; } } + if (ppVersion < 303) { // transform Saturation into Chromaticity // if Saturation == 0, should we set BWToning on? @@ -3953,6 +4002,7 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited) pedited->labCurve.lhcurve = true; } } + if (keyFile.has_key ("Luminance Curve", "hhCurve")) { labCurve.hhcurve = keyFile.get_double_list ("Luminance Curve", "hhCurve"); @@ -7185,11 +7235,13 @@ bool ProcParams::operator== (const ProcParams& other) && dehaz.scal == other.dehaz.scal && dehaz.neigh == other.dehaz.neigh && dehaz.gain == other.dehaz.gain + && dehaz.limd == other.dehaz.limd && dehaz.offs == other.dehaz.offs && dehaz.dehazmet == other.dehaz.dehazmet && dehaz.vart == other.dehaz.vart + && dehaz.medianmap == other.dehaz.medianmap && dehaz.enabled == other.dehaz.enabled - && dehaz.retinex == other.dehaz.retinex + && dehaz.retinex == other.dehaz.retinex && labCurve.lcurve == other.labCurve.lcurve && labCurve.acurve == other.labCurve.acurve && labCurve.bcurve == other.labCurve.bcurve diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 82fb2fc4d..cd9201e50 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -38,6 +38,7 @@ class WavOpacityCurveRG; class WavOpacityCurveBY; class WavOpacityCurveW; class WavOpacityCurveWL; +class DehaztransmissionCurve; namespace procparams { @@ -276,14 +277,16 @@ public: int offs; Glib::ustring dehazmet; int vart; + int limd; + bool medianmap; bool retinex; DehazParams (); - void setDefaults(); - // void getCurves(transmissionCurve &transmissionCurveLUT) const; + void setDefaults(); + void getCurves(DehaztransmissionCurve &transmissionCurveLUT) const; static void getDefaulttransmissionCurve(std::vector &curve); static void getDefaultCDCurve(std::vector &curve); - + }; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index ce945a605..c5a72e6dc 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1800,124 +1800,127 @@ void RawImageSource::demosaic(const RAWParams &raw) } } -void RawImageSource::dehaz(RAWParams raw, ColorManagementParams cmp, DehazParams lcur, LUTf & cdcurve, bool dehacontlutili) +void RawImageSource::dehaz(RAWParams raw, ColorManagementParams cmp, DehazParams deh, LUTf & cdcurve, const DehaztransmissionCurve & dehatransmissionCurve, bool dehacontlutili) { MyTime t4, t5; t4.set(); - if(!rgbSourceModified) { - if (settings->verbose) { - printf ("Applying DeHaze\n"); - } + if (settings->verbose) { + printf ("Applying DeHaze\n"); + } - TMatrix wprof = iccStore->workingSpaceMatrix (cmp.working); - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (cmp.working); + TMatrix wprof = iccStore->workingSpaceMatrix (cmp.working); + TMatrix wiprof = iccStore->workingSpaceInverseMatrix (cmp.working); - 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]} - }; + 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]} + }; - 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]} - }; + 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]} + }; - // We need a buffer with original L data to allow correct blending - // red, green and blue still have original size of raw, but we can't use the borders - const int HNew = H-2*border; - const int WNew = W-2*border; + // We need a buffer with original L data to allow correct blending + // red, green and blue still have original size of raw, but we can't use the borders + const int HNew = H - 2 * border; + const int WNew = W - 2 * border; - LabImage * labdeha = new LabImage(WNew, HNew); + LabImage * labdeha = new LabImage(WNew, HNew); - float *labTmp[HNew] ALIGNED16; - float *labTmpBuffer = new float[HNew * WNew]; - for (int i = 0; i < HNew; i++) { - labTmp[i] = &labTmpBuffer[i * WNew]; - } + float *labTmp[HNew] ALIGNED16; + float *labTmpBuffer = new float[HNew * WNew]; - // Conversion rgb -> lab is hard to vectorize because it uses a lut (that's not the main problem) - // and it uses a condition inside XYZ2Lab which is almost impossible to vectorize without making it slower... + for (int i = 0; i < HNew; i++) { + labTmp[i] = &labTmpBuffer[i * WNew]; + } + + // Conversion rgb -> lab is hard to vectorize because it uses a lut (that's not the main problem) + // and it uses a condition inside XYZ2Lab which is almost impossible to vectorize without making it slower... #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int i = border; i < H - border; i++ ) - for (int j = border; j < W - border; j++) { - float X, Y, Z, L, aa, bb; - //rgb=>lab - Color::rgbxyz(red[i][j], green[i][j], blue[i][j], X, Y, Z, wp); - //convert Lab - Color::XYZ2Lab(X, Y, Z, L, aa, bb); - labTmp[i-border][j-border] = L; - if(dehacontlutili) { - L = cdcurve[L]; //apply curve to equalize histogram - } - labdeha->L[i-border][j-border] = L; - labdeha->a[i-border][j-border] = aa; - labdeha->b[i-border][j-border] = bb; + for (int i = border; i < H - border; i++ ) + for (int j = border; j < W - border; j++) { + float X, Y, Z, L, aa, bb; + //rgb=>lab + Color::rgbxyz(red[i][j], green[i][j], blue[i][j], X, Y, Z, wp); + //convert Lab + Color::XYZ2Lab(X, Y, Z, L, aa, bb); + labTmp[i - border][j - border] = L; + + if(dehacontlutili) { + L = cdcurve[L]; //apply curve to equalize histogram } - MSR(labdeha->L, labTmp, WNew, HNew, lcur); + labdeha->L[i - border][j - border] = L; + labdeha->a[i - border][j - border] = aa; + labdeha->b[i - border][j - border] = bb; + } - delete [] labTmpBuffer; + MSR(labdeha->L, labTmp, WNew, HNew, deh, dehatransmissionCurve); + + delete [] labTmpBuffer; #ifdef __SSE2__ - vfloat wipv[3][3]; + vfloat wipv[3][3]; - for(int i = 0; i < 3; i++) - for(int j = 0; j < 3; j++) { - wipv[i][j] = F2V(wiprof[i][j]); - } + for(int i = 0; i < 3; i++) + for(int j = 0; j < 3; j++) { + wipv[i][j] = F2V(wiprof[i][j]); + } #endif // __SSE2__ #ifdef _OPENMP - #pragma omp parallel for + #pragma omp parallel for #endif - for (int i = border; i < H - border; i++ ) { - int j = border; + + for (int i = border; i < H - border; i++ ) { + int j = border; #ifdef __SSE2__ - for (; j < W - border - 3; j += 4) { - vfloat L2, a2, b2, x_, y_, z_; - vfloat R, G, B; - L2 = LVFU(labdeha->L[i-border][j-border]); - a2 = LVFU(labdeha->a[i-border][j-border]); - b2 = LVFU(labdeha->b[i-border][j-border]); - Color::Lab2XYZ(L2, a2, b2, x_, y_, z_) ; - Color::xyz2rgb(x_, y_, z_, R, G, B, wipv); - _mm_storeu_ps(&red[i][j], R); - _mm_storeu_ps(&green[i][j], G); - _mm_storeu_ps(&blue[i][j], B); - } + for (; j < W - border - 3; j += 4) { + vfloat L2, a2, b2, x_, y_, z_; + vfloat R, G, B; + L2 = LVFU(labdeha->L[i - border][j - border]); + a2 = LVFU(labdeha->a[i - border][j - border]); + b2 = LVFU(labdeha->b[i - border][j - border]); + Color::Lab2XYZ(L2, a2, b2, x_, y_, z_) ; + Color::xyz2rgb(x_, y_, z_, R, G, B, wipv); + _mm_storeu_ps(&red[i][j], R); + _mm_storeu_ps(&green[i][j], G); + _mm_storeu_ps(&blue[i][j], B); + } + #endif - for (; j < W - border; j++) { - float L2, a2, b2, x_, y_, z_; - float R, G, B; - L2 = labdeha->L[i-border][j-border]; - a2 = labdeha->a[i-border][j-border]; - b2 = labdeha->b[i-border][j-border]; - Color::Lab2XYZ(L2, a2, b2, x_, y_, z_) ; - Color::xyz2rgb(x_, y_, z_, R, G, B, wip); - red[i][j] = R; - green[i][j] = G; - blue[i][j] = B; - } + + for (; j < W - border; j++) { + float L2, a2, b2, x_, y_, z_; + float R, G, B; + L2 = labdeha->L[i - border][j - border]; + a2 = labdeha->a[i - border][j - border]; + b2 = labdeha->b[i - border][j - border]; + Color::Lab2XYZ(L2, a2, b2, x_, y_, z_) ; + Color::xyz2rgb(x_, y_, z_, R, G, B, wip); + red[i][j] = R; + green[i][j] = G; + blue[i][j] = B; } - - delete labdeha; - - t5.set(); - - if( settings->verbose ) { - printf("Dehaz=%d usec\n", t5.etime(t4)); - } - - rgbSourceModified = true; } + + delete labdeha; + + t5.set(); + + if( settings->verbose ) { + printf("Dehaz=%d usec\n", t5.etime(t4)); + } + } void RawImageSource::flushRawData() diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 2cd472de5..1fd858a17 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -151,7 +151,8 @@ public: int load (Glib::ustring fname, bool batch = false); void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse); void demosaic (const RAWParams &raw); - void dehaz (RAWParams raw, ColorManagementParams cmp, DehazParams lcur, LUTf & cdcurve, bool dehacontlutili); +// void dehaz (RAWParams raw, ColorManagementParams cmp, DehazParams lcur, LUTf & cdcurve, bool dehacontlutili); + void dehaz (RAWParams raw, ColorManagementParams cmp, DehazParams deh, LUTf & cdcurve, const DehaztransmissionCurve & dehatransmissionCurve, bool dehacontlutili); void flushRawData (); void flushRGB (); void HLRecovery_Global (ToneCurveParams hrp); @@ -227,7 +228,8 @@ public: void boxblur2(float** src, float** dst, int H, int W, int box ); void boxblur_resamp(float **src, float **dst, int H, int W, int box, int samp ); - void MSR(float** luminance, float **originalLuminance, int width, int height, DehazParams lcur); + void MSR(float** luminance, float **originalLuminance, int width, int height, DehazParams deh, const DehaztransmissionCurve & dehatransmissionCurve); +// void MSR(LabImage* lab, int width, int height, int skip, DehazParams deh, const DehaztransmissionCurve & dehatransmissionCurve); //void boxblur_resamp(float **red, float **green, float **blue, int H, int W, float thresh[3], float max[3], // multi_array2D & hfsize, multi_array2D & hilite, int box ); @@ -273,7 +275,7 @@ protected: void jdl_interpolate_omp(); void igv_interpolate(int winw, int winh); void lmmse_interpolate_omp(int winw, int winh, int iterations); - // void MSR(LabImage* lab, int width, int height, int skip, const LCurveParams &lcur); +// void MSR(LabImage* lab, int width, int height, int skip, const LCurveParams &lcur); void amaze_demosaic_RT(int winx, int winy, int winw, int winh);//Emil's code for AMaZE void fast_demosaic(int winx, int winy, int winw, int winh );//Emil's code for fast demosaicing diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index aa1cad0f7..f368b42d4 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -428,18 +428,20 @@ int refreshmap[rtengine::NUMOFEVENTS] = { DIRPYREQUALIZER, // EvWavedgeampli DIRPYREQUALIZER, //EvWavlev3nois DIRPYREQUALIZER, //EvWavNPmet - ALLNORAW, // Evdehazmet - ALLNORAW, // EvLneigh - ALLNORAW, // EvLgain - ALLNORAW, // EvLoffs - ALLNORAW, // EvLstr - ALLNORAW, // EvLscal - ALLNORAW, // EvLvart - ALLNORAW, // EvLCDCurve - ALLNORAW, // EvDehazOpacity - ALLNORAW, // EvDehazEnabled - ALLNORAW // EvDehazretinex - + DEMOSAIC, // Evdehazmet + DEMOSAIC, // EvLneigh + DEMOSAIC, // EvLgain + DEMOSAIC, // EvLoffs + DEMOSAIC, // EvLstr + DEMOSAIC, // EvLscal + DEMOSAIC, // EvLvart + DEMOSAIC, // EvLCDCurve + DEMOSAIC, // EvDehazOpacity + DEMOSAIC, // EvDehazEnabled + DEMOSAIC, // EvDehazretinex + DEMOSAIC, // EvDehazmedianmap + DEMOSAIC // EvLlimd + }; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index dbc289276..f86c1293b 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -115,25 +115,30 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if (pl) { pl->setProgress (0.30); } - + if(params.dehaz.enabled) { //enabled Dehaze LUTf cdcurve (65536, 0); - - bool dehacontlutili=false; + DehaztransmissionCurve dehatransmissionCurve; + + bool dehacontlutili = false; CurveFactory::curveDehaContL (dehacontlutili, params.dehaz.cdcurve, cdcurve, 1); - imgsrc->dehaz( params.raw, params.icm, params.dehaz, cdcurve, dehacontlutili ); + DehazParams DehaParams = params.dehaz; + DehaParams.getCurves(dehatransmissionCurve); + + imgsrc->dehaz( params.raw, params.icm, params.dehaz, cdcurve, dehatransmissionCurve, dehacontlutili ); } if (pl) { pl->setProgress (0.40); } + imgsrc->HLRecovery_Global( params.toneCurve ); - + if (pl) { pl->setProgress (0.45); } - + // set the color temperature ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.equal, params.wb.method); @@ -913,7 +918,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p params.labCurve.acurve, params.labCurve.bcurve, params.labCurve.cccurve, params.labCurve.lccurve, curve1, curve2, satcurve, lhskcurve, hist16C, hist16C, dummy, dummy, 1); - // ipf.MSR(labView, labView->W, labView->H, 1); +// ipf.MSR(labView, labView->W, labView->H, 1); ipf.chromiLuminanceCurve (NULL, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy, dummy, dummy); diff --git a/rtgui/dehaz.cc b/rtgui/dehaz.cc index 8323a6a9e..4c9d79d47 100644 --- a/rtgui/dehaz.cc +++ b/rtgui/dehaz.cc @@ -1,420 +1,493 @@ -/* - * This file is part of RawTherapee. - */ -#include "dehaz.h" -#include "mycurve.h" - -using namespace rtengine; -using namespace rtengine::procparams; - -Dehaz::Dehaz () : FoldableToolPanel(this, "dehaz", M("TP_DEHAZ_LABEL"), false, true) -{ - CurveListener::setMulti(true); - std::vector milestones; - - dehazFrame = Gtk::manage (new Gtk::Frame (M("TP_DEHAZ_LAB")) ); - dehazFrame->set_tooltip_text(M("TP_DEHAZ_LAB_TOOLTIP")); - dehazFrame->set_border_width(0); - dehazFrame->set_label_align(0.025, 0.5); - - Gtk::VBox * dehazVBox = Gtk::manage ( new Gtk::VBox()); - dehazVBox->set_border_width(4); - dehazVBox->set_spacing(2); - - Gtk::VBox * RetiVBox = Gtk::manage ( new Gtk::VBox()); - RetiVBox->set_border_width(4); - RetiVBox->set_spacing(2); - - dhbox = Gtk::manage (new Gtk::HBox ()); - labmdh = Gtk::manage (new Gtk::Label (M("TP_DEHAZE_MET") + ":")); - dhbox->pack_start (*labmdh, Gtk::PACK_SHRINK, 1); - - dehazmet = Gtk::manage (new MyComboBoxText ()); - dehazmet->append_text (M("TP_DEHAZ_LOW")); - dehazmet->append_text (M("TP_DEHAZ_UNI")); - dehazmet->append_text (M("TP_DEHAZ_HIGH")); - dehazmet->set_active(0); - dehazmetConn = dehazmet->signal_changed().connect ( sigc::mem_fun(*this, &Dehaz::dehazmetChanged) ); - dehazmet->set_tooltip_markup (M("TP_DEHAZ_MET_TOOLTIP")); - dhbox->pack_start(*dehazmet); - dehazVBox->pack_start(*dhbox); - std::vector defaultCurve; - - curveEditorGD = new CurveEditorGroup (options.lastDehazDir, M("TP_DEHAZ_CONTEDIT")); - curveEditorGD->setCurveListener (this); - rtengine::DehazParams::getDefaultCDCurve(defaultCurve); - cdshape = static_cast(curveEditorGD->addCurve(CT_Diagonal, M("TP_DEHAZ_CURVEEDITOR_CD"))); - cdshape->setResetCurve(DiagonalCurveType(defaultCurve.at(0)), defaultCurve); - cdshape->setTooltip(M("TP_DEHAZ_CURVEEDITOR_CD_TOOLTIP")); - std::vector milestones22; - - milestones22.push_back( GradientMilestone(0., 0., 0., 0.) ); - milestones22.push_back( GradientMilestone(1., 1., 1., 1.) ); - cdshape->setBottomBarBgGradient(milestones22); - cdshape->setLeftBarBgGradient(milestones22); - - curveEditorGD->curveListComplete(); - - transmissionCurveEditorG = new CurveEditorGroup (options.lastDehazDir, M("TP_DEHAZ_TRANSMISSION")); - transmissionCurveEditorG->setCurveListener (this); - - rtengine::DehazParams::getDefaulttransmissionCurve(defaultCurve); - transmissionShape = static_cast(transmissionCurveEditorG->addCurve(CT_Flat, "", NULL, false)); - transmissionShape->setIdentityValue(0.); - transmissionShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); - transmissionShape->setBottomBarBgGradient(milestones); - transmissionCurveEditorG->set_tooltip_markup (M("TP_DEHAZ_TRANS_TOOLTIP")); - - transmissionCurveEditorG->curveListComplete(); - - - - str = Gtk::manage (new Adjuster (M("TP_DEHAZ_STR"), 0, 100., 1., 60.)); - str->set_tooltip_markup (M("TP_DEHAZ_STR_TOOLTIP")); - neigh = Gtk::manage (new Adjuster (M("TP_DEHAZ_NEIGH"), 6, 100., 1., 80.)); - - retinex = Gtk::manage (new Gtk::CheckButton (M("TP_DEHAZ_RETIN"))); - retinex->set_active (true); - retinexConn = retinex->signal_toggled().connect( sigc::mem_fun(*this, &Dehaz::retinexChanged) ); - - dehazVBox->pack_start (*str); - str->show (); - - dehazVBox->pack_start (*neigh); - neigh->show (); - neigh->set_tooltip_markup (M("TP_DEHAZ_NEIGH_TOOLTIP")); - - dehazVBox->pack_start (*retinex); - retinex->show (); - - scal = Gtk::manage (new Adjuster (M("TP_DEHAZ_SCAL"), 1, 6., 1., 3.)); - gain = Gtk::manage (new Adjuster (M("TP_DEHAZ_GAIN"), 50, 150, 1, 100)); - offs = Gtk::manage (new Adjuster (M("TP_DEHAZ_OFFS"), -3000, 3000, 1, 0)); - vart = Gtk::manage (new Adjuster (M("TP_DEHAZ_VART"), 80, 250, 1, 125)); - gain->set_tooltip_markup (M("TP_DEHAZ_GAIN_TOOLTIP")); - scal->set_tooltip_markup (M("TP_DEHAZ_SCAL_TOOLTIP")); - vart->set_tooltip_markup (M("TP_DEHAZ_VART_TOOLTIP")); - - RetiVBox->pack_start (*curveEditorGD, Gtk::PACK_SHRINK, 4); - curveEditorGD->show(); - - RetiVBox->pack_start (*scal); - scal->show (); - - - RetiVBox->pack_start (*gain); - gain->show (); - - RetiVBox->pack_start (*offs); - offs->show (); - - RetiVBox->pack_start (*vart); - vart->show (); - - RetiVBox->pack_start( *transmissionCurveEditorG, Gtk::PACK_SHRINK, 2); - transmissionCurveEditorG->show(); - - - str->setAdjusterListener (this); - scal->setAdjusterListener (this); - neigh->setAdjusterListener (this); - gain->setAdjusterListener (this); - offs->setAdjusterListener (this); - vart->setAdjusterListener (this); - pack_start (*dehazVBox); - dehazFrame->add(*RetiVBox); - pack_start (*dehazFrame); - dehazFrame->hide(); - - disableListener(); - retinexChanged(); - enableListener(); - -} - -Dehaz::~Dehaz() -{ - delete curveEditorGD; - delete transmissionCurveEditorG; - -} - - -void Dehaz::read (const ProcParams* pp, const ParamsEdited* pedited) -{ - disableListener (); - dehazmetConn.block(true); - - - if (pedited) { - scal->setEditedState (pedited->dehaz.scal ? Edited : UnEdited); - neigh->setEditedState (pedited->dehaz.neigh ? Edited : UnEdited); - gain->setEditedState (pedited->dehaz.gain ? Edited : UnEdited); - offs->setEditedState (pedited->dehaz.offs ? Edited : UnEdited); - vart->setEditedState (pedited->dehaz.vart ? Edited : UnEdited); - set_inconsistent (multiImage && !pedited->dehaz.enabled); - retinex->set_inconsistent (!pedited->dehaz.retinex); - - - if (!pedited->dehaz.dehazmet) { - dehazmet->set_active_text(M("GENERAL_UNCHANGED")); - } - cdshape->setUnChanged (!pedited->dehaz.cdcurve); - transmissionShape->setUnChanged (!pedited->dehaz.transmissionCurve); - - } - - neigh->setValue (pp->dehaz.neigh); - gain->setValue (pp->dehaz.gain); - offs->setValue (pp->dehaz.offs); - str->setValue (pp->dehaz.str); - scal->setValue (pp->dehaz.scal); - vart->setValue (pp->dehaz.vart); - - setEnabled (pp->dehaz.enabled); - - retinexConn.block (true); - retinex->set_active (pp->dehaz.retinex); - retinexConn.block (false); - lastretinex = pp->dehaz.retinex; - - - if (pp->dehaz.dehazmet == "low") { - dehazmet->set_active (0); - } else if (pp->dehaz.dehazmet == "uni") { - dehazmet->set_active (1); - } else if (pp->dehaz.dehazmet == "high") { - dehazmet->set_active (2); - } - dehazmetChanged (); - retinexConn.block(false); - retinexChanged (); - retinexConn.block(false); - - cdshape->setCurve (pp->dehaz.cdcurve); - dehazmetConn.block(false); - transmissionShape->setCurve (pp->dehaz.transmissionCurve); - - - enableListener (); -} -void Dehaz::retinexUpdateUI () -{ - if (!batchMode) { - if (retinex->get_active ()) { - scal->show(); - gain->show(); - offs->show(); - vart->show(); - transmissionCurveEditorG->show(); - curveEditorGD->show(); - dehazFrame->show(); - } else { - scal->hide(); - gain->hide(); - offs->hide(); - vart->hide(); - transmissionCurveEditorG->hide(); - curveEditorGD->hide(); - dehazFrame->hide(); - } - } -} - - - -void Dehaz::write (ProcParams* pp, ParamsEdited* pedited) -{ - - pp->dehaz.str = str->getValue (); - pp->dehaz.scal = (int)scal->getValue (); - pp->dehaz.neigh = neigh->getValue (); - pp->dehaz.gain = (int)gain->getValue (); - pp->dehaz.offs = (int)offs->getValue (); - pp->dehaz.vart = (int)vart->getValue (); - pp->dehaz.cdcurve = cdshape->getCurve (); - pp->dehaz.transmissionCurve = transmissionShape->getCurve (); - pp->dehaz.enabled = getEnabled(); - pp->dehaz.retinex = retinex->get_active(); - - if (pedited) { - pedited->dehaz.dehazmet = dehazmet->get_active_text() != M("GENERAL_UNCHANGED"); - - //%%%%%%%%%%%%%%%%%%%%%% - pedited->dehaz.str = str->getEditedState (); - pedited->dehaz.scal = scal->getEditedState (); - pedited->dehaz.neigh = neigh->getEditedState (); - pedited->dehaz.gain = gain->getEditedState (); - pedited->dehaz.offs = offs->getEditedState (); - pedited->dehaz.vart = vart->getEditedState (); - pedited->dehaz.cdcurve = !cdshape->isUnChanged (); - pedited->dehaz.transmissionCurve = !transmissionShape->isUnChanged (); - pedited->dehaz.enabled = !get_inconsistent(); - pedited->dehaz.retinex = !retinex->get_inconsistent(); - - } - if (dehazmet->get_active_row_number() == 0) { - pp->dehaz.dehazmet = "low"; - } else if (dehazmet->get_active_row_number() == 1) { - pp->dehaz.dehazmet = "uni"; - } else if (dehazmet->get_active_row_number() == 2) { - pp->dehaz.dehazmet = "high"; - } -} - -void Dehaz::dehazmetChanged() -{ - if (listener) { - listener->panelChanged (Evdehazmet, dehazmet->get_active_text ()); - } - } - -void Dehaz::retinexChanged () -{ - if (batchMode) { - if (retinex->get_inconsistent()) { - retinex->set_inconsistent (false); - retinexConn.block (true); - retinex->set_active (false); - retinexConn.block (false); - } else if (lastretinex) { - retinex->set_inconsistent (true); - } - - lastretinex = retinex->get_active (); - } - retinexUpdateUI(); - - if (listener) { - if (retinex->get_active()) { - if (getEnabled()) { - listener->panelChanged (EvDehazretinex, M("GENERAL_ENABLED")); - } - } else { - if (getEnabled()) { - listener->panelChanged (EvDehazretinex, M("GENERAL_DISABLED")); - } - } - - } -} - - - -void Dehaz::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) -{ - - neigh->setDefault (defParams->dehaz.neigh); - gain->setDefault (defParams->dehaz.gain); - offs->setDefault (defParams->dehaz.offs); - str->setDefault (defParams->dehaz.str); - scal->setDefault (defParams->dehaz.scal); - vart->setDefault (defParams->dehaz.vart); - - if (pedited) { - neigh->setDefaultEditedState (pedited->dehaz.neigh ? Edited : UnEdited); - gain->setDefaultEditedState (pedited->dehaz.gain ? Edited : UnEdited); - offs->setDefaultEditedState (pedited->dehaz.offs ? Edited : UnEdited); - str->setDefaultEditedState (pedited->dehaz.str ? Edited : UnEdited); - scal->setDefaultEditedState (pedited->dehaz.scal ? Edited : UnEdited); - vart->setDefaultEditedState (pedited->dehaz.vart ? Edited : UnEdited); - - } else { - neigh->setDefaultEditedState (Irrelevant); - gain->setDefaultEditedState (Irrelevant); - offs->setDefaultEditedState (Irrelevant); - vart->setDefaultEditedState (Irrelevant); - str->setDefaultEditedState (Irrelevant); - scal->setDefaultEditedState (Irrelevant); - } -} -/* -void Dehaz::setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd) -{ - -} -*/ - -void Dehaz::adjusterChanged (Adjuster* a, double newval) -{ - - if (!listener || !getEnabled()) { - return; - } - - if (a == neigh) { - listener->panelChanged (EvLneigh, neigh->getTextValue()); - } else if (a == str) { - listener->panelChanged (EvLstr, str->getTextValue()); - } else if (a == scal) { - listener->panelChanged (EvLscal, scal->getTextValue()); - } else if (a == gain) { - listener->panelChanged (EvLgain, gain->getTextValue()); - } else if (a == offs) { - listener->panelChanged (EvLoffs, offs->getTextValue()); - } else if (a == vart) { - listener->panelChanged (EvLvart, vart->getTextValue()); - } -} - - - -void Dehaz::autoOpenCurve () -{ - cdshape->openIfNonlinear(); - transmissionShape->openIfNonlinear(); - -} - - -void Dehaz::curveChanged (CurveEditor* ce) -{ - if (listener && getEnabled()) { - if (ce == cdshape) { - listener->panelChanged (EvLCDCurve, M("HISTORY_CUSTOMCURVE")); - } else if (ce == transmissionShape) { - listener->panelChanged (EvDehaztransmission, M("HISTORY_CUSTOMCURVE")); - } - } -} - -void Dehaz::enabledChanged () -{ - - if (listener) { - if (get_inconsistent()) { - listener->panelChanged (EvDehazEnabled, M("GENERAL_UNCHANGED")); - } else if (getEnabled()) { - listener->panelChanged (EvDehazEnabled, M("GENERAL_ENABLED")); - } else { - listener->panelChanged (EvDehazEnabled, M("GENERAL_DISABLED")); - } - } -} - - -void Dehaz::trimValues (rtengine::procparams::ProcParams* pp) -{ - str->trimValue(pp->dehaz.str); - scal->trimValue(pp->dehaz.scal); - neigh->trimValue(pp->dehaz.neigh); - gain->trimValue(pp->dehaz.gain); - offs->trimValue(pp->dehaz.offs); - vart->trimValue(pp->dehaz.vart); - -} - -void Dehaz::setBatchMode (bool batchMode) -{ - ToolPanel::setBatchMode (batchMode); - neigh->showEditedCB (); - gain->showEditedCB (); - offs->showEditedCB (); - str->showEditedCB (); - scal->showEditedCB (); - vart->showEditedCB (); - curveEditorGD->setBatchMode (batchMode); - transmissionCurveEditorG->setBatchMode (batchMode); - - -} +/* + * This file is part of RawTherapee. + */ +#include "dehaz.h" +#include "mycurve.h" + +using namespace rtengine; +using namespace rtengine::procparams; + +Dehaz::Dehaz () : FoldableToolPanel(this, "dehaz", M("TP_DEHAZ_LABEL"), false, true) +{ + CurveListener::setMulti(true); + std::vector milestones; + + dehazFrame = Gtk::manage (new Gtk::Frame (M("TP_DEHAZ_LAB")) ); + dehazFrame->set_tooltip_text(M("TP_DEHAZ_LAB_TOOLTIP")); + dehazFrame->set_border_width(0); + dehazFrame->set_label_align(0.025, 0.5); + + Gtk::VBox * dehazVBox = Gtk::manage ( new Gtk::VBox()); + dehazVBox->set_border_width(4); + dehazVBox->set_spacing(2); + + Gtk::VBox * RetiVBox = Gtk::manage ( new Gtk::VBox()); + RetiVBox->set_border_width(4); + RetiVBox->set_spacing(2); + + dhbox = Gtk::manage (new Gtk::HBox ()); + labmdh = Gtk::manage (new Gtk::Label (M("TP_DEHAZE_MET") + ":")); + dhbox->pack_start (*labmdh, Gtk::PACK_SHRINK, 1); + + dehazmet = Gtk::manage (new MyComboBoxText ()); + dehazmet->append_text (M("TP_DEHAZ_LOW")); + dehazmet->append_text (M("TP_DEHAZ_UNI")); + dehazmet->append_text (M("TP_DEHAZ_HIGH")); + dehazmet->set_active(0); + dehazmetConn = dehazmet->signal_changed().connect ( sigc::mem_fun(*this, &Dehaz::dehazmetChanged) ); + dehazmet->set_tooltip_markup (M("TP_DEHAZ_MET_TOOLTIP")); + dhbox->pack_start(*dehazmet); + dehazVBox->pack_start(*dhbox); + std::vector defaultCurve; + + curveEditorGD = new CurveEditorGroup (options.lastDehazDir, M("TP_DEHAZ_CONTEDIT")); + curveEditorGD->setCurveListener (this); + rtengine::DehazParams::getDefaultCDCurve(defaultCurve); + cdshape = static_cast(curveEditorGD->addCurve(CT_Diagonal, M("TP_DEHAZ_CURVEEDITOR_CD"))); + cdshape->setResetCurve(DiagonalCurveType(defaultCurve.at(0)), defaultCurve); + cdshape->setTooltip(M("TP_DEHAZ_CURVEEDITOR_CD_TOOLTIP")); + std::vector milestones22; + + milestones22.push_back( GradientMilestone(0., 0., 0., 0.) ); + milestones22.push_back( GradientMilestone(1., 1., 1., 1.) ); + cdshape->setBottomBarBgGradient(milestones22); + cdshape->setLeftBarBgGradient(milestones22); + + curveEditorGD->curveListComplete(); + + transmissionCurveEditorG = new CurveEditorGroup (options.lastDehazDir, M("TP_DEHAZ_TRANSMISSION")); + transmissionCurveEditorG->setCurveListener (this); + + rtengine::DehazParams::getDefaulttransmissionCurve(defaultCurve); + transmissionShape = static_cast(transmissionCurveEditorG->addCurve(CT_Flat, "", NULL, false)); + transmissionShape->setIdentityValue(0.); + transmissionShape->setResetCurve(FlatCurveType(defaultCurve.at(0)), defaultCurve); + transmissionShape->setBottomBarBgGradient(milestones); + transmissionCurveEditorG->set_tooltip_markup (M("TP_DEHAZ_TRANS_TOOLTIP")); + + transmissionCurveEditorG->curveListComplete(); + + + + str = Gtk::manage (new Adjuster (M("TP_DEHAZ_STR"), 0, 100., 1., 60.)); + str->set_tooltip_markup (M("TP_DEHAZ_STR_TOOLTIP")); + neigh = Gtk::manage (new Adjuster (M("TP_DEHAZ_NEIGH"), 6, 100., 1., 80.)); + + retinex = Gtk::manage (new Gtk::CheckButton (M("TP_DEHAZ_RETIN"))); + retinex->set_active (true); + retinexConn = retinex->signal_toggled().connect( sigc::mem_fun(*this, &Dehaz::retinexChanged) ); + + dehazVBox->pack_start (*str); + str->show (); + + dehazVBox->pack_start (*neigh); + neigh->show (); + neigh->set_tooltip_markup (M("TP_DEHAZ_NEIGH_TOOLTIP")); + + dehazVBox->pack_start (*retinex); + retinex->show (); + + scal = Gtk::manage (new Adjuster (M("TP_DEHAZ_SCAL"), 1, 8., 1., 3.)); + gain = Gtk::manage (new Adjuster (M("TP_DEHAZ_GAIN"), 20, 200, 1, 100));//50 150 + offs = Gtk::manage (new Adjuster (M("TP_DEHAZ_OFFS"), -10000, 10000, 1, 0)); + vart = Gtk::manage (new Adjuster (M("TP_DEHAZ_VART"), 50, 500, 1, 125)); + limd = Gtk::manage (new Adjuster (M("TP_DEHAZ_LIMD"), 2, 100, 1, 8)); + gain->set_tooltip_markup (M("TP_DEHAZ_GAIN_TOOLTIP")); + offs->set_tooltip_markup (M("TP_DEHAZ_GAIN_TOOLTIP")); + scal->set_tooltip_markup (M("TP_DEHAZ_SCAL_TOOLTIP")); + vart->set_tooltip_markup (M("TP_DEHAZ_VART_TOOLTIP")); + limd->set_tooltip_markup (M("TP_DEHAZ_LIMD_TOOLTIP")); + + medianmap = Gtk::manage (new Gtk::CheckButton (M("TP_DEHAZ_MEDI"))); + medianmap->set_active (true); + medianmapConn = medianmap->signal_toggled().connect( sigc::mem_fun(*this, &Dehaz::medianmapChanged) ); + + RetiVBox->pack_start (*curveEditorGD, Gtk::PACK_SHRINK, 4); + curveEditorGD->show(); + + RetiVBox->pack_start (*scal); + scal->show (); + + RetiVBox->pack_start (*gain); + gain->show (); + + RetiVBox->pack_start (*offs); + offs->show (); + + RetiVBox->pack_start (*vart); + vart->show (); + + RetiVBox->pack_start (*limd); + limd->show (); + + RetiVBox->pack_start( *transmissionCurveEditorG, Gtk::PACK_SHRINK, 2); + transmissionCurveEditorG->show(); + + RetiVBox->pack_start (*medianmap); + medianmap->show (); + + str->setAdjusterListener (this); + scal->setAdjusterListener (this); + neigh->setAdjusterListener (this); + gain->setAdjusterListener (this); + offs->setAdjusterListener (this); + vart->setAdjusterListener (this); + limd->setAdjusterListener (this); + pack_start (*dehazVBox); + dehazFrame->add(*RetiVBox); + pack_start (*dehazFrame); + dehazFrame->hide(); + + disableListener(); + retinexChanged(); + medianmapChanged(); + enableListener(); + +} + +Dehaz::~Dehaz() +{ + delete curveEditorGD; + delete transmissionCurveEditorG; + +} + + +void Dehaz::read (const ProcParams* pp, const ParamsEdited* pedited) +{ + disableListener (); + dehazmetConn.block(true); + + + if (pedited) { + scal->setEditedState (pedited->dehaz.scal ? Edited : UnEdited); + neigh->setEditedState (pedited->dehaz.neigh ? Edited : UnEdited); + gain->setEditedState (pedited->dehaz.gain ? Edited : UnEdited); + offs->setEditedState (pedited->dehaz.offs ? Edited : UnEdited); + vart->setEditedState (pedited->dehaz.vart ? Edited : UnEdited); + limd->setEditedState (pedited->dehaz.limd ? Edited : UnEdited); + set_inconsistent (multiImage && !pedited->dehaz.enabled); + retinex->set_inconsistent (!pedited->dehaz.retinex); + medianmap->set_inconsistent (!pedited->dehaz.medianmap); + + + if (!pedited->dehaz.dehazmet) { + dehazmet->set_active_text(M("GENERAL_UNCHANGED")); + } + + cdshape->setUnChanged (!pedited->dehaz.cdcurve); + transmissionShape->setUnChanged (!pedited->dehaz.transmissionCurve); + + } + + neigh->setValue (pp->dehaz.neigh); + gain->setValue (pp->dehaz.gain); + offs->setValue (pp->dehaz.offs); + str->setValue (pp->dehaz.str); + scal->setValue (pp->dehaz.scal); + vart->setValue (pp->dehaz.vart); + limd->setValue (pp->dehaz.limd); + + setEnabled (pp->dehaz.enabled); + + retinexConn.block (true); + retinex->set_active (pp->dehaz.retinex); + retinexConn.block (false); + lastretinex = pp->dehaz.retinex; + + medianmapConn.block (true); + medianmap->set_active (pp->dehaz.medianmap); + medianmapConn.block (false); + lastmedianmap = pp->dehaz.medianmap; + + + if (pp->dehaz.dehazmet == "low") { + dehazmet->set_active (0); + } else if (pp->dehaz.dehazmet == "uni") { + dehazmet->set_active (1); + } else if (pp->dehaz.dehazmet == "high") { + dehazmet->set_active (2); + } + + dehazmetChanged (); + retinexConn.block(false); + retinexChanged (); + retinexConn.block(false); + + medianmapConn.block(false); + medianmapChanged (); + medianmapConn.block(false); + + cdshape->setCurve (pp->dehaz.cdcurve); + dehazmetConn.block(false); + transmissionShape->setCurve (pp->dehaz.transmissionCurve); + + + enableListener (); +} +void Dehaz::retinexUpdateUI () +{ + if (!batchMode) { + if (retinex->get_active ()) { + scal->show(); + gain->show(); + offs->show(); + vart->show(); + limd->show(); + medianmap->show(); + transmissionCurveEditorG->show(); + curveEditorGD->show(); + dehazFrame->show(); + } else { + scal->hide(); + gain->hide(); + offs->hide(); + vart->hide(); + limd->hide(); + medianmap->hide(); + transmissionCurveEditorG->hide(); + curveEditorGD->hide(); + dehazFrame->hide(); + } + } +} + + + +void Dehaz::write (ProcParams* pp, ParamsEdited* pedited) +{ + + pp->dehaz.str = str->getValue (); + pp->dehaz.scal = (int)scal->getValue (); + pp->dehaz.neigh = neigh->getValue (); + pp->dehaz.gain = (int)gain->getValue (); + pp->dehaz.offs = (int)offs->getValue (); + pp->dehaz.vart = (int)vart->getValue (); + pp->dehaz.limd = (int)limd->getValue (); + pp->dehaz.cdcurve = cdshape->getCurve (); + pp->dehaz.transmissionCurve = transmissionShape->getCurve (); + pp->dehaz.enabled = getEnabled(); + pp->dehaz.retinex = retinex->get_active(); + pp->dehaz.medianmap = medianmap->get_active(); + + if (pedited) { + pedited->dehaz.dehazmet = dehazmet->get_active_text() != M("GENERAL_UNCHANGED"); + + //%%%%%%%%%%%%%%%%%%%%%% + pedited->dehaz.str = str->getEditedState (); + pedited->dehaz.scal = scal->getEditedState (); + pedited->dehaz.neigh = neigh->getEditedState (); + pedited->dehaz.gain = gain->getEditedState (); + pedited->dehaz.offs = offs->getEditedState (); + pedited->dehaz.vart = vart->getEditedState (); + pedited->dehaz.limd = limd->getEditedState (); + pedited->dehaz.cdcurve = !cdshape->isUnChanged (); + pedited->dehaz.transmissionCurve = !transmissionShape->isUnChanged (); + pedited->dehaz.enabled = !get_inconsistent(); + pedited->dehaz.retinex = !retinex->get_inconsistent(); + pedited->dehaz.medianmap = !medianmap->get_inconsistent(); + + } + + if (dehazmet->get_active_row_number() == 0) { + pp->dehaz.dehazmet = "low"; + } else if (dehazmet->get_active_row_number() == 1) { + pp->dehaz.dehazmet = "uni"; + } else if (dehazmet->get_active_row_number() == 2) { + pp->dehaz.dehazmet = "high"; + } +} + +void Dehaz::dehazmetChanged() +{ + if (listener) { + listener->panelChanged (Evdehazmet, dehazmet->get_active_text ()); + } +} + +void Dehaz::retinexChanged () +{ + if (batchMode) { + if (retinex->get_inconsistent()) { + retinex->set_inconsistent (false); + retinexConn.block (true); + retinex->set_active (false); + retinexConn.block (false); + } else if (lastretinex) { + retinex->set_inconsistent (true); + } + + lastretinex = retinex->get_active (); + } + + retinexUpdateUI(); + + if (listener) { + if (retinex->get_active()) { + if (getEnabled()) { + listener->panelChanged (EvDehazretinex, M("GENERAL_ENABLED")); + } + } else { + if (getEnabled()) { + listener->panelChanged (EvDehazretinex, M("GENERAL_DISABLED")); + } + } + + } +} + +void Dehaz::medianmapChanged () +{ + if (batchMode) { + if (medianmap->get_inconsistent()) { + medianmap->set_inconsistent (false); + medianmapConn.block (true); + medianmap->set_active (false); + medianmapConn.block (false); + } else if (lastmedianmap) { + medianmap->set_inconsistent (true); + } + + lastmedianmap = medianmap->get_active (); + } + + if (listener) { + if (medianmap->get_active()) { + if (getEnabled()) { + listener->panelChanged (EvDehazmedianmap, M("GENERAL_ENABLED")); + } + } else { + if (getEnabled()) { + listener->panelChanged (EvDehazmedianmap, M("GENERAL_DISABLED")); + } + } + + } +} + + +void Dehaz::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) +{ + + neigh->setDefault (defParams->dehaz.neigh); + gain->setDefault (defParams->dehaz.gain); + offs->setDefault (defParams->dehaz.offs); + str->setDefault (defParams->dehaz.str); + scal->setDefault (defParams->dehaz.scal); + vart->setDefault (defParams->dehaz.vart); + limd->setDefault (defParams->dehaz.limd); + + if (pedited) { + neigh->setDefaultEditedState (pedited->dehaz.neigh ? Edited : UnEdited); + gain->setDefaultEditedState (pedited->dehaz.gain ? Edited : UnEdited); + offs->setDefaultEditedState (pedited->dehaz.offs ? Edited : UnEdited); + str->setDefaultEditedState (pedited->dehaz.str ? Edited : UnEdited); + scal->setDefaultEditedState (pedited->dehaz.scal ? Edited : UnEdited); + vart->setDefaultEditedState (pedited->dehaz.vart ? Edited : UnEdited); + limd->setDefaultEditedState (pedited->dehaz.limd ? Edited : UnEdited); + + } else { + neigh->setDefaultEditedState (Irrelevant); + gain->setDefaultEditedState (Irrelevant); + offs->setDefaultEditedState (Irrelevant); + vart->setDefaultEditedState (Irrelevant); + limd->setDefaultEditedState (Irrelevant); + str->setDefaultEditedState (Irrelevant); + scal->setDefaultEditedState (Irrelevant); + } +} +/* +void Dehaz::setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd) +{ + +} +*/ + +void Dehaz::adjusterChanged (Adjuster* a, double newval) +{ + + if (!listener || !getEnabled()) { + return; + } + + if (a == neigh) { + listener->panelChanged (EvLneigh, neigh->getTextValue()); + } else if (a == str) { + listener->panelChanged (EvLstr, str->getTextValue()); + } else if (a == scal) { + listener->panelChanged (EvLscal, scal->getTextValue()); + } else if (a == gain) { + listener->panelChanged (EvLgain, gain->getTextValue()); + } else if (a == offs) { + listener->panelChanged (EvLoffs, offs->getTextValue()); + } else if (a == vart) { + listener->panelChanged (EvLvart, vart->getTextValue()); + } else if (a == limd) { + listener->panelChanged (EvLlimd, vart->getTextValue()); + } + +} + + + +void Dehaz::autoOpenCurve () +{ + cdshape->openIfNonlinear(); + transmissionShape->openIfNonlinear(); + +} + + +void Dehaz::curveChanged (CurveEditor* ce) +{ + if (listener && getEnabled()) { + if (ce == cdshape) { + listener->panelChanged (EvLCDCurve, M("HISTORY_CUSTOMCURVE")); + } else if (ce == transmissionShape) { + listener->panelChanged (EvDehaztransmission, M("HISTORY_CUSTOMCURVE")); + } + } +} + +void Dehaz::enabledChanged () +{ + + if (listener) { + if (get_inconsistent()) { + listener->panelChanged (EvDehazEnabled, M("GENERAL_UNCHANGED")); + } else if (getEnabled()) { + listener->panelChanged (EvDehazEnabled, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvDehazEnabled, M("GENERAL_DISABLED")); + } + } +} + + +void Dehaz::trimValues (rtengine::procparams::ProcParams* pp) +{ + str->trimValue(pp->dehaz.str); + scal->trimValue(pp->dehaz.scal); + neigh->trimValue(pp->dehaz.neigh); + gain->trimValue(pp->dehaz.gain); + offs->trimValue(pp->dehaz.offs); + vart->trimValue(pp->dehaz.vart); + limd->trimValue(pp->dehaz.limd); + +} + +void Dehaz::setBatchMode (bool batchMode) +{ + ToolPanel::setBatchMode (batchMode); + neigh->showEditedCB (); + gain->showEditedCB (); + offs->showEditedCB (); + str->showEditedCB (); + scal->showEditedCB (); + vart->showEditedCB (); + limd->showEditedCB (); + curveEditorGD->setBatchMode (batchMode); + transmissionCurveEditorG->setBatchMode (batchMode); + + +} diff --git a/rtgui/dehaz.h b/rtgui/dehaz.h index 9cf0614c5..86d6e134a 100644 --- a/rtgui/dehaz.h +++ b/rtgui/dehaz.h @@ -14,7 +14,7 @@ #include "colorprovider.h" class Dehaz : public ToolParamBlock, public FoldableToolPanel, public CurveListener, - public AdjusterListener + public AdjusterListener { protected: @@ -25,24 +25,26 @@ protected: Adjuster* gain; Adjuster* offs; Adjuster* vart; - + Adjuster* limd; + Gtk::Label* labmdh; Gtk::HBox* dhbox; MyComboBoxText* dehazmet; Gtk::CheckButton* retinex; Gtk::Frame* dehazFrame; + Gtk::CheckButton* medianmap; DiagonalCurveEditor* cdshape; CurveEditorGroup* transmissionCurveEditorG; sigc::connection dehazmetConn; FlatCurveEditor* transmissionShape; - bool lastretinex; - sigc::connection retinexConn; + bool lastretinex, lastmedianmap; + sigc::connection retinexConn, medianmapConn; public: Dehaz (); ~Dehaz (); - + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = NULL); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = NULL); void setBatchMode (bool batchMode); @@ -52,6 +54,7 @@ public: // void setAdjusterBehavior (bool splitAdd, bool satThresholdAdd, bool satOpacityAdd, bool strprotectAdd, bool balanceAdd); void autoOpenCurve (); void retinexChanged (); + void medianmapChanged (); void enabledChanged (); void curveChanged (CurveEditor* ce); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 7dc1e57ea..edf449dcc 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -58,6 +58,8 @@ void ParamsEdited::set (bool v) dehaz.gain = v; dehaz.offs = v; dehaz.vart = v; + dehaz.limd = v; + dehaz.medianmap = v; dehaz.transmissionCurve = v; dehaz.retinex = v; labCurve.lcurve = v; @@ -524,8 +526,10 @@ void ParamsEdited::initFrom (const std::vector dehaz.gain = dehaz.gain && p.dehaz.gain == other.dehaz.gain; dehaz.offs = dehaz.offs && p.dehaz.offs == other.dehaz.offs; dehaz.vart = dehaz.vart && p.dehaz.vart == other.dehaz.vart; - dehaz.enabled = dehaz.enabled && p.dehaz.enabled == other.dehaz.enabled; - dehaz.retinex = dehaz.retinex && p.dehaz.retinex == other.dehaz.retinex; + dehaz.limd = dehaz.limd && p.dehaz.limd == other.dehaz.limd; + dehaz.medianmap = dehaz.medianmap && p.dehaz.medianmap == other.dehaz.medianmap; + dehaz.enabled = dehaz.enabled && p.dehaz.enabled == other.dehaz.enabled; + dehaz.retinex = dehaz.retinex && p.dehaz.retinex == other.dehaz.retinex; 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; @@ -1016,7 +1020,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (toneCurve.method) { toEdit.toneCurve.method = mods.toneCurve.method; } - + if (dehaz.enabled) { toEdit.dehaz.enabled = mods.dehaz.enabled; } @@ -1024,7 +1028,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (dehaz.cdcurve) { toEdit.dehaz.cdcurve = mods.dehaz.cdcurve; } - + if (dehaz.transmissionCurve) { toEdit.dehaz.transmissionCurve = mods.dehaz.transmissionCurve; } @@ -1040,25 +1044,35 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (dehaz.scal) { toEdit.dehaz.scal = mods.dehaz.scal; } - + if (dehaz.retinex) { toEdit.dehaz.retinex = mods.dehaz.retinex; } - + + if (dehaz.medianmap) { + toEdit.dehaz.medianmap = mods.dehaz.medianmap; + } + if (dehaz.neigh) { toEdit.dehaz.neigh = mods.dehaz.neigh; } - + + if (dehaz.limd) { + toEdit.dehaz.limd = mods.dehaz.limd; + } + if (dehaz.gain) { toEdit.dehaz.gain = mods.dehaz.gain; } + if (dehaz.offs) { toEdit.dehaz.offs = mods.dehaz.offs; } + if (dehaz.vart) { toEdit.dehaz.vart = mods.dehaz.vart; } - + if (labCurve.lcurve) { toEdit.labCurve.lcurve = mods.labCurve.lcurve; } @@ -1090,15 +1104,17 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (labCurve.lccurve) { toEdit.labCurve.lccurve = mods.labCurve.lccurve; } + // if (labCurve.dehazmet) { // toEdit.labCurve.dehazmet = mods.labCurve.dehazmet; // } if (labCurve.clcurve) { toEdit.labCurve.clcurve = mods.labCurve.clcurve; } - // if (labCurve.cdcurve) { - // toEdit.labCurve.cdcurve = mods.labCurve.cdcurve; - // } + +// if (labCurve.cdcurve) { +// toEdit.labCurve.cdcurve = mods.labCurve.cdcurve; + // } if (labCurve.brightness) { toEdit.labCurve.brightness = dontforceSet && options.baBehav[ADDSET_LC_BRIGHTNESS] ? toEdit.labCurve.brightness + mods.labCurve.brightness : mods.labCurve.brightness; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 10dbfe828..b2a7056d1 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -66,11 +66,13 @@ public: bool offs; bool dehazmet; bool vart; + bool limd; bool method; bool transmissionCurve; bool cdcurve; bool retinex; - + bool medianmap; + }; @@ -717,7 +719,7 @@ public: LCurveParamsEdited labCurve; RGBCurvesParamsEdited rgbCurves; ColorToningEdited colorToning; - DehazParamsEdited dehaz; + DehazParamsEdited dehaz; SharpeningParamsEdited sharpening; SharpeningParamsEdited prsharpening; SharpenEdgeParamsEdited sharpenEdge;